Amazon EKS용 Node Class 생성하기

Amazon EKS용 Node Class 생성하기

Amazon EKS Node Classes는 EKS Auto Mode 관리 노드의 구성에 대한 세밀한 제어를 제공하는 템플릿입니다. Node Class는 EKS 클러스터의 노드 그룹에 적용되는 인프라 수준 설정(네트워크 구성, 스토리지 설정, 리소스 태깅 포함)을 정의합니다. 이 주제는 특정 운영 요구사항을 충족하도록 Node Class를 생성·구성하는 방법을 설명합니다.

기본 설정을 넘어 EKS Auto Mode가 EC2 인스턴스를 프로비저닝·구성하는 방식을 커스터마이즈해야 할 때, Node Class를 만들면 중요한 인프라 매개변수를 정밀하게 제어할 수 있어요. 예를 들어 향상된 보안을 위해 프라이빗 서브넷 배치를 지정하고, 성능에 민감한 워크로드용 인스턴스 임시 스토리지를 구성하며, 비용 할당용 커스텀 태그를 적용할 수 있습니다.

출처: 문서

본문

Pod 분산(sparse) 또는 대규모 워크로드 고려 사항

EKS Auto Mode는 기본적으로 prefix delegation(/28 prefix)을 사용합니다. 각 노드는 16개의 Pod IP를 예약하며, 이는 그 슬롯을 채우는 pod-dense 워크로드에 효율적입니다. Availability Zone당 수백 개 노드를 넘는 pod-sparse 워크로드(ML·GPU 워크로드나 anti-affinity가 많은 워크로드에서 노드당 몇 개의 Pod)에는 보조 IP 모드("32")가 더 최적화된 구성입니다. 노드당 16개를 예약하는 대신 Pod마다 IP 하나를 할당하며, 이는 /20 Pod 서브넷의 유효 용량을 확장합니다.

자세한 내용은 Secondary IP Mode for Pods를 참고하세요. Pod를 할당 모드와 무관하게 노드와 분리된 서브넷에 두려면 Separate subnets and security groups for Pods를 참고하세요.

Node Class 생성

NodeClass를 만들려면 다음 단계를 따르세요.

  1. Node Class 구성으로 YAML 파일(예: nodeclass.yaml)을 만듭니다.
  2. kubectl로 구성을 클러스터에 적용합니다.
  3. Node Pool 구성에서 Node Class를 참조합니다. 자세한 내용은 Create a Node Pool for EKS Auto Mode를 참고하세요.

kubectl이 설치·구성되어 있어야 합니다. 자세한 내용은 Set up to use Amazon EKS를 참고하세요.

기본 Node Class 예시

다음은 Node Class 예시입니다.

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: private-compute
spec:
  subnetSelectorTerms:
    - tags:
        Name: "private-subnet"
        kubernetes.io/role/internal-elb: "1"
  securityGroupSelectorTerms:
    - tags:
        Name: "eks-cluster-sg"
  ephemeralStorage:
    size: "160Gi"

이 Node Class는 노드의 임시 스토리지 양을 늘립니다.

다음을 사용해 이 구성을 적용합니다.

kubectl apply -f nodeclass.yaml

다음으로 Node Pool 구성에서 Node Class를 참조합니다. 자세한 내용은 Create a Node Pool for EKS Auto Mode를 참고하세요.

노드 클래스 access entry 생성

커스텀 노드 클래스를 만들면 노드가 클러스터에 합류하도록 EKS Access Entry를 만들어야 합니다. EKS는 내장 노드 클래스와 노드 풀을 사용할 때 access entries를 자동으로 만듭니다.

Access Entries 작동 방식에 대한 내용은 Grant IAM users access to Kubernetes with EKS access entries를 참고하세요. EKS Auto Mode 노드 클래스용 access entries를 만들 때는 EC2 access entry 유형을 사용해야 합니다.

CLI로 access entry 생성

EC2 노드용 access entry를 만들고 EKS Auto Node Policy를 연결하려면: 클러스터 이름과 노드 역할 ARN으로 다음 CLI 명령을 업데이트합니다. 노드 역할 ARN은 노드 클래스 YAML에 지정되어 있습니다.

# Create the access entry for EC2 nodes
aws eks create-access-entry \
  --cluster-name <CLUSTER_NAME> \
  --principal-arn <NODE_ROLE_ARN> \
  --type EC2

# Associate the auto node policy
aws eks associate-access-policy \
  --cluster-name <CLUSTER_NAME> \
  --principal-arn <NODE_ROLE_ARN> \
  --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSAutoNodePolicy \
  --access-scope type=cluster

CloudFormation으로 access entry 생성

EC2 노드용 access entry를 만들고 EKS Auto Node Policy를 연결하려면: 클러스터 이름과 노드 역할 ARN으로 다음 CloudFormation을 업데이트합니다. 노드 역할 ARN은 노드 클래스 YAML에 지정되어 있습니다.

EKSAutoNodeRoleAccessEntry:
  Type: AWS::EKS::AccessEntry
  Properties:
    ClusterName: <CLUSTER_NAME>
    PrincipalArn: <NODE_ROLE_ARN>
    Type: "EC2"
    AccessPolicies:
      - AccessScope:
          Type: cluster
        PolicyArn: arn:aws:eks::aws:cluster-access-policy/AmazonEKSAutoNodePolicy
  DependsOn: [  ] # previously defined in CloudFormation

CloudFormation 스택 배포에 대한 내용은 Getting started with CloudFormation을 참고하세요.

