AEWS study

7주차 - EKS Mode/Nodes - #2

haru224 2025. 3. 22. 10:32

CloudNet@ 가시다님이 진행하는 AWS EKS Hands-on Study 내용 참고.

 

Auto mode


automode 참고 blog

  • [악분일상] EKS Auto Mode는 무엇이고 왜 출시되었을까? - Blog , Youtube

 

  • 팟캐스트 7번째 이야기] EKS AutoMode와 re:Invent 후기 - Youtube

 

이론

AWS re:Invent 2024 - The future of Kubernetes on AWS (KUB201) - Youtube , PDF

더보기
  • EKS 지난 7년 발전 과정

 

  • ECR Enhanced Image Scanning : DB와 OS 취약점 탐색 기능 추가

 

 

  • 다른 컨테이너 이미지 저장소(Upstream registry)에 동기화(sync)를 통하여 신규 이미지를 즉시에 제공 가능

 

 

  • k8s 버전 출시 후 보통 .1 패치 시점(40일 정도)에 EKS 버전 출시됨. 23년의 경우 k8s 버전을 따라가기 위해서 어쩔수없이? 1년에 4개 버전 출시됨.

 

 

  • Extended Support for Amazon EKS 연장 지원 제공

 

 

  • Upgrade insights 에서 문제가 있는 api 요청 확인 가능

 

 

  • 2개의 메트릭 추가(controller-manager, scheduler)

 

 

  • CloudWatch Network Flow Monitor

 

 

  • 파드, 네임스페이스, 클러스터 별 EC2 비용 확인 가능!

 

 

  • add-ons 추가 : CW Container Insights, CSI Snapshot Controller, Pod Identity Agent, Node Monitoring Agent

 

 

  • Add-ons 에 Pod Identity 연동 지원 확대 중

 

 

  • EKS Object 암호화에 KMS v2 기본 적용

 

 

  • ACK

 

 

  • KRO : ACK의 좀 더 발전된 오케스트레이터로 보임.

 

 

  • EKS Hybrid Nodes

 

 

  • Auto mode
출처: https://www.youtube.com/watch?v=IQjsFlkqWQY

 

 

  • Node Health and Auto-Repair

 

AWS re:Invent 2024 - Automate your entire Kubernetes cluster with Amazon EKS Auto Mode (KUB204-NEW) - Youtube

 

더보기
  • app 배포 운영

 

 

  • Auto mode 소개

 

 

  • R&R

 

  • 기능

 

  • 컴퓨팅

 

 

  • 네트워킹

 

 

  • 스토리지

 

 

  • 정리

  AWS re:Invent 2024 - Simplify Kubernetes workloads with Karpenter & Amazon EKS Auto Mode (KUB312) - Youtube , PDF

더보기
  • karpenter 사용 시

 

 

  • karpenter 는 CA 기능에 더해서, ‘비용 절감, 업그레이드/패치 도움’

 

 

  • karpenter ‘Spot Interruption handling’ 기본 내장 기능 제공

 

 

  • 스케줄링

 

  • 통합 시간 조정 설정

 

 

  • disruption budget
    • 평일 9시 부터 8시간(근무 시간) 동안은 disruption 되지 않음.
    • 다만, 노드에 아무 파드도 없을 경우에는 시간과 상관없이(100%) disruption 됨.
    • 근무 시간 이외에는 한번에 disruption 되는 비중은 10%.

 

  • drift : 운영 서버는 매칭 안됨. 트리거.. , 0.32 부터 기본 활성화

 

  • AMI Selector

 

  • before → Auto mode : 6가지 구성요소가 파드로 구성되는게 아니고, 해당 노드에 systemd 데몬(agent)로 실행됨.
  • 위 6가지 구성요소가 파드로 구성되는게 아니고, 해당 노드에 systemd 데몬(agent)로 실행됨.

 

  • NodePools

 

 

  • NodeClass

 

 

  • Strategies for defining multiple NodePools

 

 

  • Automatic updates with EKS Auto Mode

 

  [AWS Docs] Auto Mode* - Docs

  User Guide - Docs

  • 소개
    • EKS Auto Mode는 클러스터 자체를 넘어 Kubernetes 클러스터의 AWS 관리를 확장하여 AWS가 워크로드를 원활하게 운영할 수 있는 인프라를 설정하고 관리할 수 있도록 합니다. 주요 인프라 결정을 위임하고 일상적인 운영을 위해 AWS의 전문 지식을 활용할 수 있습니다. AWS가 관리하는 클러스터 인프라에는 컴퓨팅 자동 스케일링, 포드 및 서비스 네트워킹, 애플리케이션 로드 밸런싱, 클러스터 DNS, 블록 스토리지, GPU 지원과 같은 추가 기능이 아닌 많은 Kubernetes 기능이 핵심 구성 요소로 포함되어 있습니다.
    • 시작하려면 새 EKS Auto Mode 클러스터를 배포하거나 기존 클러스터에서 EKS Auto Mode를 활성화할 수 있습니다. eksctl, AWS CLI, AWS 관리 콘솔, EKS API 또는 선호하는 인프라스트럭처 코드 도구를 사용하여 EKS Auto Mode 클러스터를 배포, 업그레이드 또는 수정할 수 있습니다.
    • EKS Auto Mode를 사용하면 원하는 Kubernetes 호환 도구를 계속 사용할 수 있습니다. EKS Auto Mode는 Amazon EC2, Amazon EBS, ELB와 같은 AWS 서비스와 통합되어 모범 사례를 따르는 AWS 클라우드 리소스를 활용합니다. 이러한 리소스는 자동으로 확장, 비용 최적화 및 정기적으로 업데이트되어 운영 비용과 오버헤드를 최소화합니다.
  • 기능
    • Kubernetes 클러스터 관리 간소화: EKS Auto Mode는 운영 오버헤드를 최소화하면서 운영 준비가 완료된 클러스터를 제공하여 EKS 관리를 간소화합니다. EKS Auto Mode를 사용하면 깊은 EKS 전문 지식 없이도 까다로운 동적 워크로드를 자신 있게 실행할 수 있습니다.
    • 애플리케이션 가용성: EKS 자동 모드는 Kubernetes 애플리케이션의 요구에 따라 EKS 클러스터에서 노드를 동적으로 추가하거나 제거합니다. 이를 통해 수동 용량 계획의 필요성을 최소화하고 애플리케이션 가용성을 보장합니다.
    • 효율성: EKS 자동 모드는 NodePool 및 워크로드 요구 사항에 정의된 유연성을 준수하면서 컴퓨팅 비용을 최적화하도록 설계되었습니다. 또한 사용하지 않는 인스턴스를 종료하고 워크로드를 다른 노드로 통합하여 비용 효율성을 향상시킵니다.
    • 보안: EKS Auto Mode는 노드에 대해 불변으로 취급되는 AMI를 사용합니다. 이러한 AMI는 잠금 소프트웨어를 강제하고 SELinux 필수 액세스 제어를 활성화하며 읽기 전용 루트 파일 시스템을 제공합니다. 또한 EKS Auto Mode에서 실행하는 노드의 최대 수명은 21일이며(이를 줄일 수 있습니다), 그 후에는 자동으로 새 노드로 교체됩니다. 이 접근 방식은 이미 많은 고객이 채택한 모범 사례에 맞춰 정기적으로 노드를 순환시켜 보안 태세를 강화합니다.
    • 자동 업그레이드: EKS 자동 모드는 최신 패치를 통해 Kubernetes 클러스터, 노드 및 관련 구성 요소를 최신 상태로 유지하면서 구성된 Pod Disruption Budgets(PDB) 및 NodePool Disruption Budgets(NDB)를 준수합니다. 최대 21일의 수명까지 PDB 또는 기타 구성을 차단하여 업데이트를 방해하는 경우 개입이 필요할 수 있습니다.
    • 관리되는 구성 요소: EKS Auto 모드에는 추가 기능으로 관리해야 하는 핵심 구성 요소로 Kubernetes와 AWS 클라우드 기능이 포함되어 있습니다. 여기에는 Pod IP 주소 할당, Pod 네트워크 정책, 로컬 DNS 서비스, GPU 플러그인, 헬스 체커 및 EBS CSI 스토리지에 대한 내장 지원이 포함됩니다.
    • 사용자 지정 가능한 NodePool 및 NodeClasses: 스토리지, 컴퓨팅 또는 네트워킹 구성을 변경해야 하는 워크로드의 경우 EKS 자동 모드를 사용하여 사용자 지정 NodePool 및 NodeClasses를 만들 수 있습니다. 기본 NodePool 및 NodeClasses는 편집할 수 없지만, 특정 요구 사항을 충족하기 위해 기본 구성과 함께 새로운 사용자 지정 NodePool 또는 NodeClasses를 추가할 수 있습니다.
  • 자동화 지원 구성요소 : The following is a list of data plane components that are automated
    • Compute: EKS 자동 모드를 사용하면 많은 워크로드에서 EKS 클러스터의 여러 측면을 잊어버릴 수 있습니다. 여기에는 다음이 포함됩니다:
      • Nodes: EKS 자동 모드 노드는 가전제품처럼 취급되도록 설계되었습니다. EKS 자동 모드는 다음을 수행합니다:
        • 작업 부하를 개입 없이 실행하는 데 필요한 다양한 서비스로 구성된 적절한 AMI를 선택합니다.
        • SELinux 강제 모드와 읽기 전용 루트 파일 시스템을 사용하여 AMI의 파일에 대한 액세스를 차단합니다.
        • SSH 또는 SSM 액세스를 허용하지 않음으로써 노드에 대한 직접 액세스를 방지합니다.
        • GPU 지원이 포함되어 있으며, 별도의 커널 드라이버와 NVIDIA 및 Neuron GPU용 플러그인이 있어 고성능 워크로드를 지원합니다.
      • Auto scaling: Karpenter 자동 확장을 기반으로 EKS Auto Mode는 일정에 맞지 않는 포드를 모니터링하고 새로운 노드를 배포하여 포드를 실행할 수 있도록 합니다. 워크로드가 종료되면 EKS Auto Mode는 더 이상 필요하지 않은 노드를 동적으로 중단하고 종료하여 리소스 사용을 최적화합니다.
      • Upgrades: 노드를 제어하면 필요에 따라 보안 패치와 운영 체제 및 구성 요소 업그레이드를 제공하는 EKS Auto Mode의 기능이 간소화됩니다. 이러한 업그레이드는 워크로드의 중단을 최소화하도록 설계되었습니다. EKS Auto Mode는 최신 소프트웨어 및 API를 보장하기 위해 최대 21일의 노드 수명을 적용합니다.
    • Load balancing: EKS Auto Mode는 Amazon의 Elastic Load Balancer 서비스와 통합하여 로드 밸런싱을 간소화하여 Kubernetes 서비스 및 입력 리소스에 대한 로드 밸런싱 장치의 프로비저닝 및 구성을 자동화합니다. 이 시스템은 애플리케이션 및 네트워크 로드 밸런싱 장치 모두에 고급 기능을 지원하고, 수명 주기를 관리하며, 클러스터 수요에 맞게 확장할 수 있습니다. 이 통합은 AWS 모범 사례를 준수하는 생산 준비형 로드 밸런싱 솔루션을 제공하므로 인프라 관리보다는 애플리케이션에 집중할 수 있습니다.
    • Storage: EKS 자동 모드는 볼륨 유형, 볼륨 크기, 암호화 정책 및 노드 종료 시 삭제 정책을 설정하여 임시 스토리지를 구성합니다.
    • Networking: EKS Auto 모드는 Pod 및 서비스 연결을 위한 중요한 네트워킹 작업을 자동화합니다. 여기에는 IPv4/IPv6 지원과 IP 주소 공간 확장을 위한 보조 CIDR 블록 사용이 포함됩니다.
    • Identity and Access Management: EKS 자동 모드 클러스터에 EKS Pod Identity Agent를 설치할 필요는 없습니다.
  • 커스텀 설정
    • Kubernetes DaemonSets: 노드에 설치된 서비스를 수정하는 대신 Kubernetes 데몬세트를 사용할 수 있습니다. 데몬세트는 Kubernetes에서 관리하도록 설계되었지만 클러스터의 모든 노드에서 실행됩니다. 이러한 방식으로 노드를 모니터링하거나 모니터링하기 위한 특별한 서비스를 추가할 수 있습니다.
    • Custom NodePools 및 NodeClasses: 기본 NodePools 및 NodeClasses는 EKS 자동 모드로 구성되며 편집할 수 없습니다. 노드 동작을 사용자 지정하려면 다음과 같은 사용 사례를 위해 추가 NodePools 또는 NodeClasses를 생성할 수 있습니다:
      • 특정 인스턴스 유형(예: 가속 프로세서 또는 EC2 스팟 인스턴스) 선택하기.
      • 보안 또는 비용 추적 목적으로 워크로드를 격리합니다.
      • IOPS, 크기, 처리량과 같은 일시적인 스토리지 설정 구성.
    • Load Balancing: EKS Auto Mode가 Kubernetes 객체로 실행하는 로드 밸런싱과 같은 일부 서비스는 EKS Auto Mode 클러스터에서 직접 구성할 수 있습니다.

    Create cluster (k8s 1.29 이상 필요) : eksctl, aws cli, 관리콘솔, IaC - Docs

  • eksctl
