AEWS STUDY 2주차 - Amazon EKS Networking

Hanryang·2023년 5월 6일
0

AEWS 스터디

목록 보기
2/7

가시다님께서 진행하신 AEWS라는 스터디를 진행하면서 작성하는 글입니다.

AEWS= AWS EKS Workshop Study

AEWS 스터디는 4월 23일 ~ 6월 4일동안7번 진행될 예정입니다.

PKOS 스터디에서 정말 좋은 경험을 했어서 다시 이렇게 참가하게 되었습니다.

가시다님께서 진행하시는 스터디에 관심있으신 분들은 Cloudnet@Blog에 들어가시면 자세한 정보를 확인하실 수 있습니다.

실습 환경 배포


가시다님께서 만들어주신 Cloudformation을 이용한 EKS 원클릭 배포로 실습 환경을 쉽게 배포할 수 있습니다.

배포할 EKS 아키텍처는 아래와 같습니다.

배포를 완료한 후 잘 배포가 되었는지 노드 정보를 확인 해보겠습니다.

CNI(Container Network Interface)


Cloud Native Computing Foundation 프로젝트인 CNI( Container Network Interface ) 는 지원되는 여러 플러그인과 함께 Linux 컨테이너에서 네트워크 인터페이스를 구성하기 위한 플러그인을 작성하기 위한 사양 및 라이브러리로 구성된다고 합니다.

(출처: cni 공식 레파지토리)

AWS VPC CNI


AWS에서 만든 k8s의 pod 네트워킹을 위한 네트워킹 플러그인입니다.

  • VPC의 IP주소를 각 pod에 할당

  • pod의 IP 네트워크 대역과 워커노드의 IP 대역이 같아서 직접 통신이 가능

  • VPC ENI 에 미리 할당된 IP를 pod에서 사용할 수 있음

    • 워커노드의 서브넷에서 기본 ENI로 슬롯 풀(IP 또는 접두사)을 자동으로 할당
      • CNI 설정에 따라 슬롯은 IP 주소 또는 접두사
    • 슬롯 풀의 크기는 노드의 인스턴스 유형에 따라 결정

더 자세한 내용은 여기에서 보실 수 있습니다.

K8S Calico CNI 와 AWS VPC CNI 차이


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

파드 간 통신 시

  • k8s CNI는 오버레이 통신
    • 오버레이는 새로운 헤더가 추가되어 원본 IP헤더를 감싸는 캡슐화가 수행
    • 더 공부하기에 좋은 링크
  • VPC CNI는 동일 대역으로 직접 통신

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


  • Secondary IPv4 addresses

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

  • IPv4 Prefix Delegation

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

네트워크 기본 정보 확인


  • CNI 정보 확인

  • kube-proxy config 확인

    apiVersion: kubeproxy.config.k8s.io/v1alpha1
    bindAddress: 0.0.0.0
    clientConnection:
      acceptContentTypes: ""
      burst: 10
      contentType: application/vnd.kubernetes.protobuf
      kubeconfig: /var/lib/kube-proxy/kubeconfig
      qps: 5
    clusterCIDR: ""
    configSyncPeriod: 15m0s
    conntrack:
      maxPerCore: 32768
      min: 131072
      tcpCloseWaitTimeout: 1h0m0s
      tcpEstablishedTimeout: 24h0m0s
    enableProfiling: false
    healthzBindAddress: 0.0.0.0:10256
    hostnameOverride: ""
    iptables:
      masqueradeAll: false
      masqueradeBit: 14
      minSyncPeriod: 0s
      syncPeriod: 30s
    ipvs:
      excludeCIDRs: null
      minSyncPeriod: 0s
      scheduler: ""
      syncPeriod: 30s
    kind: KubeProxyConfiguration
    metricsBindAddress: 0.0.0.0:10249
    mode: "iptables"
    nodePortAddresses: null
    oomScoreAdj: -998
    portRange: ""
    udpIdleTimeout: 250ms
    • ipvs모드를 사용하지 않고 iptables를 사용하는 이유는..?(가시다님의 문제)
      • iptable
        • Linux 시스템에서 방화벽을 구성하고 관리하는 데 사용되는 도구
        • 네트워크 패킷을 캡처하고, 필터링하며, 수정하고, 전송하는 데 사용
      • ipvs
        • 로드 밸런서 기능을 수행하는 Linux 커널 모듈
        • 서버 그룹을 정의하고, 클라이언트 요청을 서버로 분배하고, 부하 분산 알고리즘을 적용하여 서버의 가용성과 성능을 최적화하는 데 사용
      • 부하분산은 이미 로드 밸런서인 NLB가 있기 때문에 내부에 부하 분산을 할 필요가 없어서..? 찾아봐도 정확하게 잘 이해가 가지 않는다..좀 더 공부하자..
  • 노드 IP 확인

  • pod ip 확인

    • pod가 보조 IPv4 주소를 사용하는 지 확인

노드 간 파드 통신


AWS VPC CNI 경우 별도의 오버레이(Overlay) 통신 기술 없이, VPC Native 하게 파드간 직접 통신이 가능하다는 것을 K8S Calico CNI 와 AWS VPC CNI 차이에서 알아봤습니다.

파드 간 통신 실습


파드 통신을 진행할 때 직접 통신이 되는지 테스트 해보겠습니다.

우선 테스트용 파드를 생성하고 변수를 지정했습니다.

