AWS EKS : VPC CNI

Gyullbb·2024년 11월 2일
0

K8S

목록 보기
13/13

AWS VPC CNI

AWS VPC CNI는 Amazon EKS에서 Pod가 VPC의 IP 주소를 직접 사용할 수 있게 해주는 네트워크 플러그인이다.
이를 통해 Pod와 외부 네트워크간의 통신이 VPC 내에서 직접적으로 이루어지며, 추가적인 네트워크 변환 없이 통신이 가능하도록 한다.

VPC CNI의 중요한 특징 중 하나는 Pod가 노드의 네트워크 대역(VPC 서브넷)과 동일한 IP 대역을 사용한다는 것이다.
각 Pod는 별도의 NAT나 프록시 없이 VPC 내의 다른 리소스와 직접 통신이 가능하며, pod와 노드의 네트워크 대역이 같다보니 오버레이(VXLAN, IP-IP 등)으로 통신하는 일반적인 K8s CNI와는 달리 동일 대역으로 직접 통신을 한다.

AWS VPC CNI에는 두 가지 주요 구성 요소인 CNI 바이너리(CNI Binary)IP 주소 관리(IPAM, IP Address Management)가 있다.

CNI 바이너리 (CNI Binary)

CNI 바이너리는 Pod의 네트워크 인터페이스를 생성하고 삭제하는 역할을 수행한다.

Pod가 시작될 때 ENI(Elastic Network Interface)와 연결된 IP를 Pod에 할당한다.
Pod가 종료되면 네트워크 자원을 정리한다.
이를 통해 Pod와 외부 네트워크 간의 원활한 통신이 가능하게 하며, 모든 Pod가 VPC 네트워크 대역의 IP를 사용하도록 한다.

IP 주소 관리 (L-IPAM)

IPAM은 VPC 서브넷 내에서 Pod에 할당할 IP 주소를 효율적으로 관리한다.

노드에 할당된 ENI에서 여러 IP를 미리 풀(pool) 형태로 확보해 두고, Pod가 생성될 때 즉시 할당한다.
사용하지 않는 IP는 재사용하거나 반환하여 네트워크 자원을 절약한다.
이 과정은 동적으로 관리되며, VPC 서브넷과 노드의 자원 상태에 따라 유연하게 조정된다.
이 두 요소를 통해 AWS VPC CNI는 Pod 간의 통신과 VPC 내 네트워크 자원 관리를 효율적으로 지원한다.

  • ip를 미리 가지고 있다가 warm pool에서 ip바로 pod에 할당할수있어서 pod도 빨리뜨고, api호출수도 줄어든다.

Pod 통신

기본 네트워크 구성 확인

생성된 노드(t3.medium)의 기본 네트워크 구성을 확인해보자.

현재 ENI는 2개로, 각 ENI는 자신의 IP 이외에 추가적으로 5개의 보조 프라이빗 IP를 가질수 있다.
coredns 파드는 veth 인터페이스로, 호스트에는 eniY@ifN 인터페이스와 파드에 eth0 과 연결되어 있다

파드를 배포한 후 각 워커 노드의 라우팅 정보와 ip 정보를 확인해보자.


파드가 생성 후, 워커 노드에 eniY@ifN 이 추가되고 라우팅 테이블에도 정보가 추가 된 것을 확인할 수 있다.

노드간 파드 통신

위에서 설명했듯이, AWS VPC CNI 경우 Pod가 노드의 네트워크 대역과 동일한 IP 대역을 사용하기 때문에, 별도의 오버레이(Overlay) 통신 기술 없이, VPC Native 하게 파드간 직접 통신이 가능하다
참조 : KANS Kubernetes Network Study 3기

Pod1에서 Pod2 통신을 시도함과 동시에 Pod가 떠있는 노드에서 eth0 패킷 캡처를 해본다.

패킷 캡처된 내역을 보면, 서로 다른 노드 위에 있음에도 파드 간 통신이 NAT없이 direct 통신이 이뤄짐을 알 수 있다.

