포드에 대한 사용자 지정 네트워킹 - Amazon EKS

포드에 대한 사용자 지정 네트워킹

기본적으로 Amazon VPC CNI plugin for Kubernetes는 Amazon EC2 노드의 보조 Elastic 네트워크 인터페이스(네트워크 인터페이스)를 생성하는 경우 노드의 기본 네트워크 인터페이스와 동일한 서브넷에서 생성합니다. 또한 기본 네트워크 인터페이스에 연결된 보조 네트워크 인터페이스에 동일한 보안 그룹을 연결합니다. 다음 중 하나 이상의 이유로 플러그 인이 다른 서브넷에서 보조 네트워크 인터페이스를 생성하거나 다른 보안 그룹을 보조 네트워크 인터페이스에 연결하거나, 둘 다 하려고 할 수 있습니다.

  • 기본 네트워크 인터페이스가 있는 서브넷에서 사용할 수 있는 IPv4 주소의 수는 제한되어 있습니다. 이렇게 하면 서브넷에서 생성할 수 있는 Pods의 수가 제한될 수 있습니다. 보조 네트워크 인터페이스에 다른 서브넷을 사용하면 Pods에 사용 가능한 IPv4 주소 수를 늘릴 수 있습니다.

  • 보안상의 이유로 Pods는 노드의 기본 네트워크 인터페이스와 다른 서브넷 또는 보안 그룹을 사용해야 할 수 있습니다.

  • 노드는 퍼블릭 서브넷에서 구성되며, Pods를 프라이빗 서브넷에 배치할 수 있습니다. 퍼블릭 서브넷과 연결된 라우팅 테이블에는 인터넷 게이트웨이로 가는 경로가 포함됩니다. 프라이빗 서브넷과 연결된 라우팅 테이블에는 인터넷 게이트웨이로 가는 경로가 포함되지 않습니다.

고려 사항
  • 사용자 지정 네트워킹을 사용 설정하면 기본 네트워크 인터페이스에 할당된 IP 주소가 Pods에 할당되지 않습니다. 보조 네트워크 인터페이스의 IP 주소만 Pods에 할당됩니다.

  • 클러스터에서 IPv6 패밀리를 사용하는 경우 사용자 지정 네트워킹을 사용할 수 없습니다.

  • 사용자 지정 네트워킹을 사용하여 IPv4 주소 소모를 완화하려는 경우 대신 IPv6 패밀리를 사용하여 클러스터를 생성할 수 있습니다. 자세한 정보를 알아보려면 클러스터, Pods 및 services용 IPv6 주소을 참조하세요.

  • 보조 네트워크 인터페이스에 지정된 서브넷에 배포된 Pods는 노드의 기본 네트워크 인터페이스와 다른 서브넷 및 보안 그룹을 사용할 수 있다고 해도 서브넷과 보안 그룹은 노드와 동일한 VPC에 있어야 합니다.

필수 조건
  • Amazon VPC CNI plugin for Kubernetes가 보조 네트워크 인터페이스를 생성하고 Pods에 IP 주소를 할당하는 방법을 숙지합니다. 자세한 내용을 알아보려면 GitHub의 ENI 할당을 참조하세요.

  • AWS Command Line Interface(AWS CLI) 버전 2.12.3 이상 또는 1.27.160 이상이 디바이스나 AWS CloudShell에 설치 및 구성되어 있습니다. 현재 버전을 확인하려면 aws --version | cut -d / -f2 | cut -d ' ' -f1을 사용합니다. macOS용 yum, apt-get 또는 Homebrew와 같은 패키지 관리자는 최신 버전의 AWS CLI보다 여러 버전 이전인 경우가 많습니다. 최신 버전을 설치하려면 AWS Command Line Interface 사용 설명서의 AWS CLI 설치, 업데이트 및 제거aws configure를 통한 빠른 구성을 참조하세요. AWS CloudShell에 설치된 AWS CLI 버전도 최신 버전보다 여러 버전 이전일 수도 있습니다. 업데이트하려면 AWS CloudShell 사용 설명서의 홈 디렉터리에 AWS CLI 설치를 참조하세요.

  • 디바이스 또는 AWS CloudShell에 설치된 kubectl 명령줄 도구. 버전은 클러스터의 Kubernetes 버전과 동일하거나 최대 하나 이전 또는 이후의 마이너 버전일 수 있습니다. 예를 들어 클러스터 버전이 1.28인 경우 kubectl 버전 1.27, 1.28 또는 1.29를 함께 사용할 수 있습니다. kubectl을 설치하거나 업그레이드하려면 kubectl 설치 또는 업데이트 부분을 참조하세요.

  • Bash 셸에서 이 주제의 단계를 완료하는 것이 좋습니다. Bash 셸을 사용하지 않는 경우 줄 연속 문자 및 변수 설정 및 사용 방식과 같은 일부 스크립트 명령을 통해 셸이 조정되어야 합니다. 또한 쉘의 인용 및 이스케이프 규칙이 다를 수 있습니다. 자세한 내용은 AWS Command Line Interface 사용 설명서의 AWS CLI에서 문자열에 따옴표 사용을 참조하세요.