Node Class 사양

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: my-node-class
spec:
  # Required fields

  # role and instanceProfile are mutually exclusive fields.
  role: MyNodeRole  # IAM role for EC2 instances
  # instanceProfile: eks-MyNodeInstanceProfile  # IAM instance-profile for EC2 instances

  subnetSelectorTerms:
    - tags:
        Name: "private-subnet"
        kubernetes.io/role/internal-elb: "1"
    # Alternative using direct subnet ID
    # - id: "subnet-0123456789abcdef0"

  securityGroupSelectorTerms:
    - tags:
        Name: "eks-cluster-sg"
    # Alternative approaches:
    # - id: "sg-0123456789abcdef0"
    # - name: "eks-cluster-security-group"

  # Optional: Pod subnet selector for advanced networking
  podSubnetSelectorTerms:
    - tags:
        Name: "pod-subnet"
        kubernetes.io/role/pod: "1"
    # Alternative using direct subnet ID
    # - id: "subnet-0987654321fedcba0"
  # must include Pod security group selector also
  podSecurityGroupSelectorTerms:
    - tags:
        Name: "eks-pod-sg"
    # Alternative using direct security group ID
    # - id: "sg-0123456789abcdef0"

  # Optional: Selects on-demand capacity reservations and capacity blocks
  # for EKS Auto Mode to prioritize.
  capacityReservationSelectorTerms:
    - id: cr-56fac701cc1951b03
    # Alternative Approaches
    - tags:
        Name: "targeted-odcr"
      # Optional owning account ID filter
      owner: "012345678901"

  # Optional fields
  snatPolicy: Random  # or Disabled

  networkPolicy: DefaultAllow  # or DefaultDeny
  networkPolicyEventLogs: Disabled  # or Enabled

  ephemeralStorage:
    size: "80Gi"    # Range: 1-59000Gi or 1-64000G or 1-58Ti or 1-64T
    iops: 3000      # Range: 3000-16000
    throughput: 125 # Range: 125-1000
    # Optional KMS key for encryption
    kmsKeyID: "arn:aws:kms:region:account:key/key-id"
    # Accepted formats:
    # KMS Key ID
    # KMS Key ARN
    # Key Alias Name
    # Key Alias ARN

  advancedNetworking:
    # Optional: Controls whether public IP addresses are assigned to instances that are launched with the nodeclass.
    # If not set, defaults to the MapPublicIpOnLaunch setting on the subnet.
    associatePublicIPAddress: false

    # Optional: Forward proxy, commonly requires certificateBundles as well
    # for EC2, see https://repost.aws/knowledge-center/eks-http-proxy-containerd-automation
    httpsProxy: http://192.0.2.4:3128 #commonly port 3128 (Squid) or 8080 (NGINX) #Max 255 characters
    #httpsProxy: http://[2001:db8::4]:3128 # IPv6 address with port, use []
    noProxy: #Max 50 entries
        - localhost #Max 255 characters each
        - 127.0.0.1
        #- ::1 # IPv6 localhost
        #- 0:0:0:0:0:0:0:1 # IPv6 localhost
        - 169.254.169.254 # EC2 Instance Metadata Service
        #- [fd00:ec2::254] # IPv6 EC2 Instance Metadata Service
        # Domains to exclude, put all VPC endpoints here
        - .internal
        - .eks.amazonaws.com
    # ipv4PrefixSize is default to Auto which is prefix and fallback to secondary IP. "32" is the secondary IP mode.
    ipv4PrefixSize: Auto # or "32"

    # enableV4Egress is default to true. Setting it to false when using network policy or blocking IPv4 traffic in IPv6 clusters
    enableV4Egress: false

    # Optional: Static network interface configuration for EFA workloads
    networkInterfaces:
      # The primary ENI (networkCardIndex 0, deviceIndex 0) must use interfaceType: interface
      # secondaryIPv4Count and secondaryIPv4PrefixCount are only supported on networkCardIndex 0
    - deviceIndex: 0
      interfaceType: interface
      networkCardIndex: 0
      secondaryIPv4Count: 10
    - deviceIndex: 1
      interfaceType: interface
      networkCardIndex: 0
      secondaryIPv4PrefixCount: 2 # Only one of secondaryIPv4Count or secondaryIPv4PrefixCount per ENI
    - deviceIndex: 0
      interfaceType: efa-only
      networkCardIndex: 1

  advancedSecurity:
    # Optional, US regions only: Specifying `fips: true` will cause nodes in the nodeclass to run FIPS compatible AMIs.
    fips: false

  # Optional: Custom certificate bundles.
  certificateBundles:
    - name: "custom-cert"
      data: "base64-encoded-cert-data"

  # Optional: EC2 Placement Group
  placementGroupSelector:
    name: "targeted-pg"
    # Alternative use direct placement group ID
    # id: "pg-02465754522cda020"

  # Optional: Additional EC2 tags (with restrictions)
  tags:
    Environment: "production"
    Team: "platform"
    # Note: Cannot use restricted tags like:
    # - kubernetes.io/cluster/*
    # - karpenter.sh/provisioner-name
    # - karpenter.sh/nodepool
    # - karpenter.sh/nodeclaim
    # - karpenter.sh/managed-by
    # - eks.amazonaws.com/nodeclass