# 방안1
eksctl create cluster --name=<cluster-name> --enable-auto-mode


# 방안2 : cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: <cluster-name>
  region: <aws-region>

iam:
  # ARN of the Cluster IAM Role
  # optional, eksctl creates a new role if not supplied
  # suggested to use one Cluster IAM Role per account
  serviceRoleARN: <arn-cluster-iam-role>

autoModeConfig:
  # defaults to false
  enabled: boolean
  # optional, defaults to [general-purpose, system].
  # suggested to leave unspecified
  # To disable creation of nodePools, set it to the empty array ([]).
  nodePools: []string
  # optional, eksctl creates a new role if this is not supplied
  # and nodePools are present.
  nodeRoleARN: string

#
eksctl create cluster -f cluster.yaml
..

 

 

Cluster IAM Role 생성

# Step 1: Create the Trust Policy - trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"
      ]
    }
  ]
}

# Step 2: Create the IAM Role
aws iam create-role \
    --role-name AmazonEKSAutoClusterRole \
    --assume-role-policy-document file://trust-policy.json
    
# Step 3: Note the Role ARN
aws iam get-role --role-name AmazonEKSAutoClusterRole --query "Role.Arn" --output text

# Step 4: Attach Required Policies
aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy

aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSComputePolicy

aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSBlockStoragePolicy

aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSLoadBalancingPolicy

aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSNetworkingPolicy

 

Node IAM Role 생성

# Step 1: Create the Trust Policy - trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Action": [
        "sts:AssumeRole",
        "sts:TagSession"
      ]
    }
  ]
}

# Step 2: Create the IAM Role
aws iam create-role \
    --role-name AmazonEKSAutoClusterRole \
    --assume-role-policy-document file://trust-policy.json
    
# Step 3: Note the Role ARN
aws iam get-role --role-name AmazonEKSAutoClusterRole --query "Role.Arn" --output text

# Step 4: Attach Required Policies
aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy

aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSComputePolicy

aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSBlockStoragePolicy

aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSLoadBalancingPolicy

aws iam attach-role-policy \
    --role-name AmazonEKSAutoClusterRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSNetworkingPolicy

 

Node IAM Role 생성

# Step 1: Create the Trust Policy : node-trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

# Step 2: Create the Node IAM Role
aws iam create-role \
    --role-name AmazonEKSAutoNodeRole \
    --assume-role-policy-document file://node-trust-policy.json

# Step 3: Note the Role ARN
aws iam get-role --role-name AmazonEKSAutoNodeRole --query "Role.Arn" --output text

# Step 4: Attach Required Policies
aws iam attach-role-policy \
    --role-name AmazonEKSAutoNodeRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodeMinimalPolicy
    
aws iam attach-role-policy \
    --role-name AmazonEKSAutoNodeRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly

 

Default Cluster Configurations

  • nodePools: EKS Auto Mode includes general-purpose and system default Node Pools. Learn more about Node Pools.
    • computeConfig.enabled: Automates routine compute tasks, such as creating and deleting EC2 instances.
    • kubernetesNetworkConfig.elasticLoadBalancing.enabled: Automates load balancing tasks, including creating and deleting Elastic Load Balancers.
    • storageConfig.blockStorage.enabled: Automates storage tasks, such as creating and deleting Amazon EBS volumes.
    • accessConfig.authenticationMode: Requires EKS access entries. Learn more about EKS authentication modes.

 

Run the Command

#
aws eks create-cluster \
  --region ${AWS_REGION} \
  --cli-input-json \
  "{
      \"name\": \"${CLUSTER_NAME}\",
      \"version\": \"${K8S_VERSION}\",
      \"roleArn\": \"${CLUSTER_ROLE_ARN}\",
      \"resourcesVpcConfig\": {
        \"subnetIds\": ${SUBNETS_JSON},
        \"endpointPublicAccess\": true,
        \"endpointPrivateAccess\": true
      },
      \"computeConfig\": {
        \"enabled\": true,
        \"nodeRoleArn\":\"${NODE_ROLE_ARN}\",
        \"nodePools\": [\"general-purpose\", \"system\"]
      },
      \"kubernetesNetworkConfig\": {
        \"elasticLoadBalancing\": {
          \"enabled\": true
        }
      },
      \"storageConfig\": {
        \"blockStorage\": {
          \"enabled\": true
        }
      },
      \"accessConfig\": {
        \"authenticationMode\": \"API\"
      }
    }"

# Verify Cluster Creation
aws eks describe-cluster --name "${CLUSTER_NAME}" --output json
 
# Update kubeconfig
aws eks update-kubeconfig --name "${CLUSTER_NAME}"

# Verify Node Pools
kubectl get nodepools

 

 

  ☞ Enable existing clusters : 마이그레이션은 미지원이 많으니, 사용하려면 그냥 신규 클러스터 설치를 권장 - Docs

 

AWS에서 지원하는 마이그레이션:

AWS에서 지원하지 않는 마이그레이션:

  • EBS CSI Controller에서 EKS Auto Mode Block Storage로의 볼륨 마이그레이션
    • Amazon EKS Auto Mode 클러스터에 EBS CSI Controller를 설치할 수 있습니다.
    • StorageClass를 사용하여 볼륨을 EBS CSI Controller 또는 EKS Auto Mode 중 하나와 연결할 수 있습니다.
  • AWS Load Balancer Controller에서 EKS Auto Mode로의 로드 밸런서 마이그레이션
    • Amazon EKS Auto Mode 클러스터에 AWS Load Balancer Controller를 설치할 수 있습니다.
    • IngressClass 또는 loadBalancerClass 옵션을 사용하여 Service 및 Ingress 리소스를 Load Balancer Controller 또는 EKS Auto Mode 중 하나와 연결할 수 있습니다.
  • 대체 CNI 또는 지원되지 않는 네트워킹 구성이 포함된 EKS 클러스터의 마이그레이션

Migration Reference

Capability Resource Field Self Managed EKS Auto Mode
Block Storage StorageClass provisioner kubernetes.io/aws-ebs ebs.csi.eks.amazonaws.com
Load Balancing Service loadBalancerClass service.k8s.aws/nlb eks.amazonaws.com/nlb
Load Balancing IngressClass controller ingress.k8s.aws/alb eks.amazonaws.com/alb
Load Balancing IngressClassParams apiversion elbv2.k8s.aws/v1beta1 eks.amazonaws.com/v1
Load Balancing TargetGroupBinding apiversion elbv2.k8s.aws/v1beta1 eks.amazonaws.com/v1
Compute NodeClass apiVersion karpenter.sh/v1alpha5 eks.amazonaws.com/v1

 

 