# 테스트 파드 생
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})
# 파드 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})

그리고 핑 테스트를 진행했습니다.

  • 파드1 Shell 에서 파드2로 ping 테스트
  • 파드2 Shell 에서 파드3로 ping 테스트
  • 파드3 Shell 에서 파드1로 ping 테스트

Service & AWS LoadBalancer Controller


Pod는 생성될 때 마다 IP가 변경되는 특성을 가지고 있어서 클러스터 내/외부와 통신을 유지하는 것은 어렵습니다.

그래서 k8s는 pod와 통신을 할 수 있는 고정IP를 가진 Service를 지원합니다.

  • 서비스 종류

    • Cluster IP

      • 클러스터 내부에서만 'CLUSTER-IP' 로 접근 가능
      • 서비스(ClusterIP 타입) 생성하게 되면, apiserver → kube-proxy → iptables 에 rule(룰)이 생성됨
      • 모 노드(마스터 포함)에 iptables rule 이 설정되므로, 파드에서 접속 시 해당 노드에 존재하는 iptables rule 에 의해서 분산 접속이 됨
    • NodePort

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

      • 노드는 외부에 공개되지 않고 로드밸런서만 외부에 공개되어, 외부 클라이언트는 로드밸랜서에 접속을 할 뿐 내부 노드의 정보를 알 수 없다
      • 로드밸런서가 부하분산하여 파드가 존재하는 노드들에게 전달한다, iptables 룰에서는 자신의 노드에 있는 파드만 연결한다
      • DNAT 2번 동작 : 첫번째(로드밸런서 접속 후 빠져 나갈때), 두번째(노드의 iptables 룰에서 파드IP 전달 시)
      • 외부 클라이언트 IP 보존(유지) : AWS NLB 는 타켓인스턴스일 경우 클라이언트 IP를 유지, iptables 룰 경우도 externalTrafficPolicy 로 클라이언트 IP를 보존
    • LoadBalancer Controller - AWS Load Balancer Controller + NLB IP 모드 동작 with AWS VPC CNI

      • VPC CNI와 함께 구성하면 노드와 파드의 IP 대역이 동일하기 때문에 NodePort 서비스를 거치지 않고 바로 통신(Bypass)이 가능

AWS LoadBalancer Controller,NLB 배포


  • AWS Load Balancer Controller 배포하기 위해서는 우선 IAM 정책을 생성해야합니다.
**# IAM Policy (AWSLoadBalancerControllerIAMPolicy) 생성**

curl -o **iam_policy.json** https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json
aws iam create-policy --policy-name **AWSLoadBalancerControllerIAMPolicy** --policy-document file://**iam_policy.json**
  • IAM 정책이 정상 생성이 되었는지 확인 합니다.
  • AWS Load Balancer Controller를 위한 ServiceAccount를 생성하고 정책을 연결합니다.
    eksctl create **iamserviceaccount** --cluster=$CLUSTER_NAME --namespace=kube-system --name=**aws-load-balancer-controller** \
    --attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/**AWSLoadBalancerControllerIAMPolicy** --override-existing-serviceaccounts --**approve**
  • IRSA(IAM Role for Service Account) 정보를 확인합니다.
  • 서비스 어카운트 확인
  • Helm을 이용한 AWS LoadBalancer Controller 배포를 진행합니다.
    helm repo add eks https://aws.github.io/eks-charts
    helm repo update
    **helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \
      --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller**
  • NLB service 배포를 진행합니다.
    curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/2/echo-service-nlb.yaml
    
    **kubectl apply -f echo-service-nlb.yaml**
  • 정상 배포가 되었는지 확인합니다.
  • 배포한 로드밸런서 DNS Name을 확인해봅니다.
  • DNS Name을 변수 등록한 후에 분산 접속이 되는 지 확인해 봅니다.

Ingress


클러스터 내부의 서비스(ClusterIP, NodePort, Loadbalancer)를 외부로 노출(HTTP/HTTPS) - Web Proxy 역할

  • 인그레스 컨트롤러는 K8S API서버로부터 서비스의 엔드포인트 정보(파드 IP)를 획득 후 바로 파드의 IP로 연결
  • 지원되는 인그레스 컨트롤러 : Nginx, Traefix 등 현재 대부분의 인그레스 컨트롤러가 지원함

ingress도 배포해보겠습니다.

  • AWS LoadBalancer Controller 배포가 된 상태에서 진행했습니다.

  • 게임 파드와 Service, Ingress 배포

    curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/ingress1.yaml
    kubectl apply -f ingress1.yaml
  • ingress를 확인합니다.

  • ingress DNS name을 확인 한 후 접속을 진행해보겠습니다.

  • Ingress가 어떤 pod에 트래픽을 전송하는지 AWS 콘솔 내부 Target group에서 확인할 수 있습니다.
  • 그럼 파드를 3개로 늘리면 Target Group에 자동으로 pod ip가 추가 되는지 확인해보겠습니다.
    kubectl scale deployment -n game-2048 deployment-2048 --replicas 3
  • 바로 생성이 되는 것을 확인할 수 있습니다.
  • 그럼 1개로 줄이면 어떻게 되는지 보겠습니다.
    kubectl scale deployment -n game-2048 deployment-2048 --replicas 1
  • pod 2개를 바로 draining 시킨 것을 확인 할 수 있습니다.
profile
한량이 되고싶다..

0개의 댓글