AWS: Fargate – можливості, порівняння з Lambda/EC2 та використання з AWS EKS

Автор |  03/05/2023

AWS Fargate – ще одне serverless-рішення від Amazon, яке бере на себе управління інфраструктурою, позбавляючи користувача необхідності витрачати час на налаштування ЕС2-інстансів, операційної системи, систем управління контейнерами тощо.

Взагалі, коли знайомився з Fargate, натрапив на чудове відео з AWS re:Invent 2022, де дуже добре розказано (і показано) про Shared Responsibility model у AWS – за які частини системи відповідає Амазон, а за які – користувач, тож дуже рекомендую до перегляду – AWS re:Invent 2022 – A close look at AWS Fargate and AWS App Runner.

Якщо поглянути на схему з цього відео, то там гарно відображена роль Fargate:

Тобто, AWS бере на себе все, пов’язане з серверами та операційною системою і її компонентами, тоді як нам лишається тільки створити та запустити контейнер.

При цьому, AWS Fargate можна використовувати разом із AWS Elastic Container Service або AWS Elastic Kubernetes Service, і саме його роботу з AWS EKS ми сьогодні й розглянемо.

AWS Fargate vs AWS Lambda

Перше питання, яке з’явилось у мене, коли я почав читати про Fargate – а навіщо, якщо вже є AWS Lambda? В чому різниця? До речі, у відео ще розказується і про AWS App Runner – ще один serverless-сервіс від Амазону, але зараз не про нього (а ще маємо Knative, хоча це вже не про AWS).

Functionality

Отже, концептуально – AWS Fargate являє собою CaaS, тобто Container as a Service, тоді як AWS Lambda – це FaaS, тобто Function as a Service: для роботи з Fargate вам потрібно мати зібраний docker-образ (чи будь-який інший відповідний до Open Container Initiative специфікації), тоді як для роботи з AWS Lambda вам потрібен тільки код – Lambda сама “запакує” його в контейнер, та запустить.

Крім того, для Fargate ви маєте налаштовувати автоскейлінг контейнерів, тоді як у Lambda це відбувається автоматично. Крім того, контейнери у Fargate не будуть скейлитись в нуль, коли немає роботи – для цього ви маєте виключати Fargate tasks самі (або просто скейлити в нуль поди в Kubernetes), а у Lambda фунцкції будуть запинені, як тільки до них перестануть надходити евенти, які тригерять запуск цих функцій.

Вартість та оплата за сервіс

При цьому обидва сервіси мають однакову модель оплати – pay-as-you-go model, тобто ви платите тільки за час, коли ваш контейнер або функція виконуються, хоча й мають відмінності: у Fargate оплата стягується саме за споживані CPU/RAM в секунду, тоді як у Labmda ви платите за кожен виклик функції та за час її виконання. Див. AWS Fargate Pricing.

Use Cases

Fargate добре підходить для роботи довготривалих задач, для яких ви маєте більше можливостей налаштувати робоче оточення, і маєте менше обмежень на CPU/RAM, дискову систему для збереження даних та не маєте таких суттєвих лімітів на розмір даних, які можете відправляти/отримувати.

З іншого боку Lambda дозволяє вам швидше запускати код (бо не маєте потреби збирати образ контейнеру), автоматичний скейлінг “з коробки”, моніторинг, і добре підходить для короткотривалих задач.

AWS Fargate vs AWS EKS EC2 Node Groups

Вже по ходу діла запуску перших подів у EKS з використанням Fargate з’явилося інше питання – а що там з EC2?

В цьому порівняні, у Fargate такі переваги:

  • більш швидкий скейлінг
  • може бути більше cost effective рішенням, ніж EC2
  • не потребує security патчів (хоча Managed Node Groups начебто теж самі встановлюють патчі)

Недоліки Fargate:

  • менше контролю над інфрастуктурою
  • іноді рішення з EC2 може бути більш вигідним по вартості
  • обмеження по CPU/Memory та типам інстансів (наприклад, немає змоги звикористовувати GPU)

У випадку з EC2 ви маєте більший контроль над інфрастуктурою та типами інстансів (GPU, мережа тощо), але це потребує більше роботи інженерів (запуск, обслуговання серверів, моніторинг), до того ж ви платити за сервери незважаючи на те, виконується на них якась робота, чи ні.