Load Balancer Migration

  • 자체 관리형 AWS 로드 밸런서 컨트롤러에서 EKS 자동 모드로 기존 로드 밸런서를 직접 전송할 수는 없습니다. 대신 청록색 배포 전략을 구현해야 합니다. 여기에는 기존 로드 밸런서 구성을 유지하면서 관리형 컨트롤러 아래에 새로운 로드 밸런서를 만들어야 합니다.
  • 서비스 중단을 최소화하기 위해 DNS 기반 트래픽 전환 접근 방식을 권장합니다. 먼저 기존 구성을 운영하면서 EKS 자동 모드를 사용하여 새로운 로드 밸런서를 생성합니다. 그런 다음 DNS 라우팅(예: Route 53)을 사용하여 트래픽을 점진적으로 이전 로드 밸런서에서 새로운 로드 밸런서로 전환합니다. 트래픽이 성공적으로 마이그레이션되고 새 구성을 확인한 후에는 이전 로드 밸런서와 자체 관리 컨트롤러를 해체할 수 있습니다.

Enable EKS Auto Mode on an existing cluster - Docs

Migrate from Karpenter to EKS Auto Mode using kubectl - Docs

Migrate from EKS Managed Node Groups to EKS Auto Mode - Docs

 

  ☞  Run workloads - Docs

  ☞  Configure - Docs

  ☞  How it works - Docs

  ☞ Troubleshoot* : NodeDiagnostic, get-console-output, 디버깅 컨테이너 - Docs

 

  [Containers from the Couch] Hands on with Amazon EKS Auto Mode - Youtube

  제약사항 및 고려사항 최종 정리*

  • 6가지 구성요소가 파드로 구성되는게 아니고, 해당 노드에 systemd 데몬(agent)로 실행됨. - 아래 프로세스 확인
    • kube-proxy, kubelet, eks-pod-identity-agent, eks-node-monitor-agent, eks-healthcheck, eks-ebs-csi-driver,
    • csi-node-driver-registrar, coredns, containerd, aws-network-policy-agent, apiserver, ipam
  • 노드에 대해 불변으로 취급되는 AMI를 사용합니다. 이러한 AMI는 잠금 소프트웨어를 강제하고 SELinux 필수 액세스 제어를 활성화하며 읽기 전용 루트 파일 시스템을 제공합니다. 또한 EKS Auto Mode에서 실행하는 노드의 최대 수명은 21일. SELinux 강제 모드와 읽기 전용 루트 파일 시스템을 사용하여 AMI의 파일에 대한 액세스를 차단합니다.
  • SSH 또는 SSM 액세스를 허용하지 않음으로써 노드에 대한 직접 액세스를 방지합니다.
  • 자동 업그레이드: EKS 자동 모드는 최신 패치를 통해 Kubernetes 클러스터, 노드 및 관련 구성 요소를 최신 상태로 유지하면서 구성된 Pod Disruption Budgets(PDB) 및 NodePool Disruption Budgets(NDB)를 준수합니다. 최대 21일의 수명까지 PDB 또는 기타 구성을 차단하여 업데이트를 방해하는 경우 개입이 필요할 수 있습니다.
  • 관리되는 구성 요소: EKS Auto 모드에는 추가 기능으로 관리해야 하는 핵심 구성 요소로 Kubernetes와 AWS 클라우드 기능이 포함되어 있습니다. 여기에는 Pod IP 주소 할당, Pod 네트워크 정책, 로컬 DNS 서비스, GPU 플러그인, 헬스 체커 및 EBS CSI 스토리지에 대한 내장 지원이 포함됩니다.
  • Create node class : ephemeralStorage(80GiB), 노드 당 최대 파드 110개 제한.
  • Create node pool : 기본 노드풀은 활성화/비활성화 가능, budgetsdisruption 중지 가능.
  • Create ingress class : IngressClassParams 리소스 및 API 일부 변경, 미지원 기능 확인
  • Create StorageClss : provisioner: ebs.csi.eks.amazonaws.com , EBS 성능 프로메테우스 메트릭 접근 불가.
  • Update Kubernetes version : 업그레이드 시 자체 관리 Add-on 등은 고객 담당.
  • Review build-in node pools : 공통(온디멘드) - system(amd, arm64), general-purpose(amd64).
  • Run critical add-ons : system 노드풀로 **전용인스턴스(dedicated instances)**에 파드 배포 - Docs , 전용인스턴스
  • Control deployment : mixed mode 시 Auto-mode node 사용/미사용 방법 잘 확인 할 것
  • Managed Instances : AWS 소유 관리 인스턴스(OS, CRI, Kubelet 등 관리/책임) - Docs
  • EKS Auto Mode에서 생성된 EC2 인스턴스는 다른 EC2 인스턴스와 다르며 관리되는 인스턴스입니다. 이러한 관리되는 인스턴스는 EKS가 소유하고 있으며 더 제한적입니다. EKS Auto Mode에서 관리하는 인스턴스에는 직접 액세스하거나 소프트웨어를 설치할 수 없습니다.
  • EKS 자동 모드는 다음 인스턴스 유형을 지원합니다 : vCPU 1개 이상, 불가(nano, micro, small)
  • EKS 자동 모드는 지원되는 인스턴스 유형에 대해 NVMe 로컬 스토리지자동으로 포맷하고 구성합니다. 여러 개의 NVMe 드라이브를 가진 노드의 경우, EKS는 RAID 0 어레이를 설정합니다. 이 자동화를 통해 EKS 클러스터에서 로컬 NVMe 스토리지를 수동으로 포맷하고 RAID를 구성할 필요가 없습니다.
  • EKS 자동 모드 노드에 Neuron Device Plugin을 설치할 필요가 없습니다.
  • Identity and access : Cluster IAM role, Node IAM role, Service-linked role - Docs
  • Networking : VPC CNI 관련 미지원 기능 확인 - Docs
  • Troubleshoot* : NodeDiagnostic, get-console-output, 디버깅 컨테이너 - Docs
    • Kubernetes NodeDiagnostic리소스를 사용하여 노드 모니터링 에이전트를 사용하여 노드 로그를 검색합니다. 자세한 단계는 kubectl 및 S3를 사용하여 관리 노드에 대한 노드 로그 검색을 참조하십시오.
    • AWS EC2 CLI 명령 get-console-output을 사용하여 노드에서 콘솔 출력을 가져옵니다. 자세한 단계는 AWS EC2 CLI를 사용하여 EC2 관리 인스턴스에서 콘솔 출력 가져오기를 참조하십시오.
    • Kubernetes 디버깅 컨테이너를 사용하여 노드 로그를 검색합니다. 자세한 단계는 디버그 컨테이너와 kubectl CLI를 사용하여 노드 로그 가져오기를 참조하십시오.

  • AWS EKS Auto mode 아키텍처 (추정 포함)

 

 

 

실습

 

☞  배포 : This repository provides a production-ready template for deploying various workloads on EKS Auto Mode - Github

 

variable "name" {
  description = "Name of the VPC and EKS Cluster"
  default     = "automode-cluster"
  type        = string
}

variable "region" {
  description = "region"
  default     = "ap-northeast-2" 
  type        = string
}

variable "eks_cluster_version" {
  description = "EKS Cluster version"
  default     = "1.31"
  type        = string
}

# VPC with 65536 IPs (10.0.0.0/16) for 3 AZs
variable "vpc_cidr" {
  description = "VPC CIDR. This should be a valid private (RFC 1918) CIDR range"
  default     = "10.20.0.0/16"
  type        = string
}

 

# Get the code : 배포 코드에 addon 내용이 읍다!
git clone https://github.com/aws-samples/sample-aws-eks-auto-mode.git
cd sample-aws-eks-auto-mode/terraform

# eks.tf : "system" 은 '전용인스턴스'로 추가하지 않는다
...
  cluster_compute_config = {
    enabled    = true
    node_pools = ["general-purpose"]
  }
...

# Initialize and apply Terraform
terraform init
terraform plan
terraform apply -auto-approve
...
null_resource.create_nodepools_dir: Creating...
null_resource.create_nodepools_dir: Provisioning with 'local-exec'...
null_resource.create_nodepools_dir (local-exec): Executing: ["/bin/sh" "-c" "mkdir -p ./../nodepools"]
...


# Configure kubectl
cat setup.tf
ls -l ../nodepools
$(terraform output -raw configure_kubectl)

# kubectl context 변경
kubectl ctx
kubectl config rename-context "arn:aws:eks:ap-northeast-2:$(aws sts get-caller-identity --query 'Account' --output text):cluster/automode-cluster" "automode-lab"
kubectl ns default

# 아래 IP의 ENI 찾아보자
kubectl get svc,ep 
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   172.20.0.1   <none>        443/TCP   17m

NAME                   ENDPOINTS                       AGE
endpoints/kubernetes   10.20.22.4:443,10.20.5.40:443   17m

#
terraform state list
terraform show
terraform state show 'module.eks.aws_eks_cluster.this[0]'
...
    compute_config {
        enabled       = true
        node_pools    = [
            "general-purpose",
        ]
        node_role_arn = "arn:aws:iam::339712784283:role/automode-cluster-eks-auto-20250322122251455200000001"
    }
...

 

  • 관리 콘솔 확인
    • VPC - ENI 확인 : EKS Owned-ENI
  •  

  • EKS : Cluster IAM Role, Node IAM Role, Auto Mode

  • Compute : Built-in node pools

  • Add-ons 없음!

  • Access : IAM access entries

  • kubectl 확인
