CloudNet@ 가시다님이 진행하는 쿠버네티스 네트워크 스터디 KANS 3기 내용을 정리한 글입니다.
AWS의 EKS에는 AWS에서 제공하는 공식 CNI 플러그인이 있습니다. 바로 Amazon VPC CNI입니다. 이 플러그인은 EKS 클러스터에서 파드 네트워킹을 원활하게 지원하는 핵심 요소로, 이번 글에서는 Amazon VPC CNI의 주요 기능과 이를 EKS 환경에서 효과적으로 활용하는 방법을 살펴보겠습니다.
https://github.com/aws/amazon-vpc-cni-k8s
GitHub - aws/amazon-vpc-cni-k8s: Networking plugin repository for pod networking in Kubernetes using Elastic Network Interfaces
Networking plugin repository for pod networking in Kubernetes using Elastic Network Interfaces on AWS - aws/amazon-vpc-cni-k8s
github.com
ENI
AWS ENI(Elastic Network Interface)는 Amazon Web Services에서 제공하는 가상 네트워크 인터페이스로, VPC(Virtual Private Cloud) 내에서 네트워크 연결을 관리하고 인스턴스가 네트워크와 통신할 수 있도록 해줍니다. Amazon EKS(Elastic Kubernetes Service)에서 VPC CNI(Container Network Interface) 플러그인을 사용하는 경우, 파드들이 ENI를 통해 VPC의 IP 주소를 할당받아 네트워크 통신을 수행할 수 있습니다. 이로 인해 ENI와 연결된 파드들은 같은 VPC 내에서 통신할 수 있습니다.
L-IPAM
L-IPAM은 VPC ENI에 미리 할당된 IP(=Local-IPAM Warm IP Pool)를 사용하여 파드에 필요한 네트워크 설정을 빠르게 완료할 수 있도록 지원합니다. 이를 통해 IP 할당 속도를 개선하고, 파드 생성 시 네트워킹 설정에 걸리는 시간을 단축시킬 수 있습니다.
노드에 파드 생성 갯수 제한
어떤 인스턴스를 사용하는지에 따라 생성할 수 있는 파드의 수에 제한이 있습니다. 예를 들어, t3.medium 인스턴스는 최대 약 17개의 파드를 생성할 수 있고, m5.4xlarge는 최대 234개의 파드를 생성할 수 있습니다.
Secondary IPv4 addresses
ENI는 Primary IPv4이외에도 Secondary IPv4를 추가할 수 있습니다. 노드에 여러개의 ENI를 붙일 수 있는데 이 ENI의 Secondary IPv4를 파드에 연결하는것이 해당 방식입니다. 인스턴스 유형별로 붙일 수 있는 ENI의 수가 정해져있고 인스턴스 별로 ENI의 아이피의 수가 제한되기 때문에 인스턴스 유형을 어떤것을 사용하는지에 따라 생성할 수 있는 최대 파드의 수가 정해집니다.
[🔥정리🔥]
인스턴스 타입 별 ENI수 제한
인스턴스 타입 별 ENI의 아이피 수 제한
총 IP 수 = (각 ENI당 할당 가능한 최대 IP 수 - 1) × (인스턴스에 가능한 ENI 수)
현재 인스턴스에 붙어있는 ENI는 네트워킹 부분의 아래에 있습니다.
명령어를 사용해서도 확인가능합니다.
aws ec2 describe-instances --instance-ids <INSTANCE_ID> \
--query "Reservations[].Instances[].NetworkInterfaces[].NetworkInterfaceId"
IPv4 Prefix Delegation
AWS에서 인스턴스의 네트워크 인터페이스(ENI)에 IP 주소를 개별적으로 할당하는 대신, IP 주소 블록(prefix)을 할당하여 IP 주소 관리와 할당을 더 효율적으로 할 수 있도록 하는 기능입니다.
아래의 명령어를 통해 설정할 수 있고, Nitro System계열의 인스턴스에서만 사용가능합니다.
kubectl set env daemonset aws-node -n kube-system ENABLE_PREFIX_DELEGATION=true
AWS VPC CNI Custom Networking
노드와 파드 대역 분리, 파드에 별도 서브넷 부여 후 사용
실습용 파드 생성하기
Bastion 서버 접속하기
사전에 설정해둔 키 파일을 이용해 접속합니다.
ssh -i ~/.ssh/id_rsa ec2-user@$(aws cloudformation describe-stacks --stack-name my-eks \
--query 'Stacks[*].Outputs[0].OutputValue' --output text)
실습 용 파드 생성
다음의 명령어로 실습 파드를 생성해보겠습니다.
# 테스트용 파드 netshoot-pod 생성
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: netshoot-pod
spec:
replicas: 3
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
생성 후 결과 확인하기
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath="{.items[0].status.addresses[0].address}")
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2b -o jsonpath="{.items[0].status.addresses[0].address}")
N3=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath="{.items[0].status.addresses[0].address}")
# 파드 이름 변수 지정
PODNAME1=$(kubectl get pod -l app=netshoot-pod -o jsonpath="{.items[0].metadata.name}")
PODNAME2=$(kubectl get pod -l app=netshoot-pod -o jsonpath="{.items[1].metadata.name}")
PODNAME3=$(kubectl get pod -l app=netshoot-pod -o jsonpath="{.items[2].metadata.name}")
# 파드 확인
kubectl get pod -o wide
kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP
파드를 확인해보면 호스트의 서브넷 대역과 같은 대역으로 아이피가 생성된 것을 확인할 수 있습니다.
192.168.2.26 노드(위의 캡처 이미지)에 있는 보조 프라이빗 IP가 192.168.2.90, 192.168.2.189, 192.168.2.206, 192.168.2.47, 192.168.2.162 중의 하나인 192.168.2.90 아이피가 파드의 아이피로 설정 된 것을 확인할 수 있습니다.
생성 전 라우팅 테이블
노드에서 직접 라우팅 테이블을 확인해보면 생성 전에는 아무런 라우팅 테이블이 없다가.
생성 후 라우팅 테이블
생성 후에는 라우팅 테이블이 생성되는 것을 확인할 수 있습니다.
파드 수 늘려보기
nginx 파드를 40개 띄워보면 eni가 어떻게 변하는지 확인해보도록 하겠습니다.
kubectl create deployment nginx --image nginx --replicas=40
워커노드가 3개가 있고 각 워커노드에 한개의 eni씩 붙어있는 상황에서 파드의 수를 40개까지 늘리게 되니 인스턴스에 붙은 eni가 늘어나는 것을 확인해볼 수 있습니다.
(✰) 한도 이상으로 파드 수 늘려보기
워커 노드가 3개가 있는 t3.medium 타입에서 한 워커노드당 생성가능한 파드는 15개이기 때문에 총 파드의 수를 45개 이상으로 늘려버리게 되면 어떻게 되는지 확인해보겠습니다.
기존에 존재하던 vpc-cni 파드 3개와 kube-proxy파드 3개 coredns 파드가 2개가 있습니다. 이중에서 vpc-cni 파드인 aws-node와 kube-proxy는 hostNetwork를 사용하여 별도의 eni를 붙이지 않습니다. coredns만 2개 사용중입니다. 그러므로 최대 추가가능한 파드의 수는 43개 입니다.
네트워크 트러블 슈팅용 파드 3개가 존재하는 상황에서 nginx파드를 45개까지 늘려보도록 하겠습니다. 이렇게 되면 기본 파드를 제외하고 총 48개의 파드가 생성되게 됩니다.
kubectl scale --replicas=45 deployment/nginx
hostNetwork를 사용하는 경우를 제외하고 생성가능한 파드는 총 45개이기 때문에 총 50개의 파드 중 5개의 파드가 생성이 불가능한 것을 확인할 수 있습니다.
이 상황에서 파드들을 재시작 시켜보겠습니다. 처음에 파드 재시작을 하면 사라진 아이피들이 바로 해제 되지 않아서 일시적으로 pending으로 들어가는 것을 확인할 수 있습니다.
파드 수를 줄이게 되면 다시 eni가 반납됩니다. 하지만 eni에 있는 보조 ip가 반납이되어야 eni가 해제되기 때문에
노드 간 파드 통신
다른 노드의 파드로 통신하는 과정을 tcpdump로 확인해보기 위해서는 어떤 인터페이스에 연결되어있는지 확인해야합니다.
# 네트워크 인터페이스의 IP 주소정도만 간단하게 표시
ip -br -c addr show
라우팅 테이블도 확인해보겠습니다.
인터페이스에서는 확인이 되지 않지만 라우팅 테이블을 통해 어떤 인터페이스로 통신이 되는지 확인할 수 있습니다.
파드간 통신은 다음과 같은 흐름대로 이루어집니다.
파드에서 외부 통신
파드에서 외부로 나가는 경우에는 VPC CNI 설정을 통해 SNAT를 할 것인지 아닌지 정할 수 있습니다.
SNAT 설정 여부
aws-node의 AWS_VPC_K8S_CNI_EXTERNALSNAT 이름의 환경 변수가 true로 설정되어있으면 SNAT을 설정할 수 있습니다. 파드가 프라이빗 서브넷에 있고 인터넷으로 아웃바운드 통신이 필요한 경우에 사용하면 됩니다.
확인방법입니다.
kubectl get daemonset -n kube-system aws-node \
-o yaml | yq '.spec.template.spec.containers[0].env[] | select(.name =="AWS_VPC_K8S_CNI_EXTERNALSNAT")'
'K8S > 🔥 network study🔥' 카테고리의 다른 글
[cilium] flannel 설치하기 (0) | 2025.07.16 |
---|---|
[네떡스터디🔥kans] AWS - EKS와 AWS LoadBalancer Controller (1) | 2024.11.02 |
[네떡스터디🔥kans] AWS - EKS 시작하기 (0) | 2024.11.02 |
[네떡스터디🔥kans] Cilium CNI 알아보기 - Netkit (0) | 2024.10.27 |
[네떡스터디🔥kans] Cilium CNI 알아보기 - TCX (Next-Gen TC) (0) | 2024.10.27 |