Amazon EKS에서 여러 CIDR 범위를 사용하려면 어떻게 해야 하나요?

최종 업데이트 날짜: 2021년 7월 28일

Amazon Elastic Kubernetes Service(Amazon EKS)에서 여러 CIDR 범위를 사용하여 포드 관련 문제를 해결하려고 합니다. 예를 들어 Amazon Virtual Private Cloud(Amazon VPC)에 다른 CIDR 범위가 추가된 포드를 실행하려면 어떻게 해야 합니까? 또한 서브넷에 IP 주소가 부족할 때 서브넷에 IP 주소를 추가하려면 어떻게 해야 합니까? 마지막으로 작업자 노드에서 실행되는 포드의 IP 범위가 서로 다른지 확인하려면 어떻게 해야 합니까?

간략한 설명

문제 해결 섹션의 단계를 완료하기 전에 다음 항목이 있는지 확인합니다.

  • 실행 중인 Amazon EKS 클러스터
  • AWS 명령줄 인터페이스(AWS CLI)의 버전(1.16.284 이전)에 액세스
  • Amazon VPC를 관리하기 위한 AWS Identity and Access Management(IAM) 권한
  • 사용자 지정 리소스를 생성하고 DaemonsSet를 편집할 수 있는 권한이 있는 kubectl
  • 시스템에 설치된 jq 웹 사이트의 jq 버전
  • Bash 셸을 사용하는 Unix 기반 시스템

다음 사항에 유의하세요.

  • 다른 CIDR 범위에서 포드를 실행할 경우 Amazon EKS에서 관리하는 포드에 대해 더 많은 IP 주소를 사용할 수 있습니다. 또한 네트워킹 아키텍처의 유연성을 개선할 수 있습니다. 포드는 두 가지 조건에서 VPC의 RFC 1918 IP 주소를 사용하지 않습니다. 첫 번째 조건은 100.64.0.0/10198.19.0.0/16 범위에서 VPC에 보조 CIDR 블록을 추가하는 것입니다. 두 번째 조건은 CNI 사용자 지정 네트워킹을 사용하는 것입니다.
  • 통신사급 네트워크 주소 변환(NAT)을 사용하는 시나리오에서 100.64.0.0/10은 프라이빗 네트워크 범위입니다. 이 프라이빗 네트워크 범위는 서비스 공급자와 가입자 간의 통신을 위한 공유 주소 공간에서 사용됩니다. 포드가 인터넷과 통신하려면 라우팅 테이블에 NAT 게이트웨이가 구성되어 있어야 합니다. Daemonsets는 AWS Fargate 클러스터에서 지원되지 않습니다. Fargate 프로파일에 보조 CIDR 범위를 추가하려면 VPC의 보조 CIDR 블록의 서브넷을 사용합니다. 그런 다음 Fargate 프로파일에 서브넷을 추가하기 전에 새 서브넷에 태그를 지정합니다.

중요: 특정 상황에서 Amazon EKS는 클러스터가 생성된 후 VPC에 추가된 추가 CIDR 블록에서 서브넷에서 시작된 노드와 통신할 수 없습니다. 자세한 내용은 클러스터 VPC 고려 사항의 “중요” 참고를 참조하세요.

해결 방법

참고: AWS CLI 명령을 실행할 때 오류가 발생하는 경우 최신 버전의 AWS CLI를 사용하고 있는지 확인하세요.

다음 해결 방법에서는, 우선 VPC를 설정합니다. 그런 다음, 새 CIDR 범위를 사용하도록 CNI 플러그인 구성

CIDR 범위를 추가하여 VPC 네트워크 확장

1.    VPC를 찾습니다.

VPC에 태그가 있는 경우 다음 명령을 실행하여 VPC를 찾습니다.

VPC_ID=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=yourVPCName | jq -r '.Vpcs[].VpcId')

VPC에 태그가 없는 경우 다음 명령을 실행하여 AWS 리전에 모든 VPC를 나열합니다.

aws ec2 describe-vpcs --filters  | jq -r '.Vpcs[].VpcId'

2.    VPC_ID 변수에 VPC를 연결하려면 다음 명령을 실행합니다.

export VPC_ID=vpc-xxxxxxxxxxxx