고려 사항

  • 인스턴스가 가진 로컬 스토리지 양을 확인하려면 임시 스토리지 리소스를 보기 위해 노드를 describe하면 됩니다.
  • 볼륨 암호화 — EKS는 구성된 커스텀 KMS 키로 인스턴스의 읽기 전용 루트 볼륨과 읽기·쓰기 데이터 볼륨을 암호화합니다.
  • 노드 IAM 역할 교체 — NodeClass와 연결된 노드 IAM 역할을 바꾸면 새 Access Entry를 만들어야 합니다. EKS는 클러스터 생성 중 노드 IAM 역할용 Access Entry를 자동으로 만듭니다. 노드 IAM 역할에는 AmazonEKSAutoNodePolicy EKS Access Policy가 필요합니다. 자세한 내용은 Grant IAM users access to Kubernetes with EKS access entries를 참고하세요.
  • 최대 Pod 밀도 — EKS는 노드의 최대 Pod 수를 110으로 제한합니다. 이 제한은 기존 최대 Pod 계산 후에 적용됩니다. 자세한 내용은 Choose an optimal Amazon EC2 node instance type을 참고하세요.
  • 태그 — Kubernetes에서 EC2로 태그를 전파하려면 추가 IAM 권한을 구성해야 합니다. 자세한 내용은 Learn about identity and access in EKS Auto Mode를 참고하세요.
  • 기본 노드 클래스 — 커스텀 노드 클래스를 default라고 이름 짓지 마세요. EKS Auto Mode에는 내장 NodePool을 하나 이상 활성화할 때 자동으로 프로비저닝되는 default라는 NodeClass가 포함되어 있기 때문입니다. 내장 NodePools 활성화에 대한 내용은 Enable or Disable Built-in NodePools를 참고하세요.
  • 여러 서브넷과 subnetSelectorTerms 동작 — subnetSelectorTerms 조건과 일치하거나 ID로 제공하는 여러 서브넷이 있으면 EKS Auto Mode는 서브넷에 걸쳐 분산된 노드를 만듭니다.
    • 서브넷이 다른 Availability Zones(AZ)에 있다면 Pod topology spread constraints와 Topology Aware Routing 같은 Kubernetes 기능을 사용해 Pod와 트래픽을 각각 영역에 걸쳐 분산할 수 있어요.
    • 같은 AZ에 subnetSelectorTerms와 일치하는 여러 서브넷이 있으면 EKS Auto Mode는 그 AZ의 서브넷에 걸쳐 분산된 각 노드에 Pod를 만듭니다. EKS Auto Mode는 같은 AZ의 다른 서브넷에 각 노드의 보조 네트워크 인터페이스를 만듭니다. 각 서브넷의 사용 가능한 IP 주소 수에 따라 선택해 서브넷을 더 효율적으로 사용합니다. 하지만 EKS Auto Mode가 각 Pod에 어떤 서브넷을 사용할지 지정할 수는 없어요. Pod가 특정 서브넷에서 실행되어야 한다면 Separate subnets and security groups for Pods를 대신 사용하세요.
  • 배치 그룹 전략 제한 — 각 배치 그룹 전략(cluster, partition, spread)은 인스턴스 유형, AZ, 용량에 특정 제한이 있습니다. 자세한 내용은 Amazon EC2 User Guide의 Placement group strategies를 참고하세요.
  • Spread 배치 그룹 — 7-인스턴스 제한 — 랙 수준 스프레드 배치 그룹은 그룹당 Availability Zone당 최대 7개의 실행 중인 인스턴스를 허용합니다. 이는 다음과 같은 엣지 케이스를 만듭니다.
    • 용량 한도의 드리프트 교체 차단 — EKS Auto Mode는 이전 노드를 종료하기 전에 교체 노드를 시작합니다. 스프레드 PG에 AZ의 인스턴스가 7개 있으면 교체 시작이 실패하고 드리프트된 노드는 슬롯이 확보될 때까지 실행 상태를 유지합니다.
    • 모든 AZ가 용량 한도 — 스프레드 PG의 모든 AZ가 7-인스턴스 한도에 도달하면 교체를 스케줄링할 수 없습니다. 드리프트되거나 통합 후보인 노드가 무기한 실행 상태를 유지합니다.
    • 배치 그룹 밖 대체 없음 — EKS Auto Mode는 배치 그룹 밖에서 교체 인스턴스를 시작하려고 하지 않습니다.
    • 해결 방법 — WhenEmpty 통합 정책(consolidationPolicy: WhenEmpty)을 사용하세요. 모든 비 DaemonSet Pod가 드레인된 후에만 노드가 삭제되어, 교체 시작을 먼저 할 필요 없이 PG 슬롯을 확보합니다. 드리프트는 통합 정책과 무관하게 항상 교체-후-삭제를 사용하므로, 용량 한도에서 드리프트는 여전히 차단됩니다.
  • 클러스터 배치 그룹 AZ 고정 — 첫 인스턴스가 클러스터 배치 그룹에 시작되면 PG는 그 AZ에 고정됩니다. NodePool이 여러 AZ를 허용하면 초기 확장 중 병렬 시작이 경합할 수 있어, 하나는 성공해 AZ를 고정하고 나머지는 용량 오류로 실패합니다. 일시적 실패를 피하려면 NodePool 요구사항에서 AZ를 고정하세요.
  • Partition 배치 그룹 — Partition 배치 그룹은 표준 EC2 한도를 넘는 추가 제약 없이 지원됩니다.
  • 통합이 Pod를 배치 그룹 밖으로 이동할 수 있음 — Pod에 배치 그룹 스케줄링 제약(예: eks.amazonaws.com/placement-group-id에 대한 nodeSelector)이 없으면 통합이 Pod를 PG 밖의 노드로 이동할 수 있습니다. 배치 그룹 구성원 자격이 필요한 애플리케이션은 Pod 수준 제약으로 이를 표현해야 합니다.
  • 없거나 삭제된 배치 그룹 — NodeClass가 존재하지 않거나 삭제된 배치 그룹을 참조하면 인스턴스가 시작되지 않습니다. 배치 그룹 ID 형식은 admission에서 검증되지만, 존재 여부는 시작 시에만 확인됩니다. 노드 실행 중 배치 그룹이 삭제되면 기존 노드는 드리프트로 표시되고 드리프트 교체 시작도 차단되므로 무기한 실행 상태를 유지합니다.
  • Hugepages — 노드에서 hugepages 구성에 대한 내용은 Configure hugepages on nodes를 참고하세요.
  • Kubelet 설정 — Pod 밀도, eviction 임계값, 로그 회전 같은 kubelet 설정 재정의에 대한 내용은 Configure kubelet settings on nodes를 참고하세요.
  • 커널 sysctls — 노드에서 커널 sysctls 구성에 대한 내용은 Configure kernel sysctls on nodes를 참고하세요.

Pod용 별도 서브넷과 보안 그룹

podSubnetSelectorTerms와 podSecurityGroupSelectorTerms 필드는 Pod가 노드와 다른 서브넷·보안 그룹을 사용할 수 있게 하여 고급 네트워킹 구성을 가능하게 합니다. 두 필드를 함께 지정해야 합니다. 이 분리는 네트워크 트래픽 라우팅과 보안 정책에 대한 향상된 제어를 제공합니다.

Note: 이 기능은 비 EKS Auto Mode 컴퓨트에 VPC CNI와 함께 사용되는 Security Groups for Pods(SGPP) 기능과 다릅니다. SGPP는 EKS Auto Mode에서 지원되지 않습니다. 대신 NodeClass에서 podSecurityGroupSelectorTerms를 사용해 Pod 트래픽에 별도 보안 그룹을 적용하세요. 보안 그룹은 NodeClass 수준에서 적용되므로, 해당 NodeClass를 사용하는 노드의 모든 Pod가 같은 Pod 보안 그룹을 공유합니다.

