개발자 네트워킹은 쉽던데 넌 왜... : AEWS - EKS Study 2주차 [ EKS Networking ]

Heihei·2023년 5월 6일
0

AEWS EKS STUDY

목록 보기
3/7
post-thumbnail

🎯 목표

  • EKS는 어떤 식으로 네트워킹이 이루어지는지에 대한 개념 확립

🏃 진행

👉 AWS VPC CNI

  • k8s 네트워크 환경을 구성하기 위해 k8s CNI 사용

  • 다양한 CNI 플러그인이 있지만, EKS에서 권장하는 플러그

    ❓ 왜 권장하는거죠 ❓

  • 일반적으로 파드 네트워크 / 노드 네트워크가 다름

  • 그래서 통신하려면 Calico CNI 처럼 오버레이 필요

  • 장애 발생 시 빠른 파악이 어려움

  • AWS VPC CNI는 노드 / 파드 IP가 같음

  • 인캡슐레이션 / 디캡슐레이션이 필요 없음

  • 그렇기 때문에 컴퓨팅 리소스 및 레이턴시 단축

  • 경로가 최적화 되고 운영하기 편함

실습준비 - EKS 배포

  • 스터디에서 제공 받은 Cloudformation Template으로 배포 완료

실습 1 - 네트워크 기본 정보 확인

  1. CNI 정보 확인
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
amazon-k8s-cni-init:v1.12.6-eksbuild.1

  1. kube-proxy config 확인 : 모드 iptables 사용
kubectl describe cm -n kube-system kube-proxy-config

  1. 노드 IP, 파드 IP 확인
  • 192.168.0.0 으로 진짜 노드,파드 IP가 같은 것 확인!
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

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

  1. 파드 이름 확인
kubectl get pod -A -o name

  1. 파드 갯수 확인
kubectl get pod -A -o name | wc -l


👉 노드 기본 네트워크

  • 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 과 연결되어 있음

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

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

  • 노드의 라우팅 정보 확인
ssh ec2-user@$N1 sudo ip -c route
ssh ec2-user@$N2 sudo ip -c route
ssh ec2-user@$N3 sudo ip -c route


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

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

실습 3 - 파드 간 통신 테스트 및 확인

  • 파드1,2,3 Shell에서 각자 다른 파드로 ping 테스트 하여 통신 되는 것 확인

👉 파드에서 외부 통신

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

실습 4 - 파드에서 외부 통신 테스트 및 확인

👉 노드에 파드 생성 개수 제한

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

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

🥕 이 부분은 설명을 들어도 어렵.. 우선 개수가 제한 되어 있다는 것만 알고 넘어가보자!

👉 Service & AWS LoadBalancer Controller

서비스란?
Pod의 IP가 바뀔 확률이 높기 때문에, 고정 진입점을 만들기 위해 필요한 오브젝트

서비스 종류 - ClusterIP, NodePort, LoadBalancer(기본 모드), LoadBalancer Controller

clusterIP

  • 각각의 파드에 접근하기 위한 virtual IP 생성
  • Test Pod가 ClusterIP에 접근 시 랜덤으로 각각의 파드에 로드 밸런싱
  • 쿠버네티스 클러스터에서만 접근
  • IP와 DNS 두 가지 제공

nodePort

  • 쿠버네티스가 배포되지 않은 외부 클라이언트에서 노드 포트에 접근하면 클러스터IP가

LoadBalancaer(기본 모드)

  • CLB나 NLB 형태의 로드밸런서에 들어오고, 노드포트를 타고 분산
  • 컨트랙트라는 자원을 계속 소모함

LoadBalancer Controller

  • NLB가 노드포트를 타지 않고 pod IP로 바로 접근
    • AWS VPC CNI로 노드/파드가 결합되어 있기 때문에 가능
  • 로드밸런서를 컨트롤 하기 위한 파드가 생성됨
  • 생성 된 파드를 통해 AWS의 NLB가 생성, 제거 됨

    ❗️타겟그룹 설정 시 주의사항

    1. 인스턴스 유형
    • externalTrafficPolicy : ClusterIP ⇒ 2번 분산 및 SNAT으로 Client IP 확인 불가능 ← LoadBalancer 타입 (기본 모드) 동작
    • externalTrafficPolicy : Local ⇒ 1번 분산 및 ClientIP 유지, 워커 노드의 iptables 사용함
    1. IP 유형 ⇒ 반드시 AWS LoadBalancer 컨트롤러 파드 및 정책 설정이 필요함!
      • Proxy Protocol v2 비활성화 ⇒ NLB에서 바로 파드로 인입, 단 ClientIP가 NLB로 SNAT 되어 Client IP 확인 불가능
      • Proxy Protocol v2 활성화 ⇒ NLB에서 바로 파드로 인입 및 ClientIP 확인 가능(→ 단 PPv2 를 애플리케이션이 인지할 수 있게 설정 필요)

실습 5 - AWS LoadBalancer Controller 배포 with IRSA

  1. OIDC 확인
aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text
aws iam list-open-id-connect-providers | jq


2. 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


3. Helm Chart를 이용하여 LoadBalancer controller pod 배포

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


4. LoadBalancer controller pod 배포 확인

kubectl get crd
kubectl get deployment -n kube-system aws-load-balancer-controller
kubectl describe deploy -n kube-system aws-load-balancer-controller
kubectl describe deploy -n kube-system aws-load-balancer-controller | grep 'Service Account'


5. 2번에서 부여해준 정책이 제대로 적용 되었는지 role 확인

kubectl describe clusterrolebindings.rbac.authorization.k8s.io aws-load-balancer-controller-rolebinding
kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role

실습 6 - 서비스/파드 배포 테스트 with NLB

  1. 디플로이먼트 & 서비스 생성
  • 왼쪽 세션에서 모니터링으로 디플로이먼트와 서비스가 생성 되는 것을 확인
# 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/2/echo-service-nlb.yaml
cat echo-service-nlb.yaml | yh
kubectl apply -f echo-service-nlb.yaml

# 모니터링
watch -d kubectl get pod,svc,ep

  1. 컨트롤러가 생성한 ELB 확인
kubectl get deploy,pod
kubectl get svc,ep,ingressclassparams,targetgroupbindings
kubectl get targetgroupbindings -o json | jq

  1. AWS ELB 정보 확인
aws elbv2 describe-load-balancers | jq
aws elbv2 describe-load-balancers --query 'LoadBalancers[*].State.Code' --output text

  1. 웹 접속 주소 확인
kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Pod Web URL = http://"$1 }'

  1. 파드 로깅 모니터링과 함께 분산 접속 확인
  • NLB로 요청을 100번 보냈을 때, 2개의 파드에 51/49 번의 요청으로 나뉘어져서 분산 되는 것 확인
# 모니터링
kubectl logs -l app=deploy-websrv -f

# 분산 접속 확인
NLB=$(kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname})
curl -s $NLB
for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr

👉 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
               

👉 ExternalDNS

  • K8S 서비스/인그레스 생성 시 도메인을 설정하면, AWS(Route 53), Azure(DNS), GCP(Cloud DNS) 에 A 레코드(TXT 레코드)로 자동 생성/삭제
profile
모르면 배우면 된다!

0개의 댓글