3.    VPC에 대해 100.64.0.0/16 범위의 CIDR 블록을 연결하려면 다음 명령을 실행합니다.

aws ec2 associate-vpc-cidr-block --vpc-id $VPC_ID --cidr-block 100.64.0.0/16

새 CIDR 범위를 사용하여 서브넷 생성

1.    AWS 리전의 모든 가용 영역을 나열하려면 다음 명령을 실행합니다.

aws ec2 describe-availability-zones --region us-east-1 --query 'AvailabilityZones[*].ZoneName'

참고: us-east-1을 사용자의 AWS 리전으로 바꿉니다.

2.    서브넷을 추가할 가용 영역을 선택한 다음 해당 가용 영역을 변수에 할당합니다. 예를 들면 다음과 같습니다.

export AZ1=us-east-1a
export AZ2=us-east-1b
export AZ3=us-east-1c

참고: 변수를 더 생성하여 가용 영역을 추가할 수 있습니다.

3.    VPC에서 새 CIDR 범위를 사용하여 새 서브넷을 생성하려면 다음 명령을 실행합니다.

CUST_SNET1=$(aws ec2 create-subnet --cidr-block 100.64.0.0/19 --vpc-id $VPC_ID --availability-zone $AZ1 | jq -r .Subnet.SubnetId)
CUST_SNET2=$(aws ec2 create-subnet --cidr-block 100.64.32.0/19 --vpc-id $VPC_ID --availability-zone $AZ2 | jq -r .Subnet.SubnetId)
CUST_SNET3=$(aws ec2 create-subnet --cidr-block 100.64.64.0/19 --vpc-id $VPC_ID --availability-zone $AZ3 | jq -r .Subnet.SubnetId)

새 서브넷에 태그 지정

Kubernetes 1.18 이전 버전에서 실행되는 클러스터의 경우, 모든 서브넷에 태그를 지정해야 Amazon EKS가 서브넷을 검색할 수 있습니다.

참고: Amazon EKS는 Kubernetes 버전 1.19부터는 kubernetes.io 태그 없이도 서브넷 자동 검색을 지원합니다. 자세한 내용은 Kubernetes GitHub 사이트의 변경 로그를 참조하세요.

1.    (선택 사항) 키–값 페어를 설정하여 서브넷에 이름 태그를 추가합니다. 예를 들면 다음과 같습니다.

aws ec2 create-tags --resources $CUST_SNET1 --tags Key=Name,Value=SubnetA
aws ec2 create-tags --resources $CUST_SNET2 --tags Key=Name,Value=SubnetB
aws ec2 create-tags --resources $CUST_SNET3 --tags Key=Name,Value=SubnetC

2.    Kubernetes 1.18 이하 버전에서 실행되는 클러스터의 경우, Amazon EKS에서 검색할 수 있도록 서브넷에 태그를 지정합니다. 예를 들면 다음과 같습니다.

aws ec2 create-tags --resources $CUST_SNET1 --tags Key=kubernetes.io/cluster/yourClusterName,Value=shared
aws ec2 create-tags --resources $CUST_SNET2 --tags Key=kubernetes.io/cluster/yourClusterName,Value=shared
aws ec2 create-tags --resources $CUST_SNET3 --tags Key=kubernetes.io/cluster/yourClusterName,Value=shared

참고: yourClusterName을 Amazon EKS 클러스터 이름으로 바꾸세요.

팁: Elastic Load Balancing을 사용하려 하는 경우, 추가 태그를 더하는 것이 좋습니다.

새 서브넷을 라우팅 테이블에 연결

1.    VPC에서 전체 라우팅 테이블을 나열하려면 다음 명령을 실행합니다.

aws ec2 describe-route-tables --filters Name=vpc-id,Values=$VPC_ID |jq -r '.RouteTables[].RouteTableId'

2.    서브넷과 연결하려는 라우팅 테이블에 대해 다음 명령을 실행하여 변수로 내보냅니다. 그런 다음 rtb-xxxxxxxxx를 1단계의 값으로 바꿉니다.

export RTASSOC_ID=rtb-xxxxxxxxx

3.    라우팅 테이블을 모든 새 서브넷에 연결합니다. 예를 들면 다음과 같습니다.