#
kubectl get crd
NAME                                         CREATED AT
cninodes.eks.amazonaws.com                   2025-03-22T12:31:19Z
cninodes.vpcresources.k8s.aws                2025-03-22T12:28:04Z
ingressclassparams.eks.amazonaws.com         2025-03-22T12:31:17Z
nodeclaims.karpenter.sh                      2025-03-22T12:31:19Z
nodeclasses.eks.amazonaws.com                2025-03-22T12:31:19Z
nodediagnostics.eks.amazonaws.com            2025-03-22T12:31:20Z
nodepools.karpenter.sh                       2025-03-22T12:31:19Z
policyendpoints.networking.k8s.aws           2025-03-22T12:28:05Z
securitygrouppolicies.vpcresources.k8s.aws   2025-03-22T12:28:04Z
targetgroupbindings.eks.amazonaws.com        2025-03-22T12:31:17Z

kubectl api-resources | grep -i node
nodes                               no           v1                                false        Node
cninodes                            cni,cnis     eks.amazonaws.com/v1alpha1        false        CNINode
nodeclasses                                      eks.amazonaws.com/v1              false        NodeClass
nodediagnostics                                  eks.amazonaws.com/v1alpha1        false        NodeDiagnostic
nodeclaims                                       karpenter.sh/v1                   false        NodeClaim
nodepools                                        karpenter.sh/v1                   false        NodePool
runtimeclasses                                   node.k8s.io/v1                    false        RuntimeClass
csinodes                                         storage.k8s.io/v1                 false        CSINode
cninodes                            cnd          vpcresources.k8s.aws/v1alpha1     false        CNINode

# 노드에 Access가 불가능하니, 분석 지원(CRD)제공
kubectl explain nodediagnostics
GROUP:      eks.amazonaws.com
KIND:       NodeDiagnostic
VERSION:    v1alpha1

DESCRIPTION:
    The name of the NodeDiagnostic resource is meant to match the name of the
    node which should perform the diagnostic tasks
    

#
kubectl get nodeclasses.eks.amazonaws.com
NAME      ROLE                                                   READY   AGE
default   automode-cluster-eks-auto-20250314121820950800000003   True    29m

kubectl get nodeclasses.eks.amazonaws.com -o yaml
...
  spec:
    ephemeralStorage:
      iops: 3000
      size: 80Gi
      throughput: 125
    networkPolicy: DefaultAllow
    networkPolicyEventLogs: Disabled
    role: automode-cluster-eks-auto-20250322122251455200000001
    securityGroupSelectorTerms:
    - id: sg-0c0edd07593e62ab5
    snatPolicy: Random
    subnetSelectorTerms:
    - id: subnet-015e12e395ade6b2e
    - id: subnet-0b282efa5a98fee1f
    - id: subnet-032eb987a2609eaf9
  status:
    conditions:
    - lastTransitionTime: "2025-03-22T12:31:37Z"
      message: ""
      observedGeneration: 1
      reason: SubnetsReady
      status: "True"
      type: SubnetsReady
    - lastTransitionTime: "2025-03-22T12:31:37Z"
      message: ""
      observedGeneration: 1
      reason: SecurityGroupsReady
      status: "True"
      type: SecurityGroupsReady
    - lastTransitionTime: "2025-03-22T12:31:37Z"
      message: ""
      observedGeneration: 1
      reason: InstanceProfileReady
      status: "True"
      type: InstanceProfileReady
    - lastTransitionTime: "2025-03-22T12:31:37Z"
      message: ""
      observedGeneration: 1
      reason: Ready
      status: "True"
      type: Ready
    instanceProfile: eks-ap-northeast-2-automode-cluster-369013734164143935

#
kubectl get nodepools
NAME              NODECLASS   NODES   READY   AGE
general-purpose   default     0       True    29m

kubectl get nodepools -o yaml
...
  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
...

#
kubectl get mutatingwebhookconfiguration
kubectl get validatingwebhookconfiguration

 

 

☞ kube-ops-view 설치

# 모니터링
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 배포
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' # 출력 이벤트 로그 분석해보자

# 확인
kubectl get nodeclaims
NAME                      TYPE         CAPACITY    ZONE              NODE                  READY   AGE
general-purpose-8r8jg   c5a.large   on-demand   ap-northeast-2b   i-06c3e5a7f95a4eff2   True    5m25s

# OS, KERNEL, CRI 확인
kubectl get node -owide
NAME                  STATUS   ROLES    AGE     VERSION               INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                                           KERNEL-VERSION   CONTAINER-RUNTIME
i-06c3e5a7f95a4eff2   Ready    <none>   5m59s   v1.31.4-eks-0f56d01   10.20.27.102   <none>        Bottlerocket (EKS Auto) 2025.3.14 (aws-k8s-1.31)   6.1.129          containerd://1.7.25+bottlerocket

# CNI 노드 확인
kubectl get cninodes.eks.amazonaws.com   
NAME                  AGE
i-06c3e5a7f95a4eff2   6m35s
 
 
#[신규 터미널] 포트 포워딩
kubectl port-forward deployment/kube-ops-view -n kube-system 8080:8080 &

# 접속 주소 확인 : 각각 1배, 1.5배, 3배 크기
echo -e "KUBE-OPS-VIEW URL = http://localhost:8080"
echo -e "KUBE-OPS-VIEW URL = http://localhost:8080/#scale=1.5"
echo -e "KUBE-OPS-VIEW URL = http://localhost:8080/#scale=3"

# open "http://127.0.0.1:8080/#scale=1.5" # macOS

  • AWS 관리콘솔 : EC2 확인

 

☞  [컴퓨팅] karpenter 동작 확인

  • 실습을 위해 deployment 배포
# Step 1: Review existing compute resources (optional)
kubectl get nodepools
NAME              NODECLASS   NODES   READY   AGE
general-purpose   default     1       True    42m

# Step 2: Deploy a sample application to the cluster
# eks.amazonaws.com/compute-type: auto selector requires the workload be deployed on an Amazon EKS Auto Mode node.
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


# Step 3: Watch Kubernetes Events
kubectl get events -w --sort-by '.lastTimestamp'
kubectl get nodes

 

  • 스케일링 설정 후 확인 : kube-ops-view 파드 evict 되면, port-forward 명령 다시 입력 할것! → pod 안전성 설정이 없을 경우에 대한 간접 경험

# 모니터링
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

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

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

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

# 실습 확인 후 삭제
kubectl delete deployment inflate && kubectl get events -w --sort-by '.lastTimestamp'

pod를 100개로 증설하여 대기 중임
AWS vcpu limit으로 replicas=5 로 변경하여 진행
서버가 교체되고 pod 모두 이전됨

 

☞  [네트워킹] Graviton Workloads (2048 game) 배포 with ingress(ALB) : custom nodeclass/pool 사용

  • custom nodeclass/pool, ment 배포
# custom node pool 생성 : 고객 NodePool : Karpenter 와 키가 다르니 주의!
## 기존(karpenter.k8s.aws/instance-family) → 변경(eks.amazonaws.com/instance-family) - Link
ls ../nodepools
cat ../nodepools/graviton-nodepool.yaml
kubectl apply -f ../nodepools/graviton-nodepool.yaml
---
apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: graviton-nodeclass
spec:
  role: automode-cluster-eks-auto-20250314121820950800000003
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: "automode-demo"
  securityGroupSelectorTerms:
    - tags:
        kubernetes.io/cluster/automode-cluster: owned
  tags:
    karpenter.sh/discovery: "automode-demo"
---
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: graviton-nodepool
spec:
  template:
    spec:
      nodeClassRef:
        group: eks.amazonaws.com
        kind: NodeClass
        name: graviton-nodeclass
      requirements:
        - key: "eks.amazonaws.com/instance-category"
          operator: In
          values: ["c", "m", "r"]
        - key: "eks.amazonaws.com/instance-cpu"
          operator: In
          values: ["4", "8", "16", "32"]
        - key: "kubernetes.io/arch"
          operator: In
          values: ["arm64"]
      taints:
        - key: "arm64"
          value: "true"
          effect: "NoSchedule"  # Prevents non-ARM64 pods from scheduling
  limits:
    cpu: 1000
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 30s

#
kubectl get NodeClass
NAME                 ROLE                                                   READY   AGE
default              automode-cluster-eks-auto-20250322122251455200000001   True    110m
graviton-nodeclass   automode-cluster-eks-auto-20250322122251455200000001   True    67s

kubectl get NodePool
NAME                NODECLASS            NODES   READY   AGE
general-purpose     default              1       True    111m
graviton-nodepool   graviton-nodeclass   0       True    118s

#
ls ../examples/graviton
cat ../examples/graviton/game-2048.yaml
...
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "200m"
              memory: "256Mi"
      automountServiceAccountToken: false
      tolerations:
      - key: "arm64"
        value: "true"
        effect: "NoSchedule"
      nodeSelector:
        kubernetes.io/arch: arm64
...

kubectl apply -f ../examples/graviton/game-2048.yaml

# c6g.xlarge : vCPU 4, 8 GiB RAM > 스팟 선택됨!
kubectl get nodeclaims
NAME                      TYPE         CAPACITY   ZONE              NODE                  READY   AGE
general-purpose-9qgzv     c5a.2xlarge   on-demand   ap-northeast-2c   i-0dbcf4f22528b63f0   True    64m
graviton-nodepool-jm5lf   m7g.xlarge    spot        ap-northeast-2a   i-0b0a19034a8531e1a   True    25s

kubectl get nodeclaims -o yaml
...
  spec:
    expireAfter: 336h
    ...