작동 방식:

  • podSubnetSelectorTerms와 podSecurityGroupSelectorTerms를 구성하면:
    • 노드의 기본 ENI는 subnetSelectorTerms와 securityGroupSelectorTerms의 서브넷·보안 그룹을 사용합니다. 노드 자체 IP 주소만 이 인터페이스에 할당됩니다.
    • EKS Auto Mode는 podSubnetSelectorTerms와 일치하는 서브넷에 podSecurityGroupSelectorTerms의 보안 그룹이 연결된 보조 ENI를 만듭니다. Pod IP 주소는 기본적으로 /28 prefix를 사용해 이 보조 ENI에서 할당되며, 연속 prefix 블록을 사용할 수 없으면 보조 IP(/32)로 자동 폴백합니다. advancedNetworking에서 ipv4PrefixSize가 "32"로 설정되면 보조 IP만 사용됩니다.
    • podSecurityGroupSelectorTerms에 지정된 보안 그룹은 VPC 내 Pod 트래픽에 적용됩니다. VPC 밖으로 나가는 트래픽의 경우 Pod가 노드의 기본 ENI(및 그 보안 그룹)를 사용하는데, 소스 네트워크 주소 변환(SNAT)이 Pod IP를 노드 IP로 변환하기 때문입니다. NodeClass의 snatPolicy 필드로 이 동작을 수정할 수 있어요.

사용 사례 — 다음이 필요할 때 podSubnetSelectorTerms와 podSecurityGroupSelectorTerms를 사용하세요.

  • 노드와 Pod의 트래픽을 별도로 제어하는 다른 보안 그룹을 적용합니다.
  • 인프라 트래픽(노드 간 통신)을 애플리케이션 트래픽(Pod 간 통신)과 분리합니다.
  • Pod 서브넷과 다른 네트워크 구성을 노드 서브넷에 적용합니다.
  • Pod 트래픽에 영향을 주지 않고 노드 트래픽 전용으로 역방향 프록시나 네트워크 필터링을 구성합니다. 프록시용 역방향 프록시와 자체 서명·프라이빗 인증서를 정의하려면 advancedNetworking과 certificateBundles를 사용하세요.

예시 구성:

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: advanced-networking
spec:
  role: MyNodeRole

  # Subnets and security groups for EC2 instances (nodes)
  subnetSelectorTerms:
    - tags:
        Name: "node-subnet"
        kubernetes.io/role/internal-elb: "1"

  securityGroupSelectorTerms:
    - tags:
        Name: "eks-cluster-sg"

  # Separate subnets and security groups for Pods
  podSubnetSelectorTerms:
    - tags:
        Name: "pod-subnet"
        kubernetes.io/role/pod: "1"

  podSecurityGroupSelectorTerms:
  - tags:
      Name: "eks-pod-sg"

별도 Pod 서브넷·보안 그룹 고려 사항:

  • 보안 그룹 범위 — podSecurityGroupSelectorTerms의 보안 그룹은 보조 ENI에 연결되고 VPC 내 Pod 트래픽에 적용됩니다. SNAT가 활성화되면(기본 snatPolicy: Random) VPC를 나가는 트래픽이 노드의 기본 ENI IP 주소로 변환되므로 대신 securityGroupSelectorTerms의 노드 보안 그룹이 적용됩니다. snatPolicy: Disabled로 설정하면 Pod가 모든 트래픽에 자체 IP 주소를 사용하며, 라우팅과 보안 그룹을 그에 맞게 구성해야 합니다.
  • NodeClass 수준 세분성 — Pod 보안 그룹은 NodeClass를 사용하는 노드에 스케줄링된 모든 Pod에 적용됩니다. 다른 워크로드에 다른 보안 그룹을 적용하려면 별도의 NodeClass와 NodePool 리소스를 만들고 taints, tolerations, node selectors로 워크로드를 적절한 노드에 스케줄링하세요.
  • 감소된 Pod 밀도 — 노드의 기본 네트워크 인터페이스가 노드 IP에 예약되어 Pod에 사용할 수 없으므로 각 노드에서 더 적은 Pod가 실행될 수 있습니다.
  • 서브넷 셀렉터 제한 — 표준 subnetSelectorTerms와 securityGroupSelectorTerms 구성은 Pod 서브넷·보안 그룹 선택에 적용되지 않습니다.
  • 네트워크 계획 — 워크로드 요구를 지원하도록 노드와 Pod 서브넷 모두에 충분한 IP 주소 공간을 확보하세요.
  • 라우팅 구성 — 노드와 Pod 서브넷 간 통신을 위해 Pod 서브넷의 라우트 테이블과 네트워크 Access Control List(ACL)가 올바르게 구성되었는지 확인합니다.
  • Availability Zones — 여러 AZ에 걸쳐 Pod 서브넷을 만들었는지 확인합니다. 특정 Pod 서브넷을 사용한다면 노드 서브넷 AZ와 같은 AZ에 있어야 합니다.

Pod용 보조 IP 모드(Secondary IP Mode)

ipv4PrefixSize 필드는 노드에 보조 IP 주소만 할당해 고급 네트워킹 구성을 가능하게 합니다. 이 기능은 노드에 prefix(/28)를 할당하지 않고 MinimalIPTarget로 보조 IP 하나만 유지합니다.

advancedNetworking.ipv4PrefixSize는 두 값을 허용합니다. Auto(기본; prefix delegation; 더 높은 Pod 생성 속도; 노드당 최소 16 IP 예약)와 "32"(보조 IP 모드; Pod당 1 IP; Pod별 AssignPrivateIpAddresses 호출 추가; 노드당 Pod가 인스턴스 유형의 ENI IP-제한으로 제한).

Auto 모드에서 EKS Auto Mode는 각 노드에 /28 prefix(16 IP)를 사전 할당하고 Pod 수요가 현재 블록 용량을 초과하면 /28을 또 추가하므로, 16은 노드당 최소값이지 상한이 아닙니다.