본 튜토리얼에서는 example values를 바꾸라고 언급된 경우를 제외하고는 이를 사용하는 것이 좋습니다. 프로덕션 클러스터의 단계를 완료하는 경우 모든 example value를 바꿀 수 있습니다. 동일한 터미널에서 모든 단계를 완료하는 것이 좋습니다. 이는 변수가 여러 단계에서 설정되고 사용되면서 서로 다른 터미널에 존재하지 않기 때문입니다.

이 주제의 명령은 AWS CLI 예제 사용에 나열된 규칙에 따라 형식이 지정되었습니다. 사용 중인AWS CLI 프로필에 정의된 기본 AWS 리전과 다른 AWS 리전에 있는 리소스에 대해 명령줄의 명령을 실행하는 경우에는 명령에 --region region-code를 추가해야 합니다.

프로덕션 클러스터에 사용자 지정 네트워킹을 배포하려면 2단계: VPC 구성로 이동합니다.

1단계: 테스트 VPC 및 클러스터 생성

클러스터 생성

다음 절차를 활용하면 테스트 VPC 및 클러스터를 생성하고 해당 클러스터에 대해 사용자 지정 네트워킹을 구성할 수 있습니다. 프로덕션 클러스터에서 사용할 수 있는 관련 없는 기능들은 이 주제에서 다루지 않으므로 프로덕션 워크로드에 테스트 클러스터를 사용하지 않는 것이 좋습니다. 자세한 내용은 Amazon EKS 클러스터 생성 단원을 참조하십시오.

  1. 나머지 단계에서 사용할 몇 가지 변수를 정의합니다.

    export cluster_name=my-custom-networking-cluster account_id=$(aws sts get-caller-identity --query Account --output text)
  2. VPC를 생성합니다.

    1. Amazon EKS AWS CloudFormation 템플릿을 사용하여 VPC를 생성합니다.

      aws cloudformation create-stack --stack-name my-eks-custom-networking-vpc \ --template-url https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/amazon-eks-vpc-private-subnets.yaml \ --parameters ParameterKey=VpcBlock,ParameterValue=192.168.0.0/24 \ ParameterKey=PrivateSubnet01Block,ParameterValue=192.168.0.64/27 \ ParameterKey=PrivateSubnet02Block,ParameterValue=192.168.0.96/27 \ ParameterKey=PublicSubnet01Block,ParameterValue=192.168.0.0/27 \ ParameterKey=PublicSubnet02Block,ParameterValue=192.168.0.32/27

      AWS CloudFormation 스택을 만드는 데 몇 분 정도 걸립니다. 스택의 배포 상태를 확인하려면 다음 명령을 실행합니다.

      aws cloudformation describe-stacks --stack-name my-eks-custom-networking-vpc --query Stacks\[\].StackStatus --output text

      명령의 출력이 CREATE_COMPLETE가 될 때까지 다음 단계를 계속하지 마세요.

    2. 템플릿에서 생성한 프라이빗 서브넷 ID 값으로 변수를 정의합니다.

      subnet_id_1=$(aws cloudformation describe-stack-resources --stack-name my-eks-custom-networking-vpc \ --query "StackResources[?LogicalResourceId=='PrivateSubnet01'].PhysicalResourceId" --output text) subnet_id_2=$(aws cloudformation describe-stack-resources --stack-name my-eks-custom-networking-vpc \ --query "StackResources[?LogicalResourceId=='PrivateSubnet02'].PhysicalResourceId" --output text)
    3. 이전 단계에서 검색된 서브넷의 가용 영역으로 변수를 정의합니다.

      az_1=$(aws ec2 describe-subnets --subnet-ids $subnet_id_1 --query 'Subnets[*].AvailabilityZone' --output text) az_2=$(aws ec2 describe-subnets --subnet-ids $subnet_id_2 --query 'Subnets[*].AvailabilityZone' --output text)
  3. 클러스터 IAM 역할을 생성합니다.

    1. 다음 명령을 실행하여 IAM 신뢰 정책 JSON 파일을 생성합니다.

      cat >eks-cluster-role-trust-policy.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "eks.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOF
    2. Amazon EKS 클러스터 IAM 역할을 생성합니다. 필요한 경우 eks-cluster-role-trust-policy.json 앞에 이전 단계에서 파일을 작성한 컴퓨터의 경로를 붙입니다. 명령은 사용자가 이전 단계에서 생성한 신뢰 정책을 역할에 연결합니다. IAM 보안 주체를 생성하려면 역할을 생성하는 IAM 보안 주체에 iam:CreateRole 작업(권한)을 할당해야 합니다.

      aws iam create-role --role-name myCustomNetworkingAmazonEKSClusterRole --assume-role-policy-document file://"eks-cluster-role-trust-policy.json"
    3. Amazon EKS 관리형 AmazonEKSClusterPolicy를 역할에 연결합니다. IAM 정책을 IAM 보안 주체에 연결하려면 정책을 연결하는 보안 주체에 iam:AttachUserPolicy 또는 iam:AttachRolePolicy의 IAM 작업(권한) 중 하나를 할당해야 합니다.

      aws iam attach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy --role-name myCustomNetworkingAmazonEKSClusterRole
  4. Amazon EKS 클러스터를 생성하고 이와 통신하도록 디바이스를 구성합니다.

    1. 클러스터를 생성합니다.

      aws eks create-cluster --name my-custom-networking-cluster \ --role-arn arn:aws:iam::$account_id:role/myCustomNetworkingAmazonEKSClusterRole \ --resources-vpc-config subnetIds=$subnet_id_1","$subnet_id_2
      참고

      요청의 가용 영역 중 하나에 Amazon EKS 클러스터를 생성하는 데 충분한 용량이 없다는 오류가 표시될 수 있습니다. 이 경우 오류 출력에는 새 클러스터를 지원할 수 있는 가용 영역이 포함됩니다. 사용자 계정의 지원 가용 영역에 있는 2개 이상의 서브넷을 사용하여 클러스터를 다시 생성합니다. 자세한 정보를 알아보려면 용량 부족을 참조하세요.

    2. 클러스터를 생성하는 데 몇 분 정도 걸립니다. 클러스터의 배포 상태를 확인하려면 다음 명령을 실행합니다.

      aws eks describe-cluster --name my-custom-networking-cluster --query cluster.status

      명령의 출력이 "ACTIVE"가 될 때까지 다음 단계를 계속하지 마세요.

    3. 클러스터와 통신하도록 kubectl을 구성합니다.

      aws eks update-kubeconfig --name my-custom-networking-cluster