kubectl get cninodes.eks.amazonaws.com
kubectl get cninodes.eks.amazonaws.com -o yaml
eks-node-viewer --resources cpu,memory
kubectl get node -owide
kubectl describe node
...
Taints:             arm64=true:NoSchedule
...
Conditions:
  Type                    Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----                    ------  -----------------                 ------------------                ------                       -------
  MemoryPressure          False   Sat, 22 Mar 2025 23:46:25 +0900   Sat, 22 Mar 2025 23:25:29 +0900   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure            False   Sat, 22 Mar 2025 23:46:25 +0900   Sat, 22 Mar 2025 23:25:29 +0900   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure             False   Sat, 22 Mar 2025 23:46:25 +0900   Sat, 22 Mar 2025 23:25:29 +0900   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready                   True    Sat, 22 Mar 2025 23:46:25 +0900   Sat, 22 Mar 2025 23:25:30 +0900   KubeletReady                 kubelet is posting ready status
  NetworkingReady         True    Sat, 22 Mar 2025 23:45:34 +0900   Sat, 22 Mar 2025 23:25:34 +0900   NetworkingIsReady            Monitoring for the Networking system is active
  KernelReady             True    Sat, 22 Mar 2025 23:45:34 +0900   Sat, 22 Mar 2025 23:25:34 +0900   KernelIsReady                Monitoring for the Kernel system is active
  ContainerRuntimeReady   True    Sat, 22 Mar 2025 23:45:34 +0900   Sat, 22 Mar 2025 23:25:34 +0900   ContainerRuntimeIsReady      Monitoring for the ContainerRuntime system is active
  StorageReady            True    Sat, 22 Mar 2025 23:45:34 +0900   Sat, 22 Mar 2025 23:25:34 +0900   DiskIsReady                  Monitoring for the Disk system is active
...
System Info:
  Machine ID:                 ec255393897f6c81e70285e0d87e0ba8
  System UUID:                ec255393-897f-6c81-e702-85e0d87e0ba8
  Boot ID:                    0bb56d99-81e8-4bb2-820e-4ab5f9911bea
  Kernel Version:             6.1.129
  OS Image:                   Bottlerocket (EKS Auto) 2025.3.14 (aws-k8s-1.31)
  Operating System:           linux
  Architecture:               arm64
  Container Runtime Version:  containerd://1.7.25+bottlerocket
  Kubelet Version:            v1.31.4-eks-0f56d01
  Kube-Proxy Version:         v1.31.4-eks-0f56d01
ProviderID:                   aws:///ap-northeast-2a/i-0b0a19034a8531e1a

#
kubectl get deploy,pod -n game-2048 -owide

 

  • 관리 콘솔 확인
    • EKS - Compute : 내장 node pool 이 아닌 별도 node pool 생성 확인.
    •  

 

  • EC2 - 1대 생성 확인!, 참고로 접근 안됨. ⇒ Reboot 해보자 ⇒ Terminated 해보자!

reboot fail ->AWS에서 직접 관리함

 

  • 참고로, 생성되는 EC2의 OS는 Bottlerocket 이며, 루트 볼륨은 읽기 전용임.

  • 해당 EC2에서 Monitoring → Instance audit 확인 ⇒ 맨 하단에 RunInstances(CloudTrail) 클릭 , 재부팅/삭제 실패도 클릭 

 

  • CloudTrail 확인 : 실행 주체 확인

  • EC2 - 보안 그룹 확인

  • EC2 - ENI 추가됨

 

  • ALB(Ingress) 설정
#
cat ../examples/graviton/2048-ingress.yaml
...
apiVersion: eks.amazonaws.com/v1
kind: IngressClassParams
metadata:
  namespace: game-2048
  name: params
spec:
  scheme: internet-facing

---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  namespace: game-2048
  labels:
    app.kubernetes.io/name: LoadBalancerController
  name: alb
spec:
  controller: eks.amazonaws.com/alb
  parameters:
    apiGroup: eks.amazonaws.com
    kind: IngressClassParams
    name: params

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: game-2048
  name: ingress-2048
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: service-2048
                port:
                  number: 80

kubectl apply -f ../examples/graviton/2048-ingress.yaml

#
kubectl get ingressclass,ingressclassparams,ingress,svc,ep -n game-2048
NAME                                 CONTROLLER              PARAMETERS                                    AGE
ingressclass.networking.k8s.io/alb   eks.amazonaws.com/alb   IngressClassParams.eks.amazonaws.com/params   9s

NAME                                          GROUP-NAME   SCHEME            IP-ADDRESS-TYPE   AGE
ingressclassparams.eks.amazonaws.com/params                internet-facing                     9s

NAME                                     CLASS   HOSTS   ADDRESS                                                                       PORTS   AGE
ingress.networking.k8s.io/ingress-2048   alb     *       k8s-game2048-ingress2-db993ba6ac-647037050.ap-northeast-2.elb.amazonaws.com   80      9s

NAME                   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/service-2048   NodePort   172.20.168.23   <none>        80:30802/TCP   9s

NAME                     ENDPOINTS        AGE
endpoints/service-2048   10.20.11.48:80   9s

  • Configure Security Groups : Configure security group rules to allow communication between the ALB and EKS cluster
  • 보안 그룹 소스에 ALB SG ID가 이미 들어가 있는 상태라서 아래 규칙 추가 없이 접속이 되어야 하지만, 혹시 잘 안될 경우 아래 추가 할 것
# Get security group IDs 
ALB_SG=$(aws elbv2 describe-load-balancers \
  --query 'LoadBalancers[?contains(DNSName, `game2048`)].SecurityGroups[0]' \
  --output text)

EKS_SG=$(aws eks describe-cluster \
  --name automode-cluster \
  --query 'cluster.resourcesVpcConfig.clusterSecurityGroupId' \
  --output text)

echo $ALB_SG $EKS_SG # 해당 보안그룹을 관리콘솔에서 정책 설정 먼저 확인해보자

# Allow ALB to communicate with EKS cluster : 실습 환경 삭제 때, 미리 $EKS_SG에 추가된 규칙만 제거해둘것.
aws ec2 authorize-security-group-ingress \
  --group-id $EKS_SG \
  --source-group $ALB_SG \
  --protocol tcp \
  --port 80
 
# 아래 웹 주소로 http 접속!
kubectl get ingress ingress-2048 \
  -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' \
  -n game-2048
k8s-game2048-ingress2-db993ba6ac-782663732.ap-northeast-2.elb.amazonaws.com

 

 

  • 삭제
# Remove application components
kubectl delete ingress -n game-2048 ingress-2048 # 먼저 $EKS_SG에 추가된 규칙만 제거할것!!!
kubectl delete svc -n game-2048 service-2048
kubectl delete deploy -n game-2048 deployment-2048

# 생성된 노드가 삭제 후에 노드 풀 제거 할 것 : Remove Graviton node pool
kubectl delete -f ../nodepools/graviton-nodepool.yaml

 

 

[스토리지] stateful workload with PV(EBS) 배포 : EBS Controller 동작 확인

  • EKS Auto Mode does not create a StorageClass for you.
    • You must create a StorageClass referencing ebs.csi.eks.amazonaws.com to use the storage capability of EKS Auto Mode.
  • 배포
# Create the storage class
cat <<EOF | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: auto-ebs-sc
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.eks.amazonaws.com  # Uses EKS Auto Mode
volumeBindingMode: WaitForFirstConsumer  # Delays volume creation until a pod needs it
parameters:
  type: gp3
  encrypted: "true" 
EOF

# Create the persistent volume claim
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: auto-ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: auto-ebs-sc
  resources:
    requests:
      storage: 8Gi
EOF

# Deploy the Application : The Deployment runs a container that writes timestamps to the persistent volume.
## Simple bash container that writes timestamps to a file
## Mounts the PVC at /data
## Requests 1 CPU core
## Uses node selector for EKS managed nodes
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inflate-stateful
spec:
  replicas: 1
  selector:
    matchLabels:
      app: inflate-stateful
  template:
    metadata:
      labels:
        app: inflate-stateful
    spec:
      terminationGracePeriodSeconds: 0
      nodeSelector:
        eks.amazonaws.com/compute-type: auto
      containers:
        - name: bash
          image: public.ecr.aws/docker/library/bash:4.4
          command: ["/usr/local/bin/bash"]
          args: ["-c", "while true; do echo \$(date -u) >> /data/out.txt; sleep 60; done"]
          resources:
            requests:
              cpu: "1"
          volumeMounts:
            - name: persistent-storage
              mountPath: /data
      volumes:
        - name: persistent-storage
          persistentVolumeClaim:
            claimName: auto-ebs-claim
EOF
kubectl get events -w --sort-by '.lastTimestamp'

  • 관리 콘솔 : EBS

  • 동작 확인 후 삭제
# Verify the Setup
kubectl get pods -l app=inflate-stateful
kubectl get pvc auto-ebs-claim

# Check the EBS volume : 관리콘솔에서 EBS 확인
## Get the PV name
PV_NAME=$(kubectl get pvc auto-ebs-claim -o jsonpath='{.spec.volumeName}')
## Describe the EBS volume
aws ec2 describe-volumes \
  --filters Name=tag:CSIVolumeName,Values=${PV_NAME}
  
# Verify data is being written:
kubectl exec "$(kubectl get pods -l app=inflate-stateful \
  -o=jsonpath='{.items[0].metadata.name}')" -- \
  cat /data/out.txt

kubectl exec "$(kubectl get pods -l app=inflate-stateful \
  -o=jsonpath='{.items[0].metadata.name}')" -- \
  tail -f /data/out.txt

# Cleanup - Delete all resources in one command
kubectl delete deployment/inflate-stateful pvc/auto-ebs-claim storageclass/auto-ebs-sc

 

 

☞ [운영] 노드 특정 프로세스 로그 실시간 확인 : debug container - Docs

  • Get node logs by using *debug containers and the kubectl CLI*
  • EKS Auto Mode 노드에서 로그를 검색하는 권장 방법은 NodeDiagnostic 리소스를 사용하는 것입니다. 이러한 단계는 kubectl 및 S3를 사용하여 관리 노드에 대한 노드 로그 검색을 참조하십시오.
  • 그러나 kubectl debug node 명령을 사용하여 인스턴스에서 로그를 실시간으로 스트리밍할 수 있습니다. 이 명령어는 디버그하려는 노드에서 새로운 Pod를 실행하여 대화형으로 사용할 수 있습니다.
