AEWS 4기 - 2주차: EKS Networking
1. Amazon EKS 배포 및 확인
- 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
- 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 |
|---|