2단계: VPC 구성

이 튜토리얼을 시작하려면 1단계: 테스트 VPC 및 클러스터 생성에서 생성된 VPC가 있어야 합니다. 프로덕션 클러스터의 경우 모든 example values을 사용자 값으로 바꿔 사용자 VPC 맞게 단계를 조정합니다.

  1. 현재 설치된 Amazon VPC CNI plugin for Kubernetes이(가) 최신 버전인지 확인하세요. Amazon EKS 추가 기능 유형의 최신 버전을 확인하고 사용 중인 버전을 이 버전으로 업데이트하려면 추가 기능 업데이트 부분을 참조하세요. 자체 관리형 추가 기능 유형의 최신 버전을 확인하고 사용 중인 버전을 이 버전으로 업데이트하려면 Amazon VPC CNI plugin for Kubernetes Amazon EKS 추가 기능을 사용한 작업 부분을 참조하세요.

  2. 클러스터 VPC ID를 검색하여 이후 단계에서 사용할 수 있도록 변수에 저장합니다. 프로덕션 클러스터의 경우 my-custom-networking-cluster를 클러스터의 이름으로 바꿉니다.

    vpc_id=$(aws eks describe-cluster --name my-custom-networking-cluster --query "cluster.resourcesVpcConfig.vpcId" --output text)
  3. 추가 Classless Inter-Domain Routing(CIDR) 블록을 클러스터의 VPC 연결합니다. CIDR 블록은 기존에 연결된 모든 CIDR 블록과 겹칠 수 없습니다.

    1. VPC에 연결된 현재 CIDR 블록을 봅니다.

      aws ec2 describe-vpcs --vpc-ids $vpc_id \ --query 'Vpcs[*].CidrBlockAssociationSet[*].{CIDRBlock: CidrBlock, State: CidrBlockState.State}' --out table

      예제 출력은 다음과 같습니다.

      ----------------------------------
      |          DescribeVpcs          |
      +-----------------+--------------+
      |    CIDRBlock    |    State     |
      +-----------------+--------------+
      |  192.168.0.0/24 |  associated  |
      +-----------------+--------------+
    2. 추가 CIDR 블록을 VPC에 연결합니다. 자세한 내용을 알아보려면 Amazon VPC 사용 설명서의 추가 IPv4 CIDR 블록을 VPC와 연결을 참조하세요.

      aws ec2 associate-vpc-cidr-block --vpc-id $vpc_id --cidr-block 192.168.1.0/24
    3. 새 블록이 연결되어 있는지 확인합니다.

      aws ec2 describe-vpcs --vpc-ids $vpc_id --query 'Vpcs[*].CidrBlockAssociationSet[*].{CIDRBlock: CidrBlock, State: CidrBlockState.State}' --out table

      예제 출력은 다음과 같습니다.

      ----------------------------------
      |          DescribeVpcs          |
      +-----------------+--------------+
      |    CIDRBlock    |    State     |
      +-----------------+--------------+
      |  192.168.0.0/24 |  associated  |
      |  192.168.1.0/24 |  associated  |
      +-----------------+--------------+

    새 CIDR 블록의 Stateassociated가 될 때까지 다음 단계를 진행하지 마세요.

  4. 기존 서브넷이 있는 각 가용 영역에서 사용하려는 만큼 서브넷을 생성합니다. 이전 단계에서 VPC와 연결한 CIDR 블록 내에 있는 CIDR 블록을 지정합니다.

    1. 새 서브넷을 생성합니다. 서브넷은 기존 서브넷이 있는 것과 다른 VPC CIDR 블록에서 생성되어야 하지만 기존 서브넷과 동일한 가용 영역에서 생성되어야 합니다. 이 예제에서는 하나의 서브넷이 현재 프라이빗 서브넷이 존재하는 각 가용 영역의 새 CIDR 블록에서 생성됩니다. 생성된 서브넷의 ID는 이후 단계에서 사용할 수 있도록 변수에 저장됩니다. Name 값은 이전 단계에서 Amazon EKS VPC 템플릿을 사용하여 생성된 서브넷에 할당된 값과 일치합니다. 이름은 필요하지 않습니다. 다른 이름을 사용할 수 있습니다.

      new_subnet_id_1=$(aws ec2 create-subnet --vpc-id $vpc_id --availability-zone $az_1 --cidr-block 192.168.1.0/27 \ --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=my-eks-custom-networking-vpc-PrivateSubnet01},{Key=kubernetes.io/role/internal-elb,Value=1}]' \ --query Subnet.SubnetId --output text) new_subnet_id_2=$(aws ec2 create-subnet --vpc-id $vpc_id --availability-zone $az_2 --cidr-block 192.168.1.32/27 \ --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=my-eks-custom-networking-vpc-PrivateSubnet02},{Key=kubernetes.io/role/internal-elb,Value=1}]' \ --query Subnet.SubnetId --output text)
      중요

      기본적으로 새로운 서브넷은 VPC의 기본 라우팅 테이블과 암시적으로 연결됩니다. 이 라우팅 테이블을 사용하면 VPC 배포된 모든 리소스 간에 통신할 수 있습니다. 그러나 VPC와 연결된 CIDR 블록 외부에 있는 IP 주소를 보유한 리소스와는 통신할 수 없습니다. 자체 라우팅 테이블을 서브넷에 연결하여 이 동작을 변경할 수 있습니다. 자세한 내용을 알아보려면 Amazon VPC 사용 설명서의 서브넷 라우팅 테이블을 참조하세요.

    2. VPC에서 현재 서브넷을 확인합니다.

      aws ec2 describe-subnets --filters "Name=vpc-id,Values=$vpc_id" \ --query 'Subnets[*].{SubnetId: SubnetId,AvailabilityZone: AvailabilityZone,CidrBlock: CidrBlock}' \ --output table

      예제 출력은 다음과 같습니다.

      ----------------------------------------------------------------------
      |                           DescribeSubnets                          |
      +------------------+--------------------+----------------------------+
      | AvailabilityZone |     CidrBlock      |         SubnetId           |
      +------------------+--------------------+----------------------------+
      |  us-west-2d      |  192.168.0.0/27    |     subnet-example1        |
      |  us-west-2a      |  192.168.0.32/27   |     subnet-example2        |
      |  us-west-2a      |  192.168.0.64/27   |     subnet-example3        |
      |  us-west-2d      |  192.168.0.96/27   |     subnet-example4        |
      |  us-west-2a      |  192.168.1.0/27    |     subnet-example5        |
      |  us-west-2d      |  192.168.1.32/27   |     subnet-example6        |
      +------------------+--------------------+----------------------------+

      생성한 192.168.1.0 CIDR 블록의 서브넷이 192.168.0.0 CIDR 블록의 서브넷과 동일한 가용 영역에 있는지 확인할 수 있습니다.