# 노드 인스턴스 ID 확인
kubectl get node
NODEID=<각자 자신의 노드ID>
NODEID=i-0dbcf4f22528b63f0

# 디버그 컨테이너를 실행합니다. 다음 명령어는 노드의 인스턴스 ID에 i-01234567890123456을 사용하며, 
# 대화형 사용을 위해 tty와 stdin을 할당하고 kubeconfig 파일의 sysadmin 프로필을 사용합니다.
## Create an interactive debugging session on a node and immediately attach to it.
## The container will run in the host namespaces and the host's filesystem will be mounted at /host
## --profile='legacy': Options are "legacy", "general", "baseline", "netadmin", "restricted" or "sysadmin"
kubectl debug -h
kubectl debug node/$NODEID -it --profile=sysadmin --image=public.ecr.aws/amazonlinux/amazonlinux:2023
-------------------------------------------------
bash-5.2# whoami

# 셸에서 이제 nsenter 명령을 제공하는 util-linux-core를 설치할 수 있습니다.
# nsenter를 사용하여 호스트에서 PID 1의 마운트 네임스페이스(init)를 입력하고 journalctl 명령을 실행하여 큐블릿에서 로그를 스트리밍합니다:
yum install -y util-linux-core htop
nsenter -t 1 -m journalctl -f -u kubelet
htop # 해당 노드(인스턴스) CPU,Memory 크기 확인

# 정보 확인
nsenter -t 1 -m ip addr
nsenter -t 1 -m ps -ef
nsenter -t 1 -m ls -l /proc
nsenter -t 1 -m df -hT 

nsenter -t 1 -m ctr
nsenter -t 1 -m ctr ns ls
nsenter -t 1 -m ctr -n k8s.io containers ls
CONTAINER                                                           IMAGE                                          RUNTIME                  
010a460185bd16997cdf48845542c88a8fafb97bd6287d42e8cbaa25aac75bf1    localhost/kubernetes/pause:0.1.0                  io.containerd.runc.v2    
027f9a355b9e83ef48b54fd313db061becdb8f4efdff1049d49101f5efd43ec7    public.ecr.aws/eks-distro/kubernetes/pause:3.7    io.containerd.runc.v2    
3e3a1b35f3dd90c76d07b55aa8fa8c58e62e123be498556b364f54362cb0eff5    localhost/kubernetes/pause:0.1.0                  io.containerd.runc.v2    
42809f9caa08c03dd8264373210960ad49e6aa8bb90045e715fca3eabe379684    public.ecr.aws/eks-distro/kubernetes/pause:3.7    io.containerd.runc.v2    
8cd9bd12770582756ede5bb0e37111a457f25befd15299f35b0d019d5b6c1847    localhost/kubernetes/pause:0.1.0                  io.containerd.runc.v2   
...

# (참고) 보안을 위해 Amazon Linux 컨테이너 이미지는 기본적으로 많은 바이너리를 설치하지 않습니다.
# yum whatproved 명령을 사용하여 특정 바이너리를 제공하기 위해 설치해야 하는 패키지를 식별할 수 있습니다.
yum whatprovides ps
-------------------------------------------------

  • 디버그 파드 삭제 kubectl delete pod <node-debugger-#>

☞  [보안] 호스트 네임스페이스를 공유하는 파드 탈옥(?) 를 통해 호스트 정보 획득 시도 - Blog

  • 호스트 네임스페이스를 공유하는 파드 실행
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: root-shell
  namespace: kube-system
spec:
  containers:
  - command:
    - /bin/cat
    image: alpine:3
    name: root-shell
    securityContext:
      privileged: true
    tty: true
    stdin: true
    volumeMounts:
    - mountPath: /host
      name: hostroot
  hostNetwork: true
  hostPID: true
  hostIPC: true
  tolerations:
  - effect: NoSchedule
    operator: Exists
  - effect: NoExecute
    operator: Exists
  volumes:
  - hostPath:
      path: /
    name: hostroot
EOF

# 파드 확인 : 파드와 노드의 IP가 같다 (hostNetwork: true)
kubectl get pod -n kube-system root-shell
kubectl get node,pod -A -owide
NAME                       STATUS   ROLES    AGE   VERSION               INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                                          KERNEL-VERSION   CONTAINER-RUNTIME
node/i-0dbcf4f22528b63f0   Ready    <none>   170m   v1.31.4-eks-0f56d01   10.20.42.187   <none>        Bottlerocket (EKS Auto) 2025.3.14 (aws-k8s-1.31)   6.1.129          containerd://1.7.25+bottlerocket

NAME                                 READY   STATUS    RESTARTS   AGE    IP             NODE                  NOMINATED NODE   READINESS GATES
pod/kube-ops-view-657dbc6cd8-fzlgp   1/1     Running   0          121m   10.20.43.179   i-0dbcf4f22528b63f0   <none>           <none>
pod/root-shell                       1/1     Running   0          94s    10.20.42.187   i-0dbcf4f22528b63f0   <none>           <none>

# 호스트패스 : 파드에 /host 경로에 rw로 마운트 확인
kubectl describe pod -n kube-system root-shell
...
    Mounts:
      /host from hostroot (rw)
    ...
Volumes:
  hostroot:
    Type:          HostPath (bare host directory volume)
    Path:          /
    HostPathType:  
...

# 탈취 시도!
kubectl -n kube-system exec -it root-shell -- chroot /host /bin/sh

  • 파드 내 shell 진입 후 확인
#
kubectl -n kube-system exec -it root-shell -- sh
------------------------------------------------
whoami
pwd

# 네트워크 정보 확인 : 호스트와 같다 (hostNetwork: true)
ip link
ip addr # eth0, pod-id-link0, coredns

netstat -tnlp
netstat -unlp

# 프로세스 정보 확인 : 호스트와 같다 (hostPID: true)
top -d 1

ps aux
ps -ef

pstree
pstree -p

apk add htop
htop

# 마운트 정보 : 데이터 EBS (80GiB)
df -hT | grep -v host
Filesystem           Type            Size      Used Available Use% Mounted on
overlay              overlay        79.9G      1.9G     78.0G   2% /
...

df -hT | grep host
/dev/root            ext4            2.1G      1.1G    901.5M  55% /host
...

cat /etc/hostname
ip-10-20-1-198.ap-northeast-2.compute.internal

## (호스트패스 : 파드에 /host 경로에 rw로 마운트 확인)
ls -l /host 
cat /host/usr/share/kube-proxy/kube-proxy-config
cat /host/etc/coredns/Corefile
cat /host/etc/kubernetes/ipamd/kubeconfig
cat /host/etc/kubernetes/eks-node-monitoring-agent/kubeconfig

# 루트볼륨에 파일 생성 시도 : rw로 마운트
echo "hello" > /host/home/1.txt
sh: can't create /host/home/1.txt: Read-only file system

# 탈취 시도!
which apiclient
which sh
/bin/sh

chroot /host /bin/sh
chroot: can't execute '/bin/sh': No such file or directory

# 정보 확인
nsenter -t 1 -m journalctl -f -u kubelet
nsenter -t 1 -m ip addr
nsenter -t 1 -m ps -ef
nsenter -t 1 -m ls -l /proc
nsenter -t 1 -m df -hT 

nsenter -t 1 -m ctr
nsenter -t 1 -m ctr ns ls
nsenter -t 1 -m ctr -n k8s.io containers ls
CONTAINER                                                           IMAGE                                          RUNTIME                  
010a460185bd16997cdf48845542c88a8fafb97bd6287d42e8cbaa25aac75bf1    localhost/kubernetes/pause:0.1.0                  io.containerd.runc.v2    
027f9a355b9e83ef48b54fd313db061becdb8f4efdff1049d49101f5efd43ec7    public.ecr.aws/eks-distro/kubernetes/pause:3.7    io.containerd.runc.v2    
3e3a1b35f3dd90c76d07b55aa8fa8c58e62e123be498556b364f54362cb0eff5    localhost/kubernetes/pause:0.1.0                  io.containerd.runc.v2    
42809f9caa08c03dd8264373210960ad49e6aa8bb90045e715fca3eabe379684    public.ecr.aws/eks-distro/kubernetes/pause:3.7    io.containerd.runc.v2    
6ee633f8bf9a8c4324b6eb7f0c2440c9bb287dd06691c9d1e116c8dd6f60f51a    docker.io/library/alpine:3                        io.containerd.runc.v2    
------------------------------------------------

  • 프로세스 확인 : 컨테이너로 기동되지 않음을 확인
    • kube-proxy, kubelet, eks-pod-identity-agent, eks-node-monitor-agent, eks-healthcheck, eks-ebs-csi-driver,
    • csi-node-driver-registrar, coredns, containerd, aws-network-policy-agent, apiserver, ipam
...
 1024 root      0:00 /usr/bin/apiserver --datastore-path /var/lib/bottlerocket/datastore/current --socket-gid 274
 1147 root      0:01 /usr/bin/aws-network-policy-agent --kubeconfig /etc/kubernetes/aws-network-policy-agent/kubeconfig -
 1148 root      0:15 /usr/bin/containerd
 1169 root      0:02 /usr/bin/eks-healthchecker
 1171 root      0:00 /usr/bin/kube-proxy --hostname-override i-0b12733f9b75cd835 --config=/usr/share/kube-proxy/kube-prox
 1216 root      0:00 /usr/bin/eks-pod-identity-agent server --metrics-address 127.0.0.1 --cluster-name automode-cluster -
 1231 root      0:27 /usr/bin/kubelet --cloud-provider external --kubeconfig /etc/kubernetes/kubelet/kubeconfig --config 
 1255 root      0:00 /usr/bin/csi-node-driver-registrar --csi-address=/var/lib/kubelet/plugins/ebs.csi.eks.amazonaws.com/
 1270 root      0:00 /usr/bin/eks-ebs-csi-driver node --kubeconfig /etc/kubernetes/eks-ebs-csi-driver/kubeconfig --endpoi
 1543 root      0:13 /usr/bin/eks-node-monitoring-agent --kubeconfig /etc/kubernetes/eks-node-monitoring-agent/kubeconfig
 1611 root      0:01 /usr/bin/ipamd --kubeconfig /etc/kubernetes/ipamd/kubeconfig --metrics-bind-addr 127.0.0.1:8172 --he
 1644 983       0:06 /usr/bin/coredns -conf=/etc/coredns/Corefile