계획에는 다음 숫자를 사용하세요(실제 클러스터는 다를 수 있음). Pod 서브넷이 단편화되고 사용 가능한 연속 /28이 없으면 Auto 모드는 그 노드에서 IP별 할당으로 폴백합니다. 그러면 노드당 IP 수는 아래 표시된 16-per-prefix 패턴 아래로 내려갑니다.

예시 A — 노드에 Pod 1개:

  • 보조 IP 모드: Pod IP 1개 + 노드 IP 1개 = 사용 중인 IP 2개.
  • Prefix 모드: 노드 IP 1개 + 첫 /28 prefix의 IP 16개(1개는 Pod가 사용, 15개는 향후 Pod용으로 보유) = 할당 IP 17개, 사용 중 2개.

예시 B — 노드에 Pod 18개:

  • 보조 IP 모드: Pod IP 18개 + 노드 IP 1개 = 사용 중인 IP 19개.
  • Prefix 모드: 노드 IP 1개 + /28 prefix 2개(총 32 IP, 첫 /28은 16 Pod에서 꽉 참, 둘째 /28은 17-18 Pod 보유하고 14개는 향후 Pod용으로 보유) = 할당 33 IP, 사용 중 19개.

pod-sparse 워크로드용 보조 IP 모드(Pod당 1 IP, prefix 예약 없음)로 전환하려면 advancedNetworking.ipv4PrefixSize: "32"가 있는 커스텀 NodeClass를 만들고 커스텀 NodePool이 이를 가리키게 하세요. 내장 general-purpose와 system 노드 풀은 자동으로 프로비저닝된 default NodeClass를 사용합니다. ipv4PrefixSize를 재정의하려면 커스텀 NodeClass를 커스텀 NodePool과 짝지어야 합니다.

사용 사례:

  • 더 나은 서브넷 IP 주소 활용
  • prefix 단편화 없음

예시 구성:

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: advanced-networking
spec:
  role: MyNodeRole

  advancedNetworking:
    ipv4PrefixSize: "32"

보조 IP 모드 고려 사항:

  • 감소된 Pod 생성 속도 — 보조 IP 하나만 준비되므로 더 많은 Pod가 생성될 때 IPAM 서비스가 IP를 프로비저닝하는 데 더 많은 시간이 필요합니다.

IPv6 클러스터에서 IPv6 Pod의 IPv4 이그레스 비활성화

enableV4Egress 필드는 기본적으로 true입니다. Auto Mode IPv6 클러스터에서 이 기능을 비활성화해 Auto Mode가 IPv6 Pod용 egress-only IPv4 인터페이스를 만들지 않도록 할 수 있습니다. IPv4 이그레스 인터페이스는 Network Policy 시행 대상이 아니므로 중요합니다. 네트워크 정책은 Pod의 기본 인터페이스(eth0)에서만 시행됩니다.

사용 사례 — 다음이 필요할 때 enableV4Egress를 사용하세요.

  • IPv6 클러스터 사용: IPv4 이그레스 트래픽이 기본적으로 허용됩니다.
  • Network Policy 사용: 현재 EKS Network Policy는 dual stack을 지원하지 않습니다. enableV4Egress를 비활성화하면 Pod 트래픽이 예기치 않게 IPv4로 이그레스하는 것을 방지할 수 있어요.

예시 구성:

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: advanced-networking
spec:
  role: MyNodeRole

  advancedNetworking:
    enableV4Egress: false

enableV4Egress 비활성화 고려 사항:

  • IPv6 클러스터의 Network Policy — IPv6 클러스터는 기본적으로 IPv4 트래픽을 허용합니다. enableV4Egress: false를 설정하면 IPv4 이그레스 트래픽을 차단하여, 특히 Network Policies와 함께 사용할 때 향상된 보안을 제공합니다.

정적 네트워크 인터페이스 구성

advancedNetworking의 networkInterfaces 필드는 시작 시 인스턴스에 연결된 네트워크 인터페이스를 정적으로 정의할 수 있게 합니다. 이는 분산 학습·추론 워크로드에서 고성능 노드 간 통신용 Elastic Fabric Adapter(EFA) 디바이스를 구성하는 데 주로 사용됩니다. 이 기능은 정적 용량 노드 풀과 짝지어 미리 준비된 EFA-ready 노드를 유지할 수 있습니다. EKS에서 EFA 디바이스 관리에 대한 자세한 내용은 Manage EFA devices on Amazon EKS를 참고하세요. 특정 인스턴스 유형의 권장 EFA 구성은 Amazon EC2 User Guide의 Maximize network bandwidth for EFA-enabled instance types를 참고하세요.

작동 방식: networkInterfaces의 각 항목은 시작 중 인스턴스에 연결되는 네트워크 인터페이스를 정의합니다. 각 항목은 networkCardIndex(네트워크 카드, 0이 기본), deviceIndex(해당 카드의 디바이스 위치), interfaceType(표준 IP 기반 트래픽용 interface, IP 주소 없이 RDMA 트래픽 전용 EFA 인터페이스용 efa-only)을 지정합니다. 기본 ENI(networkCardIndex: 0, deviceIndex: 0)는 IP 기반 노드 통신을 지원하려면 interfaceType: interface를 사용해야 합니다. efa-only 인터페이스는 RDMA용 EFA 디바이스 기능만 지원하며 IP 주소로 구성할 수 없습니다.

secondaryIPv4Count(각 단위가 IP 주소 1개 제공) 또는 secondaryIPv4PrefixCount(각 단위가 16 IP 주소의 /28 prefix 제공)를 사용해 기본 네트워크 카드(networkCardIndex: 0)의 인터페이스에 IP 용량을 할당할 수 있습니다. 이 중 하나만 인터페이스당 사용할 수 있으며 networkCardIndex: 0에서만 지원됩니다. efa-only 인터페이스에서는 사용할 수 없습니다.

Important: networkInterfaces가 구성되면 EKS Auto Mode는 인스턴스 시작 후 추가 IP, prefix, ENI를 연결하지 않습니다. 시작 시 구성된 인터페이스와 IP 주소만 Pod가 사용할 수 있어요. 구성된 IP 수에 따라 Pod 밀도를 계획해야 합니다.