3단계: Kubernetes 리소스 구성

Kubernetes 리소스를 구성하려면 다음을 수행합니다.
  1. AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG 환경 변수를 aws-node DaemonSettrue로 설정합니다.

    kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true
  2. 클러스터 보안 그룹의 ID를 검색하여 이후 단계에서 사용할 수 있도록 변수에 저장합니다. Amazon EKS는 클러스터를 생성하는 경우 이 보안 그룹을 자동으로 생성합니다.

    cluster_security_group_id=$(aws eks describe-cluster --name $cluster_name --query cluster.resourcesVpcConfig.clusterSecurityGroupId --output text)
  3. Pods를 배포하려는 각 서브넷에 대해 ENIConfig 사용자 지정 리소스를 생성합니다.

    1. 각 네트워크 인터페이스 구성에 대해 고유한 파일을 생성합니다.

      다음 명령은 이전 단계에서 생성된 두 서브넷용 ENIConfig 파일을 별도로 생성합니다. name의 값은 고유해야 합니다. 이름은 서브넷이 있는 가용 영역과 동일합니다. 클러스터 보안 그룹은 ENIConfig에 할당됩니다.

      cat >$az_1.yaml <<EOF apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: $az_1 spec: securityGroups: - $cluster_security_group_id subnet: $new_subnet_id_1 EOF
      cat >$az_2.yaml <<EOF apiVersion: crd.k8s.amazonaws.com/v1alpha1 kind: ENIConfig metadata: name: $az_2 spec: securityGroups: - $cluster_security_group_id subnet: $new_subnet_id_2 EOF

      프로덕션 클러스터의 경우 이전 명령을 다음과 같이 변경할 수 있습니다.

      • $cluster_security_group_id를 각 ENIConfig에 대해 사용하려는 기존 보안 그룹 ID로 바꿉니다.

      • 가능하면 ENIConfig를 사용할 가용 영역과 동일하게 ENIConfigs의 이름을 지정하는 것이 좋습니다. 여러 이유로 가용 영역의 이름과 다른 ENIConfigs의 이름을 사용해야 할 수 있습니다. 예를 들어 동일한 가용 영역에 두 개 이상의 서브넷이 있고 사용자 지정 네트워킹에서 둘 다 사용하려는 경우 동일한 가용 영역에 대한 여러 ENIConfigs가 필요합니다. 각 ENIConfig는 고유한 이름이 필요하므로 가용 영역 이름을 사용하여 ENIConfigs에 두 개 이상의 이름을 지정할 수 없습니다.

        ENIConfig 이름이 모두 가용 영역 이름과 동일하지 않은 경우 $az_1$az_2를 이전 명령의 사용자 자신의 이름으로 바꾸고 이 자습서의 뒷부분에서 ENIConfig를 사용하여 노드에 주석을 답니다.

      참고

      프로덕션 클러스터에서 사용할 유효한 보안 그룹을 지정하지 않고 다음을 사용하는 경우,

      • Amazon VPC CNI plugin for Kubernetes의 버전 1.8.0 이상을 사용하는 경우 노드의 기본 Elastic 네트워크 인터페이스와 연결된 보안 그룹이 사용됩니다.

      • 1.8.0 이전 버전의 Amazon VPC CNI plugin for Kubernetes를 사용하는 경우 VPC의 기본 보안 그룹이 보조 Elastic 네트워크 인터페이스에 할당됩니다.

      중요
      • AWS_VPC_K8S_CNI_EXTERNALSNAT=false는 Kubernetes용 Amazon VPC CNI 플러그인 구성의 기본 설정입니다. 기본 설정을 사용하는 경우 VPC와 연결된 CIDR 블록 중 하나에 있지 않은 IP 주소로 향하는 트래픽은 노드의 기본 네트워크 인터페이스의 보안 그룹 및 서브넷을 사용합니다. 보조 네트워크 인터페이스를 생성하는 데 사용된 ENIConfigs에서 정의된 서브넷 및 보안 그룹은 이 트래픽에는 사용되지 않습니다. 이 설정에 대한 자세한 내용을 알아보려면 Pods용 SNAT 섹션을 참조하세요.

      • Pods의 보안 그룹도 사용하는 경우 SecurityGroupPolicy에서 지정된 보안 그룹이 ENIConfigs에서 지정된 보안 그룹 대신 사용됩니다. 자세한 정보를 알아보려면 Pods의 보안 그룹을 참조하세요.

    2. 다음 명령을 사용하여 생성된 각 사용자 지정 리소스 파일을 클러스터에 적용합니다.

      kubectl apply -f $az_1.yaml kubectl apply -f $az_2.yaml
  4. ENIConfigs가 생성되었는지 확인합니다.

    kubectl get ENIConfigs

    예제 출력은 다음과 같습니다.

    NAME AGE us-west-2a 117s us-west-2d 105s
  5. 프로덕션 클러스터에서 사용자 지정 네트워킹을 사용 설정하고 사용 중인 가용 영역 이외의 것으로 ENIConfigs의 이름을 지정한 경우 다음 단계로 이동하여 Amazon EC2 노드를 배포합니다.

    Kubernetes가 클러스터에 생성된 모든 새로운 Amazon EC2 노드에 가용 영역의 ENIConfig를 자동으로 적용할 수 있습니다.

    1. 이 튜토리얼의 테스트 클러스터의 경우 다음 단계로 이동합니다.

      프로덕션 클러스터의 경우 ENI_CONFIG_ANNOTATION_DEF 환경 변수에 대한 키 k8s.amazonaws.com/eniConfig가 포함된 annotation이 aws-node DaemonSet의 컨테이너 사양에 있는지 확인합니다.

      kubectl describe daemonset aws-node -n kube-system | grep ENI_CONFIG_ANNOTATION_DEF

      출력이 반환되는 경우 주석이 존재합니다. 출력이 반환되지 않으면 변수가 설정되지 않은 것입니다. 프로덕션 클러스터의 경우 이 설정이나 다음 단계의 설정 중 하나를 사용할 수 있습니다. 이 설정을 사용하는 경우 다음 단계의 설정을 재정의합니다. 이 튜토리얼에서는 다음 단계의 설정이 사용됩니다.

    2. aws-node DaemonSet를 업데이트하여 클러스터에 생성된 모든 새로운 Amazon EC2 노드에 가용 영역의 ENIConfig를 자동으로 적용합니다.

      kubectl set env daemonset aws-node -n kube-system ENI_CONFIG_LABEL_DEF=topology.kubernetes.io/zone