[ec2-user@ip-192-168-1-193 ~]$ ip route show table main
default via 192.168.1.1 dev eth0
169.254.169.254 dev eth0
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.193
192.168.1.72 dev eni6376c4bd6b9 scope link

노드에서 라우팅 정보를 확인하면, default via 192.168.1.1 dev eth0라는 라우팅 정보가 있는데, 이는 서버에서 로컬 네트워크에 속하지 않는 패킷을 전송할 때 기본 게이트웨이(192.168.1.1)를 통해 eth0 네트워크 인터페이스로 보낸다는 뜻이다.

이 라우팅 경로가 default로 설정되어 있기 때문에, 이 서버에서 외부 네트워크나 인터넷으로 나가는 모든 트래픽은 eth0을 통해 빠져나가게 된다.

파드에서 외부 통신

https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md

파드에서 외부 통신을 함과 동시에 파드가 떠있는 워커노드에서 eth0 패킷을 캡처해본다.

파드가 외부 통신 할 때에는 'AWS-SNAT-CHAIN-0' 룰(rule)에 의해서 SNAT 되어서 외부와 통신이 된다.
해당 룰에 대해 확인해본다.

[ec2-user@ip-192-168-2-90 ~]$ 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.2.90 --random-fully

-A AWS-SNAT-CHAIN-0 -d 192.168.0.0/16 -m comment --comment "AWS SNAT CHAIN" -j RETURN

이 규칙은 destination ip가 192.168.0.0/16 대역에 속하는 패킷을 SNAT 적용에서 제외시킨다. 즉, 로컬 서브넷 안에서의 트래픽은 SNAT을 적용하지 않도록 하는 설정이다.

-A AWS-SNAT-CHAIN-0 ! -o vlan+ -m comment --comment "AWS, SNAT" -m addrtype ! --dst-type LOCAL -j SNAT --to-source 192.168.2.90 --random-fully

이 규칙은 VLAN을 제외한 다른 인터페이스를 통한 트래픽에 SNAT을 적용하는 규칙이다. AWS 네트워크 외부로 나가는 트래픽에 대해 출발지 IP 주소를 노드 IP인 192.168.2.90으로 설정하여 관리 및 라우팅을 일관되게 유지할 수 있다.

노드에 파드 생성 갯수 제한

AWS는 워커 노드의 인스턴스 타입 별로 파드 생성 갯수를 제한한다.
인스턴스 타입 별 ENI 최대 갯수와 할당 가능한 최대 IP 갯수에 따라서 파드 배치 갯수가 결정되는데, aws-node 와 kube-proxy 파드의 경우 호스트의 IP를 사용함으로 최대 갯수에서 제외한다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# aws ec2 describe-instance-types --filters Name=instance-type,Values=t3.* \
>  --query "InstanceTypes[].{Type: InstanceType, MaxENI: NetworkInfo.MaximumNetworkInterfaces, IPv4addr: NetworkInfo.Ipv4AddressesPerInterface}" \
>  --output table
--------------------------------------
|        DescribeInstanceTypes       |
+----------+----------+--------------+
| IPv4addr | MaxENI   |    Type      |
+----------+----------+--------------+
|  12      |  3       |  t3.large    |
|  6       |  3       |  t3.medium   |
|  15      |  4       |  t3.xlarge   |
|  15      |  4       |  t3.2xlarge  |
|  2       |  2       |  t3.micro    |
|  2       |  2       |  t3.nano     |
|  4       |  3       |  t3.small    |
+----------+----------+--------------+

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl describe node | grep Allocatable: -A6
Allocatable:
  cpu:                1930m
  ephemeral-storage:  27905944324
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             3388312Ki
  pods:               17

제한된 개수 이상의 파드를 생성했을 때, 어떻게 되는지 알아본다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl scale deployment nginx-deployment --replicas=50
deployment.apps/nginx-deployment scaled



제한 개수를 넘어가면 pod가 Pending상태로 정상 기동되지 않는다.