Взагалі, ви просто можете в одному EKS-кластері мати і Node Groups, і Fargate-інстанси для різних подів.

Amazon EKS та AWS Fargate

Отже, у EKS наші поди мають чомусь запускатись. Зазвичай для цього використовуються NodeGrops (Managed та Self-managed), які являють собою звичайні AWS EC2 інстанси, але замість віртуальних машин ми можемо використати AWS Fargate, див. Amazon EKS nodes.

Які саме поди будуть запускатись налаштовується у Fargate profiles, які являються частиною вашого EKS-кластеру. Сам EKS інтегруються з Fargate через контролери, які вбудовані в сервіс EKS і працюють на його control plane. Крім того, для запуску подів у Fargate є окремий scheduler – fargate-scheduler (на відміну від default-scheduler, котрий відповідає за запуск подів на ЕС2-інстансах).

Див. AWS Fargate.

Особливості Fargate у EKS

При планувані використання AWS Fargate разом з вашим EKS, майте на увазі, що:

  • Network Load Balancers та Application Load Balancers при використанні Fargate мають бути з IP targets
  • DaemonSets не підтримуються
  • Privileged containers не підтримуються
  • Pods у Fargate не можуть мати HostPort або HostNetwork
  • Pods у Fargate можуть бути запущені тільки у приватних мережах (private subnets)
  • ви можете використовувати Vertical Pod Autoscaler щоб задати потрібні resources.requests для подів, і потім скейлити їх за допомогою Horizontal Pod Autoscaler
  • Amazon EC2 instance metadata service (IMDS) не підтримується у Fargate
  • на Fargate нодах використовується Amazon VPC CNI plugin for Amazon EKS, альтернативні CNI plugins не підтримуються
  • ви можете використовувати Amazon EBS CSI controller з Fargate, але не маєте змоги підключати додаткові EBS
  • при використанні Kubernetes job з Fargate важливо видаляти ці джоби після завершення їхньої роботи навіть якщо Failed, інакше вони продовжуватимуть використовувати Fargate ноди, а ви продовжите платити
  • максимум 16 vCPU та 120 GB RAM (див. AWS Fargate increases compute and memory resource configurations by 4x)
  • у AWS ECS наче вже є можливість використовувати Fargate Spot instances, але у EKS такого поки нема (але є GitHub issue з таким реквестом)

Див. всі у AWS Fargate considerations.

Створення EKS кластеру

Тут все будемо “клікопсити”, якось іншим разом розгорнемо EKS за допомогою Terraform або AWS CDK.

EKS cluster IAM role

Спершу, нам потрібна AIM роль, через яку майбутній кластер буде спілкуватись з сервісами Амазону, див. Amazon EKS cluster IAM role.

Переходимо в АІМ, клікаємо Create role, у Trusted entity type залишаємо AWS service, у Use case зі списку вибираємо EKS – Cluster:

На сторінці Add permissions лишаємо за-замовченням, та натискаємо Next:

Далі, задаємо ім’я ролі, і тиснемо Create Role:

Створення VPC та Subnets

Боже, сто років не створював їх… Тим більш вручну.

Окей, що нам треба:

  • VPC
  • її розбити на кілька сабнетів в різних AvailabilityZones
    • частина – публічні, з Internet Gateway – для всяких AWS LoadBalancer
    • частина – приватні, тут будуть жити поди Куберу, для них створимо NAT Gateway
  • і ще там щось було з SecurityGroups

Поїхали.

І – оп… Приїхали) Інтерфейс створення VPC переробили прям круто…

Переходимо до VPC, створюємо нову мережу, вибираємо VPC and more – мені просто цікаво, як воно, і виглядає воно прям реально зручно – все створюємо відразу, а не півгодини клікаємо по VPC dashboard, а потім думаємо де ми накосячили в route tables.

Тож створюємо VPC з сабнетами в кожній Availability Zone, створюємо публічні сабнети з Internet Gateway, та приватні с NAT Gateway у кожній Availability Zone (дороже, але надійніше, якщо таке робити для Продакшену). Заодно додамо VPC S3 endpoints – зараз він не потрібен, але взагалі дуже корисна штука в плані security та cost-effective:

Внизу перевіряємо, що DNS hostnames та DNS resolution включені – це вимога для роботи Fargate (описано у тому ж AWS Fargate considerations, якщо ви його пропустили):