4단계: Amazon EC2 노드 배포

Amazon EC2 노드 배포
  1. 노드 IAM 역할을 생성합니다.

    1. 다음 명령을 실행하여 IAM 신뢰 정책 JSON 파일을 생성합니다.

      cat >node-role-trust-relationship.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOF
    2. 다음 명령을 실행하여 역할 이름에 대한 변수를 설정합니다. myCustomNetworkingAmazonEKSNodeRole을 선택한 모든 이름으로 바꿀 수 있습니다.

      export node_role_name=myCustomNetworkingAmazonEKSNodeRole
    3. IAM 역할을 생성하고 이후 단계에서 사용할 수 있도록 반환된 Amazon 리소스 이름(ARN)을 변수에 저장합니다.

      node_role_arn=$(aws iam create-role --role-name $node_role_name --assume-role-policy-document file://"node-role-trust-relationship.json" \ --query Role.Arn --output text)
    4. 필요한 3개의 IAM 관리형 정책을 IAM 역할에 연결합니다.

      aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy \ --role-name $node_role_name aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \ --role-name $node_role_name aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy \ --role-name $node_role_name
      중요

      이 튜토리얼에서는 단순화를 위해 노드 IAM 역할에 AmazonEKS_CNI_Policy 정책이 연결되어 있습니다. 그러나 프로덕션 클러스터에서는 정책을 Amazon VPC CNI plugin for Kubernetes에서만 사용되는 별도의 IAM 역할에 연결하는 것이 좋습니다. 자세한 정보를 알아보려면 서비스 계정용 IAM 역할(IRSA)을 사용하도록 Amazon VPC CNI plugin for Kubernetes 구성을 참조하세요.

  2. 다음 노드 그룹 유형 중 하나를 생성합니다. 배포할 인스턴스 유형을 확인하려면 Amazon EC2 인스턴스 유형 선택 섹션을 참조하세요. 이 자습서에서는 관리형(Managed), 시작 템플릿을 사용하지 않거나 AMI ID가 지정되지 않은 시작 템플릿을 사용하는 경우(Without a launch template or with a launch template without an AMI ID specified)의 옵션을 완료합니다. 프로덕션 워크로드의 노드 그룹을 사용하려는 경우 노드 그룹을 배포하기 전에 관리형자체 관리형 노드 그룹 옵션을 모두 숙지하는 것이 좋습니다.

    • 관리형(Managed) - 다음 옵션 중 하나를 사용하여 노드 그룹을 배포합니다.

      • 시작 템플릿을 사용하지 않거나 AMI ID가 지정되지 않은 시작 템플릿을 사용하는 경우(Without a launch template or with a launch template without an AMI ID specified) - 다음 명령을 실행합니다. 본 튜토리얼에서는 example values를 사용합니다. 프로덕션 노드 그룹의 경우 모든 example values을 사용자의 것으로 바꿉니다. 노드 그룹 이름은 63자를 초과할 수 없습니다. 문자나 숫자로 시작하되, 나머지 문자의 경우 하이픈과 밑줄을 포함할 수 있습니다.

        aws eks create-nodegroup --cluster-name $cluster_name --nodegroup-name my-nodegroup \ --subnets $subnet_id_1 $subnet_id_2 --instance-types t3.medium --node-role $node_role_arn
      • AMI ID가 지정된 시작 템플릿을 사용하는 경우(With a launch template with a specified AMI ID)

        1. Amazon EKS 권장 노드의 최대 Pods 수를 확인합니다. 각 Amazon EC2 인스턴스 유형의 Amazon EKS 권장 최대 Pods 수의 지침을 따라 해당 주제의 3단계에 --cni-custom-networking-enabled를 추가하세요. 다음 단계에서 사용할 수 있도록 출력을 적어 둡니다.

        2. 시작 템플릿에서 Amazon EKS 최적화 AMI ID 또는 Amazon EKS 최적화 AMI에서 빌드한 사용자 지정 AMI를 지정한 다음 시작 템플릿을 사용하여 노드 그룹 배포를 지정하고 시작 템플릿에 다음 사용자 데이터를 입력합니다. 이 사용자 데이터는 인수를 bootstrap.sh 파일에 전달합니다. 부트스트랩 파일에 대한 자세한 내용은 GitHub에서 bootstrap.sh 섹션을 참조하세요. 20을 이전 단계의 값(권장) 또는 고유한 값으로 바꿉니다.

          /etc/eks/bootstrap.sh my-cluster --use-max-pods false --kubelet-extra-args '--max-pods=20'

          Amazon EKS 최적화 AMI에서 빌드되지 않은 사용자 지정 AMI를 생성한 경우 직접 구성을 사용자 지정하여 생성해야 합니다.

    • 자체 관리형(Self-managed)

      1. Amazon EKS 권장 노드의 최대 Pods 수를 확인합니다. 각 Amazon EC2 인스턴스 유형의 Amazon EKS 권장 최대 Pods 수의 지침을 따라 해당 주제의 3단계에 --cni-custom-networking-enabled를 추가하세요. 다음 단계에서 사용할 수 있도록 출력을 적어 둡니다.

      2. 자체 관리형 Amazon Linux 노드 시작하기의 지침에 따라 노드 그룹을 배포합니다. BootstrapArguments 파라미터에 다음 텍스트를 지정합니다. 20을 이전 단계의 값(권장) 또는 고유한 값으로 바꿉니다.

        --use-max-pods false --kubelet-extra-args '--max-pods=20'
    참고

    프로덕션 클러스터의 노드가 훨씬 더 많은 수의 Pods를 지원하도록 하려는 경우 다시 각 Amazon EC2 인스턴스 유형의 Amazon EKS 권장 최대 Pods 수에서 스크립트를 실행합니다. 또한 --cni-prefix-delegation-enabled 옵션을 명령에 추가합니다. 예를 들어 m5.large 인스턴스 유형에 대해 110이 반환됩니다. 이 기능을 사용 설정하는 방법에 대한 지침은 Amazon EC2 노드에 사용 가능한 IP 주소 증량 부분을 참조하세요. 사용자 지정 네트워킹에서 이 기능을 사용할 수 있습니다.

    노드 그룹을 생성하는 데 몇 분 정도 걸립니다. 다음 명령을 사용하여 관리형 노드 그룹의 생성 상태를 확인할 수 있습니다.

    aws eks describe-nodegroup --cluster-name $cluster_name --nodegroup-name my-nodegroup --query nodegroup.status --output text

    반환되는 출력이 ACTIVE가 될 때까지 다음 단계를 진행하지 마세요.

  3. 튜토리얼에서는 이 단계를 건너뛸 수 있습니다.

    프로덕션 클러스터의 경우 사용 중인 가용 영역과 동일하게 ENIConfigs의 이름을 지정하지 않은 경우 노드에서 사용해야 하는 ENIConfig 이름으로 해당 노드에 주석을 달아야 합니다. 각 가용 영역에 서브넷이 하나만 있고 가용 영역과 동일한 이름으로 ENIConfigs의 이름을 지정한 경우에는 이 단계가 필요하지 않습니다. 이는 Amazon VPC CNI plugin for Kubernetes가 이전 단계에서 그렇게 하도록 사용 설정한 경우 사용자 노드와 올바른 ENIConfig을 자동으로 연결하기 때문입니다.

    1. 클러스터의 노드 목록을 가져옵니다.

      kubectl get nodes

      예제 출력은 다음과 같습니다.

      NAME STATUS ROLES AGE VERSION ip-192-168-0-126.us-west-2.compute.internal Ready <none> 8m49s v1.22.9-eks-810597c ip-192-168-0-92.us-west-2.compute.internal Ready <none> 8m34s v1.22.9-eks-810597c
    2. 각 노드가 있는 가용 영역을 확인합니다. 이전 단계에서 반환된 각 노드에 대한 다음 명령을 실행합니다.

      aws ec2 describe-instances --filters Name=network-interface.private-dns-name,Values=ip-192-168-0-126.us-west-2.compute.internal \ --query 'Reservations[].Instances[].{AvailabilityZone: Placement.AvailabilityZone, SubnetId: SubnetId}'

      예제 출력은 다음과 같습니다.

      [ { "AvailabilityZone": "us-west-2d", "SubnetId": "subnet-Example5" } ]
    3. 각 노드에 서브넷 ID 및 가용 영역에 대해 생성한 ENIConfig로 주석을 답니다. 여러 노드에 동일한 ENIConfig로 주석을 달 수 있지만, 노드에는 하나의 ENIConfig로만 주석을 달 수 있습니다. example values을 사용자의 값으로 교체합니다.

      kubectl annotate node ip-192-168-0-126.us-west-2.compute.internal k8s.amazonaws.com/eniConfig=EniConfigName1 kubectl annotate node ip-192-168-0-92.us-west-2.compute.internal k8s.amazonaws.com/eniConfig=EniConfigName2
  4. 사용자 지정 네트워킹 기능 사용으로 전환하기 전에 프로덕션 클러스터에 Pods를 실행 중인 노드가 있는 경우 다음 작업을 완료해야 합니다.

    1. 사용자 지정 네트워킹 기능을 사용하는 사용 가능한 노드가 있는지 확인합니다.

    2. 노드를 차단하고 드레이닝하여 Pods를 정상적으로 종료합니다. 자세한 내용을 알아보려면 Kubernetes 설명서의 안전한 노드 드레이닝을 참조하세요.

    3. 노드를 종료합니다. 노드가 기존 관리형 노드 그룹에 있는 경우 노드 그룹을 삭제할 수 있습니다. 다음 명령을 디바이스에 복사합니다. 필요에 따라 명령을 다음과 같이 수정한 다음에 수정한 명령을 실행합니다.

      • my-cluster를 클러스터 이름으로 변경합니다.

      • my-nodegroup을 노드 그룹의 이름으로 변경합니다.

      aws eks delete-nodegroup --cluster-name my-cluster --nodegroup-name my-nodegroup

    k8s.amazonaws.com/eniConfig 레이블에 등록된 새 노드만 사용자 지정 네트워킹 기능을 사용합니다.

  5. Pods가 이전 단계에서 생성한 서브넷 중 하나에 연결된 CIDR 블록의 IP 주소를 할당하는지 확인합니다.

    kubectl get pods -A -o wide

    예제 출력은 다음과 같습니다.

    NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kube-system aws-node-2rkn4 1/1 Running 0 7m19s 192.168.0.92 ip-192-168-0-92.us-west-2.compute.internal <none> <none> kube-system aws-node-k96wp 1/1 Running 0 7m15s 192.168.0.126 ip-192-168-0-126.us-west-2.compute.internal <none> <none> kube-system coredns-657694c6f4-smcgr 1/1 Running 0 56m 192.168.1.23 ip-192-168-0-92.us-west-2.compute.internal <none> <none> kube-system coredns-657694c6f4-stwv9 1/1 Running 0 56m 192.168.1.28 ip-192-168-0-92.us-west-2.compute.internal <none> <none> kube-system kube-proxy-jgshq 1/1 Running 0 7m19s 192.168.0.92 ip-192-168-0-92.us-west-2.compute.internal <none> <none> kube-system kube-proxy-wx9vk 1/1 Running 0 7m15s 192.168.0.126 ip-192-168-0-126.us-west-2.compute.internal <none> <none>

    coredns Pods에 VPC 추가한 192.168.1.0 CIDR 블록의 IP 주소가 할당되는지 볼 수 있습니다. 사용자 지정 네트워킹을 사용하지 않는 경우 원래 CIDR 블록만 VPC와 연결되기 때문에 192.168.0.0 CIDR 블록의 주소가 할당되었을 것입니다.

    Pod's spechostNetwork=true를 포함하는 경우 노드의 기본 IP 주소가 할당됩니다. 추가한 서브넷의 주소는 할당되지 않습니다. 기본적으로 이 값은 false로 설정됩니다. 이 값은 클러스터에서 실행되는 kube-proxy 및 Amazon VPC CNI plugin for Kubernetes(aws-node) Pods에 대해 true로 설정됩니다. 따라서 kube-proxy 및 플러그인의 aws-node Pods에 이전 출력의 192.168.1.x 주소가 할당되지 않습니다. Pod's hostNetwork 설정에 대한 자세한 내용을 알아보려면 Kubernetes API 참조에서 PodSpec v1 코어를 참조하세요.

5단계: 튜토리얼 리소스 삭제

튜토리얼을 완료하면 생성한 리소스를 삭제하는 것이 좋습니다. 그런 다음 단계를 조정하여 프로덕션 클러스터에 대해 사용자 지정 네트워킹을 사용 설정할 수 있습니다.

튜토리얼 리소스 삭제
  1. 생성한 노드 그룹이 테스트용일 경우 삭제하세요.

    aws eks delete-nodegroup --cluster-name $cluster_name --nodegroup-name my-nodegroup

    AWS CLI 출력에 클러스터가 삭제되었다고 표시된 이후에도 삭제 프로세스는 실제로 완료되지 않을 수 있습니다. 삭제 프로세스는 몇 분 정도 걸릴 수 있습니다. 다음 명령을 실행하여 완료되었는지 확인합니다.

    aws eks describe-nodegroup --cluster-name $cluster_name --nodegroup-name my-nodegroup --query nodegroup.status --output text

    반환된 출력이 다음 출력과 비슷하게 될 때까지 진행하지 마세요.

    An error occurred (ResourceNotFoundException) when calling the DescribeNodegroup operation: No node group found for name: my-nodegroup.
  2. 생성한 노드 그룹이 테스트용일 경우 노드 IAM 역할을 삭제하세요.

    1. 역할에서 정책을 분리합니다.

      aws iam detach-role-policy --role-name myCustomNetworkingAmazonEKSNodeRole --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy aws iam detach-role-policy --role-name myCustomNetworkingAmazonEKSNodeRole --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly aws iam detach-role-policy --role-name myCustomNetworkingAmazonEKSNodeRole --policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
    2. 역할을 삭제합니다.

      aws iam delete-role --role-name myCustomNetworkingAmazonEKSNodeRole
  3. 클러스터를 삭제하세요.

    aws eks delete-cluster --name $cluster_name

    다음 명령을 사용하여 클러스터가 삭제되었는지 확인합니다.

    aws eks describe-cluster --name $cluster_name --query cluster.status --output text

    다음과 비슷한 출력이 반환되면 클러스터가 성공적으로 삭제됩니다.

    An error occurred (ResourceNotFoundException) when calling the DescribeCluster operation: No cluster found for name: my-cluster.
  4. 클러스터 IAM 역할을 삭제합니다.

    1. 역할에서 정책을 분리합니다.

      aws iam detach-role-policy --role-name myCustomNetworkingAmazonEKSClusterRole --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
    2. 역할을 삭제합니다.

      aws iam delete-role --role-name myCustomNetworkingAmazonEKSClusterRole
  5. 이전 단계에서 생성한 서브넷을 삭제합니다.

    aws ec2 delete-subnet --subnet-id $new_subnet_id_1 aws ec2 delete-subnet --subnet-id $new_subnet_id_2
  6. 생성한 VPC를 삭제합니다.

    aws cloudformation delete-stack --stack-name my-eks-custom-networking-vpc