워커노드에 pod ip할당도 제한된 개수까지 할당된 것을 볼 수 있다.

Service & AWS LoadBalancer Controller

AWS 환경에서 쿠버네티스 서비스의 트래픽을 외부로 노출하기 위해 AWS Load Balancer Controller와 Network Load Balancer(NLB)를 활용할 수 있다.

AWS Load Balancer Controller

AWS Load Balancer Controller는 쿠버네티스 클러스터 내 서비스의 트래픽을 AWS의 네트워크 로드 밸런서(NLB)로 자동 연결해 주는 컨트롤러이다. 이 컨트롤러는 LoadBalancer 타입의 서비스를 생성할 때 자동으로 NLB를 프로비저닝하고 이를 통해 서비스 트래픽을 처리합니다.

NLB

NLB 모드에는 인스턴스 유형과 IP 유형이 있다.
1. 인스턴스 유형

  • 인스턴스 유형 로드 밸런서는 Amazon EC2 인스턴스를 대상으로 사용한다.
  • 주로 기존의 Classic Load Balancer(CLB)와 연결되며, 대상 인스턴스는 EC2의 ID를 기준으로 로드 밸런서에 등록된다.
  • 인스턴스의 상태에 따라 자동으로 로드 밸런서의 트래픽이 분배되며, 인스턴스가 중지 또는 종료되면 로드 밸런서에서 자동으로 제거된다.
  • 탄력적 IP 주소(EIP)를 사용하지 않는 경우 IP 주소가 동적으로 할당되므로, 인스턴스의 IP 주소가 변경될 수 있다.
  1. IP 유형
  • IP 유형 로드 밸런서는 특정 IP 주소를 대상으로 사용하며, 인스턴스뿐만 아니라 온프레미스 서버 등 다양한 IP 주소를 대상으로 로드 밸런싱할 수 있다.
  • 주로 Application Load Balancer(ALB)와 Network Load Balancer(NLB)에서 사용되며, 로드 밸런서가 VPC 외부의 IP 주소로도 트래픽을 분배할 수 있다.
  • 각 대상 IP는 탄력적 IP 또는 고정 IP일 수 있어 IP 주소가 변경되지 않고 고정된 대상 서버에 트래픽을 전달하는 경우 유용하다.
  • IP 기반 로드 밸런서를 사용하면 컨테이너화된 환경이나 서버리스 아키텍처에서도 효과적으로 로드 밸런싱을 수행할 수 있다.

AWS LoadBalancer Controller, Service/Pod 배포

AWS LoadBalancer Controller를 배포하여 분산 접속을 확인해보자.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get crd
NAME                                         CREATED AT
cninodes.vpcresources.k8s.aws                2024-11-02T13:55:05Z
eniconfigs.crd.k8s.amazonaws.com             2024-11-02T13:58:33Z
ingressclassparams.elbv2.k8s.aws             2024-11-02T18:31:35Z
policyendpoints.networking.k8s.aws           2024-11-02T13:55:06Z
securitygrouppolicies.vpcresources.k8s.aws   2024-11-02T13:55:05Z
targetgroupbindings.elbv2.k8s.aws            2024-11-02T18:31:35Z


