AWS EKS Auto Mode
Wprowadzenie
Re:Invent 2024 należy już do historii. I to jakiej historii, mówię wam! Amazon ogłosił dziesiątki nowych funkcji dla AWS Cloud, wiele z nich jest naprawdę ekscytujących! Ale jest jedna, która według mnie przewyższa inne – to EKS Auto Mode. W tym artykule chciałbym opowiedzieć wam trochę więcej o tej funkcji.
Funkcje i korzyści EKS Auto Mode
Pierwszą i najważniejszą cechą EKS Auto Mode jest zdjęcie całego ciężaru związanego z utrzymaniem klastrów EKS.
Na podstawie przykładu dostępnego obecnie na stronie EKS Pricing, koszt tej funkcji wynosi 12% całkowitego kosztu instancji. Amazon podaje w swoim przykładzie 1 046,82 USD miesięcznie za instancje EC2 oraz opłatę 125,62 USD za EKS Auto Mode dla tych instancji. Pełny przykład jest dostępny tutaj.
Co więc dostajemy za tę opłatę 12%?
- Automatyczne aktualizacje i łatki instancji EC2 w obrębie klastra
- Autoskalowanie dzięki integracji z Karpenter
- Skalowanie klastra do zera!
- Optymalizacja kosztów bez kompromisów w elastyczności
- Poprawa bezpieczeństwa dzięki integracjom z usługami bezpieczeństwa AWS
- Redukcja obciążenia związanego z utrzymaniem
- Łatwiejszy start z EKS! Poziom wejścia jest teraz znacznie niższy!
- Automatyczne zarządzanie pamięcią masową, siecią i IAM
Wszystkie szczegóły są dostępne w oficjalnej dokumentacji. Jest tam również sekcja How it works, która wyjaśnia zarządzanie instancjami, IAM i siecią przy użyciu EKS Auto Mode.
Łatwy start i utrzymanie
EKS Auto Mode współpracuje z Karpenter i zarządza podzbiorem dodatków klastra. Dzięki temu nie musimy martwić się o prawidłowe utrzymanie i skalowanie węzłów oraz podstawowych komponentów, np. CoreDNS (miałem z nim do czynienia w przeszłości, to była udręka!). Funkcja ta również upraszcza zarządzanie zależnościami między dodatkami, aktualizacje wersji, a nawet cały proces aktualizacji klastra! Ostatnia opcja otwiera ciekawą drogę do automatycznej aktualizacji klastrów zamiast płacenia za rozszerzone wsparcie, które wynosi około 440 USD (zamiast standardowej ceny 70 USD) na klaster – wyobraźcie sobie posiadanie 15 klastrów na rozszerzonym wsparciu – 6 600 USD miesięcznie (zamiast standardowych 1 050 USD)! To dużo! A dlaczego rozszerzone wsparcie jest tak kosztowne? Ponieważ zarządzanie różnymi i starymi wersjami EKS oraz ich utrzymywanie jest trudne i kosztowne – a Amazon bardzo dobrze o tym wie!
Ale wspomniałem, że koszt EKS Auto Mode wynosi około 12% ceny instancji w klastrze. To nie wydaje się dużo w przypadku małych klastrów, ale dla dużych klastrów może stać się kosztowne. Czy zatem zawsze powinniśmy korzystać z EKS Auto Mode? Zdecydowanie nie! Jeśli macie odpowiednie kompetencje na pokładzie i nie potrzebujecie zatrudniać nowych ludzi tylko do zarządzania EKS, lub jeśli posiadacie duże klastry, które znacząco podniosą całkowity koszt EKS Auto Mode, lepiej pozostać przy klasycznym podejściu. Matematyka wciąż jest po waszej stronie; wybór należy do was – płacić AWS za ich ekspertyzę czy opłacać własnych inżynierów. Pamiętajcie, że inżynierowie mogą zajmować się innymi rzeczami, gdy nie muszą zarządzać klastrami – pomyślcie o kosztach alternatywnych, być może mogą przynieść firmie większą wartość, niż zaoszczędzicie, nie korzystając z EKS Auto Mode.
Funkcje bezpieczeństwa
EKS Auto Mode obsługuje wiele funkcji i mechanizmów związanych z bezpieczeństwem. Integruje API Kubernetes z wpisami dostępu EKS, które są zintegrowane z użytkownikami i rolami AWS IAM. Pozwala to na precyzyjną kontrolę dostępu do API K8s, wykorzystując wpisy dostępu EKS.
Są także funkcje dotyczące bezpieczeństwa sieci. EKS Auto Mode obsługuje silną integrację z VPC, działa bez ograniczeń VPC, obsługuje niestandardowe VPC z ich konfiguracjami i prywatną siecią między komponentami klastra. Tryb ten obsługuje również Kubernetes Network Policies, umożliwiając użytkownikom definiowanie niestandardowych reguł ruchu sieciowego, co spełnia najbardziej wymagające wymagania przedsiębiorstw.
Kolejna grupa funkcji bezpieczeństwa w EKS Auto Mode dotyczy zabezpieczeń EC2. Tryb ten ma maksymalny czas życia instancji wynoszący 21 dni, dzięki czemu nie będziemy uruchamiać niezałatanych instancji (ponieważ tryb ten zarządza także ich aktualizacjami), a w przypadku jakichkolwiek niepożądanych elementów w instancji, zostanie ona regularnie wymieniona. Pamięć masowa EC2 w tym trybie jest szyfrowana – wszystkie dyski tworzone wraz z instancjami będą zabezpieczone. Ale jest jedno ważne zastrzeżenie – niestandardowe EBS-y zarządzane w Kubernetes przy użyciu konfiguracji trwałej pamięci masowej nie są w pełni zarządzane przez EKS Auto Mode i trzeba o tym pamiętać!
Instancje EC2 w tym trybie nie są w ogóle dostępne – nie ma dostępu SSH ani SSM. Jeśli musicie uzyskać dostęp do instancji EC2 w swoich klastrach z jakiegokolwiek powodu, musicie zarządzać klastrami EKS samodzielnie dla każdego klastra, który ma takie wymagania dostępu. Ale jeśli macie takie potrzeby, mogę założyć, że doskonale wiecie, co robicie, i jesteście w stanie zarządzać klastrami samodzielnie – EKS Auto Mode jest głównie po to, by wam pomóc, a nie rozwiązywać każdy możliwy przypadek brzegowy.
Ważna uwaga!
EKS Auto Mode używa AMI specjalnie dostosowanych do tego trybu! Jeśli polityka waszej firmy wymaga, aby instancje klastra spełniały określone wymagania bezpieczeństwa, ten tryb nie jest dla was i musicie działać samodzielnie! Co mogę tu zalecić? Dokładnie przeanalizujcie dostarczone AMI wraz ze swoimi zespołami ds. bezpieczeństwa, aby upewnić się, czy można je wykorzystać – i upewnijcie się, że członkowie zespołu zdobyli wiedzę o tych AMI, jeśli zdecydują się ich nie używać, tak aby uzasadnienie nie sprowadzało się do „mamy swoje standardy” lub „nie znamy tych AMI”.
Czas na zabawę!
Wymagania środowiskowe
Aby przejść przez ten przewodnik, będziecie potrzebować następujących narzędzi:
- AWS CLI
- Terraform
- kubectl
- helm
- aws-vault (opcjonalnie)
Oraz następujących zasobów:
- Konto AWS
- Użytkownik IAM
- Rola IAM (opcjonalnie)
- AWS managed policy Administrator Access (dla łatwego PoC)
Jeśli chcecie to wypróbować prywatnie i nie znacie AWS, bądźcie gotowi na koszty – zasoby i usługi używane tutaj mogą nie kwalifikować się do AWS Free Tier.
Konfiguracja środowiska testowego
Aby zobaczyć EKS Auto Mode w akcji, skonfigurujmy podstawowy klaster i użyjmy go!
Najpierw skonfigurujmy klaster EKS przy użyciu Terraform.
W tym celu skorzystałem z oficjalnej dokumentacji Terraform dotyczącej eks_cluster
i dodałem dodatkową konfigurację dla mojego użytkownika IAM, aby mógł on wchodzić w interakcję z klastrem. Użyłem także lokalnego stanu Terraform, ponieważ nie chciałem konfigurować zdalnego backendu tylko dla PoC, który wiedziałem, że usunę wkrótce po eksperymentach.
Poniżej znajduje się konfiguracja Terraform, którą przygotowałem:
terraform.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
# Amazon EKS Auto Mode support was added in version 5.79
version = ">= 5.79"
}
}
}
providers.tf
provider "aws" {
# Instances in Ireland are cheaper than in Frankfurt.
# You can check costs e.g. at https://instances.vantage.sh/
region = "eu-west-1"
default_tags {
tags = {
Terraform = "true"
Environment = "eks-auto-mode-poc"
}
}
}
data.tf
data "aws_region" "current" {}
# I added my user to the EKS cluster, as it was not included in the example from Terraform docs.
data "aws_iam_user" "jan_tyminski" {
user_name = "jan.tyminski@j-labs.pl"
}
vpc.tf
# I didn’t want to put a lot of effort in it so I used the official module from the Terraform registry.
# This is the module supported by Anton Babenko and his modules are well maintained and well tested.
module "jlabs_eks_poc_vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "jlabs-eks-poc"
cidr = "10.0.0.0/16"
azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
enable_vpn_gateway = false
# single nat gateway is used to reduce costs of the PoC
single_nat_gateway = true
}
eks.tf
resource "aws_eks_cluster" "jlabs_eks_poc" {
name = "jlabs_eks_poc"
access_config {
authentication_mode = "API"
}
role_arn = aws_iam_role.jlabs_eks_poc_cluster.arn
version = "1.31"
bootstrap_self_managed_addons = false
# compute_config block is required for EKS Auto Mode, with enabled = true
compute_config {
enabled = true
node_pools = ["general-purpose"]
node_role_arn = aws_iam_role.jlabs_eks_poc_node.arn
}
kubernetes_network_config {
elastic_load_balancing {
enabled = true
}
}
storage_config {
block_storage {
enabled = true
}
}
vpc_config {
endpoint_private_access = true
endpoint_public_access = true
subnet_ids = module.jlabs_eks_poc_vpc.private_subnets
}
# Ensure that IAM Role permissions are created before and deleted
# after EKS Cluster handling. Otherwise, EKS will not be able to
# properly delete EKS managed EC2 infrastructure such as Security Groups.
depends_on = [
aws_iam_role_policy_attachment.cluster_AmazonEKSClusterPolicy,
aws_iam_role_policy_attachment.cluster_AmazonEKSComputePolicy,
aws_iam_role_policy_attachment.cluster_AmazonEKSBlockStoragePolicy,
aws_iam_role_policy_attachment.cluster_AmazonEKSLoadBalancingPolicy,
aws_iam_role_policy_attachment.cluster_AmazonEKSNetworkingPolicy,
]
}
eks_roles.tf
resource "aws_iam_role" "jlabs_eks_poc_node" {
name = "eks_auto_mode-jlabs_eks_poc-node-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = ["sts:AssumeRole"]
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
},
]
})
}
resource "aws_iam_role_policy_attachment" "node_AmazonEKSWorkerNodeMinimalPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodeMinimalPolicy"
role = aws_iam_role.jlabs_eks_poc_node.name
}
resource "aws_iam_role_policy_attachment" "node_AmazonEC2ContainerRegistryPullOnly" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly"
role = aws_iam_role.jlabs_eks_poc_node.name
}
resource "aws_iam_role" "jlabs_eks_poc_cluster" {
name = "eks_auto_mode-jlabs_eks_poc-cluster-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"sts:AssumeRole",
"sts:TagSession"
]
Effect = "Allow"
Principal = {
Service = "eks.amazonaws.com"
}
},
]
})
}
resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSClusterPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
role = aws_iam_role.jlabs_eks_poc_cluster.name
}
resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSComputePolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSComputePolicy"
role = aws_iam_role.jlabs_eks_poc_cluster.name
}
resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSBlockStoragePolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSBlockStoragePolicy"
role = aws_iam_role.jlabs_eks_poc_cluster.name
}
resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSLoadBalancingPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSLoadBalancingPolicy"
role = aws_iam_role.jlabs_eks_poc_cluster.name
}
resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSNetworkingPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSNetworkingPolicy"
role = aws_iam_role.jlabs_eks_poc_cluster.name
}
# I added my user to the EKS cluster, as it was not included in the example from Terraform docs.
resource "aws_eks_access_entry" "jan_tyminski" {
cluster_name = aws_eks_cluster.jlabs_eks_poc.name
principal_arn = data.aws_iam_user.jan_tyminski.arn
type = "STANDARD"
}
resource "aws_eks_access_policy_association" "jan_tyminski_AmazonEKSAdminPolicy" {
cluster_name = aws_eks_cluster.jlabs_eks_poc.name
policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSAdminPolicy"
principal_arn = aws_eks_access_entry.jan_tyminski.principal_arn
access_scope {
type = "cluster"
}
}
resource "aws_eks_access_policy_association" "jan_tyminski_AmazonEKSClusterAdminPolicy" {
cluster_name = aws_eks_cluster.jlabs_eks_poc.name
policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy"
principal_arn = aws_eks_access_entry.jan_tyminski.principal_arn
access_scope {
type = "cluster"
}
}
eks_outputs.tf
# Outputs in this PoC are not necessary, but I will add them for the sake of completeness
# and have commands to update kubeconfig and describe the cluster ready for me.
output "eks_cluster_name" {
value = aws_eks_cluster.jlabs_eks_poc.name
}
output "eks_cluster_region" {
value = data.aws_region.current.name
}
output "update_kubeconfig" {
value = "aws eks --region ${data.aws_region.current.name} update-kubeconfig --name ${aws_eks_cluster.jlabs_eks_poc.name}"
}
output "describe_cluster" {
value = "aws eks --region ${data.aws_region.current.name} describe-cluster --name ${aws_eks_cluster.jlabs_eks_poc.name}"
}
Now we can run terraform apply, review the resources to be created and confirm their creation. After a couple of minutes - let's say 15 - we should have our cluster ready.
In the meantime make yourself a coffee, tea or some other beverage, take time to talk with someone or to make some quick exercises - breaks are important to keep your brain rested and work properly.
Set a timer for 15 minutes to check if everything is ready to continue - if not, take 5-10 more minutes with another timer.
Or just go to lunch and everything should be ready when you return.
Konfigurowanie dostępu do klastra
Teraz, gdy klaster jest już skonfigurowany, możemy skonfigurować kubectl
dla tego nowego klastra.
W moim przypadku wymagało to uruchomienia:
aws eks --region eu-west-1 update-kubeconfig --name jlabs_eks_poc
W Twoim przypadku – sprawdź swoje wyjścia Terraform (terraform outputs
) – polecenie powinno być tam wygenerowane!
Aby sprawdzić, czy wszystko działa, uruchom:
kubectl get nodes
W tym momencie powinieneś otrzymać informację, że nie znaleziono żadnych węzłów – i to jest w porządku, ponieważ to właśnie funkcja EKS Auto Mode – możemy skalować klaster do zera!
Testowanie Amazon EKS Auto Mode
Gdy wszystko jest gotowe, możemy kontynuować pracę z zasobami Kubernetes.
Istnieje bardziej szczegółowy przewodnik dostępny na Blogu AWS, ale zrobiłem to nieco inaczej, stosując krótszą metodę, aby sprawdzić, czy skalowanie działa. Oczywiście możesz postępować zgodnie z oficjalnym przewodnikiem – ja nie generuję rzeczywistego obciążenia na wdrożeniach, a jedynie skaluję repliki dla jednego z nich.
Zatem skonfigurujmy plik wartości:
values.yaml
catalog:
mysql:
secret:
create: true
name: catalog-db
username: catalog
persistentVolume:
enabled: true
accessMode:
- ReadWriteOnce
size: 30Gi
storageClass: eks-auto-ebs-csi-sc
ui:
endpoints:
catalog: http://retail-store-app-catalog:80
carts: http://retail-store-app-carts:80
checkout: http://retail-store-app-checkout:80
orders: http://retail-store-app-orders:80
assets: http://retail-store-app-assets:80
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 10
targetCPUUtilizationPercentage: 80
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: ui
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: ui
ingress:
enabled: true
className: eks-auto-alb
Uruchom:
helm install -f values.yaml retail-store-app oci://public.ecr.aws/aws-containers/retail-store-sample-chart --version 0.8.3
Następnie sprawdź, czy wszystkie wdrożenia są gotowe:
kubectl wait --for=condition=available deployments --all
A w osobnym terminalu możesz uruchomić:
kubectl get nodes --watch
NAME STATUS ROLES AGE VERSION
i-013641a69e7d4e3f6 Ready <none> 35s v1.31.1-eks-1b3e656
i-06f0cf4305b4bd90a Ready <none> 49s v1.31.1-eks-1b3e656
Tak to wygląda w konsoli AWS:

kubectl get nodes
NAME STATUS ROLES AGE VERSION
i-0125aff84e741bb4c Ready <none> 81s v1.31.1-eks-1b3e656
i-013641a69e7d4e3f6 Ready <none> 78m v1.31.1-eks-1b3e656
i-06f0cf4305b4bd90a Ready <none> 78m v1.31.1-eks-1b3e656
Aby zobaczyć, jak skalowanie działa na węzłach, sprawdźmy, co się stanie, gdy zmniejszymy liczbę replik w wdrożeniu:
kubectl scale --replicas=5 deployment/retail-store-app-ui
A po około 10 minutach możemy zobaczyć następujące wyniki:

kubectl get nodes
NAME STATUS ROLES AGE VERSION
i-013641a69e7d4e3f6 Ready <none> 86m v1.31.1-eks-1b3e656
i-06f0cf4305b4bd90a Ready <none> 86m v1.31.1-eks-1b3e656
Czyszczenie
Aby usunąć wszystko i uniknąć generowania kosztów po przetestowaniu, wykonaj następujące polecenie:
helm uninstall retail-store-app
kubectl delete pvc/data-retail-store-app-catalog-mysql-0
A postęp możemy obserwować interaktywnie:
kubectl get nodes --watch
NAME STATUS ROLES AGE VERSION
i-013641a69e7d4e3f6 Ready <none> 3h1m v1.31.1-eks-1b3e656
i-06f0cf4305b4bd90a Ready <none> 3h1m v1.31.1-eks-1b3e656
i-013641a69e7d4e3f6 Ready <none> 3h1m v1.31.1-eks-1b3e656
i-013641a69e7d4e3f6 Ready <none> 3h1m v1.31.1-eks-1b3e656
i-013641a69e7d4e3f6 Ready <none> 3h1m v1.31.1-eks-1b3e656
i-06f0cf4305b4bd90a Ready <none> 3h2m v1.31.1-eks-1b3e656
i-013641a69e7d4e3f6 NotReady <none> 3h2m v1.31.1-eks-1b3e656
i-013641a69e7d4e3f6 NotReady <none> 3h2m v1.31.1-eks-1b3e656
i-013641a69e7d4e3f6 NotReady <none> 3h2m v1.31.1-eks-1b3e656
Wynik tutaj nie jest najlepszy, trochę się zacina, ale możemy zobaczyć, że węzeł zmienia status na NotReady.
Konsola AWS to odzwierciedla:

A gdy nasze węzły są oznaczone jako NotReady, możemy teraz usunąć całą konfigurację za pomocą:
terraform destroy -auto-approve
I nasze środowisko powinno zostać wyczyszczone, nie generując już żadnych dodatkowych kosztów.
Podsumowanie
Amazon EKS Auto Mode jest dość prosty w użyciu i skalowanie działa szybko oraz efektywnie. Wykonując ten PoC, mogliśmy nabrać pewności w jego stosowaniu. Myślę, że ta nowa funkcja ma ogromny potencjał i że jej wprowadzenie przyspieszy adopcję Kubernetes w wielu organizacjach.
Pamiętam pracę w małym zespole, gdzie przygotowanie klastra EKS do wdrożeń stagingowych zajęło nam około trzech miesięcy. Oczywiście, były pewne inne czynniki niezwiązane bezpośrednio z samym klastrem, ale uważam, że dzięki EKS Auto Mode moglibyśmy zaoszczędzić około miesiąca pracy dla każdego członka zespołu.
Dodatkowo, nie trzeba przejmować się konfiguracją Karpenter, która nie jest trywialna i może stanowić poważną przeszkodę dla osób z małym doświadczeniem w Kubernetes. Zwłaszcza że Karpenter 1.0 został wydany 14 sierpnia 2024 roku.
Kod, którego użyłem w tym PoC, jest dostępny na J-Lab’s GitHub. Całkowity koszt AWS dla tego testu wyniósł mniej niż 2 USD.
Poznaj mageek of j‑labs i daj się zadziwić, jak może wyglądać praca z j‑People!
Skontaktuj się z nami


