새소식

AWS/EKS

[PKOS Study 2주차] Kubernetes Network ( AWS VPC CNI )

  • -

CloudNet@ 팀의 가시다님께서 Leading 하시는 PKOS 2기 Study 내용 요약

해당 Kubernetes Study 는 '24단계 실습으로 정복하는 쿠버네티스' 책을 기반으로 진행 중입니다.



이번 포스팅에서는 k8s 의 CNI 중 하나인 AWS VPC CNI 에 대해 알아보겠습니다.

 

 

1. AWS VPC CNI 소개

AWS VPC 를 사용하기 위한 Kubernetes Container Network Interface

온프레미스 환경에서 k8s 를 설치하면 기본적으로 쿠버네티스는 Calico CNI 를 사용하고 있습니다.
k8s 의 Calico CNI 는 노드의 IP 대역과 Pod의 IP 대역이 다른 Overlay Network 의 형태를 취하고 있습니다.

 

하지만 AWS 에서는 쿠버네티스 통신 최적화를 위해 Pod 에 AWS Subnet 의 IP 를 부여하는데,

이를 가능하게 해주는 것이 바로 AWS VPC CNI 입니다.

 

이미지에서 볼 수 있는 것처럼 Calico CNI 는 가상의 라우터를 한 번 더 거치기 때문에,
AWS 상에서 k8s 를 운영할 때 VPC CNI 보다 네트워크 성능이 다소 떨어질 수 있습니다.

 

VPC CNI 를 사용할 경우에 장단점은 아래와 같습니다.

 

장점
  1. AWS에 최적화된 네트워크
  2. AWS VPC Flow Logs, 라우팅 정책, 보안 그룹 등의 AWS VPC 서비스 사용 가능

 

단점
  1. Pod 1개당 Subnet IP 를 잡아먹기 때문에, IP 부족현상 발생
  2. Node 의 최대 IP 개수에 따른 Pod 배포 제한 발생

 

이제 AWS VPC CNI 의 동작 원리와 VPC CNI 의 단점인 Pod 개수 제한을 회피할 수 있는 방법에 대해서 알아보겠습니다.

실습을 위한 EKS 아키텍처 구성이며 비용과 시간 절감을 위해 EKS가 아닌 Kops 로 실습을 진행하였습니다.



2. AWS VPC CNI 실습

AWS VPC CNI 는 aws-node 라는 이름의 pod가 Daemonset 형태로 각 노드마다 배포되어 있습니다.

 

2.1. AWS VPC CNI 정보 확인

  • 먼저 Node 에 대한 정보를 확인합니다.
kubectl get nodes -o wide

 

  • 이후 aws-node Pod 가 어떻게 배포되어 있는지 확인해봅니다.
kubectl get pods -A -o wide | grep -i -e "aws-node" -e "name"

 

Node 에 1개씩 배포되어 있는 것을 확인할 수 있습니다.

 

  • 좀 더 자세히 확인하기 위해 daemonset 을 확인해봅시다.
kubectl describe daemonsets.apps aws-node -n kube-system

 

많은 정보들이 있지만 그 중에도 빨간 상자 안의 부분은 AWS VPC CNI 가 가지고 있는 기능에 대한 부분입니다.



2.2. AWS VPC CNI 의 Pod IP 부여

AWS VPC CNI 는 Pod 에 Subnet IP 를 부여한다고 하였습니다.
실제로 그렇게 작동하는 지 확인해봅시다.

 

테스트를 위해 Pod 를 배포합니다.

cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netshoot-pod
spec:
  replicas: 2
  selector:
    matchLabels:
      app: netshoot-pod
  template:
    metadata:
      labels:
        app: netshoot-pod
    spec:
      containers:
      - name: netshoot-pod
        image: nicolaka/netshoot
        command: ["tail"]
        args: ["-f", "/dev/null"]
      terminationGracePeriodSeconds: 0
EOF

 

kubectl get pods -o wide

 

실제 Subnet 대역에 속한 IP 를 가지는 것을 확인할 수 있습니다.



2.3. Pod 간 통신

  • AWS VPC CNI 를 사용했을 때, 서로 다른 노드에 있는 Pod 들은 어떻게 통신이 될까요??

VPC IP 대역을 할당받았으니 Direct 로 통신할 지 , Node 의 IP 를 가지고 통신할 지 한 번 테스트 해봅시다.

 

  • Pod 에서 다른 Pod 로 Ping 테스트를 진행합니다.
kubectl exec -it netshoot-pod-7757d5dd99-57nzf -- ping -c 2 172.30.53.115

 

