본문 바로가기

Engineering/Ops

AEWS 4기 - 2주차: EKS Networking

AEWS 4기 - 2주차: EKS Networking

1. Amazon EKS 배포 및 확인

  1. Amazon EKS 배포 준비
    실습을 위해 필요한 코드를 다운로드하고 작업 디렉터리로 이동
# 코드 다운로드
git clone [https://github.com/gasida/aews.git](https://github.com/gasida/aews.git)
cd aews
tree -L 2
.
├── 1w
│   ├── eks.tf
│   ├── var.tf
│   └── vpc.tf
├── 2w
│   ├── eks.tf
│   ├── outputs.tf
│   ├── var.tf
│   └── vpc.tf
└── eks-private
    ├── ec2.tf
    ├── main.tf
    ├── outputs.tf
    └── versions.tf

# 2주차 실습
> cd aews/2w

# EC2 키페어 확인 및 변수 지정
aws ec2 describe-key-pairs --query "KeyPairs[].KeyName" --output text
export TF_VAR_KeyName=$(aws ec2 describe-key-pairs --query "KeyPairs[].KeyName" --output text)
# 현재 접속 IP 확인 및 변수 지정
export TF_VAR_ssh_access_cidr=$(curl -s ipinfo.io/ip)/32
# 설정 확인
echo $TF_VAR_KeyName $TF_VAR_ssh_access_cidr
  1. Terraform 배포 및 확인
    2-1. 초기화 및 실행 계획 확인
    # 배포 : 12분 정도 소요
    terraform init
    terraform plan
    # 너무길어서 빼봤다 
    terraform plan > plan_result.txt
    

2-2. 백그라운드 배포 실행

# 위에서 분명 환경변수를 지정했는데 안먹어서 nobup 환경변수로 재지정해줬다
nohup sh -c "terraform apply -auto-approve" > create.log 2>&1 &

# 실시간 로그 모니터링
tail -f create.log

 

3. EKS 클러스터 접속 및 자격 증명

# 자격증명 설정
terraform output -raw configure_kubectl
aws eks --region ap-northeast-2 update-kubeconfig --name myeks

# 3-1. 자격 증명 업데이트 (접속 티켓 발급)
❯ aws eks update-kubeconfig --region ap-northeast-2 --name myeks
Added new context arn:aws:eks:ap-northeast-2:032952487857:cluster/myeks to /Users/seohyunkim/.kube/config
3-2. 기본 정보 확인
  • EKS 관리 콘솔 확인
  • EKS 기본 정보 확인
# 클러스터 확인
kubectl cluster-info
eksctl get cluster

# 네임스페이스 default 변경 적용
kubens default

# 노드 정보 확인
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
kubectl get node -v=6

# 노드 라벨 확인
kubectl get node --show-labels
kubectl get node -l tier=primary


# 파드 정보 확인
kubectl get pod -A
kubectl get pdb -n kube-system
NAME             MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
coredns          N/A             1                 1                     28m
metrics-server   N/A             1                 1                     28m

# 관리형 노드 그룹 확인
aws eks describe-nodegroup --cluster-name myeks --nodegroup-name myeks-1nd-node-group | jq

# eks addon 확인
aws eks list-addons --cluster-name myeks | jq
eksctl get addon --cluster myeks 
NAME            VERSION                 STATUS  ISSUES  IAMROLE UPDATE AVAILABLE        CONFIGURATION VALUES            NAMESPACE POD IDENTITY ASSOCIATION ROLES
coredns         v1.13.2-eksbuild.3      ACTIVE  0                                                                       kube-system
kube-proxy      v1.34.5-eksbuild.2      ACTIVE  0                                                                       kube-system
vpc-cni         v1.21.1-eksbuild.5      ACTIVE  0                                       {"env":{"WARM_ENI_TARGET":"1"}} kube-system
  • EC2 관리 콘솔 확인 : type, az, IP, ec2 instance profile → iam role 확인

2. 노드에서 기본 네트워크 정보 확인

  • 노드 접속 및 IP 변수 지정
    # EC2 ENI IP 확인
    aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table
    

- 네트워크 기본 정보 확인
- 워커 노드1 기본 네트워크 구성
- 보조 IPv4 주소를 coredns 파드가 사용하는지 확인 ⇒ coredns 파드가 배치되지 않은 워커 노드에 ENI 갯수 확인!
- Network-Multitool 디플로이먼트 생성

### 3. 노드 간 파드 통신
- 목표 : 파드간 통신 시 tcpdump 내용을 확인하고 통신 과정을 알아본다
- [실습] 파드간 통신 테스트 및 확인 : 별도의 NAT 동작 없이 통신 가능!

```bash
# 파드 IP 변수 지정
PODIP1=$(kubectl get pod -l app=netshoot-pod -o jsonpath='{.items[0].status.podIP}')
PODIP2=$(kubectl get pod -l app=netshoot-pod -o jsonpath='{.items[1].status.podIP}')
PODIP3=$(kubectl get pod -l app=netshoot-pod -o jsonpath='{.items[2].status.podIP}')
echo $PODIP1 $PODIP2 $PODIP3

# 파드1 Shell 에서 파드2로 ping 테스트
kubectl exec -it $PODNAME1 -- ping -c 2 $PODIP2
kubectl exec -it $PODNAME1 -- curl -s http://$PODIP2
kubectl exec -it $PODNAME1 -- curl -sk https://$PODIP2

# 파드2 Shell 에서 파드3로 ping 테스트
kubectl exec -it $PODNAME2 -- ping -c 2 $PODIP3

# 파드3 Shell 에서 파드1로 ping 테스트
kubectl exec -it $PODNAME3 -- ping -c 2 $PODIP1


# 워커 노드 EC2 : TCPDUMP 확인
## For Pod to external (outside VPC) traffic, we will program iptables to SNAT using Primary IP address on the Primary ENI.
sudo tcpdump -i any -nn icmp
sudo tcpdump -i ens5 -nn icmp
sudo tcpdump -i ens6 -nn icmp
sudo tcpdump -i eniYYYYYYYY -nn icmp

[워커 노드1]
# routing policy database management 확인
ip rule

# routing table management 확인
ip route show table local
ip route show table main
ip route show table 2

4. 파드에서 외부 통신

# pod-1 Shell 에서 외부로 ping
kubectl exec -it $PODNAME1 -- ping -c 1 www.google.com
kubectl exec -it $PODNAME1 -- ping -i 0.1 www.google.com
kubectl exec -it $PODNAME1 -- ping -i 0.1 8.8.8.8

# 워커 노드 EC2 : TCPDUMP 확인
sudo tcpdump -i any -nn icmp
sudo tcpdump -i ens5 -nn icmp

# 퍼블릭IP 확인
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i curl -s ipinfo.io/ip; echo; echo; done

# 작업용 EC2 : pod-1 Shell 에서 외부 접속 확인 - 공인IP는 어떤 주소인가?
## The right way to check the weather - 링크
for i in $PODNAME1 $PODNAME2 $PODNAME3; do echo ">> Pod : $i <<"; kubectl exec -it $i -- curl -s ipinfo.io/ip; echo; echo; done
kubectl exec -it $PODNAME1 -- curl -s wttr.in/seoul
kubectl exec -it $PODNAME1 -- curl -s wttr.in/seoul?format=3
kubectl exec -it $PODNAME1 -- curl -s wttr.in/Moon
kubectl exec -it $PODNAME1 -- curl -s wttr.in/:help


# 워커 노드 EC2
## 출력된 결과를 보고 어떻게 빠져나가는지 고민해보자!
ip rule
ip route show table main
sudo iptables -L -n -v -t nat
sudo iptables -t nat -S

# 파드가 외부와 통신시에는 아래 처럼 'AWS-SNAT-CHAIN-0' 룰(rule)에 의해서 SNAT 되어서 외부와 통신!
# 참고로 뒤 IP는 eth0(ENI 첫번째)의 IP 주소이다
# --random-fully 동작 - 링크1  링크2
sudo iptables -t nat -S | grep 'A AWS-SNAT-CHAIN'
-A AWS-SNAT-CHAIN-0 ! -d 192.168.0.0/16 -m comment --comment "AWS SNAT CHAIN" -j RETURN
-A AWS-SNAT-CHAIN-0 ! -o vlan+ -m comment --comment "AWS, SNAT" -m addrtype ! --dst-type LOCAL -j SNAT --to-source 192.168.1.251 --random-fully

## 아래 'mark 0x4000/0x4000' 매칭되지 않아서 RETURN 됨!
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
-A KUBE-POSTROUTING -j MARK --set-xmark 0x4000/0x0
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
...

# 카운트 확인 시 AWS-SNAT-CHAIN-0에 매칭되어, 목적지가 192.168.0.0/16 아니고 외부 빠져나갈때 SNAT 192.168.1.251(EC2 노드1 IP) 변경되어 나간다!
sudo iptables -t filter --zero; sudo iptables -t nat --zero; sudo iptables -t mangle --zero; sudo iptables -t raw --zero
watch -d 'sudo iptables -v --numeric --table nat --list AWS-SNAT-CHAIN-0; echo ; sudo iptables -v --numeric --table nat --list KUBE-POSTROUTING; echo ; sudo iptables -v --numeric --table nat --list POSTROUTING'

# conntrack 확인 : EC2 메타데이터 주소(169.254.169.254) 제외 출력
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo conntrack -L -n |grep -v '169.254.169'; echo; done
conntrack v1.4.5 (conntrack-tools): 
icmp     1 28 src=172.30.66.58 dst=8.8.8.8 type=8 code=0 id=34392 src=8.8.8.8 dst=172.30.85.242 type=0 code=0 id=50705 mark=128 use=1
tcp      6 23 TIME_WAIT src=172.30.66.58 dst=34.117.59.81 sport=58144 dport=80 src=34.117.59.81 dst=172.30.85.242 sport=80 dport=44768 [ASSURED] mark=128 use=1

5. AWS VPC CNI 설정 변경

  • 현재 상태 확인
    # aws-node DaemonSet의 env 확인
    kubectl get ds aws-node -n kube-system -o json | jq '.spec.template.spec.containers[0].env'
    ...
    {
      "name": "WARM_ENI_TARGET",
      "value": "1"
    },
    ...
    

- AWS VPC CNI 설정 변경 적용
  - eks.tf 수정
```bash
  # add-on
  addons = {
    coredns = {
      most_recent = true
    }
    kube-proxy = {
      most_recent = true
    }
    vpc-cni = {
      most_recent = true
      before_compute = true
      configuration_values = jsonencode({
        env = {
          #WARM_ENI_TARGET = "1" # 현재 ENI 외에 여유 ENI 1개를 항상 확보
          WARM_IP_TARGET  = "5" # 현재 사용 중인 IP 외에 여유 IP 5개를 항상 유지, 설정 시 WARM_ENI_TARGET 무시됨
          MINIMUM_IP_TARGET   = "10" # 노드 시작 시 최소 확보해야 할 IP 총량 10개
          #ENABLE_PREFIX_DELEGATION = "true" 
          #WARM_PREFIX_TARGET = "1" # PREFIX_DELEGATION 사용 시, 1개의 여유 대역(/28) 유지
        }
      })
    }
  }
  • 설정 적용
# 모니터링
watch -d kubectl get pod -n kube-system -l k8s-app=aws-node # aws-node 데몬셋 파드 확인
watch -d eksctl get addon --cluster myeks # addon 확인

# 적용
terraform plan
terraform apply -auto-approve
  • 확인
    # 파드 재생성 확인
    kubectl get pod -n kube-system -l k8s-app=aws-node
    
    addon 확인
    eksctl get addon --cluster myeks
    NAME VERSION STATUS ISSUES IAMROLE UPDATE AVAILABLE CONFIGURATION VALUES NAMESPACE POD IDENTITY ASSOCIATION ROLES
    coredns v1.13.2-eksbuild.3 ACTIVE 0 kube-system
    kube-proxy v1.34.5-eksbuild.2 ACTIVE 0 kube-system
    vpc-cni v1.21.1-eksbuild.5 ACTIVE 0 {"env":{"MINIMUM_IP_TARGET":"10","WARM_IP_TARGET":"5"}} kube-system
    
    aws-node DaemonSet의 env 확인
    kubectl get ds aws-node -n kube-system -o json | jq '.spec.template.spec.containers[0].env'
    kubectl describe ds aws-node -n kube-system | grep -E "WARM_IP_TARGET|MINIMUM_IP_TARGET"
    
    노드 정보 확인 : (hostNetwork 제외) 파드가 없는 노드에도 ENI 추가 확인!
    for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c addr; echo; done
    for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c route; echo; done
    
    cni log 확인
    for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i tree /var/log/aws-routed-eni ; echo; done
    for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo cat /var/log/aws-routed-eni/plugin.log | jq ; echo; done
    for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo cat /var/log/aws-routed-eni/ipamd.log | jq ; echo; done
    
    IpamD debugging commands https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/troubleshooting.md
    for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i curl -s http://localhost:61679/v1/enis | jq; echo; done

 

### 6. 노드에 파드 생성 갯수 제한
### 7. Service & Amazon EKS 네트워킹 지원
### 8. AWS LoadBalancer Controller (LBC) & Service (L4)
### 8. Ingress (L7 : HTTP)
### 9. ExternalDNS
### 10. Gateway API
### 11. CoreDNS

### 12. 자원 삭제

# IRSA 설정 삭제
CLUSTER_NAME=myeks
eksctl delete iamserviceaccount --cluster=$CLUSTER_NAME --namespace=kube-system --name=external-dns
eksctl delete iamserviceaccount --cluster=$CLUSTER_NAME --namespace=kube-system --name=aws-load-balancer-controller

# 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
  • 테라폼으로 생성된 리소스 삭제
    terraform destroy -auto-approve && rm -rf ~/.kube/config

모니터링

watch -d -n 5 "
echo '=== [1. Bastion EC2 & Status] ===' && \
aws ec2 describe-instances --region ap-northeast-2 --filters 'Name=tag:Name,Values=bastion-ec2' --query 'Reservations[].Instances[].{ID:InstanceId,IP:PublicIp,State:State.Name}' --output table && \
echo '=== [2. EKS Clusters] ===' && \
aws eks list-clusters --region ap-northeast-2 --query 'clusters' --output table && \
echo '=== [3. NAT Gateway & Elastic IPs] ===' && \
aws ec2 describe-nat-gateways --region ap-northeast-2 --query 'NatGateways[?State!=\`deleted\`].{ID:NatGatewayId,State:State}' --output table && \
aws ec2 describe-addresses --region ap-northeast-2 --query 'Addresses[].{IP:PublicIp,ID:AllocationId}' --output table && \
echo '=== [4. VPC Endpoints (12 Services)] ===' && \
aws ec2 describe-vpc-endpoints --region ap-northeast-2 --query 'VpcEndpoints[?State!=\`deleted\`].{ID:VpcEndpointId,Service:ServiceName}' --output table && \
echo '=== [5. Security Groups] ===' && \
aws ec2 describe-security-groups --region ap-northeast-2 --filters 'Name=tag:Name,Values=bastion-ec2-sg' --query 'SecurityGroups[].{ID:GroupId,Name:GroupName}' --output table
"

 

- 추가 공부가 필요하다..

'Engineering > Ops' 카테고리의 다른 글

AEWS 4기 - 1주차: Amazon EKS 소개 및 배포  (0) 2026.03.18