Клікаємо Create.

Чорт – реально круто зробили!

Чекаємо створення ресурсів:

Створення EKS cluster

Переходимо до Elastic Kubernetes Service, клікаємо Add cluster > Create:

Задаємо ім’я кластеру, вибираємо створену роль, та клікаємо Next (Secrets encryption – щось новеньке, треба якось потестити):

Далі, вибираємо нашу VPS – сабнети підтянуться самі, нижче вибирамо SecurityGroup, наразі можна дефолтну з нашой VPC:

Далі, налаштовуємо доступ до нашого кластеру.


AWS Fargate Pod зависає у статусі Pending

Трохи забігаючи наперед – про можливу проблему. Після налаштування начебто всього – тестовий под завис у стаутсі Pedning з такими повідомленнями:

[simterm]

$ kubectl describe pod nginx
Name:                 nginx
Namespace:            default
...
Labels:               eks.amazonaws.com/fargate-profile=fargate-test-eu-central-1-profile
...
Status:               Pending
...
  Warning  LoggingDisabled   11m    fargate-scheduler  Disabled logging because aws-logging configmap was not found. configmap "aws-logging" not found
  Warning  FailedScheduling  8m48s  fargate-scheduler  Pod provisioning timed out (will retry) for pod: default/nginx

[/simterm]

Я вже все перебрав і перегуглив – Fargate profiles, SecurityGroup EKS, NAT Gateways у subnets – всюди все вірно. WTF?

Виявилось, що коли в цьому пості трохи нижче написав:

Вазагалі, звісно бажано відключати публічний доступ до АПІ, і ходити через приватний ендпоінт, наприклад через ВПН. Але зараз залимо обидва варвіанти – і публічний, і приватний, тіль задамо ліміт на ІП.

То побіг далі, і не переключив доступ до кластеру з дефолтного значення Public на Public and private, що й призвело до проблеми.

І це сказано у перших строках документації, і я навіть цитував це, коли описував процес:

Without the private endpoint enabled, the CIDR blocks that you specify for public access must include the outbound sources from your VPC.

Але я тупо пропустив переключити опцію, і півгодини намагався зрозуміти в чьому проблема.

Окей, йдемо далі – на цей раз вже правильно.


Отже, взагалі, звісно бажано відключати публічний доступ до Kubernetes API, і ходити через приватний ендпоінт, наприклад через VPN. Але зараз включимо обидва варіанти – і публічний, і приватний, тільки задамо ліміт на мій домашній IP.

Знаходимо його:

[simterm]

$ curl ifconfig.me
217.***.***.253

[/simterm]

Та додаємо його у дозволені:

Далі, налаштовуємо логування. Тут теж бажано включати якщо не всі, то хоча б логи API-серверу, Audit або Authentificator, та Scheduler:

На наступному кроці, вибираємо Addons (теж наче не було такого раніше), тут ще й GuardDuty з’явився:

На наступній сторінці не бачу, що можна було б міняти – лишаємо, клікаємо Next:

І нарешті останнє – ревью, та створюємо кластер:

Чекаємо. Раніше це займало хвилин 15-20, але були новини, що Амазон пришвидшив процесс.

Налаштування kubectl

Для перевірки того, що з кластером все гаразд і для подальшого тестування подів додамо його у наш ~/.kube/config.

Додаємо у конфіг:

[simterm]

$ aws --profile setevoy eks update-kubeconfig --name fargate-test-eu-central-1-cluster --alias setevoy-fargate-test-eu-central-1-cluster
Added new context setevoy-fargate-test-eu-central-1-cluster to /home/setevoy/.kube/config

[/simterm]

Перевіряємо:

[simterm]

$ kk get pod --all-namespaces
NAMESPACE     NAME                      READY   STATUS    RESTARTS   AGE
kube-system   coredns-cbbbbb9cb-2hhx2   0/1     Pending   0          18h
kube-system   coredns-cbbbbb9cb-4xf2w   0/1     Pending   0          18h

[/simterm]

Поки що маємо тільки два поди с CoreDNS, зараз у Pending, бо намає ані Woker Nodes, ані Fargate profile.

Переходимо до Fargate.

Підключення AWS Fargate

Тепер, як маємо EKS кластер, настав час підключати Fargate.

