본문 바로가기
카테고리 없음

[AEWS-3기] EKS Auto Mode에 대해서

by james_janghun 2025. 3. 22.


EKS Auto Mode란?

 

기본적으로 Auto Mode는 Karpenter를 사용합니다. 따라서 노드 자체의 Auto Scaling 기능을 갖추게 됩니다. 뿐만아니라 EKS Auto Mode를 사용하게되면 모든 AWS EKS Addon과 EBS Controller, ELB Controller 등 다양한 컨트롤러들을 AWS에서 관리하게 됩니다.

 

즉, 기본적인 개념 자체가 Control-plane 뿐만아니라 NodeGroup도 이제는 AWS에서 관리해주겠다 로 이해하면 될 것 같습니다.

 


특징 (및 제약사항)

모든 것을 AWS에서 관리하기 때문에 다음과 같은 제약사항이 있습니다.

 

기본 NodeClass 사용

- NodeClass는 기본적으로 80GiB의 EphemeralStorage와 노드당 최대 110개의 pod로 제한합니다.

- NodeClass를 별도로 추가할 수 있으며, IAM 역할, 보안그룹, 서브넷을 정의하여 추가하게 됩니다.

 

기본 NodePool 사용

- 기본 Nodepool은 system(amd64/arm64), general-purpose(amd64)가 기본으로 존재합니다.

- system의 경우 전용인스턴스를 추가하는 것이기 때문에 일반적으로 general-purpose를 사용합니다.

- 새로운 NodePool을 추가해서 사용할 수 있습니다. 다만 콘솔에서 해당 부분은 표시되지 않으므로 (딱 general-purpose와 system만 표시됨) kubectl로 조회해야합니다.

 

AWS에서 관리

- SSH와 SSM 엑세스까지 금지하고 있어 노드에 직접 엑세스를 차단합니다.

- 주요 에이전트(kube-proxy, kubelet 등) pod가 systemd 데몬으로 실행되어 해당 pod들이 없습니다.

- GPU도 내장 플러그인을 사용합니다.

 

Karpenter 설정상 제약

Karpenter 설정 상 기본적으로 14일 이후 노드가 교체되도록 설정되어 있으며, budget 설정을 통해서 그 교체 시기를 변경할 수 있습니다. 변경할 경우 최대 21일까지 사용이 가능합니다.

이 때문에 AMI도 교체도 자동으로 최신화 됩니다.

 

네트워킹

- IngressClassParams를 지원하는데 일부 기능은 제한됩니다.

 

스토리지

- 스토리지는 EBS CSI 내장 드라이버를 사용합니다. (Provisioner : ebs.csi.eks.amazonaws.com)

- EBS 성능 프로메테우스 메트릭에 접근할 수 없습니다.

- NVMe 스토리지를 자동으로 구성하여, 다중 NVMe 드라이브는 RAID 0으로 설정됩니다.

 

Auto 모드를 위한 테라폼 코드

https://github.com/aws-samples/sample-aws-eks-auto-mode

 

GitHub - aws-samples/sample-aws-eks-auto-mode

Contribute to aws-samples/sample-aws-eks-auto-mode development by creating an account on GitHub.

github.com

 

eks.tf

module "eks" {
  source  = "terraform-aws-modules/eks/aws"
  version = "~> 20.24"

  cluster_name    = var.name
  cluster_version = var.eks_cluster_version

  # Give the Terraform identity admin access to the cluster
  # which will allow it to deploy resources into the cluster
  enable_cluster_creator_admin_permissions = true
  cluster_endpoint_public_access           = true

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnets

  cluster_compute_config = {
    enabled    = true
    node_pools = ["general-purpose"]
  }
  tags = local.tags
}

 

 

eks에서 Auto Mode에 대한 설정은 딱 이 부분입니다.

  cluster_compute_config = {
    enabled    = true
    node_pools = ["general-purpose"]
  }

node_pools에서 general-purpose와 system 두 가지가 있는데, general-purpose를 일반적으로 사용합니다.

system은 전용인스턴스를 사용합니다. 주로 kube-system에서 쓰이는 시스템 컴포넌트를 위한 특수 목적 파드들을 놓게되는데 최소 노드가 보통 1개 이상으로 유지됩니다. 고가용성을 위한 노드라고 볼 수 있을 것 같습니다.

 

이 부분은 콘솔의 노드 구성에서도 살펴볼 수 있으며, general-purpose와 system을 제외한 별도로 개인이 만든 노드 풀은 내장 노드 풀에 나오지 않습니다. kubectl을 통해서 확인해야 합니다.

 

정보를 일단 차근차근 살펴봅시다.

ENI

