ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [eks 스터디 2주차] - EKS Networking
    AWS 2023. 5. 6. 15:05

     

    참고 링크 

    0. 실습 환경 배포

    Amazon EKS 윈클릭 배포 & 기본 설정

    더보기
    # YAML 파일 다운로드
    curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/eks-oneclick.yaml
    
    # CloudFormation 스택 배포
    # aws cloudformation deploy --template-file eks-oneclick.yaml --stack-name myeks --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 MyIamUserAccessKeyID=<IAM User의 액세스키> MyIamUserSecretAccessKey=<IAM User의 시크릿 키> ClusterBaseName='<eks 이름>' --region ap-northeast-2
    예시) aws cloudformation deploy --template-file eks-oneclick.yaml --stack-name myeks --parameter-overrides KeyName=kp-gasida SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32  MyIamUserAccessKeyID=AKIA5... MyIamUserSecretAccessKey='CVNa2...' ClusterBaseName=myeks --region ap-northeast-2
    
    # CloudFormation 스택 배포 완료 후 작업용 EC2 IP 출력
    aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text
    
    # 마스터노드 SSH 접속
    ssh -i ~/.ssh/kp-gasida.pem ec2-user@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)

     

    기본 설정

    # default 네임스페이스 적용
    kubectl ns default
    
    # 노드 정보 확인
    kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
    eksctl get iamidentitymapping --cluster myeks
    
    # 노드 IP 확인 및 PrivateIP 변수 지정
    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})
    echo "export N1=$N1" >> /etc/profile
    echo "export N2=$N2" >> /etc/profile
    echo "export N3=$N3" >> /etc/profile
    echo $N1, $N2, $N3
    
    # 노드 보안그룹 ID 확인
    NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ng1* --query "SecurityGroups[*].[GroupId]" --output text)
    aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32
    
    # 워커 노드 SSH 접속
    ssh ec2-user@$N1 hostname
    ssh ec2-user@$N2 hostname
    ssh ec2-user@$N3 hostname

    설치 정보 확인

    # 이미지 정보 확인
    kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
          3 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon-k8s-cni:v1.12.6-eksbuild.1
          2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.9.3-eksbuild.3
          3 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/kube-proxy:v1.24.10-minimal-eksbuild.2
    
    # eksctl 설치/업데이트 addon 확인
    eksctl get addon --cluster $CLUSTER_NAME
    NAME		   VERSION			       STATUS	ISSUES	IAMROLE
    coredns		 v1.9.3-eksbuild.3	 ACTIVE	0
    kube-proxy v1.24.10-eksbuild.2 ACTIVE	0
    vpc-cni		 v1.12.6-eksbuild.1	 ACTIVE	0	      arn:aws:iam::911283464785:role/eksctl-myeks-addon-vpc-cni-Role1-1TZPXJONK9XGE

     

     

    1. AWS VPC CNI 소개

    K8S CNI : Container Network Interface 는 k8s 네트워크 환경을 구성해준다 - 링크, 다양한 플러그인이 존재 - 링크

    AWS VPC CNI : 파드의 IP를 할당해준다, 파드의 IP 네트워크 대역과 노드(워커)의 IP 대역이 같아서 직접 통신이 가능하다 - AWS_CNI Github Proposal

    • Amazon EKS supports native VPC networking with the Amazon VPC Container Network Interface (CNI) plugin for Kubernetes.
    • VPC 와 통합 : VPC Flow logs , VPC 라우팅 정책, 보안 그룹(Security group) 을 사용 가능함
    • This plugin assigns an IP address from your VPC to each pod.
    • VPC ENI 에 미리 할당된 IP를 파드에서 사용할 수 있음

    K8S Calico CNI 와 AWS VPC CNI 차이

    • 네트워크 통신의 최적화(성능, 지연)를 위해서 노드와 파드의 네트워크 대역을 동일하게 설정함

     

    • 파드간 통신 시 일반적으로 K8S CNI는 오버레이(VXLAN, IP-IP 등) 통신을 하고, AWS VPC CNI는 동일 대역으로 직접 통신을 한다

     

    워커 노드에 생성 가능한 최대 파드 갯수

    1. Secondary IPv4 addresses : 인스턴스 유형에 최대 ENI 갯수와 할당 가능 IP 수를 조합하여 선정
    2. IPv4 Prefix Delegation : IPv4 28bit 서브넷(prefix)를 위임하여 할당 가능 IP 수와 인스턴스 유형에 권장하는 최대 갯수로 선정

     

    2. AWS VPC CNI - 파드 기본 통신

    실습 환경 소개

    • AWS EKS 클러스터, 관리형 노드 그룹(t3.medium, 노드 2대

     👉🏻 실습 사용 버전 : EKS(K8S) v1.21.2 , AWS VPC CNI v1.7.5 , kube-ops-view

    (옵션) kube-ops-view 설치 - 링크

    더보기
    # 설치
    curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
    helm repo add stable https://charts.helm.sh/stable
    helm install kube-ops-view stable/kube-ops-view --set service.type=LoadBalancer --set rbac.create=True --namespace kube-system
    
    # 접속 URL 확인
    kubectl get svc kube-ops-view -n kube-system | tail -n 1 | awk '{ print "Kube-ops-view URL = http://"$4 }'

     

    2.1 워커 노드 기본 정보 확인

    워커노드1 기본 네트워크 구성 : 워커노드2는 구성이 유사하여 생략

    • Network 네임스페이스는 호스트(Root)와 파드 별(Per Pod)로 구분된다
    • 특정한 파드(kube-proxy, aws-node)는 호스트(Root)의 IP를 그대로 사용한다
    • t3.medium 의 경우 ENI 에 최대 6개의 IP를 가질 수 있다
    • ENI0, ENI1 으로 2개의 ENI는 자신의 IP 이외에 추가적으로 5개의 보조 프라이빗 IP를 가질수 있다
    • coredns 파드는 veth 으로 호스트에는 eniY@ifN 인터페이스와 파드에 eth0 과 연결되어 있다

    워커 노드1 인스턴스의 네트워크 정보 확인 : 프라이빗 IP와 보조 프라이빗 IP 확인

    kubectl , aws cli 등 정보 확인

    더보기
    # 노드 정보 확인
    kubectl get node
    
    ...
    NAME                                               STATUS   ROLES    AGE    VERSION
    ip-192-168-1-64.ap-northeast-2.compute.internal    Ready    <none>   117m   v1.21.2-eks-55daa9d
    ip-192-168-2-235.ap-northeast-2.compute.internal   Ready    <none>   117m   v1.21.2-eks-55daa9d
    ...
    
    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
    
    ...
    -------------------------------------------------------------------------
    |                           DescribeInstances                           |
    +-------------------------+----------------+----------------+-----------+
    |      InstanceName       | PrivateIPAdd   |  PublicIPAdd   |  Status   |
    +-------------------------+----------------+----------------+-----------+
    |  myeks-ng-b760da78-Node |  192.168.1.64  |  3.34.127.206  |  running  |
    |  myeks-ng-b760da78-Node |  192.168.2.235 |  54.180.85.80  |  running  |
    +-------------------------+----------------+----------------+-----------+
    ...
    
    # 파드 정보(IP) 확인
    kubectl get pod -n kube-system -o=custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase
    
    ...
    NAME                             IP              STATUS
    aws-node-5fzgw                   192.168.1.64    Running
    aws-node-w9b6m                   192.168.2.235   Running
    coredns-6dbb778559-ddwzr         192.168.1.235   Running
    kube-ops-view-5557846b44-dh74l   192.168.2.171   Running
    kube-proxy-6hpj7                 192.168.1.64    Running
    kube-proxy-xvdsj                 192.168.2.235   Running
    ...
    
    [워커노드1]에서 확인
    docker ps --format 'table {{.Names}}\t{{.Status}}' | grep -v POD
    
    ...
    NAMES                                                                                     STATUS
    k8s_coredns_coredns-6dbb778559-ddwzr_kube-system_0f29c550-f412-4a73-879d-82a2b892d4bc_0   Up 2 hours
    k8s_aws-node_aws-node-5fzgw_kube-system_c8404b73-a683-476d-b06e-87171d693fe5_0            Up 2 hours
    k8s_kube-proxy_kube-proxy-6hpj7_kube-system_e0c71d53-43d5-445e-86db-b805168cdec8_0        Up 2 hours
    ...
    
    [워커노드2]에서 확인
    docker ps --format 'table {{.Names}}\t{{.Status}}' | grep -v POD
    
    ...
    NAMES                                                                                                 STATUS
    k8s_kube-ops-view_kube-ops-view-5557846b44-dh74l_kube-system_c2549f52-2740-4709-ad64-6e509247dd9a_0   Up 2 hours
    k8s_aws-node_aws-node-w9b6m_kube-system_7a324f78-1ff2-4efb-96ae-755e82955ddf_0                        Up 2 hours
    k8s_kube-proxy_kube-proxy-xvdsj_kube-system_d268e74d-58bd-4e2e-8e45-a373e25ca7f3_0                    Up 2 hours
    ...
    
    # 노드에서 네트워크 인터페이스 정보 확인
    ip -br -c addr
    ip -c link
    ip -c addr
    ip route # 혹은 route -n
    
    [워커노드1]에서 확인
    ip -br -c addr
    
    ...
    lo                 UNKNOWN        127.0.0.1/8 ::1/128
    eth0               UP             192.168.1.64/24 fe80::7d:8bff:fe4f:10a6/64
    eni4bae37b3559@if3 UP             fe80::c03:12ff:fe56:dfb0/64
    eth1               UP             192.168.1.65/24 fe80::ed:35ff:fe37:f35a/64
    ...
    
    # eni4bae37b3559@if3 는 pod network 네임스페이스와 veth pair
    # if3 은 nsenter 로 파드 내부에서 ip a 확인 시 NIC 의 number (3번)
    ip -c addr
    
    ...
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host
           valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
        link/ether 02:7d:8b:4f:10:a6 brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.64/24 brd 192.168.1.255 scope global dynamic eth0
           valid_lft 2519sec preferred_lft 2519sec
        inet6 fe80::7d:8bff:fe4f:10a6/64 scope link
           valid_lft forever preferred_lft forever
    4: eni4bae37b3559@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
        link/ether 0e:03:12:56:df:b0 brd ff:ff:ff:ff:ff:ff link-netnsid 1
        inet6 fe80::c03:12ff:fe56:dfb0/64 scope link
           valid_lft forever preferred_lft forever
    5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
        link/ether 02:ed:35:37:f3:5a brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.65/24 brd 192.168.1.255 scope global eth1
           valid_lft forever preferred_lft forever
        inet6 fe80::ed:35ff:fe37:f35a/64 scope link
           valid_lft forever preferred_lft forever
    ...
    
    # 노드에 생성된 파드는 host 라우팅 정보로 파드로 직접 통신
    route -n
    
    ...
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
    169.254.169.254 0.0.0.0         255.255.255.255 UH    0      0        0 eth0
    192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
    192.168.1.235   0.0.0.0         255.255.255.255 UH    0      0        0 eni4bae37b3559
    ...
    
    # 파드의 네트워크 정보 확인
    # 네임스페이스 정보 출력 -t net(네트워크 타입) : pause(컨테이너) 확인, PID 1 을 제외
    lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}'
    
    ...
    4399
    ...
    
    # 변수 지정
    MyPID1=<위 출력된 PID>
    MyPID1=4399
    
    # nsenter(=namespace enter) 로 격리된 namespace 에 enter 하는 명령어 (-n 명령어 실행)
    # IP 확인(/32bit)! , if4 는 호스트 네트워크 정보 (ip a) 확인 시 NIC 의 number (4번)
    nsenter -t $MyPID1 -n ip a
    ...
    3: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
        link/ether ce:00:5b:24:2d:6a brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 192.168.1.235/32 scope global eth0
           valid_lft forever preferred_lft forever
    ...
    
    # 169.254.1.1 디폴트 루트가 잡혀있다 
    nsenter -t $MyPID1 -n ip route
    
    ...
    default via 169.254.1.1 dev eth0
    169.254.1.1 dev eth0 scope link
    ...

    [실습] 보조 IPv4 주소를 파드가 사용하는지 확인

    더보기
    # coredns 파드 IP 정보 확인
    kubectl get pod -n kube-system -l k8s-app=kube-dns -owide
    NAME                       READY   STATUS    RESTARTS   AGE   IP              NODE                                               NOMINATED NODE   READINESS GATES
    coredns-6777fcd775-57k77   1/1     Running   0          70m   192.168.1.142   ip-192-168-1-251.ap-northeast-2.compute.internal   <none>           <none>
    coredns-6777fcd775-cvqsb   1/1     Running   0          70m   192.168.2.75    ip-192-168-2-34.ap-northeast-2.compute.internal    <none>           <none>
    
    # 노드의 라우팅 정보 확인 >> EC2 네트워크 정보의 '보조 프라이빗 IPv4 주소'와 비교해보자
    ssh ec2-user@$N1 sudo ip -c route
    ssh ec2-user@$N2 sudo ip -c route
    ssh ec2-user@$N3 sudo ip -c route

     

    2.2 테스트용 파드 생성 및 확인

    테스트용 파드 생성 - nicolaka/netshoot   

    더보기
    # 워커 노드 - 모니터링
    watch -d "ip link | egrep 'eth|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"
    
    
    # 작업용 EC2 - 파드 2개 생성
    cat <<EOF | kubectl create -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-1
      labels:
        app: pod
    spec:
      containers:
      - name: netshoot-pod
        image: nicolaka/netshoot
        command: ["tail"]
        args: ["-f", "/dev/null"]
      terminationGracePeriodSeconds: 0
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-2
      labels:
        app: pod
    spec:
      containers:
      - name: netshoot-pod
        image: nicolaka/netshoot
        command: ["tail"]
        args: ["-f", "/dev/null"]
      terminationGracePeriodSeconds: 0
    EOF
    
    # 파드 확인
    kubectl get pod -o wide
    
    ...
    NAME    READY   STATUS    RESTARTS   AGE   IP              NODE                                               NOMINATED NODE   READINESS GATES
    pod-1   1/1     Running   0          20m   192.168.2.63    ip-192-168-2-235.ap-northeast-2.compute.internal   <none>           <none>
    pod-2   1/1     Running   0          20m   192.168.1.249   ip-192-168-1-64.ap-northeast-2.compute.internal    <none>           <none>
    ...
    
    kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP

    파드가 생성되면, 워커 노드eniY@ifN 추가되고 라우팅 테이블에도 정보가 추가된다

     

    테스트용 파드 eniY 정보 확인 - 워커 노드 EC2

    더보기
    # 노드에서 네트워크 인터페이스 정보 확인
    ip -br -c addr show
    ip -c link
    ip -c addr
    ip route # 혹은 route -n
    
    # 마지막 생성된 네임스페이스 정보 출력 -t net(네트워크 타입)
    lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}' | tail -n 1
    28596
    
    # 마지막 생성된 네임스페이스 net PID 정보 출력 -t net(네트워크 타입)를 변수 지정
    MyPID2=$(lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}' | tail -n 1)
    
    # 파드 정보 확인
    nsenter -t $MyPID2 -n ip a
    
    ...
    3: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default
        link/ether c6:94:16:91:74:9e brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 192.168.1.249/32 scope global eth0
           valid_lft forever preferred_lft forever
    ...
    
    nsenter -t $MyPID2 -n ip route

     

    2.3 파드간 통신

    파드간 통신 흐름 : 별도의 오버레이(Overlay) 통신 기술 없이, VPC Native 하게 파드간 직접 통신이 가능하다

     

    pod-2(192.168.1.249) → pod-1(192.168.2.63) 으로 통신 확인

     

    파드간 통신 시 과정 참고

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

     

    파드간 통신 테스트 및 확인

    더보기
    # 작업용 EC2
    kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP
    kubectl exec -it pod-2 -- zsh
    
    ip a
    route
    ping -c 2 192.168.2.63
    exit
    
    
    # pod-1 Shell 실행
    kubectl exec -it pod-1 -- zsh
    
    # 아래부터는 pod-1 Shell 에서 실행 : 파드 통신 확인, 외부 통신 확인
    ----------------------------
    ip a
    route
    ping -c 1 <pod-2 IP>  # 아래 tcpdump 시 실행
    exit
    ----------------------------
    
    # (옵션) nsenter 를 사용해서 통신 테스트 가능
    nsenter -t $MyPID2 -n ping -c 2 8.8.8.8
    [root@ip-192-168-1-251 ~]# nsenter -t $MyPID1 -n "ping -c 2 8.8.8.8"
    64 bytes from 8.8.8.8: icmp_seq=1 ttl=100 time=32.1 ms
    64 bytes from 8.8.8.8: icmp_seq=2 ttl=100 time=32.0 ms
    
    # 워커 노드 EC2
    # 각 개별 PID 값으로 lsns -t net 으로 -n ip a 명령어 실행 
    for PID in $(lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}'); do nsenter -t $PID -n ip a | grep eth0@ -A2; echo "-----------"; done
    
    # TCPDUMP 확인 : eth1 은 패킷 덤프에서 출력되지 않는다
    yum -y install tcpdump
    tcpdump -i any -nn icmp
    tcpdump -i eth0 -nn icmp
    tcpdump -i eth1 -nn icmp
    
    [워커 노드1]
    # routing policy database management 확인
    ip rule
    0:	from all lookup local
    512:	from all to 192.168.1.235 lookup main
    512:	from all to 192.168.1.249 lookup main
    1024:	from all fwmark 0x80/0x80 lookup main
    32766:	from all lookup main
    32767:	from all lookup default
    
    # routing table management 확인
    ip route show table local
    ...
    local 192.168.1.64 dev eth0 proto kernel scope host src 192.168.1.64
    local 192.168.1.65 dev eth1 proto kernel scope host src 192.168.1.65
    ...
    
    # 디폴트 네트워크 정보를 eth0 을 통해서 빠져나간다
    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.64
    192.168.1.235 dev eni4bae37b3559 scope link
    192.168.1.249 dev enifbd243bfedd scope link

     

    2.4 파드 → 외부(인터넷) 통신

    파드에서 외부 통신 흐름

    • iptable 에 SNAT 을 통하여 노드의 eth0 IP로 변경되어서 외부와 통신됨

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

    • VPC CNI 의 External source network address translation (SNAT) 설정에 따라, 외부(인터넷) 통신 시 SNAT 하거나 혹은 SNAT 없이 통신을 할 수 있다 - 링크
    • 파드가 VPC peering, Transit VPC, or Direct Connect 등으로 연결된 곳과 통신 시 문제 발생 시 VPC CNI v1.8 이상으로 업데이트를 하자 - 링크 링크2

    파드에서 외부 통신 테스트 및 확인

    - 파드 shell 실행 후 외부로 ping 테스트

    - 워커 노드에서 tcpdump 및 iptables 정보 확인

    더보기
    ```bash
    **# 작업용 EC2**
    kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP
    kubectl exec -it pod-2 -- zsh
    
    ip a
    route
    ping -c 2 192.168.2.63
    exit
    
    # pod-1 Shell 실행
    kubectl exec -it pod-1 -- zsh
    
    # 아래부터는 pod-1 Shell 에서 실행 : 파드 통신 확인, 외부 통신 확인
    ----------------------------
    ip a
    route
    ping -c 1 <pod-2 IP>  # 아래 tcpdump 시 실행
    exit
    ----------------------------
    
    # (옵션) nsenter 를 사용해서 통신 테스트 가능
    nsenter -t $MyPID2 -n ping -c 2 8.8.8.8
    [root@ip-192-168-1-251 ~]# nsenter -t $MyPID1 -n "ping -c 2 8.8.8.8"
    64 bytes from 8.8.8.8: icmp_seq=1 ttl=100 time=32.1 ms
    64 bytes from 8.8.8.8: icmp_seq=2 ttl=100 time=32.0 ms
    
    **# 워커 노드 EC2**
    # 각 개별 PID 값으로 lsns -t net 으로 -n ip a 명령어 실행 
    for PID in $(lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}'); do nsenter -t $PID -n ip a | grep eth0@ -A2; echo "-----------"; done
    
    # TCPDUMP 확인 : eth1 은 패킷 덤프에서 출력되지 않는다
    yum -y install tcpdump
    tcpdump -i any -nn icmp
    tcpdump -i eth0 -nn icmp
    tcpdump -i eth1 -nn icmp
    
    [워커 노드1]
    # routing policy database management 확인
    ip rule
    0:	from all lookup local
    512:	from all to 192.168.1.235 lookup main
    512:	from all to 192.168.1.249 lookup main
    1024:	from all fwmark 0x80/0x80 lookup main
    32766:	from all lookup main
    32767:	from all lookup default
    
    # routing table management 확인
    ip route show table local
    ...
    local 192.168.1.64 dev eth0 proto kernel scope host src 192.168.1.64
    local 192.168.1.65 dev eth1 proto kernel scope host src 192.168.1.65
    ...
    
    # 디폴트 네트워크 정보를 eth0 을 통해서 빠져나간다
    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.64
    192.168.1.235 dev eni4bae37b3559 scope link
    192.168.1.249 dev enifbd243bfedd scope link
    ```

     

    3. 노드에 파드 생성 갯수 제한

    Secondary IPv4 addresses : 인스턴스 유형에 최대 ENI 갯수와 할당 가능 IP 수를 조합하여 선정

    워커 노드의 인스턴스 타입 별 파드 생성 갯수 제한

    • 인스턴스 타입 별 ENI 최대 갯수와 할당 가능한 최대 IP 갯수에 따라서 파드 배치 갯수가 결정됨
    • 단, aws-node 와 kube-proxy 파드는 호스트의 IP를 사용함으로 최대 갯수에서 제외함

     

    워커 노드의 인스턴스 정보 확인 : 필자는 현재 t3.medium 사용 중

    더보기
    # t3 타입의 정보(필터) 확인
    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      |
    +----------+----------+--------------+
    |  15      |  4       |  t3.2xlarge  |
    |  6       |  3       |  t3.medium   |
    |  12      |  3       |  t3.large    |
    |  15      |  4       |  t3.xlarge   |
    |  2       |  2       |  t3.micro    |
    |  2       |  2       |  t3.nano     |
    |  4       |  3       |  t3.small    |
    +----------+----------+--------------+
    
    # 파드 사용 가능 계산 예시 : aws-node 와 kube-proxy 파드는 host-networking 사용으로 IP 2개 남음
    ((MaxENI * (IPv4addr-1)) + 2)
    t3.medium 경우 : ((3 * (6 - 1) + 2 ) = 17개 >> aws-node 와 kube-proxy 2개 제외하면 15개
    
    # 워커노드 상세 정보 확인 : 노드 상세 정보의 Allocatable 에 pods 에 17개 정보 확인
    kubectl describe node ip-192-168-1-64.ap-northeast-2.compute.internal | grep Allocatable: -A7
    Allocatable:
      attachable-volumes-aws-ebs:  25
      cpu:                         1930m
      ephemeral-storage:           18242267924
      hugepages-1Gi:               0
      hugepages-2Mi:               0
      memory:                      3412904Ki
      pods:

     

     

    최대 파드 생성 및 확인

    더보기
    # 워커 노드 EC2
    # 모니터링
    watch -d "ip link | egrep 'eth|eni'"
    while true; do ip -br -c addr show && echo "--------------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done
    
    # 작업용 EC2 - 터미널1
    watch -d 'kubectl get pods -o wide'
    
    # 작업용 EC2 - 터미널2
    # 디플로이먼트 생성
    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
    
    # 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인
    kubectl scale deployment nginx-deployment --replicas=8
    
    # 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인 >> 어떤일이 벌어졌는가?
    kubectl scale deployment nginx-deployment --replicas=10
    
    # 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인
    kubectl scale deployment nginx-deployment --replicas=30
    
    # 파드 생성 실패!
    kubectl get pods | grep Pending
    nginx-deployment-7fb7fd49b4-d4bk9   0/1     Pending   0          3m37s
    nginx-deployment-7fb7fd49b4-qpqbm   0/1     Pending   0          3m37s
    
    kubectl describe pod <Pending 파드> | grep Events: -A5
    Events:
      Type     Reason            Age                 From               Message
      ----     ------            ----                ----               -------
      Warning  FailedScheduling  57s (x4 over 3m5s)  default-scheduler  0/3 nodes are available: 3 Too many pods.
    
    # 디플로이먼트 삭제
    kubectl delete deploy nginx-deployment

     

    - kube-ops-view 웹에서 확인 : 워커 노드 마다 최대 17개(2개는 aws-node, kube-proxy) 파드 생성 이후에 오른쪽 상단에 미 배치된 파드 정보

     

    4. 노드에 파드 생성 갯수 증가

    IPv4 Prefix Delegation : IPv4 28bit 서브넷(prefix)를 위임하여 할당 가능 IP 수와 인스턴스 유형에 권장하는 최대 갯수로 선정

    AWS VPC CNI prefix assignment mode 에서 최대 파드 생성 갯수

    • 간단한 동작 확인을 위해서 기존의 관리형 노드 그룹을 삭제하고, 신규 관리형 노드 그룹(Nitro-base, c5.large, 1대)을 생성하였다
    • IPv4 Prefix Delegation 대역의 IP를 파드가 사용 가능하다

     

    • AWS VPC CNI prefix assignment mode 필수 조건
      • 인스턴스 유형 : AWS Nitro-based nodes use this capability
      • VPC CNI 버전 : Version 1.9.0 or later of the Amazon VPC CNI add-on added to your cluster.

    육아로 아직 아래 부분은 남아있는데 일요일 중에 업데이트 할게요~ㅠ

Designed by Tistory.