고려 사항:

  • 정적으로 정의된 네트워크 인터페이스에서는 IPv6가 지원되지 않습니다. associatePublicIPAddress는 둘 이상의 네트워크 인터페이스가 정의될 때 호환되지 않으므로, 여러 인터페이스를 사용하는 노드는 공용 IP를 가질 수 없습니다(공용 전용 또는 공용·프라이빗 혼합 클러스터 모두).
  • 정적 네트워크 인터페이스와 함께 podSubnetSelectorTerms와 podSecurityGroupSelectorTerms를 사용할 때는 기본 ENI를 보조 IP 0개로 구성하세요. 기본 ENI는 노드 서브넷과 보안 그룹을, Pod 트래픽은 보조 ENI의 Pod 서브넷 구성을 사용합니다.

예시: GPU 학습용 EFA-only 인터페이스 — 다음 예시는 분산 학습에 사용되는 GPU 인스턴스용 EFA-only 인터페이스로 구성된 NodeClass를 보여 줍니다. 기본 인터페이스는 /28 prefix(16 Pod IP)를 가지며, 4개의 추가 EFA-only 인터페이스가 RDMA 연결을 제공합니다. 이 구성은 정적 용량 노드 풀과 짝지어 미리 준비된 EFA-ready 노드를 유지할 수 있어요.

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: efa-training
spec:
  role: MyNodeRole
  subnetSelectorTerms:
    - tags:
        Name: "private-subnet"
  securityGroupSelectorTerms:
    - tags:
        Name: "efa-security-group"
  placementGroupSelector:
    name: "ml-training-pg"
  advancedNetworking:
    networkInterfaces:
    - deviceIndex: 0
      interfaceType: interface
      networkCardIndex: 0
      secondaryIPv4PrefixCount: 1
    - deviceIndex: 1
      interfaceType: efa-only
      networkCardIndex: 0
    - deviceIndex: 0
      interfaceType: efa-only
      networkCardIndex: 1
    - deviceIndex: 0
      interfaceType: efa-only
      networkCardIndex: 2
    - deviceIndex: 0
      interfaceType: efa-only
      networkCardIndex: 3

노드에서 hugepages 구성

advancedCompute.hugepages 필드로 NodeClass의 노드에 hugepages를 구성할 수 있습니다. Hugepages는 고성능 컴퓨팅(HPC), 데이터베이스, 네트워크 집약 애플리케이션 같은 지연 시간에 민감한 워크로드의 메모리 접근 성능을 개선합니다. 두 개의 독립적인 hugepages 구성을 별도로 또는 함께 사용할 수 있어요.

  • 정적 hugepages — pages 필드를 사용해 각 노드에 고정된 수의 2Mi 또는 1Gi hugepages 또는 두 크기의 혼합을 사전 할당합니다. 정적 hugepages는 스케줄링 가능한 노드 리소스입니다. 이를 사용하려면 Pod가 hugepages-2Mi 또는 hugepages-1Gi 같은 hugepage 리소스를 명시적으로 요청하도록 구성하세요. 자세한 내용은 Kubernetes 문서의 Manage HugePages를 참고하세요.
  • 투명 hugepages(THP) — transparent 필드를 사용해 커널의 THP 정책을 구성합니다. THP는 할당 가능한 리소스가 아닌 커널 전체 정책입니다. 스케줄링이나 노드 용량에 영향을 주지 않으며, Pod가 이를 요청하지 않아요. 자세한 내용은 Linux 커널 문서의 Transparent Hugepage Support를 참고하세요.

예시 구성:

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: hugepages-compute
spec:
  role: MyNodeRole

  subnetSelectorTerms:
    - tags:
        Name: "private-subnet"

  securityGroupSelectorTerms:
    - tags:
        Name: "eks-cluster-sg"

  advancedCompute:
    hugepages:
      # Static hugepage reservations: up to one entry for each size
      pages:
        - size: "2Mi"
          count: 512
        - size: "1Gi"
          count: 2
      # Transparent hugepages (THP) kernel policy
      transparent:
        enabled: always  # or madvise, never
        defrag: defer    # or always, defer+madvise, madvise, never

투명 hugepage 설정:

  • 두 transparent 설정 모두 선택 사항입니다. 설정을 생략하면 노드는 커널 기본값(madvise)을 사용합니다.
  • enabled — THP 할당 정책을 제어합니다. 시스템 전체에 THP를 적용하려면 always로 설정하고, madvise(MADV_HUGEPAGE)로 옵트인하는 메모리 영역에만 THP를 적용하려면 madvise로 설정하며, THP를 비활성화하려면 never로 설정합니다.
  • defrag — THP 할당을 충족하기 위해 커널이 메모리를 얼마나 공격적으로 컴팩트하는지 제어합니다. 유효한 값은 always, defer, defer+madvise, madvise, never입니다.

THP를 끄려면(권장하는 데이터베이스 워크로드 등) enabled: never로 설정합니다. enabled가 never일 때는 defrag를 설정하지 않거나 never로 설정하세요. NodeClass 검증은 다른 조합을 거부합니다.

Hugepages 고려 사항:

  • 정적 hugepage 크기 — pages 필드를 사용해 각 hugepage 크기(2Mi, 1Gi)당 최대 하나의 항목을 지정합니다. 같은 노드에 두 크기를 모두 예약할 수 있어요.
  • 메모리 예약 — 정적 hugepages는 인스턴스의 총 메모리로 계산됩니다. 모든 페이지 크기의 결합 hugepages 예약이 총 메모리의 80%를 초과하면 Amazon EKS는 인스턴스 유형을 NodeClass와 호환되지 않는 것으로 표시합니다.
  • EFA 상호 배제 — Elastic Fabric Adapter(EFA)와 정적 hugepages는 같은 NodeClass에 공존할 수 없습니다. interfaceType: efa-only를 pages와 함께 설정하면 NodeClass 검증이 실패합니다. Amazon EKS는 정적 hugepages가 있는 NodeClass에서 vpc.amazonaws.com/efa를 요청하는 Pod를 프로비저닝하지 않습니다. EFA 워크로드에는 별도 NodeClass를 사용하세요. 투명 hugepages는 EFA와 충돌하지 않습니다. EFA 인터페이스를 사용하는 NodeClass에 transparent를 구성할 수 있어요.