EKS Owned ENI로 별도로 생성됩니다.

 

EKS 자율 모드라고하는 곳에서 활성화 표시 및 사용할 노드 IAM을 별도로 잡게됩니다.

 

추가 기능 (Add on)

정말 특이한 것은 Add on 까지도 관리해주기 때문에 표시되지 않는다는 것입니다.

 

액세스

AWS 자체에서 관리하기 때문에 해당 부분의 내용에 access 허용이 됩니다.

 

특히 아래 내용에 보면 Amazon EKS Pod Identity가 이미 설치되어 있으니 별도로 노드그룹을 사용할게 아니라면 별도로 추가하지 않아도 됨을 알 수 있습니다.

 

 

kubectl을 통한 확인

kubectl get crd

kubectl api-resources | grep -i node

kubectl get nodepools

 

실제 nodepool 정보를 보면 다음과 같이 node의 타입등이 모두 정해져있는 것을 확인할 수 있다.

spec:
  disruption:
    budgets:
    - nodes: 10%
    consolidateAfter: 30s
    consolidationPolicy: WhenEmptyOrUnderutilized
  template:
    metadata: {}
    spec:
      expireAfter: 336h
      nodeClassRef:
        group: eks.amazonaws.com
        kind: NodeClass
        name: default
      requirements:
      - key: karpenter.sh/capacity-type
        operator: In
        values:
        - on-demand
      - key: eks.amazonaws.com/instance-category
        operator: In
        values:
        - c
        - m
        - r
      - key: eks.amazonaws.com/instance-generation
        operator: Gt
        values:
        - "4"
      - key: kubernetes.io/arch
        operator: In
        values:
        - amd64
      - key: kubernetes.io/os
        operator: In
        values:
        - linux
      terminationGracePeriod: 24h0m0s

 

kube-ops-view를 배포해보면서 확인해봅시다.

먼저 eks-node-viewer를 통해서 모니터링을 하면서 이벤트기반으로 로그를 추출해보았다.

eks-node-viewer --node-sort=eks-node-viewer/node-cpu-usage=dsc --extra-labels eks-node-viewer/node-age
watch -d kubectl get node,pod -A

helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ="Asia/Seoul" --namespace kube-system
kubectl get events -w --sort-by '.lastTimestamp' # 출력 이벤트 로그 분석해보자

 

노드가 필요해 NodeClaim이 general-purpose의 nodepool에서 적당한 타입의 노드를 선택해 프로비저닝하였습니다.

 

이런식으로 nodeclaims를 확인할 수도 있습니다.

kubectl get nodeclaims

 

 

잘보면 별다른 aws-node 와 같은 애드온 pod들은 전혀 안보이는게 특이한 점입니다.

 

예시로 한번 애플리케이션 pod를 엄청 많이 배포해보겠습니다.

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inflate
spec:
  replicas: 1
  selector:
    matchLabels:
      app: inflate
  template:
    metadata:
      labels:
        app: inflate
    spec:
      terminationGracePeriodSeconds: 0
      nodeSelector:
        eks.amazonaws.com/compute-type: auto
      securityContext:
        runAsUser: 1000
        runAsGroup: 3000
        fsGroup: 2000
      containers:
        - name: inflate
          image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
          resources:
            requests:
              cpu: 1
          securityContext:
            allowPrivilegeEscalation: false
EOF

 

 

pod가 많아지면서 노드에 자원이 부족해지고, nodeclaim을 통해서 또 다른 노드를 생성하는 것을 확인할 수 있습니다.

kubectl scale deployment inflate --replicas 100 && kubectl get events -w --sort-by '.lastTimestamp'

 

인스턴스 타입도 갑자기 극단적으로 c5a.large -> c5a.2xlarge -> r5b.metal로 원하는 pod가 모두 들어갈 수 있는 node로 급격하게 띄웠습니다.

 

5분도 안되서 생각보다 빠르게 불필요한 node는 정리해버리는 것을 확인할 수 있었습니다.

 

 

노드가 계속 변경되는데도 전혀 노드란에는 반영되지 않습니다.

 

 

노드 콘솔 출력 정보 확인 (get-console-output)

아래 공식문서를 보면 다양한 방법으로 디버깅이 가능하다고 소개하고 있습니다. 그 중 하나가 get-console-output입니다.

https://docs.aws.amazon.com/eks/latest/userguide/auto-troubleshoot.html

 

Troubleshoot EKS Auto Mode - Amazon EKS

EKS Auto Mode uses EC2 managed instances. You cannot directly access EC2 managed instances, including by SSH.

docs.aws.amazon.com

 

