7주차 - EKS Mode/Nodes - #2
CloudNet@ 가시다님이 진행하는 AWS EKS Hands-on Study 내용 참고.
Auto mode
automode 참고 blog
- 팟캐스트 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



- 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일의 노드 수명을 적용합니다.
- Nodes: EKS 자동 모드 노드는 가전제품처럼 취급되도록 설계되었습니다. EKS 자동 모드는 다음을 수행합니다:
- 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를 설치할 필요는 없습니다.
- Compute: EKS 자동 모드를 사용하면 많은 워크로드에서 EKS 클러스터의 여러 측면을 잊어버릴 수 있습니다. 여기에는 다음이 포함됩니다:
- 커스텀 설정
- 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
..
- aws cli - Docs
- Cluster IAM Role : Cluster IAM Role to perform actions in your AWS account, such as provisioning new EC2 instances
- Node IAM Role
- AmazonEKSWorkerNodeMinimalPolicy
- AmazonEC2ContainerRegistryPullOnly
- EKS Auto Mode also requires a Service-Linked Role, which is automatically created and configured by AWS.
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에서 지원하는 마이그레이션:
- Karpenter에서 EKS Auto Mode 노드로의 마이그레이션
- EKS Managed Node Groups에서 EKS Auto Mode 노드로의 마이그레이션
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
- Deploy a sample inflate workload to an Amazon EKS Auto Mode cluster
- Deploy a Sample Load Balancer Workload to EKS Auto Mode
- Deploy a sample stateful workload to EKS Auto Mode
- Control if a workload is deployed on EKS Auto Mode nodes : 아래 Configure 에서 확인
☞ 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 : 기본 노드풀은 활성화/비활성화 가능, budgets 로 disruption 중지 가능.
- 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
- 테라폼 배포 : 조금 더 자세한 테라폼 코드 내용은 악분님 블로그 참고 https://malwareanalysis.tistory.com/787
- variables.tf 수정 : ap-northeast-2 , 10.20.0.0/16
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'
☞ [네트워킹] 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 해보자!
- 참고로, 생성되는 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
- 삭제 kubectl delete -f https://github.com/aws-containers/retail-store-sample-app/releases/latest/download/kubernetes.yaml
- 실습 환경 삭제
- helm uninstall -n kube-system kube-ops-view → 노드(인스턴스)까지 삭제 확인 후 아래 테라폼 삭제 할 것
- terraform destroy --auto-approve
- 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 VPN, AWS 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




☞ 실습 환경 Blog 참고
- VPC Peering 으로 한쪽 VPC(dns option 별도 사용)를 온프레미스 환경으로 가정
- 연결 정보는 생략되었지만, 나머지 환경 구성 절차가 잘 설명되어 있음. 온프렘은 Cilium CNI 사용
- Raspbery Pi에 SW VPN(libresawan) 을 통해 AWS와 S2S VPN 구성 후, Pi를 하이브리드 노드로 활용 - 개요 , 배포
- EKS Auto mode에서 Pi 노드에 웹 서비스 파드를 기동 후, Ingress(ALB)를 통하여 외부 요청을 집에 있는 Pi에 기동되는 파드가 처리.
- [AWS EKS Workshop] Hybrid Nodes Lab - Link
- Cloud Bursting : Kyverno - Pod delection cost 활용 - Docs