노드에서 kubelet 설정 구성

advancedCompute.kubelet 필드를 사용해 NodeClass의 노드에서 kubelet 설정을 재정의합니다. 이 재정의로 Pod 밀도, 리소스 압력 eviction, 컨테이너 로그 회전, OOM(메모리 부족) 동작을 조정할 수 있어요. Amazon EKS는 Auto Mode 노드에 기본 kubelet 설정을 적용하므로, 워크로드가 다른 동작을 요구할 때만 이 필드를 구성하세요. 기반 설정에 대한 자세한 내용은 Kubernetes 문서의 Kubelet Configuration을 참고하세요.

다음 kubelet 설정을 사용할 수 있습니다.

  • maxPods: 노드에서 실행할 수 있는 최대 Pod 수.
  • podPidsLimit: Pod당 최대 프로세스 ID(PID) 수.
  • idsPerPod: kubelet이 각 Pod의 사용자 네임스페이스에 할당하는 UID·GID 수.
  • singleProcessOOMKill: kubelet OOM이 컨테이너의 프로세스를 그룹으로가 아닌 개별적으로 죽이는지 여부.
  • eviction: 리소스 압력 신호에 대한 하드·소프트 eviction 임계값.
  • logging: 컨테이너 로그 회전 크기와 파일 수.
  • allowedUnsafeSysctls: 노드에 스케줄링된 Pod가 설정할 수 있는 안전하지 않은 sysctls 또는 *로 끝나는 네임스페이스 패턴 목록.

예시 구성:

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: kubelet-compute
spec:
  role: MyNodeRole

  subnetSelectorTerms:
    - tags:
        Name: "private-subnet"

  securityGroupSelectorTerms:
    - tags:
        Name: "eks-cluster-sg"

  advancedCompute:
    kubelet:
      # Range: 1-110
      maxPods: 60
      # -1 disables the limit, or specify 100 or greater
      podPidsLimit: 4096
      # Multiple of 65536, range: 65536-4294967295. Requires
      # advancedCompute.kernel.sysctl.user.max_user_namespaces > 0.
      idsPerPod: 65536
      singleProcessOOMKill: false
      eviction:
        # Valid signals: memory.available, nodefs.available, nodefs.inodesFree,
        # imagefs.available, imagefs.inodesFree, pid.available
        hard:
          memory.available: "100Mi"
          nodefs.available: "10%"
        soft:
          memory.available: "500Mi"
          nodefs.available: "15%"
        # Required when soft thresholds are set
        softGracePeriod:
          memory.available: "1m30s"
          nodefs.available: "2m"
        # 0 uses each Pod's terminationGracePeriodSeconds
        maxPodGracePeriod: 60
      logging:
        containerLogMaxSize: "10Mi"
        # Minimum: 2
        containerLogMaxFiles: 5
      # Up to 64 entries. Allowed patterns: kernel.shm*, kernel.msg*,
      # kernel.sem, fs.mqueue.*, net.*
      allowedUnsafeSysctls:
        - "net.core.somaxconn"
        - "kernel.shm*"

Kubelet 설정 고려 사항:

  • 노드 교체 — 기존 NodeClass에서 kubelet 설정을 변경하면 그것을 사용하는 노드가 드리프트로 표시됩니다. Amazon EKS는 업데이트된 구성을 사용하는 새 노드로 그 노드들을 교체합니다. Amazon EKS는 실행 중인 노드에 kubelet 설정을 제자리에서 적용하지 않습니다.
  • maxPods 클램핑 — 설정한 값은 보장이 아닌 상한입니다. 런타임에서 Amazon EKS는 세 값 중 가장 낮은 값을 적용합니다. 이는 사용자의 maxPods 값, 인스턴스 유형에 사용 가능한 IP 주소, 노드당 110 Pod의 Auto Mode 한도입니다. 자세한 내용은 Choose an optimal Amazon EC2 node instance type을 참고하세요.
  • podPidsLimit 값 — 한도를 비활성화하려면 -1, 또는 100 이상의 값을 지정하세요. NodeClass 검증은 0~99 사이 값을 거부합니다.
  • idsPerPod 요구사항 — 값은 65536~4294967295 사이의 65536 배수여야 합니다. idsPerPod를 설정하려면 같은 NodeClass에서 advancedCompute.kernel.sysctl.user.max_user_namespaces를 양수 값으로 설정해야 합니다. user.max_user_namespaces를 0보다 크게 설정하지 않고 idsPerPod를 설정하는 구성은 NodeClass admission이 거부합니다. user.max_user_namespaces에 대한 자세한 내용은 Supported sysctls를 참고하세요.
  • 소프트 eviction 임계값 — 같은 신호의 소프트 임계값은 하드 임계값보다 덜 공격적이어야 하며, 즉 더 일찍 트리거됩니다. 소프트 임계값을 설정하면 각 신호에 대해 softGracePeriod도 설정해야 합니다. 소프트 임계값과 하드 임계값은 백분율과 절대 수량처럼 다른 단위를 사용할 수 있어요. 그 경우 Amazon EKS가 각 인스턴스 유형에 대해 두 값을 모두 해석하고, 비교를 위반하는 인스턴스 유형을 NodeClass와 호환되지 않는 것으로 표시합니다.
  • singleProcessOOMKill 버전 요구사항 — 이 설정은 Kubernetes 1.32 이상이 필요합니다. 이전 버전에서는 Amazon EKS가 NodeClass에 경고 이벤트를 내보내고 설정은 효과가 없습니다.
  • allowedUnsafeSysctls 제한 — 최대 64개 항목을 지정할 수 있으며, 각 항목은 허용 패턴(kernel.shm*, kernel.msg*, kernel.sem, fs.mqueue.*, net.*) 중 하나와 일치해야 합니다. 노드에서 안전하지 않은 sysctl을 허용하면 Pod가 그것을 요청할 수만 있게 됩니다. 각 Pod는 여전히 securityContext.sysctls에 sysctl을 나열해야 합니다. 자세한 내용은 Kubernetes 문서의 Using sysctls in a Kubernetes Cluster를 참고하세요.