아무래도 문제가 생길 때는 노드도 디버깅이 필요한데 EC2 접근이 안되기 때문에 어떻게 디버깅할지가 이슈가 됩니다. 따라서 get-console-output을 제공하고 이 정보를 통해 확인이 가능합니다.

kubectl get node

NODEID=i-0530c4f48b50073d8

 

aws ec2 get-console-output을 통해서 바로 확인할 수가 있습니다.

aws ec2 get-console-output --instance-id $NODEID --latest --output text

 

기본적으로 kubelet의 로그를 가져온다고 봐도될 것으로 보입니다.

 

 

노드 로그 수집 by S3(Node monitoring agent NodeDiagnostic)

EKS Auto Mode에서는 자동으로 eks 노드 모니터링 agent가 포함되어 있습니다. 이 agent를 통해서 노드에 대해 문제 해결이나 디버깅 정보를 파악할 수 있습니다. 

https://docs.aws.amazon.com/eks/latest/userguide/auto-get-logs.html

 

Retrieve node logs for a managed node using kubectl and S3 - Amazon EKS

You must use the AWS API or a SDK to create the pre-signed S3 upload URL for EKS to upload the log file. You cannot create a pre-signed S3 upload URL using the AWS CLI.

docs.aws.amazon.com

 

S3버킷생성

먼저 로그를 저장할 S3 버킷을 생성합니다.

BUCKETNAME=james-aews-study
aws s3api create-bucket --bucket $BUCKETNAME --create-bucket-configuration LocationConstraint=ap-northeast-2 --region ap-northeast-2
aws s3 ls

 

 

S3 pre-signed-url 생성

미리 서명된 url을 생성하기 위해 cloudshell에서 실행합니다.

#
aws sts get-caller-identity --query Arn
which python
python -V
pip list

# presign-upload.py 파일 작성 예시
import boto3; print(boto3.client('s3').generate_presigned_url(
   ClientMethod='put_object',
   Params={'Bucket': 'james-aews-study', 'Key': '2025-03-23/logs1.tar.gz'},
   ExpiresIn=1000
))

# 각자 아래 버킷명과 키값 수정
cat << EOF > presign-upload.py
import boto3; print(boto3.client('s3').generate_presigned_url(
   ClientMethod='put_object',
   Params={'Bucket': 'james-aews-study', 'Key': '2025-03-23/logs1.tar.gz'},
   ExpiresIn=1000
))
EOF
cat presign-upload.py

# 아래 출력된 presign url 메모(복사해두기)
python presign-upload.py
https://james-aews-study.s3.amazonaws.com/2025-03-22/logs1.tar.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIASK5OAMM3CR45Z2M4%2F20250322%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20250322T235327Z&X-Amz-Expires=1000&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHAaDmFwLW5vcnRoZWFzdC0yIkgwRgIhAPpJsWzJcJFcXl%2FGEwg5VTDVFjv6h8KRV%2BHkn71hPkdOAiEAs4LVXmcbENGZjCuTlblouN2BOXI%2FpOKImlnfLQtkUn0q%2FwIIyf%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARABGgwxNjA4ODkzMzI1MzQiDKEAurh0vvdNDElMhSrTAkaC3DAEt7Q1FfGEBepE%2Brhjm8HpO4iESABNGrClvgNnBKfDKDw2ZwMGDgylEI6lTBEYO6VIF5JZy2HOOOt44ckgs%2FQ%2FDj5WxHNoDKmgEftEPpY%2FLkFsMdcrHjChJdkcJR9bptHjJX6Zv70CWV6%2FnxUFaklZf1DZBkScygWA%2F5Cja7R66JjBsWQH%2BAfFP9%2B4LCLlKmwZq8RzUFSeoCE4eMO7XMMTn39gt6jJgJHdcO2nbHy%2FE8JY9Kv%2FFlCz1C7Gme%2BKCdgxrLbLR9mvYiawtp1uZtHegNJheJ7e%2BU%2FIghJihEHJyMR6yrljitGJzJRrQKojmloU06QIohl6cvYIwBI6CjXWcD3Mx2sP6FDFpDNtRHmvUObeOVjWC2wYhw2XLe9sv4bChBsOeD9hIJeN%2FU2YRSdWoxUV8S0%2FrxAFDQU1ZxbtPy1Bn8OKIhQ7peGjw4FoZzCqivu%2BBjqyAh677TXB1TZvnMIn3nIUW14urHTiDGYb6kdg1R2oyeI%2FDQVNydTjrpvzRNxya2WhlOxPYeuSqUpp1uTlmkEpxx%2BVZ4TNhBy8HcYPNBYkZykMh3UQRNAu%2BpuXoCGyLi1Lnw%2BQ4D3KYBcEE%2FqE4Ls539v13xS8x9Z3yDreK%2F1K9dvwDy6Ej47eBGoM%2FNPM98hJgSgvRi%2FoZoL840uPqBBD2qi37tiou8w4Qq1dvL%2Fdu85ponEGJCAOgurVOPtDhAY1CdzkteRYvY6uLaLGcEebmJintGfS9SVKEA8XO0cG2irhvhbH8HhekaHHZyBmrVPbFriCpY2tk5Jjic9Cy9c63NmugDxUFkqLyYgjvwxovbcoJmb1Jnx0crWtAkPYqzZ7zhw0lRCOc%2FdfaOcUM2KfsT7%2F5A%3D%3D&X-Amz-Signature=b1ff4fd5683ca44a8f8445379936d83f1cc11a5a339eb387d872e54f02167a03

 

