본문 바로가기

Server Infra/Kubernetes

PKOS 2기 2주차 - k8s network(feat. EKS)

728x90

이번 주차는 네트워크 주차입니다.

이번에는 이전 포스팅의 연장선으로 VPC의 IP가 완전히 소모된 경우 secondary IP를 추가하여 추가 서브넷의 네트워크 대역을 활용하는 법을 포스팅 하려 합니다. 이 또한 VPC CNI의 Custom 기능으로 사용이 가능합니다.

자 우선 위와 같은 구성의 EKS Cluster가 있다고 가정해 보겠습니다. 현재 저의 VPC는 10.201.0.0/16대역입니다. EKS의 Pod는 VPC CNI에 의해 VPC IP를 직접적으로 사용합니다. 따라서 VPC의 IP가 부족해지면 더이상 Pod가 Provisioning되지 않습니다.

이때 secondary IP를 추가하면 아래와 같이 사용할 수 있습니다.

VPC에 10.64.0.0/16 대역을 추가하여 위처럼 추가 Subnet에 있는 IP를 사용할 수 있습니다. 그럼 시작하겠습니다.

우선 Test용 EKS Cluster를 배포해 보겠습니다.

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: pkos-cluster
  region: ap-northeast-2
  version: "1.25"

iam:
  withOIDC: true

addons:
  - name: vpc-cni
    version: 1.12.5
    attachPolicyARNs: #optional
      - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy

vpc:
  id: "vpc-xxxxx"
  subnets:
    private:
      # Private Subnetll
      ap-northeast-2a: { id: subnet-xxx }
      ap-northeast-2c: { id: subnet-xxx }
      

managedNodeGroups:
- name: managed-ng
  desiredCapacity: 3
  instanceType: m5.xlarge
  labels: {intent: control-apps}
  volumeSize: 100
  volumeType: gp3
  iam:
    attachPolicyARNs:
      - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
      - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
      - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
      - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
  ssh:
    enableSsm: true
  privateNetworking: true
  enableDetailedMonitoring: true

# To enable all of the control plane logs, uncomment below:
cloudWatch:
  clusterLogging:
    enableTypes: ["api","scheduler"]
    logRetentionInDays: 1

클러스터 생성시 별도로 구성한 VPC를 대상으로 할 예정입니다. 생성이 완료되면 VPC에 보조 IP를 붙여 보겠습니다.

VPC_ID=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=CT-PoC-EKS-vpc* --query 'Vpcs[].VpcId' --output text)

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

다음은 VPC에 EKS Cluster가 배치된 Node들의 AZ별로 Subnet을 생성해 주려고 합니다.

export POD_AZS=($(aws ec2 describe-instances --filters "Name=tag-key,Values=eks:cluster-name" "Name=tag-value,Values=pkos-cluster*" --query 'Reservations[*].Instances[*].[Placement.AvailabilityZone]' --output text | sort | uniq))

echo ${POD_AZS[@]}

CGNAT_SNET1=$(aws ec2 create-subnet --cidr-block 100.64.0.0/24 --vpc-id $VPC_ID --availability-zone ${POD_AZS[0]} --query 'Subnet.SubnetId' --output text)
CGNAT_SNET2=$(aws ec2 create-subnet --cidr-block 100.64.10.0/24 --vpc-id $VPC_ID --availability-zone ${POD_AZS[1]} --query 'Subnet.SubnetId' --output text)

생성이 완료되면 두개의 VPC IP에 맞게 라우팅테일블을 세팅해주어야 합니다.

다음은 VPC-CNI를 조절해 줘야 합니다

kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
amazon-k8s-cni-init:v1.12.5-eksbuild.2
amazon-k8s-cni:v1.12.5-eksbuild.2

저는 1.12.5 버전의 cni를 사용하고 있습니다. 아래와 같이 CUSTOM Network 환경 변수를 추가 해 주어야 합니다.

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

kubectl describe daemonset aws-node -n kube-system | grep -A5 Environment

Environment:
      DISABLE_TCP_EARLY_DEMUX:             false
      ENABLE_IPv6:                         false
      AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG:  true
    Mounts:
      /host/opt/cni/bin from cni-bin-dir (rw)
--
    Environment:
      ADDITIONAL_ENI_TAGS:                    {}
      ANNOTATE_POD_IP:                        false
      AWS_VPC_CNI_NODE_PORT_SUPPORT:          true
      AWS_VPC_ENI_MTU:                        9001
      AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG:     true

다음은 Node에 위해 vpc cni pod를 재실행 해 주어야 합니다. 다만 저 설정을 업데이트 하면 자동으로 다시 생성됩니다. 정상적으로 pod가 살아나면 AZ별로 ENIConfig 를 적용해 주어야 합니다.

apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
  name: ap-northeast-2a
spec:
  subnet: subnet-xxx
  securityGroups:
    - sg-xxx
---
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
  name: ap-northeast-2c
spec:
  subnet: subnet-xxx
  securityGroups:
    - sg-xxx

위와 같은 포멧으로 생성해 주면 됩니다. 그리고 각 Node별로 annotate중 AZ를 식별할 수 있는 값을 추가해야 합니다. 다만 1.21 version 이후 자동으로 topology.kubernetes.io/zone label이 자동으로 붙기 때문에 이 작업은 생략해도 됩니다.

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

자 준비가 완료 되었으니 이제 테스트를 해보겠습니다. 아래와 같이 VPC의 CIDR는 정상적으로 두개 다 붙어 있습니다.

테스트를 위해 pod를 배포해 보겠습니다. 테스트 용으로는 nginx pod를 쓰겠습니다.

kubectl create deployment nginx --image=nginx
kubectl scale --replicas=3 deployments/nginx
kubectl expose deployment/nginx --type=NodePort --port 80
kubectl get pods -o wide

NAME                    READY   STATUS    RESTARTS   AGE   IP             NODE                                               NOMINATED NODE   READINESS GATES
nginx-76d6c9b8c-7q9gm   1/1     Running   0          26s   100.64.10.85   ip-10-201-30-85.ap-northeast-2.compute.internal    <none>           <none>
nginx-76d6c9b8c-l8xwh   1/1     Running   0          27s   100.64.0.96    ip-10-201-20-73.ap-northeast-2.compute.internal    <none>           <none>
nginx-76d6c9b8c-stgmb   1/1     Running   0          26s   100.64.0.133   ip-10-201-20-178.ap-northeast-2.compute.internal   <none>           <none>

위처럼 10.201.0.0/16 대역이 아닌 100.64.0.0/16 대역이 생성되었습니다.

EKS Worker Node를 보면 위처럼 vpc의 보조 IP ENI가 붙은것을 확인 할 수도 있습니다.

ENI도 정상적으로 잘 붙었네요. 이상 VPC secondary IP를 활용한 vpc cni의 custom 기능 활용 방법 이었습니다.

728x90

'Server Infra > Kubernetes' 카테고리의 다른 글

PKOS 2기 4주차 - Argo Rollout(feat. Prometheus)  (0) 2023.04.02
PKOS 2기 3주차 - Argo Rollout(feat. EKS)  (0) 2023.03.19
PKOS 2기 1주차 - kops  (0) 2023.03.06
Chaos mesh!!  (0) 2022.11.07
EKS 쉽게 만드려고 삽질하는중  (1) 2022.09.19