노드에서 커널 sysctls 구성

advancedCompute.kernel.sysctl 필드를 사용해 NodeClass의 노드에서 Linux 커널 sysctls를 설정합니다. Sysctls는 더 높은 네트워킹 한도, 다른 메모리 관리 정책, 특정 TCP 설정이 필요한 워크로드의 런타임 커널 동작을 조정합니다. sysctl 필드의 속성 이름은 기반 커널 sysctl 이름과 정확히 일치합니다(예: vm.swappiness, net.core.somaxconn). Amazon EKS는 노드 부팅 시 sysctl 값을 적용합니다. 기존 NodeClass에서 sysctl을 변경하면 Amazon EKS가 새 값을 적용하기 위해 노드 교체를 시작합니다.

예시 구성:

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
  name: tuned-compute
spec:
  role: MyNodeRole

  subnetSelectorTerms:
    - tags:
        Name: "private-subnet"

  securityGroupSelectorTerms:
    - tags:
        Name: "eks-cluster-sg"

  advancedCompute:
    kernel:
      sysctl:
        vm.swappiness: 30
        net.core.somaxconn: 4096
        net.ipv4.tcp_congestion_control: "cubic"
        vm.dirty_background_ratio: 10
        vm.dirty_ratio: 20

지원되는 sysctls: Amazon EKS는 다음 표의 sysctls만 지원합니다. 각 숫자 sysctl은 표시된 최소·최대를 시행하며, NodeClass admission은 해당 범위 밖의 값을 거부합니다. 문자열 sysctls는 나열된 값만 허용합니다.

Sysctl 설명 허용 값
fs.aio-max-nr 비동기 I/O 요청의 최대 수 65536–4194304
fs.inotify.max_user_instances 실제 사용자 ID당 최대 inotify 인스턴스 수 8192–1048576
fs.inotify.max_user_watches 실제 사용자 ID당 최대 inotify watch 수 8192–1048576
fs.nr_open 프로세스가 할당할 수 있는 최대 파일 핸들 수 1048576–2147483584
kernel.perf_event_paranoid 성능 이벤트 시스템에 대한 비특권 접근 제어 -1–2
net.core.netdev_max_backlog CPU당 INPUT 쪽에 대기 중인 최대 패킷 수 1000–3240000
net.core.rmem_max 최대 수신 소켓 버퍼 크기(바이트) 212992–134217728
net.core.somaxconn listen syscall의 backlog 인수 최대값 4096–3240000
net.core.wmem_max 최대 송신 소켓 버퍼 크기(바이트) 212992–134217728
net.ipv4.neigh.default.gc_thresh1 가비지 컬렉션이 실행될 수 있기 전의 최소 ARP-캐시 항목 0–262144
net.ipv4.neigh.default.gc_thresh2 ARP-캐시 항목의 소프트 최대 수 512–524288
net.ipv4.neigh.default.gc_thresh3 ARP-캐시 항목의 하드 최대 수 1024–1048576
net.ipv4.tcp_congestion_control 새 연결의 TCP 혼잡 제어 알고리즘 cubic, reno
net.ipv4.tcp_fin_timeout 고아 연결이 로컬 끝에서 중단되기 전에 FIN_WAIT_2 상태로 유지되는 시간(초) 5–120
net.ipv4.tcp_keepalive_time keepalive 활성화 시 TCP가 keepalive 메시지를 보내는 주기(초) 30–432000
net.ipv4.tcp_max_syn_backlog 허용되는 미해결 SYN 요청의 최대 수. 이 값을 넘는 요청은 커널이 버림 128–3240000
net.ipv4.tcp_tw_reuse 프로토콜 관점에서 안전할 때 새 연결에 TIME-WAIT 소켓 재사용. 0은 비활성화, 1은 전역 활성화, 2는 루프백만 활성화 0–2
user.max_user_namespaces 사용자가 생성할 수 있는 최대 사용자 네임스페이스 수. 0은 사용자 네임스페이스 비활성화 0–2147483647
vm.dirty_background_ratio 커널 플러셔 스레드가 더티 페이지를 디스크에 쓰기 시작하는 사용 가능한 메모리 백분율 1–20
vm.dirty_expire_centisecs 더티 페이지가 writeback 자격을 얻기까지의 100분의 1초 0–6000
vm.dirty_ratio 쓰기 프로그램이 쓰기에서 차단되도록 강제되는 사용 가능한 메모리 백분율 5–40
vm.dirty_writeback_centisecs 플러셔-스레드 호출 사이의 100분의 1초 0–1000
vm.max_map_count 단일 프로세스가 가질 수 있는 최대 메모리 맵 영역 수 65530–2147483647
vm.swappiness 스와핑과 파일 시스템 페이징의 상대적 IO 비용 0–200
vm.watermark_scale_factor 10,000분율 단위의 메모리 회수 워터마크 비율 10–3000

Sysctls 고려 사항:

  • 지원되는 sysctls — Supported sysctls에 나열된 sysctls만 지원됩니다. 각 필드는 문서화된 최소·최대를 시행하며, NodeClass admission은 해당 범위 밖의 값을 거부합니다.
  • 부팅 시 적용 — Sysctls는 노드 부팅 시 Bottlerocket의 [settings.kernel.sysctl]에 기록됩니다. spec.advancedCompute.kernel.sysctl의 런타임 변경은 기존 노드를 드리프트로 표시하며, 새 값은 교체 노드에서만 적용됩니다.
  • vm.dirty_background_ratio와 vm.dirty_ratio — 이 두 필드는 둘 다 설정하거나 둘 다 생략해야 하며, vm.dirty_background_ratio는 vm.dirty_ratio보다 엄격히 작아야 합니다. NodeClass admission은 두 규칙 중 하나라도 위반하는 구성을 거부합니다.
  • net.ipv4.neigh.default.gc_thresh1, gc_thresh2, gc_thresh3 — 세 ARP-캐시 임계값은 모두 함께 설정하거나 모두 생략해야 하며, 값은 gc_thresh1 < gc_thresh2 < gc_thresh3를 충족해야 합니다.
  • net.ipv4.tcp_congestion_control — cubic과 reno만 허용됩니다.

더 알아보기 (Learn more)