aws ec2 associate-route-table --route-table-id $RTASSOC_ID --subnet-id $CUST_SNET1
aws ec2 associate-route-table --route-table-id $RTASSOC_ID --subnet-id $CUST_SNET2
aws ec2 associate-route-table --route-table-id $RTASSOC_ID --subnet-id $CUST_SNET3

자세한 정보는 라우팅을 참조하세요.

새 CIDR 범위를 사용하도록 CNI 플러그인 구성

1.    최신 버전의 CNI 플러그인이 있는지 확인하려면 다음 명령을 실행합니다.

kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2

CNI 플러그인 버전이 1.5.3 이하인 경우 다음 명령을 실행하여 최신 버전으로 업데이트합니다.

kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/v1.5/aws-k8s-cni.yaml

2.    CNI 플러그인에 대한 사용자 지정 네트워크 구성을 활성화하려면 다음 명령을 실행합니다.

kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true

3.    작업자 노드를 식별하기 위한 ENIConfig 레이블을 추가하려면 다음 명령을 실행합니다.

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

4.    ENIConfig 사용자 지정 리소스 정의를 설치하려면(Kubernetes 웹사이트에서) 다음 명령을 실행합니다.

cat << EOF | kubectl apply -f -
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: eniconfigs.crd.k8s.amazonaws.com
spec:
  scope: Cluster
  group: crd.k8s.amazonaws.com
  version: v1alpha1
  names:
    plural: eniconfigs
    singular: eniconfig
    kind: ENIConfig
EOF

5.    모든 서브넷 및 가용 영역에 대해 ENIConfig 사용자 지정 리소스를 생성하려면 다음 명령을 실행합니다.

cat <<EOF  | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ1
spec:
  subnet: $CUST_SNET1
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ2
spec:
  subnet: $CUST_SNET2
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ3
spec:
  subnet: $CUST_SNET3
EOF

참고: ENIConfig는 작업자 노드의 가용 영역과 일치해야 합니다.

6.    새 작업자 노드를 시작한 다음, 이전 작업자 노드를 종료합니다.

참고: 6단계를 완료하면 CNI 플러그인(ipamd)이 새 작업자 노드에서 새 CIDR 범위의 IP 주소를 할당할 수 있습니다.

사용자 지정 네트워킹을 사용하는 경우 기본 네트워크 인터페이스는 포드 배치에 사용되지 않습니다. 이 시나리오에서는 우선 다음 수식을 사용하여 max-pods를 업데이트해야 합니다.

maxPods = (number of interfaces - 1) * (max IPv4 addresses per interface - 1) + 2

그런 다음 자체 관리형 노드의 사용자 데이터를 업데이트하여 사용자 데이터를 추가한 후 새로운 max-pods 값을 전달해야 합니다. BootstrapArguments 필드에 다음을 입력합니다.

--use-max-pods false --kubelet-extra-args '--max-pods=<20>'

참고: Amazon Machine Image(AMI)를 생성하려면 관리형 노드 그룹이 필요합니다.

자체 관리형 노드의 새 그룹을 생성한 경우 ENIConfig를 업데이트해야 합니다. 새 서브넷에 대해 CloudFormation 스택이 생성한 보안 그룹으로 ENIConfig를 업데이트합니다. 예를 들면 다음과 같습니다.

cat <<EOF  | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ1
spec:
  securityGroups: 
    - sg-xxxxxxxxxxxx
  subnet: $CUST_SNET1
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ2
spec:
  securityGroups: 
    - sg-xxxxxxxxxxxx
  subnet: $CUST_SNET2
EOF

cat <<EOF | kubectl apply -f -
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
 name: $AZ3
spec:
  securityGroups: 
    - sg-xxxxxxxxxxxx
  subnet: $CUST_SNET3
EOF

참고: 관리형 노드 그룹을 사용하는 경우 클러스터 보안 그룹을 업데이트하세요. sg-XXXXXXXXXXXX를 클러스터 보안 그룹으로 바꿉니다.

7.    포드를 시작하여 구성을 테스트하려면 다음 명령을 실행합니다.

kubectl run nginx --image nginx --replicas 10
kubectl get pods -o wide

이제 10개의 새 포드가 추가되고 새 CIDR 범위가 새 작업자 노드에서 예약됩니다.


이 문서가 도움이 되었나요?


결제 또는 기술 지원이 필요하세요?