[aews] EKS Networking

xgro·2023년 5월 1일
1

AEWS

목록 보기
2/7

📌 Review

AEWS 스터디는 [PKOS 스터디]와 비슷한 내용으로 구성되어 있습니다. K8s 클러스터를 운영하기 위해서 알아야하는 기본적인 네트워크 지식을 한번더 스터디하며 그때는 이해하지 못하고 넘어간 부분들이 지금에 와서는 조금더 눈에 들어오기 시작했습니다.

🎤 Speech

2주차는 육용수 님과 고재성 님의 경험발표를 들을 수 있었습니다.

육용수님은 EKS 템플릿을 테라폼으로 구축하는 경험을 공유해주셨습니다.

고재성님은 AWS 신상 서비스인 VPC Latteci에 대해서 설명해주시고 핸즈온을 직접 시연해주셨습니다.

📌 Summary

  • 2주차는 쿠버네티스의 Network에 대해서 스터디 하였습니다.
  • K8S CNI - AWSVPC를 사용하는 경우 강점에 대해서 정리할 수 있습니다.
  • Service & AWS LoadBalancer Controller를 직접 배포하여 AWS NLB를 이용할 수 있습니다.

PKOS 스터디를 통해 한번 진행한 내용이므로, 간단하게 중요한 내용 위주로 정리하였습니다.

📌 Study

👉 Step 00. 실습 환경 배포

가시다님의 원클릭 실습 배포 Cloudformation Template를 이용하여 손쉽게 배포하였습니다.

배포가 완료된 아키텍처는 아래와 같습니다.

Architecture

👉 Step 01. AWS VPC CNI 소개

AWS를 이용하는 경우 AWSVPC CNI를 이용할 수 있습니다.

다양한 플러그인이 존재하지만, 대표적으로 많이 사용하는 Calico CNI 등 여러 플러그인과 대조되는 차이점으로는

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

  • VPC 와 통합 : VPC Flow logs , VPC 라우팅 정책, 보안 그룹(Security group) 을 사용 가능함
  • This plugin assigns an IP address from your VPC to each pod.
  • VPC ENI 에 미리 할당된 IP(=Local-IPAM Warm IP Pool)를 파드에서 사용할 수 있음

여러가지 장점이 있습니다.

Important !!

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

이를 통해 패킷을 위한 오버헤드를 줄여 네트워크 성능을 향상할 수 있습니다.

👉 Step 02. 노드에서 기본 네트워크 정보 확인

  • 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 과 연결되어 있습니다

실습

네트워크 정보를 확인합니다.

👉 Step 03. 서로 다른 노드에 배포된 파드 간 통신

서로 다른 노드에 배포 되어있는 파드간 통신에서 AWS VPC CNI 경우 별도의 오버레이(Overlay) 통신 기술 없이, VPC Native 하게 파드간 직접 통신이 가능합니다.

Architecture

Life of a Pod to Pod Ping Packet

👉 Step 04. 파드에서 외부 통신

iptable의 SNAT 을 통하여 노드의 eth0 IP로 변경되어서 외부와 통신하게 됩니다.

Architecture

실습

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

파드 shell 실행 후 외부로 ping 테스트 & 워커 노드에서 tcpdump 및 iptables 정보 확인 합니다.

Iptable의 내용을 조회하면 현재 사용중인 CIDR를 제외한 연결은 SNAT으로 향하도록 설정된 내용을 확인 할 수 있습니다.

👉 Step 05. 노드에 파드 생성 갯수 제한

Secondary IPv4 addresses (기본값) : 인스턴스 유형에 최대 ENI 갯수와 할당 가능 IP 수를 조합하여 선정합니다. PKOS 스터디때도 이부분이 제일 이해하기 힘들었습니다.

👉🏻 최대 파드 생성 갯수 : (Number of network interfaces for the instance type × (the number of IP addressess per network interface - 1)) + 2

실습
파드 50개 배포시 Pending 됨을 확인할 수 있습니다.