Pod 에서 tcpdump 로 확인 결과, Pod IP 간 Direct 통신을 확인할 수 있습니다.



2.4. Pod 의 외부 통신

  • 그럼 Pod 에서 외부로 통신할 때는 어떤 IP 를 가지고 통신할까요??

 

  • Pod 에서 외부 사이트로 연결해봅니다.
kubectl exec -it netshoot-pod-7757d5dd99-57nzf -- ping -c 1 www.google.com

 

Pod 내부 tcpdump

 

Pod 간 통신과는 다르게 중간 IP 를 거쳐서 통신을 한다.

해당 IP 는 Pod 가 배포된 노드의 IP 인 것을 확인할 수 있습니다.

 

  • Pod가 외부와 통신할 때의 공인 IP 를 확인해봅시다.
kubectl exec -it netshoot-pod-7757d5dd99-57nzf -- curl -s ipinfo.io/ip ; echo

 

해당 IP 는 노드의 공인 IP 임을 확인할 수 있습니다.
만약 Private Subnet 에 배포된 노드라면 NAT IP 를 사용한다는 것을 알 수 있습니다.



3. VPC CNI 의 Pod 제한

VPC CNI 의 특징에 의해 , EC2 인스턴스 타입별 ENI 최대 개수와 할당 가능한 최대 IP 개수에 의해 파드 개수가 결정됩니다.

 

인스턴스 타입별 최대 ENI 개수와 IP 개수는 아래 공식 문서에서 확인할 수 있습니다.

 

탄력적 네트워크 인터페이스 - Amazon Elastic Compute Cloud

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

  • Max Pod 공식은 다음과 같습니다.

( MaxENI * (IPv4addr-1) + 2 )

 

ENI 당 할당 가능한 최대 IP 개수를 곱하되, 첫 번째 IP 는 Node 의 IP 이므로, Pod 가 할당되지 않습니다.
또한 , aws-node 와 kube-proxy Pod 는 host-networking 을 사용하므로 별도의 VPC IP 가 필요하지 않아 2개를 더해주게 됩니다.

 

 

4. VPC CNI Pod 제한 해결

VPC CNI Pod 제한을 해결할 수 있는 방안으로는 Prefix Delegation, WARM & MIN IP/Prefix Target , Custom Network 등이 있습니다.

 

4.1. Prefix Delegation

  • AWS Docs
 

Amazon EC2 노드에 사용 가능한 IP 주소의 양 늘리기 - Amazon EKS

관리형 노드 그룹은 maxPods의 값에 최대 수를 적용합니다. vCPU가 30개 미만인 인스턴스의 경우 최대 수는 110이고 다른 모든 인스턴스의 경우 최대 수는 250입니다. 이 최대 수는 접두사 위임의 활성

docs.aws.amazon.com

 

EC2 인스턴스의 ENI Prefix 할당 모드를 통해 더 많고 탄력적인 IP 를 가질 수 있게 되었습니다.
이 기능은 AWS Nitro 기반의 EC2 인스턴스 유형일 경우에만 사용 가능합니다.

 

접두사 할당모드를 활성화 시키기 위해서는 앞서 우리가 보았던 AWS Node 의 옵션 중 ENABLE_PREFIX_DELEGATION 옵션을 활성화 시켜야 합니다.

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

 

기존의 IP 할당 방식과 다른 점은 , ENI 에 개별 Secondary IP 가 부여되지 않고 /28 의 범위의 IP 대역이 부여된다는 것입니다.

 

해당 옵션을 활성화 했다면 실제 Pod 를 여러개 배포해봅시다.

먼저, 쿠버네티스에 limitranges 정책이 걸려있는지 확인합니다.

kubectl describe limitranges

 

쿠버네티스 상에 올라오는 컨테이너의 성능을 보장하기 위해 컨테이너 당 최소 0.1CPU 를 사용하도록 보장해주는 정책입니다.
실습이니 해당 정책을 삭제합니다.

 

kubectl delete limitranges limits

 

이후 Pod 를 배포해봅시다.

cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80
EOF

 

kubectl scale deployment nginx-deployment --replicas=100

 

100개를 배포했을 때, 모두 Running 이 되는 것을 확인할 수 있습니다.

 

 


이번에는 쿠버네티스 CNI 중 AWS 환경에서 사용하는 AWS VPC CNI 에 대해서 알아보았습니다.

다음에는 AWS LoadBalancer Controller 에 대해서 알아보겠습니다.

Contents

포스팅 주소를 복사했습니다