(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get deployment -n kube-system aws-load-balancer-controller
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           5m10s
Every 2.0s: kubectl get pod,svc,ep                                                                             Sun Nov  3 03:37:11 2024

NAME                                READY   STATUS    RESTARTS   AGE
pod/deploy-echo-857b6cfb88-mgdcm    1/1     Running   0          5m12s
pod/deploy-echo-857b6cfb88-z9qv7    1/1     Running   0          5m12s
pod/netshoot-pod-74b7555dc7-7hpkt   1/1     Running   0          175m
pod/netshoot-pod-74b7555dc7-mjs77   1/1     Running   0          175m
pod/netshoot-pod-74b7555dc7-s76j2   1/1     Running   0          175m

NAME                      TYPE           CLUSTER-IP     EXTERNAL-IP
     PORT(S)        AGE
service/kubernetes        ClusterIP      10.100.0.1     <none>
     443/TCP        4h42m
service/svc-nlb-ip-type   LoadBalancer   10.100.12.82   k8s-default-svcnlbip-4588d22da5-bd009cf4bd83d981.elb.ap-northeast-2.amazonaws.c
om   80:31013/TCP   5m12s

NAME                        ENDPOINTS                               AGE
endpoints/kubernetes        192.168.2.143:443,192.168.3.204:443     4h42m
endpoints/svc-nlb-ip-type   192.168.1.170:8080,192.168.3.113:8080   5m12s

(bgrtest@myeks:default) [root@myeks-bastion ~]# for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
     50 Hostname: deploy-echo-857b6cfb88-z9qv7
     50 Hostname: deploy-echo-857b6cfb88-mgdcm

pod 개수를 변화시켜도 정상적으로 분배를 수행한다.
이 때, NLB 대상 타겟이 모두 정상 반영되었는지를 확인해야한다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl scale deployment deploy-echo --replicas=1

deployment.apps/deploy-echo scaled

(bgrtest@myeks:default) [root@myeks-bastion ~]# for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
    100 Hostname: deploy-echo-857b6cfb88-mgdcm
    
(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl scale deployment deploy-echo --replicas=3
deployment.apps/deploy-echo scaled


# 아직 NLB 대상 타겟이 아직 initial 상태 : 타겟이 정상 반영되기 전
(bgrtest@myeks:default) [root@myeks-bastion ~]# for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
    100 Hostname: deploy-echo-857b6cfb88-mgdcm
    
(bgrtest@myeks:default) [root@myeks-bastion ~]# for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
     41 Hostname: deploy-echo-857b6cfb88-cqt65
     31 Hostname: deploy-echo-857b6cfb88-mgdcm
     28 Hostname: deploy-echo-857b6cfb88-znshb     

Ingress

AWS Load Balancer Controller는 Kubernetes 환경에서 AWS Application Load Balancer(ALB)와 통합되어 Ingress 리소스를 통해 트래픽을 관리한다. AWS VPC CNI를 사용해 IP 모드로 동작하는 경우, ALB는 Kubernetes 서비스의 개별 Pod IP를 대상으로 직접 트래픽을 라우팅한다.

ALB IP 모드

ALB의 기본 연결 방식은 NodePort이지만, IP 모드에서는 Pod의 IP가 ALB 타겟 그룹에 직접 등록된다. NodePort를 거치지 않고 트래픽을 바로 Pod로 라우팅하여 지연 시간을 줄이고 성능을 개선할 수 있다.

AWS VPC CNI는 Pod에게 VPC IP를 직접 할당하여 VPC 네트워크에 직접 연결되도록 한다. IP 모드의 ALB와 연동 시 각 Pod가 고유한 IP를 가져 네트워크 성능과 유연성이 개선된다.

실습

ALB 대상 그룹에 등록된 대상을 확인한다. ALB 대상에 파드 IP가 바로 등록되어 있음을 확인할 수 있다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get pod -n game-2048 -o wide
NAME                              READY   STATUS    RESTARTS   AGE     IP              NODE                                               NOMINATED NODE   READINESS GATES
deployment-2048-85f8c7d69-k6t8b   1/1     Running   0          3m45s   192.168.3.113   ip-192-168-3-157.ap-northeast-2.compute.internal   <none>           <none>
deployment-2048-85f8c7d69-nrpsx   1/1     Running   0          3m45s   192.168.1.251   ip-192-168-1-193.ap-northeast-2.compute.internal   <none>           <none>

인그레스를 통한 접속을 확인해본다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# # Ingress 확인

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl describe ingress -n game-2048 ingress-2048
Name:             ingress-2048
Labels:           <none>
Namespace:        game-2048
Address:          k8s-game2048-ingress2-70d50ce3fd-900250973.ap-northeast-2.elb.amazonaws.com
Ingress Class:    alb
Default backend:  <default>
Rules:
  Host        Path  Backends
  ----        ----  --------
  *
              /   service-2048:80 (192.168.1.251:80,192.168.3.113:80)
Annotations:  alb.ingress.kubernetes.io/scheme: internet-facing
              alb.ingress.kubernetes.io/target-type: ip
Events:
  Type    Reason                  Age    From     Message
  ----    ------                  ----   ----     -------
  Normal  SuccessfullyReconciled  4m46s  ingress  Successfully reconciled
  
(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get ingress -n game-2048 ingress-2048 -o jsonpath="{.status.loadBalancer.ingress[*].hostname}{'\n'}"
k8s-game2048-ingress2-70d50ce3fd-900250973.ap-northeast-2.elb.amazonaws.com

(bgrtest@myeks:default) [root@myeks-bastion ~]# # 게임 접속 : ALB 주소로 웹 접속
(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get ingress -n game-2048 ingress-2048 -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Game URL = http://"$1 }'
Game URL = http://k8s-game2048-ingress2-70d50ce3fd-900250973.ap-northeast-2.elb.amazonaws.com

ALB 주소로 웹 접속하면 재밌는 게임도 즐길 수 있다.

Topology aware routing

Topology Aware Routing(토폴로지 인식 라우팅)은 네트워크의 구조를 고려하여 데이터 패킷을 전송하는 방식이다. 다음과 같은 장점을 제공한다

  • 지연 최소화: 지리적으로 가까운 노드 간에 트래픽을 라우팅하여 지연을 줄인다.
  • 부하 분산: 노드 간의 트래픽 분산을 최적화하여 특정 노드에 트래픽이 몰리는 것을 방지한다.
  • 장애 복구: 경로 실패 시 대체 경로를 신속하게 찾아 트래픽을 재조정할 수 있다.
  • 비용 효율성: 최소한의 경로를 사용하여 데이터 전송 비용을 절감한다.

Kubernetes에서는 topologyKeys를 설정하여 특정 노드의 레이블에 따라 요청을 분산시키는 방식으로 Topology Aware Routing을 구현한다. 이를 통해 대규모 분산 시스템에서 성능 최적화와 자원 관리를 효과적으로 수행할 수 있다.

현재 노드 AZ 분산을 확인해본다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get node --label-columns=topology.kubernetes.io/zone

NAME                                               STATUS   ROLES    AGE     VERSION               ZONE
ip-192-168-1-193.ap-northeast-2.compute.internal   Ready    <none>   5h14m   v1.30.4-eks-a737599   ap-northeast-2a
ip-192-168-2-90.ap-northeast-2.compute.internal    Ready    <none>   5h14m   v1.30.4-eks-a737599   ap-northeast-2b
ip-192-168-3-157.ap-northeast-2.compute.internal   Ready    <none>   5h14m   v1.30.4-eks-a737599   ap-northeast-2c

Topology aware routing 적용 전

테스트 파드(netshoot-pod)에서 ClusterIP 접속 시 부하분산을 확인하면 AZ(zone) 상관없이 랜덤 확률 부하분산 동작하는 것을 볼 수 있다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get pod -l app=deploy-websrv -owide
NAME                           READY   STATUS    RESTARTS   AGE    IP              NODE                                               NOMINATED NODE   READINESS GATES
deploy-echo-859cc9b57d-2sk67   1/1     Running   0          115s   192.168.2.215   ip-192-168-2-90.ap-northeast-2.compute.internal    <none>           <none>
deploy-echo-859cc9b57d-6dczc   1/1     Running   0          115s   192.168.3.174   ip-192-168-3-157.ap-northeast-2.compute.internal   <none>           <none>
deploy-echo-859cc9b57d-dn4cz   1/1     Running   0          115s   192.168.1.170   ip-192-168-1-193.ap-northeast-2.compute.internal   <none>           <none>

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl exec -it netshoot-pod -- zsh -c "for i in {1..100}; do curl -s svc-clusterip | grep Hostname; done | sort | uniq -c | sort -nr"
      37 Hostname: deploy-echo-859cc9b57d-dn4cz
     33 Hostname: deploy-echo-859cc9b57d-6dczc
     30 Hostname: deploy-echo-859cc9b57d-2sk67

Topology aware routing 적용 이후

Topology Mode 설정 후 테스트 파드(netshoot-pod)에서 ClusterIP 접속 시 부하분산을 확인하면 같은 AZ(zone)의 목적지 파드로만 접속하는 것을 볼 수 있다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl annotate service svc-clusterip "service.kubernetes.io/topology-mode=auto"
service/svc-clusterip annotated
(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl exec -it netshoot-pod -- zsh -c "for i in {1..100}; do curl -s svc-clusterip | grep Hostname; done | sort | uniq -c | sort -nr"
    100 Hostname: deploy-echo-859cc9b57d-6dczc

endpointslices를 확인하면 기존에 없던 hints 가 추가되어 있다.
Topology Hints는 Pod와 Node의 지리적 위치나 네트워크 토폴로지 정보를 제공하여 라우팅 결정을 돕는다. 각 Pod의 위치 정보가 힌트로 제공되면, 클러스터는 이 힌트를 기반으로 가까운 경로로 트래픽을 라우팅한다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get endpointslices -l kubernetes.io/service-name=svc-clusterip -o yaml
apiVersion: v1
items:
- addressType: IPv4
  apiVersion: discovery.k8s.io/v1
  endpoints:
  - addresses:
    - 192.168.3.174
    conditions:
      ready: true
      serving: true
      terminating: false
    hints:
      forZones:
      - name: ap-northeast-2c
    nodeName: ip-192-168-3-157.ap-northeast-2.compute.internal
...

iptables

iptables로 확인했을 때, SEP(Endpoint) 파드가 각 노드 당 노드와 동일한 AZ에 배포된 파드1개만 출력되는 것을 확인할 수 있다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# ssh ec2-user@$N1 sudo iptables -v --numeric --table nat --list KUBE-SERVICES
Chain KUBE-SERVICES (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SVC-UAGC4PYEYZJJEW6D  tcp  --  *      *       0.0.0.0/0            10.100.245.133       /* kube-system/aws-load-balancer-webhook-service:webhook-server cluster IP */ tcp dpt:443
    0     0 KUBE-SVC-KBDEBIL6IU6WL7RF  tcp  --  *      *       0.0.0.0/0            10.100.229.199       /* default/svc-clusterip:svc-webport cluster IP */ tcp dpt:80
    0     0 KUBE-SVC-NPX46M4PTMTKRN6Y  tcp  --  *      *       0.0.0.0/0            10.100.0.1           /* default/kubernetes:https cluster IP */ tcp dpt:443
    0     0 KUBE-SVC-I7SKRZYQ7PWYV5X7  tcp  --  *      *       0.0.0.0/0            10.100.238.197       /* kube-system/eks-extension-metrics-api:metrics-api cluster IP */ tcp dpt:443
    0     0 KUBE-SVC-TCOU7JCQXEZGVUNU  udp  --  *      *       0.0.0.0/0            10.100.0.10          /* kube-system/kube-dns:dns cluster IP */ udp dpt:53
    0     0 KUBE-SVC-ERIFXISQEP7F7OF4  tcp  --  *      *       0.0.0.0/0            10.100.0.10          /* kube-system/kube-dns:dns-tcp cluster IP */ tcp dpt:53
    0     0 KUBE-SVC-JD5MR3NA4I4DYORP  tcp  --  *      *       0.0.0.0/0            10.100.0.10          /* kube-system/kube-dns:metrics cluster IP */ tcp dpt:9153
   39  2340 KUBE-NODEPORTS  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL

(bgrtest@myeks:default) [root@myeks-bastion ~]#
(bgrtest@myeks:default) [root@myeks-bastion ~]# ssh ec2-user@$N1 sudo iptables -v --numeric --table nat --list KUBE-SVC-KBDEBIL6IU6WL7RF
Chain KUBE-SVC-KBDEBIL6IU6WL7RF (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SEP-2ZUOF3KQXKLOSGMW  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/svc-clusterip:svc-webport -> 192.168.1.170:8080 */
(bgrtest@myeks:default) [root@myeks-bastion ~]# ssh ec2-user@$N2 sudo iptables -v --numeric --table nat --list KUBE-SVC-KBDEBIL6IU6WL7RF
Chain KUBE-SVC-KBDEBIL6IU6WL7RF (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SEP-SX6FOWFFGSKOV6K3  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/svc-clusterip:svc-webport -> 192.168.2.215:8080 */
(bgrtest@myeks:default) [root@myeks-bastion ~]# ssh ec2-user@$N3 sudo iptables -v --numeric --table nat --list KUBE-SVC-KBDEBIL6IU6WL7RF
Chain KUBE-SVC-KBDEBIL6IU6WL7RF (1 references)
 pkts bytes target     prot opt in     out     source               destination
  200 12000 KUBE-SEP-L65MDBTORLAOI3KR  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/svc-clusterip:svc-webport -> 192.168.3.174:8080 */

동일 AZ에 목적지 파드가 없다면?

파드 개수를 1개로 줄여서 동일 AZ노드에 목적지 파드가 없는 상황을 만들어보자.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl scale deployment deploy-echo --replicas 1

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get pod -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP              NODE                                               NOMINATED NODE   READINESS GATES
deploy-echo-859cc9b57d-dn4cz    1/1     Running   0          12m     192.168.1.170   ip-192-168-1-193.ap-northeast-2.compute.internal   <none>           <none>
netshoot-pod                    1/1     Running   0          11m     192.168.3.37    ip-192-168-3-157.ap-northeast-2.compute.internal   <none>           <none>
netshoot-pod-74b7555dc7-7hpkt   1/1     Running   0          3h48m   192.168.2.196   ip-192-168-2-90.ap-northeast-2.compute.internal    <none>           <none>
netshoot-pod-74b7555dc7-mjs77   1/1     Running   0          3h48m   192.168.3.12    ip-192-168-3-157.ap-northeast-2.compute.internal   <none>           <none>
netshoot-pod-74b7555dc7-s76j2   1/1     Running   0          3h48m   192.168.1.72    ip-192-168-1-193.ap-northeast-2.compute.internal   <none>

이전과 달리 hint 정보가 사라져있다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# kubectl get endpointslices -l kubernetes.io/service-name=svc-clusterip -o yaml | grep -i hint

iptables를 확인해보면 AZ와 관련없이 3개 노드 모두 SVC에 1개의 SEP 정책 존재함을 확인할 수 있다.

(bgrtest@myeks:default) [root@myeks-bastion ~]# ssh ec2-user@$N1 sudo iptables -v --numeric --table nat --list KUBE-SVC-KBDEBIL6IU6WL7RF
Chain KUBE-SVC-KBDEBIL6IU6WL7RF (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SEP-2ZUOF3KQXKLOSGMW  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/svc-clusterip:svc-webport -> 192.168.1.170:8080 */
(bgrtest@myeks:default) [root@myeks-bastion ~]# ssh ec2-user@$N2 sudo iptables -v --numeric --table nat --list KUBE-SVC-KBDEBIL6IU6WL7RF
Chain KUBE-SVC-KBDEBIL6IU6WL7RF (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SEP-2ZUOF3KQXKLOSGMW  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/svc-clusterip:svc-webport -> 192.168.1.170:8080 */
(bgrtest@myeks:default) [root@myeks-bastion ~]# ssh ec2-user@$N3 sudo iptables -v --numeric --table nat --list KUBE-SVC-KBDEBIL6IU6WL7RF
Chain KUBE-SVC-KBDEBIL6IU6WL7RF (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SEP-2ZUOF3KQXKLOSGMW  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/svc-clusterip:svc-webport -> 192.168.1.170:8080 */

0개의 댓글