ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [AEWS] Wk2-1. EKS Networking
    IT/AWS 2023. 5. 7. 06:05

    안녕하세요, 본 포스팅은 CloudNet의 AEWS 스터디 2주 차 스터디 자료입니다.

    1. EKS VPC CNI

    K8S의 CNI는 K8S의 파드가 VPC 네트워크에서와 같이 동일한 IP를 가질 수 있도록 합니다.

    VPC CNI의 주요 구성 요소 중의 하나는 L-IPAM 데몬입니다.

    이 L-IPAM 데몬은 노드에 IP 주소를 할당해 주고, 사용가능한 IP 주소 혹은 접두사의 웜풀을 유지하는 역할을 수행합니다.

     

    여기서 아래의 그림을 확인하기 전에, 역할을 나눠서 설명해보면 다음과 같습니다.

     

    IPAMD : 워커노드에 네트워크 인터페이스를 생성 및 연결, 네트워크 인터페이스에 접두사 할당, 예약 파드를 할당하기 위해서 각 노드에 IP 접두사의 웜풀 유지하는 일을 담당합니다.

     

    CNI 플러그인 : 호스트 네트워크에 연결(네트워크 인터페이스 및 가상 이더넷 쌍을 구성) 하고 파드의 네임스페이스에 올바른 네트워크 인터페이스 추가를 담당합니다. CNI 플러그인은 gRPC(원격 프로시저 호출)을 통해서 IPAMD와 통신합니다. 

     

    따라서, 만약 새 파드가 노드에 스케줄링 될 경우, 아래 그림과 같이 kubelet이 CNI 바이너리를 호출하고,

    CNI Plugin은 L-IPAM 데몬을 호출해서 새 파드의 IP 주소를 가져옵니다.

    그런 다음에 파드는 인스턴스에 연결된 ENI와 IP 주소를 추적할 수 있습니다.

     

    L-IPAM 데몬은 파드에 할당할 노드의 IP 관리를 담당하며, Kubernetes Daemonset으로 워커노드에 배포됩니다.

     

    구성 변수는 다음과 같이 설정할 수 있습니다.

    (WARM_ENI_TARGET, WARM_IP_TARGET, MINIMUM_IP_TARGET, WARM_PREFIX_TARGET)

     

    1) WARM_ENI_TARGET 이를 통해서 L-IPAMD가 사용 가능한 상태로 유지하는 ENI 수를 결정하여 노드 스케줄링시 파드에 IP 주소 즉시 할당되도록 합니다.

    - 애플리케이션이 크게 확장될 경우, WARM_ENI_TARGET을 활용해서 신규 예약 파드를 빠르게 수용 가능합니다.

     

    2) WARM_IP_TARGET 해당 변수를 통해서 L-IPAMD의 웜풀에서 사용가능한 IP 주소 개수가 정의되어 있는지 확인합니다. 

     

    3) MINIMUM_IP_TARGET 노드가 처음 나타날때 노드에 최소 IP 주소 수가 할당되어 있는지 확인합니다.

    노드당 최소 실행 파드 수를 알고 있을 경우에 사용합니다.

    (대개는 WARM_IP_TARGET과 함께 사용합니다.)

     

    4) WARM_PREFIX_TARGET

    인스턴스의 네트워크 인터페이스에 항상 정의된 접두사(/28 CIDR 블록)가 추가되어 있는지 확인합니다.

    CNI 버전 1.9.0 이상에만 사용 가능하며, Amazon VPC CNI IP 주소 접두사 배정 기능을 활성화해야 합니다.

     

    kubectl set env daemonset aws-node -n kube-system ENABLE_PREFIX_DELEGATION=true

     

    접두사 모드가 활성화 될 경우, 다음과 같이 IP 할당 프로세스를 갖습니다.

     

     

    VPC CNI 플러그인을 통해서 VPC 네트워킹을 가능케 하여,

    VPC Flow logs, VPC 라우팅 정책, 보안 그룹등을 사용할 수 있게 됩니다. 

     

     

    2. Calico CNI와 AWS VPC CNI의 차이점

    그림에서 확인하시다시피, Calico와 VPC CNI는 파드와 노드 간의 대역 설정에 있어서 차이를 보입니다.

    왼편의 Calico CNI는 파드와 노드의 대역이 다르고, AWS VPC CNI는 파드와 노드의 대역이 같습니다.

     

    그 이유는, K8S CNI는 오버레이 통신 (VXLAN / IP - IP)을 사용하고, AWS VPC CNI의 경우 동일한 대역으로 직접 통신하게 되기 때문입니다.

     

    Calico CNI의 경우 파드 1에서 원본 패킷이 Encapsulation 과정을 통해서 tunl0 인터페이스를 통해 ip 헤더에 감싸져, 상대측 노드로 도달한 후 tunl0 인터페이스에서 Outer 헤더를 제거하고 내부의 파드와 통신하게 됩니다.

     

    AWS VPC CNI의 경우 이러한 Encapsulation 과정을 거치지 않기 때문에, 통신이 더욱 효율적이고 장애처리 역시 빨라집니다.

     

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

    워커 노드에 생성 가능한 총 파드 수는 ENI 수에 ENI당 보조 IP를 곱한 값으로 제한되며,

    인스턴스 크기에 따라서 다릅니다.

     

     

    참조 링크 : https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html#AvailableIpPerENI

     

    Elastic network interfaces - Amazon Elastic Compute Cloud

    For EC2 instances in an IPv6-only subnet, if you attach a secondary network interface to the instance, the private DNS hostname of the second network interface will resolve to the first IPv6 address on the instance's first network interface. For more infor

    docs.aws.amazon.com

     

    4. [실습] - 기본 네트워크 정보 확인

    다음의 내용을 통해서 CNI 정보를 확인하고, kube-proxy config를 확인합니다.

    # kube-proxy config 확인 :
    kubectl describe cm -n kube-system kube-proxy-config
    ...
    mode: "iptables"
    ...

    여기서 kube-proxy config 확인 시 iptables로 확인됩니다.

     

    다음의 명령어를 실행합니다. 그러면, 다음과 같이 192.168.0.0 대역으로 확인되는데,

    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

    하기 명령어를 실행해서, 파드 IP 역시 동일하게 매핑되어 있는 것을 확인할 수 있습니다.

    kubectl get pod -n kube-system -o=custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase

    콘솔에서 확인하면, EC2 노드의 보조 프라이빗 IPv4 주소는 다음과 같습니다.

     

    다음으로, 노드에 툴을 설치하고, 정보를 확인합니다.

     

    links는 텍스트 기반 웹 브라우저,

    tree는 트리구조로 디렉터리 목록을 보기 위한 도구,

    jq는 json processor,

    tcpdump는 패킷 덤프를 위한 도구입니다.

     

    # 노드에 툴 설치
    ssh ec2-user@$N1 sudo yum install links tree jq tcpdump -y
    ssh ec2-user@$N2 sudo yum install links tree jq tcpdump -y
    ssh ec2-user@$N3 sudo yum install links tree jq tcpdump -y
    
    # CNI 정보 확인
    ssh ec2-user@$N1 tree /var/log/aws-routed-eni
    ssh ec2-user@$N1 cat /var/log/aws-routed-eni/plugin.log | jq
    ssh ec2-user@$N1 cat /var/log/aws-routed-eni/ipamd.log | jq
    ssh ec2-user@$N1 cat /var/log/aws-routed-eni/egress-v4-plugin.log | jq
    
    # 네트워크 정보 확인 : eniY는 pod network 네임스페이스와 veth pair
    ssh ec2-user@$N1 sudo ip -br -c addr
    ssh ec2-user@$N1 sudo ip -c addr
    ssh ec2-user@$N1 sudo ip -c route
    ssh ec2-user@$N1 sudo iptables -t nat -S
    ssh ec2-user@$N1 sudo iptables -t nat -L -n -v

     

    차례로 명령을 실행해서, 노드 1번에 로그 폴더에 aws-routed-eni 파일이 쌓이고 있는지 확인하고,

    차례로 폴더 내부에 있는 플러그인 로그, ipamd 로그, egress-v4-plugin 로그를 확인해 봅니다.

    다음은 IPAMD에 받아둔 웜풀 보조 IPv4 주소를 파드가 사용 중인지 확인해 봅시다.

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

    # coredns 파드 IP 정보 확인
    kubectl get pod -n kube-system -l k8s-app=kube-dns -owide

    여기서 확인되는 192.168.1.52, 192.168.2.94, 192.168.3.56 모두 다음과 같이 확인됩니다.

     

    6. [실습] 테스트용 파드 생성 - nicolaka/netshoot

     

    다음으로, 테스트용 파드를 생성해 봅시다.

    netshoot이라는 만능 파드를 사용할 예정입니다.

    # [터미널1~3] 노드 모니터링
    ssh ec2-user@$N1
    watch -d "ip link | egrep 'eth|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"
    
    ssh ec2-user@$N2
    watch -d "ip link | egrep 'eth|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"
    
    ssh ec2-user@$N3
    watch -d "ip link | egrep 'eth|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"
    
    # 테스트용 파드 netshoot-pod 생성
    cat <<EOF | kubectl create -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
    
    # 파드 이름 변수 지정
    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

    파드를 생성한 후에, 잘 생성되었는지 확인해 봅시다.

    # 노드3에서 네트워크 인터페이스 정보 확인
    ssh ec2-user@$N3
    ----------------
    ip -br -c addr show
    ip -c link
    ip -c addr
    ip route # 혹은 route -n
    
    # 마지막 생성된 네임스페이스 정보 출력 -t net(네트워크 타입)
    sudo lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}' | tail -n 1
    
    # 마지막 생성된 네임스페이스 net PID 정보 출력 -t net(네트워크 타입)를 변수 지정
    MyPID=$(sudo lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}' | tail -n 1)
    
    # PID 정보로 파드 정보 확인
    sudo nsenter -t $MyPID -n ip -c addr
    sudo nsenter -t $MyPID -n ip -c route
    
    exit
    ----------------

    다음으로, 테스트 파드에 접속하여 확인합니다.

    # 테스트용 파드 접속(exec) 후 Shell 실행
    kubectl exec -it $PODNAME1 -- zsh
    
    # 아래부터는 pod-1 Shell 에서 실행 : 네트워크 정보 확인
    ----------------------------
    ip -c addr
    ip -c route
    route -n
    ping -c 1 <pod-2 IP>
    ps
    cat /etc/resolv.conf
    exit
    ----------------------------
    
    # 파드2 Shell 실행
    kubectl exec -it $PODNAME2 -- ip -c addr
    
    # 파드3 Shell 실행
    kubectl exec -it $PODNAME3 -- ip -br -c addr

     

    7. 노드 간 파드 통신

    파드간 통신은 앞서 다뤘던 것과 같이 AWS VPC CNI의 경우, 파드간의 직접 통신이 가능합니다.

     

    파드간 통신 과정은 다음과 같습니다.

     

    8. 파드에서 외부로 통신 

     

    VPC CNI의 SNAT 설정에 따라서, 외부(인터넷) 통신 시 SNAT 하거나 혹은 SNAT 없이 통신을 할 수 있습니다.

     

    9. 서비스 & 로드밸런서 컨트롤러

    1) ClusterIP 타입

    • 각각의 파드에 접근하기 위한 virtual IP 생성
    • 모드 노드(마스터 포함)에 iptables rule 이 설정되므로, 파드에서 접속 시 해당 노드에 존재하는 iptables rule에 의해서 분산 접속이 됨

     

    2) NodePort 타입

    • 외부에서 클러스터의 '서비스(NodePort)'로 접근 가능
    • 모드 노드(마스터 포함)에 iptables rule 이 설정되므로, 모든 노드에 NodePort로 접속 시 iptables rule에 의해서 분산 접속이 됨

     

    3) LoadBalancer 타입 (기본 모드) : NLB 인스턴스 유형

    4) Service (LoadBalancer Controller : AWS Load Balancer Controller + NLB IP 모드 동작 with AWS VPC CNI

     

    NLB 모드는 1. 인스턴스 유형, 2. IP 유형이 있습니다.

    IP 유형의 경우, AWS LoadBalancer 컨트롤러의 파드 및 정책 설정이 필요합니다.

     

    1. 인스턴스 유형

    • externalTrafficPolicy : ClusterIP ⇒ 2번 분산 및 SNAT으로 Client IP 확인 불가능 ← LoadBalancer 타입 (기본 모드) 동작
    • externalTrafficPolicy : Local ⇒ 1번 분산 및 ClientIP 유지, 워커 노드의 iptables 사용함


    2. IP 유형 ⇒ 반드시 AWS LoadBalancer 컨트롤러 파드 및 정책 설정이 필요함!

    • Proxy Protocol v2 비활성화 ⇒ NLB에서 바로 파드로 인입, 단 ClientIP가 NLB로 SNAT 되어 Client IP 확인 불가능
    • Proxy Protocol v2 활성화 ⇒ NLB에서 바로 파드로 인입 및 ClientIP 확인 가능(→ 단 PPv2를 애플리케이션이 인지할 수 있게 설정 필요)

     

    참조 링크 : https://aws.amazon.com/ko/blogs/containers/amazon-vpc-cni-increases-pods-per-node-limits/

     

    Amazon VPC CNI plugin increases pods per node limits | Amazon Web Services

    As of August 2021, Amazon VPC Container Networking Interface (CNI) Plugin supports “prefix assignment mode”, enabling you to run more pods per node on AWS Nitro based EC2 instance types. To achieve higher pod density, the VPC CNI plugin leverages a new

    aws.amazon.com

    참조 링크 : https://aws.github.io/aws-eks-best-practices/networking/vpc-cni/

     

    Amazon VPC CNI - EKS Best Practices Guides

    Amazon VPC CNI Amazon EKS implements cluster networking through the Amazon VPC Container Network Interface(VPC CNI) plugin. The CNI plugin allows Kubernetes Pods to have the same IP address as they do on the VPC network. More specifically, all containers i

    aws.github.io

    참조 링크 : https://repost.aws/ko/knowledge-center/eks-configure-cni-plugin-use-ip-address

     

    VPC 서브넷에서 IP 주소를 사용하도록 CNI 플러그인 구성

    Amazon Elastic Kubernetes Service(Amazon EKS)를 통해 VPC 서브넷의 IP 주소를 사용하도록 Amazon Virtual Private Cloud(VPC) 컨테이너 네트워크 인터페이스(CNI) 플러그인을 구성하려고 합니다. 모범 사례는 무엇입니

    repost.aws

    참조 링크 : https://nyyang.tistory.com/139

     

    [Kubernetes] Calico CNI 개념 알아보기

    - 가시다님 주관 Kubernetes network 스터디를 진행하고 있었지만, 개인 사유로 인해 스터디를 진행하지 못하게 되어 이번이 마지막 쿠버네티스 네트워크 글이 될 것 같습니다. (물론 스터디 수행하면

    nyyang.tistory.com

     

    감사합니다.

    728x90
    반응형
Designed by Tistory.