NodeDiagnostic 생성

cat <<EOF | kubectl apply -f -
apiVersion: eks.amazonaws.com/v1alpha1
kind: NodeDiagnostic
metadata:
  name: i-0530c4f48b50073d8
spec:
  logCapture:
    destination: https://james-aews-study.s3.ap-northeast-2.amazonaws.com/logs1.tar.gz?response-content-disposition=inline&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEHAaDmFwLW5vcnRoZWFzdC0yIkcwRQIgOqe4guHSmI5nF9Ou1sI6aNln7ToDl6d6jKSRxE66KIcCIQC1DXN%2FzJTrcCyavAVzLUvv9fcjsD9RKW8EDIPk5ILBtirUAwjJ%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAEaDDE2MDg4OTMzMjUzNCIMqf%2FwakluQItOAYfuKqgDsv%2B9ivQiENMhboBfePEZe3MZ043wEVm9O2NHTCFYv%2FIxsERP2OWVvMI7FMsbMFNV8kO4Bl0K9qq5r82lJ3P%2BuHhu7ek5%2FLe3CPQI3vk1fPHuYkufM%2FCIMlbp5aoAav%2BGFaOc91%2BT5xWWk%2F168HdJEL1A7V8EDJ3s41xixNBoUQmNac%2BrmlfjUW2SAtuf0EysFiPCxgT4X3N2hlzZFHtUhITfXcG6pTfK9EQRKqvWIk9Pn3q13wMIpB02d5SoYpr%2FEhfCAsGtX3IzK40UBrEvnOPUhLlhoNfIinDpShMEwSIpoIiO1Eom1KjerN%2FahYvWFvTsCtcuK2C1ABX9KEsSfOGNCgpuc9WZde7B6Y4Pblxh26FWXbIRfO%2FdccnKxPfMWLco%2BQdouc9rxkvvDuh9d%2B4ZXus%2BaDTv9ckG3jI23sdcw3SIfORUtI4mEakCYoQr65gUJMzu4h%2FN4tBw4aEFgusj7B55K%2FI3%2FwpWpJSVpNr0%2B4szz7EKsPArrLZ7PivFz4VFiivI9bul1GW6YWFjO4aZyDcnIrCw%2BFEkxS8ySQShtKs5TBsFrjCqivu%2BBjrkAjOmZqhcTLt7asj26z19N%2Flnw4ltfUz2yhPqvWrIEcYsCDcEU15rvIiJ%2FyADFe4fNgxfONHNyklVnenk2kQRghWkgun4CCCqx%2BrRQZHSGpk1ey8sbNVk2Z%2FL8MFthjIQla3wU6QHzT74LrB1UQsMNjNCtOe6aHU5krep9dHFC0ZThNZUrotFg81gTOA%2BUzPv5OEPeyGGRm7f9xq14FZH1HOhoPZiscFgD%2FpdCvB%2Bf6tvSiLhJ7t8DpBQ%2Bct7nG3iyc2Aypy0RVHdhBEKOY%2BupYx8%2BtS4OwMqP%2B9FKSQxKeO7MceMVpF0rXApf8%2B2H3Nww%2B%2FopvKPgDJ7B62UWyP%2BBYB5MkEYwwOaReeLtOiHFC%2BF5TUSoU%2FCyWWOjFYhNB8%2FJBT1g3FRLMXOiTb15%2BAsfoeiV0hTUijFCGyTjWSYQ5IHKZMkx537mqVcflhWq1OtErJI%2BHYeGWFi7hOXkdIWn63WQfNE&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIASK5OAMM3AYQHZMLH%2F20250323%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20250323T001749Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=e6540517f6865fb9d8961e0c9eaefba391250a91f92d9a18e07016a04daaa315
EOF

kubectl get nodediagnostic
kubectl describe nodediagnostic