...

 

  • 삭제 : kubectl delete pod -n kube-system root-shell

[추가 시도 1] 노드(Bottlerocket)에 apiclient 파드를 배포하여 enter-admin-container 진입

# kube-system 네임스페이스에 파드 배포
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: apiclient
  namespace: kube-system
spec:
  containers:
  - command:
    - sleep
    - infinity
    image: fedora
    imagePullPolicy: Always
    name: regain-access
    securityContext:
      seLinuxOptions:
        level: s0
        role: system_r
        type: control_t
        user: system_u
    volumeMounts:
    - mountPath: /usr/bin/apiclient
      name: apiclient
      readOnly: true
    - mountPath: /run/api.sock
      name: apiserver-socket
  restartPolicy: Always
  terminationGracePeriodSeconds: 0
  volumes:
  - hostPath:
      path: /usr/bin/apiclient
      type: File
    name: apiclient
  - hostPath:
      path: /run/api.sock
      type: Socket
    name: apiserver-socket
EOF

# 파드 배포 확인
kubectl get pod -n kube-system apiclient

# 관리 컨테이너 활성화 및 진입 시도!
kubectl exec -i -t -n kube-system apiclient -- apiclient exec -t control enter-admin-container
ctr: failed to dial "/run/host-containerd/containerd.sock": context deadline exceeded: connection error: desc = "transport: error while dialing: dial unix:///run/host-containerd/containerd.sock: timeout"
command terminated with exit code 1

# 파드 삭제
kubectl delete pod -n kube-system apiclient

[추가 시도 2] aws ssm start-session --target <ID> 실패! 

 

 

☞  [운영] 노드 로그 수집 by S3 : Node monitoring agent NodeDiagnostic - Docs , Link ← 실패

  • EKS 자동 모드에는 Amazon EKS 노드 모니터링 에이전트가 포함되어 있습니다.
  • 이 에이전트를 사용하여 노드에 대한 문제 해결 및 디버깅 정보를 볼 수 있습니다.
  • 노드 모니터링 에이전트는 Kubernetes 이벤트와 노드 상태를 게시합니다.
  • 자세한 내용은 노드 자동 복구 활성화 및 노드 상태 조사를 참조하십시오 - Docs
  • NodeDiagnostic리소스를 사용하여 노드 모니터링 에이전트를 사용하여 노드 로그를 검색합니다.
  • S3 버킷 생성
# 버킷 생성 : 버킷명은 유일한 이름
BUCKETNAME=gasida-aews-study
aws s3api create-bucket --bucket $BUCKETNAME --create-bucket-configuration LocationConstraint=ap-northeast-2 --region ap-northeast-2
aws s3 ls
#
  • AWS CloudShell 에서 아래 실행 : S3 pre-sign url 생성 : 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.
#
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': '<bucket-name>', 'Key': '<key>'},
   ExpiresIn=1000
))

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

# 아래 출력된 presign url 메모(복사해두기)
python presign-upload.py
https://gasida-aews-study.s3.amazonaws.com/2025-03-16/logs.tar.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA5ILF2FJIVEY6H47U%2F20250316%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20250316T080839Z&X-Amz-Expires=1000&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEND%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDmFwLW5vcnRoZWFzdC0yIkYwRAIgGZBQBCm2fYhS9i8ASAXANhvn%2FfmoGLV3qwcQY%2BZ%2FfaACIG0jp98qd4905o1cyZwU6fc8w6oRokzRMRyBZq0fUFr1Ko8DCCkQAhoMOTExMjgzNDY0Nzg1IgxAtlJD5L30UOD%2BZWQq7AKcLNL8wbvupei585IRr4zbyID1Psu12HCUAMHZoEjKzqKor6V9Wi04WHvLJc6VEZZikErAX1jJ4AZd33EyJxY42gPxmKHy%2BnAe%2FA0rd1rmkoplJMAsCi68uXMxHF3mds2V7phEjIS4agvhce7nIpZhUvXqpJUn70MV2eZ8CJF%2BxV%2FjsxoJQ4dr40ibDxwsv%2F%2FobKK8Bl2Ta3mILfrLbcJNYG%2Bszs5D85B8FufRofdoUbqjDSHejX08%2BuJd1q6Z1Iw2Jnyzqdn2D2OyNKXx8El8FR%2FztAYBxP8%2BKnCo%2BFLInc8%2ByzHaqGJBYjKce9GPNNH0a9wO7Om%2BfpZBch8TYHnY4w1iq9sjUcJiU6mrJ45B7ZhTs3UnjbDdDPlJbeIkcOGxsINGA22Qr7MVpu0SCsOppYLKR%2BVwHsRb5ESfRerdxxVf1QYP3SyZTIK5pDEJfJh6KKWL0%2BnZzmOVX69khyf36KDi%2Fl7nWREh5mP7MLjD2L4GOrQCjZaBRM4YrzEokAZVJljmkaOv%2BFr44nYk358nnpJQE3HKoCY2qjvv9ed5Y5agGyIjmjd9q5M2rbx576ifjuM9n5ys9TyzhPPb%2BoFi1DGJO9leyxq2%2F%2FZ6SlCkCojSnmfCS4jnmiKBEAKQjCh4%2FR2QqFOmfdAGfI7aRthxmdfXlYqM4zZyn5popkkbJF%2FLH%2FDa8%2B5%2Fy6nPeBtDJcBNvAT4MwTWZ%2BamlHBAW%2FYt1hjPzCvh0Vrxy%2BIEMejhS2R63fhMvLtPCD%2BNr%2FVfVz9D1eVSPRUIGLaq7KjniM9dZYE3UqFttJcoFl6IODk%2BAJ4S0Yviy19OITrlUZHN0Tdt92a46Rqxx9Qn5hZVVIQ7KxeqsohZ652SBrmVnAQCmksP4ScgzptY7Wa3LIzbROyNPDEMOEp%2FdaI%3D&X-Amz-Signature=dcf7a5d8c5b26e9c55182e7cc285a735ea06df8750dfbcc40f944cb064629455

 

  • NodeDiagnostic 생성
#
cat <<EOF | kubectl apply -f -
apiVersion: eks.amazonaws.com/v1alpha1
kind: NodeDiagnostic
metadata:
  name: i-0a1abba3d52c59da0
spec:
  logCapture:
    destination: https://gasida-aews-study.s3.amazonaws.com/2025-03-16/logs1.tar.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA5ILF2FJI2ZTNQEGA%2F20250316%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20250316T141832Z&X-Amz-Expires=1000&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjENb%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDmFwLW5vcnRoZWFzdC0yIkYwRAIgFB5O2tYI%2BtLDbdcqM2XOdpPlex%2Bejbu7idKpA3EzljQCIH9nSq2HIpiLMlz%2BR08uWKU4jG8nMIx24EcoUr5O9yG7KpYDCC8QAhoMOTExMjgzNDY0Nzg1Igyd4uJrSWVA1qnT5Gwq8wI9QsXOjuMn%2BIqkk8aZN1jtzkveuTw1Yv%2BJVaDs3krxWZiDU5KjWrzy1MW1%2B7lHsCDKo9Of%2B%2BlvTTegVxzzQS%2FdUPaIVQI5uPjblX0jag8HwrhB%2BpBm8vks0MDrELZoMVuUvGK6g1mkoFoRJ14Ot2f8IVRUnZCoLTZoDHy5euuh5wVw2QnUPovk5whxmwieszR4r8FjBmwy%2BVnjzaWcMTQPApQX19gkd3Gw4DciuSRBHK0tx8%2BBo8O1IJVCSjEMxdauUIn7rZYH8JDRn3odDoezTx%2BVdc%2BJViOdYwouScSoYXi9RyaDAhmWO2Gu%2Fg3p7ojfPPRylfEOh4h252Hf1t6%2F7YY7P2pnaEhBndVBc8IzqXA2pKMCglXGoFIQu7e%2F8PkXr0jjTv7t5EvM7fAlCbnE5nOJcuDy%2BjBz3Gq7DGfdHPoCYXfPNlX61aMZslKKdcKd7hGlVgOPr3Tkt7TffON7UUJvsg7qNo35Qpebzc2w%2FuwwejDUnNu%2BBjq0AqBy%2Fk3O%2FNggSTAuRwdvfmlbarX1tVW66qWebKGXmSCgJFgZ%2FTIE0lSX%2BvZtNxGilZWwDCUXuOuFLqli2pWK008jVwOpq3jYJcAbmua250SWEy4WruK1Ecgk7w52HDCRHA%2BOq9aHxgyeAh3nCVlHL2QUYkwu9HvkR6%2B3f%2BlyREkZXMztxadYf9Blf%2FeR2O1Dj9XcwL6uwZEZzY1ZGXYr1Ju%2BdbwqdEydlkjvHiA5XmhsgpOmAApzaj%2FLi1Nu%2Fc3hKFte172%2BwerUYLIX2m5yUP2M3LLB316r2uG15wysAswTWiMvTRJjxfZisH%2BCPV9JD8TM4Ey%2FzQy1agNZ3XamdUX8GdoTuiYWQUzTbStOwr37pboXMY58S0Fhe65s3KGUNWJCUDLLG0NkOpBzA05ay%2FJW7ao0&X-Amz-Signature=3463ba2536c1e0de75dd4d4d8cac91165419b093c872945d80d8b25870200c06