👉 Step 06. Service & AWS LoadBalancer Controller

쿠버네티스에서는 서비스로 ClusterIP NodePort Loadbalancer 등 다양한 형태의 리소스가 존재합니다.

이중 LoadBalancer Controller 에 대해서 정리하겠습니다.

Service - LoadBalancer Controller

다른 서비스와 차이점은 Load Balancer를 컨트롤 하기위한 파드가 생성되며, 이 파드를 통해 AWS의 NLB가 사용자의 요청에 의해 생성, 제거 됩니다.

또한, AWS NLB에서 노드의 IP를 통해 파드로 트래픽이 전달되는 것이 아닌, 파드의 IP에 직접 트래픽을 전달하는 것을 볼 수 있습니다.

AWS NLB 모드에서의 타겟그룹 설정시 주의사항 입니다.

  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 를 애플리케이션이 인지할 수 있게 설정 필요)

실습

AWS Loadbalancer 컨트롤러 파드를 Helm 차트를 이용하여 배포합니다.

요청에 따라, 적절하게 ELB를 생성, 삭제 등 컨트롤 할 수 있어야 하므로, 동작에 필요한 Policy가 부여되어 있는것을 확인 할 수 있습니다.

Deployment를 생성하여 NLB의 동작을 확인합니다.

배포 후 NLB의 주소로 요청을 보내면 아래와 같이 로드밸런싱 동작이 잘 수행되는것을 확인할 수 있습니다.

👉 Step 07. Ingress

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

역시 alb를 확인하면 pod의 ip로 직접 통신하는것을 확인할 수 있습니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: game-2048
  name: ingress-2048
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: service-2048
              port:
                number: 80

👉 Step 08. ExternalDNS

K8S 서비스/인그레스 생성 시 도메인을 설정하면, AWS(Route 53), Azure(DNS), GCP(Cloud DNS) 에 A 레코드(TXT 레코드)로 자동 생성/삭제 합니다.

실습 - tetris ExternelDNS 사용하여 배포하기
externelDNS 기능을 이용해서, k8s 리소스의 설정만으로 도메인을 할당할 수 있는 것을 확인할 수 있습니다.

✅ Assignment

SSL 이용하여 NLB에 Https 적용

Tetris를 tetris.<자신의 도메인>으로 배포하며 NLB에서 SSL 적용하여 https 통신을 하는 실습을 추가로 진행 하였습니다.


# 도메인 및 HTTPS 적용을 위한 ACM 변수 설정
MyDomain=<도메인 이름>
MyDomain=xgro.be

CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
echo $MyDomain $CERT_ARN

# 테트리스 배포
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tetris
  labels:
    app: tetris
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tetris
  template:
    metadata:
      labels:
        app: tetris
    spec:
      containers:
      - name: tetris
        image: bsord/tetris
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: tetris
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
    # service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "80"
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "${CERT_ARN}"
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
    external-dns.alpha.kubernetes.io/hostname: "tetris.${MyDomain}"
spec:
  selector:
    app: tetris
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    name: http
  - port: 443
    targetPort: 80
    protocol: TCP
    name: https
  type: LoadBalancer
  loadBalancerClass: service.k8s.aws/nlb
EOF

결과

도메인이 https 프로토콜을 이용하여 연결되는것을 확인할 수 있습니다.

📌 Reference

AWS Docs - https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html
ExternelDNS - https://edgehog.blog/a-self-hosted-external-dns-resolver-for-kubernetes-111a27d6fc2c
AWSVPC_CNI - https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md

profile
안녕하세요! DevOps 엔지니어 이재찬입니다. 블로그에 대한 피드백은 언제나 환영합니다! 기술, 개발, 운영에 관한 다양한 주제로 함께 나누며, 더 나은 협업과 효율적인 개발 환경을 만드는 과정에 대해 인사이트를 나누고 싶습니다. 함께 여행하는 기분으로, 즐겁게 읽어주시면 감사하겠습니다! 🚀

0개의 댓글