Див. документацію у Getting started with AWS Fargate using Amazon EKS, і перше, на шо звертаємо увагу – це Security Groups на Worker Nodes:

If you restrict access to the public endpoint of your cluster using CIDR blocks, we recommend that you also enable private endpoint access. This way, Fargate pods can communicate with the cluster. Without the private endpoint enabled, the CIDR blocks that you specify for public access must include the outbound sources from your VPC.

В нашому випадку ніяких Node Groups нема, тож продовжуємо.

EKS pod execution IAM Role

Спочатку нам треба додати АІМ роль, яка дозволить подам у Fargate комунікувати з Амазоном, див. Amazon EKS pod execution IAM role (обожнюю документацію Амазону).

Переходимо в AIM > Roles > Create role.

На цей раз вибираємо EKS – Fragate pod:

Далі – Next, на сторінці Add permissions лишаємо, як є (можна подивитись самі пермішени), переходимо далі, задаємо ім’я і натискаємо Create role:

Після створення знаходимо роль, переходимо до вкладки Trust relationships, редагуємо роль:

Прописуємо нову політику доступу до цієї ролі:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Condition": {
         "ArnLike": {
            "aws:SourceArn": "arn:aws:eks:eu-central-1:26***286:fargateprofile/fargate-test-eu-central-1-cluster/*"
         }
      },
      "Principal": {
        "Service": "eks-fargate-pods.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Натискаємо Update policy, та переходимо до створення Fargate profile.

Створення Fargate profile

Fargate профіль описує, які саме поди з Kubernetes-кластру будут запускатись у Fargate, див. AWS Fargate profile.

Для створення, переходимо до EKS, потім до нашого кластеру, на вкладці Compute знизу знаходимо Add Fargate profile:

Задаємо ім’я, АІМ роль підставилась автоматично, як і приватні сабнету нашої VPC:

У Pod selectors описується які поди з яких неймспейсів будуть запускатись з цим Fargate профілем.

Зараз для тесту нехай будуть всі, але в цілому можна створювати різні профайли для різних типів подів з виборкою по неймспейсам та/або лейблам, які додані подам:

Далі, перевіряємо, що все вірно, та створюємо профайл:

Створення зайняло хвилин 5.

Запуск Kubernetes-подів у Fargate

Отже, поки що маємо тільки два поди з CoreDNS, які знаходяться у статусі Pending.

Щоб CoreDNS поди запустились у Fargate – редагуємо їхній Deployment, та прибираємо аннотацію eks.amazonaws.com/compute-type: ec2:

 

За хвилину-дві перевіряємо:

[simterm]

$ kubectl -n kube-system get pod
NAME                       READY   STATUS    RESTARTS   AGE
coredns-75694977b5-m7smc   0/1     Pending   0          5m48s
coredns-75694977b5-tgwdl   1/1     Running   0          50s

[/simterm]

Перший пішов.

І після запуску перших подів на вкладці Compute нашого кластеру маємо побачити Fargate-ноди у EKS-кластері:

Поки стартує другий под з CoreDNS – додамо звичайний тестовий под, щоб ще раз побачити як воно працює:

[simterm]

$ kubectl run nginx --image=nginx
pod/nginx created

[/simterm]

І за пару хвилин перевіряємо поди:

[simterm]

$ kubectl get pod --all-namespaces
NAMESPACE     NAME                       READY   STATUS    RESTARTS   AGE
default       nginx                      1/1     Running   0          2m27s
kube-system   coredns-75694977b5-r8d6b   1/1     Running   0          46s
kube-system   coredns-75694977b5-tgwdl   1/1     Running   0          5m52s

[/simterm]

Та Fargate-ноди:

Щодо івенту “Disabled logging because aws-logging configmap was not found” – можно окремо налаштувати логгінг, див. Fargate logging, на запуск подів не впливає.

Ще з цікавого, що добре знати, це те, що IAM-роль для наших подів додається до aws-auth ConfigMap кластеру:

[simterm]

$ kk -n kube-system get cm aws-auth -o yaml
apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      - system:node-proxier
      rolearn: arn:aws:iam::264***286:role/AmazonEKSFargatePodExecutionRole-fargate-test-eu-central-1
      username: system:node:{{SessionName}}

[/simterm]

Так начебто все.

Можна пробувати користуватись замість звичайних EC2.

Посилання по темі