EOF

#
kubectl get nodediagnostic
kubectl describe nodediagnostic

#
BUCKETNAME=gasida-aews-study
aws s3 ls s3://$BUCKETNAME --recursive
aws s3 cp s3://$BUCKETNAME/2025-03-16/logs1.tar.gz ./node-logs.tar.gz
tar -zxvf node-logs.tar.gz

# 디렉터리 구성 (예시)
% tree .
.
├── bottlerocket
│   └── application-inventory.json
├── cni
│   └── 10-aws.conflist
├── containerd
│   ├── containerd-config.txt
│   ├── containerd-containers.txt
│   ├── containerd-images.txt
│   ├── containerd-log.txt
│   ├── containerd-namespaces.txt
│   ├── containerd-plugins.txt
│   ├── containerd-tasks.txt
│   └── containerd-version.txt
├── ipamd
│   ├── ipam.json
│   └── metrics.json
├── kernel
│   ├── dmesg.current
│   ├── dmesg.human.current
│   └── uname.txt
├── kubelet
│   ├── config.json
│   ├── kubeconfig.yaml
│   ├── kubelet.log
│   └── kubelet_service.txt
├── log-capture-errors.log
├── networking
│   ├── configure-multicard-interfaces.txt
│   ├── conntrack.txt
│   ├── conntrack6.txt
│   ├── ethtool.txt
│   ├── get_api_server.txt
│   ├── ip6route.txt
│   ├── ip6rule.txt
│   ├── ip6tables-filter.txt
│   ├── ip6tables-mangle.txt
│   ├── ip6tables-nat.txt
│   ├── ip6tables-save.txt
│   ├── ip6tables.txt
│   ├── iproute.txt
│   ├── iprule.txt
│   ├── iptables-filter.txt
│   ├── iptables-mangle.txt
│   ├── iptables-nat.txt
│   ├── iptables-save.txt
│   ├── iptables.txt
│   └── resolv.conf
├── nodeadm
│   ├── nodeadm-config.log
│   └── nodeadm-run.log
├── sandbox-image
│   └── sandbox-image-log.txt
├── storage
│   ├── inodes.txt
│   ├── lsblk.txt
│   ├── mounts.txt
│   ├── pod_local_storage.txt
│   └── xfs.txt
├── sysctls
│   └── sysctl_all.txt
├── system
│   ├── allprocstat.txt
│   ├── availability-zone.txt
│   ├── cpu_throttling.txt
│   ├── instance-id.txt
│   ├── io_throttling.txt
│   ├── procstat.txt
│   ├── ps-threads.txt
│   ├── ps.txt
│   ├── region.txt
│   ├── services.txt
│   └── top.txt
└── var_log
    └── aws-routed-eni
        ├── ebpf-sdk.log
        ├── ipamd.log
        ├── network-policy-agent.log
        └── plugin.log

15 directories, 64 files

 

  • 삭제 kubectl delete nodediagnostics.eks.amazonaws.com --all

 

☞  [네트워킹] Service(LoadBalancer) AWS NLB 사용해보기 - sample-app , Workshop

  • 샘플 앱 배포

 

# 배포 시간 3분 정도 소요 : CrashLoopBackOff 는 다른 파드를 정상 상태되면서 자연 해소
kubectl apply -f https://github.com/aws-containers/retail-store-sample-app/releases/latest/download/kubernetes.yaml
kubectl get events -w --sort-by '.lastTimestamp'
watch -d kubectl get node,pod -owide

#
kubectl get svc ui -o yaml | kubectl neat
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: service
    app.kubernetes.io/instance: ui
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: ui
    app.kubernetes.io/owner: retail-store-sample
    helm.sh/chart: ui-1.0.2
  name: ui
  namespace: default
spec:
  clusterIP: 172.20.143.34
  clusterIPs:
  - 172.20.143.34
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  loadBalancerClass: eks.amazonaws.com/nlb
  ports:
  - name: http
    nodePort: 30292
    port: 80
    targetPort: http
  selector:
    app.kubernetes.io/component: service
    app.kubernetes.io/instance: ui
    app.kubernetes.io/name: ui
    app.kubernetes.io/owner: retail-store-sample
  type: LoadBalancer

#
kubectl get targetgroupbindings.eks.amazonaws.com
NAME                        SERVICE-NAME   SERVICE-PORT   TARGET-TYPE   AGE
k8s-default-ui-55f14a70a2   ui             80             ip            4m15s

kubectl get targetgroupbindings.eks.amazonaws.com -o yaml
...

# 아래 EXTERNAL-IP로 웹 접속
kubectl get svc,ep ui
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                                   PORT(S)        AGE
service/ui   LoadBalancer   172.20.143.34   k8s-default-ui-b879d2eec9-7679402f558c42f7.elb.ap-northeast-2.amazonaws.com   80:30292/TCP   5m46s

NAME           ENDPOINTS           AGE
endpoints/ui   10.20.43.191:8080   5m46s

  • 접속 안됨 → Auto mode yaml 규칙 확인
# 접속 안됨 => 아래 annotate 설정 후 신규 NLB 생성 되어 정상되면 접속 가능!
kubectl annotate svc ui service.beta.kubernetes.io/aws-load-balancer-scheme=internet-facing

# NLB 신규 확인
kubectl get svc,ep ui
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                                   PORT(S)        AGE
service/ui   LoadBalancer   172.20.143.34   k8s-default-ui-efb76b7fa6-f55a6357f0b6b2ef.elb.ap-northeast-2.amazonaws.com   80:30292/TCP   7m34s

NAME           ENDPOINTS           AGE
endpoints/ui   10.20.43.191:8080   7m34s

#
kubectl get svc ui -o yaml | kubectl neat
kubectl get targetgroupbindings.eks.amazonaws.com
kubectl get targetgroupbindings.eks.amazonaws.com -o yaml

 

 

  • 실습 환경 삭제
  1. helm uninstall -n kube-system kube-ops-view → 노드(인스턴스)까지 삭제 확인 후 아래 테라폼 삭제 할 것
  2. terraform destroy --auto-approve
  3. rm -rf ~/.kube/config

 

HyBrid Nodes


☞  참고자료

  • AWS Blog EKS 정보
    • Amazon EKS HyBrid Nodes 출시: EKS 클러스터 온프레미스 인프라 사용 가능 - Link
  • AWS Youtube EKS 정보
    • [Youtube] AWS re:Invent 2024 중 EKS 업데이트Hybrid Node PoC 사례 소개 - Link
  • Blog 및 실습 환경 구성 관련
    • [codingnyan] Amazon EKS Hybrid Nodes: EKS 하이브리드 노드를 리뷰 - Blog

 

☞ HyBrid Nodes 아키텍처

더보기
  • EKS Hybirid/Edge overview

 

 

  • EKS Hybrid Nodes

 

  • EKS Hybrid Nodes shared responsibility

 

 

  • EKS Hybrid Nodes networking
  • AWS Site-to-Site VPNAWS Direct Connect 또는 다른 가상 프라이빗 네트워크(VPN) 솔루션을 사용하여 온 프레미스 환경에서 AWS와 주고받는 하이브리드 네트워크 연결
  • 가상 프라이빗 게이트웨이(VGW) 또는 전송 게이트웨이(TGW)를 대상으로 하는 온프레미스 노드 및 선택적으로 포드 네트워크용 라우팅 테이블에 경로가 있는 가상 프라이빗 클라우드(VPC)
  • 물리적 또는 가상 시스템 형태의 인프라
  • 하이브리드 노드와 호환되는 운영 체제 : Amazon Linux 2023, Ubuntu 20.04, Ubuntu 22.04, Ubuntu 24.04 또는 Red Hat Enterprise Linux(RHEL) 8 및 9를 하이브리드 노드의 노드 운영 체제
  • AWS IAM Roles Anywhere 또는AWS Systems Manager가 컨트롤 플레인을 통해 하이브리드 노드를 인증(SSM Hybrid Activation)하도록 설정되어 있습니다.
  • EKS 클러스터 IAM 역할 및 EKS 하이브리드 노드 IAM 역할

 

☞ (참고) An on-premises Kubernetes cluster accessing AWS APIs using IAM Roles Anywhere with X.509 certificates issued by AWS Private CA in short-lived-certificate mode

더보기
출처: https://aws.amazon.com/ko/blogs/security/connect-your-on-premises-kubernetes-cluster-to-aws-apis-using-iam-roles-anywhere/

 

Components of IAM Roles Anywhere

 

Detailed overview of cert-manager setup

 

Pod configuration using a sidecar

 

 

☞ 실습 환경 Blog 참고

  • VPC Peering 으로 한쪽 VPC(dns option 별도 사용)를 온프레미스 환경으로 가정

출처: https://www.beex-inc.com/blog/eks-hybrid-nodes-calico

 

  • 연결 정보는 생략되었지만, 나머지 환경 구성 절차가 잘 설명되어 있음. 온프렘은 Cilium CNI 사용

Amazon EKS - Hybrid Nodes : 온프레미스의 인프라를 Amazon EKS에서 활용하기

 

  • Raspbery Pi에 SW VPN(libresawan) 을 통해 AWS와 S2S VPN 구성 후, Pi를 하이브리드 노드로 활용 - 개요 , 배포 
  • EKS Auto mode에서 Pi 노드에 웹 서비스 파드를 기동 후, Ingress(ALB)를 통하여 외부 요청을 집에 있는 Pi에 기동되는 파드가 처리.

출처: https://www.beex-inc.com/blog/eks-automode-hybrid-nodes-raspberrypi

 

  • [AWS EKS Workshop] Hybrid Nodes Lab - Link

  • Cloud Bursting : Kyverno - Pod delection cost 활용 - Docs