PKOS 2기 2주차 학습 스터디-2

Louis·2023년 3월 18일
0

PKOS 2기

목록 보기
3/7
post-thumbnail

2023년 3월 6일부터 @cloudnet study를 시작 하였다.

[24단계 실습으로 정복하는 쿠버네티스][이정훈 지음]의 책을 기본으로 학습을 한다.

운영을 하면서도 부족한 부분을 배울 수 있을 것이란 기대감과 함께 시작한 수업이나 숙제를 하지 못해서 발생하는 불상사를 경험하지 않고 5주간의 스터디를 잘 마무리 했으면 좋겠다.

2주차 스터디 내용을 정리해 본다.

2주차에는 네트워크와 스토리지 관련 내용을 스터디 하고 실습 진행하였다.

K8S Service & AWS LoadBalancer Controller

K8S가 통신하기 위해서는 다양한 서비스 방식이 있다

  • ClusterIP

  • NodePort

  • LoadBalancer - On-Prem 일 경우 - MetalLB 와 같은 솔루션 활용

  • LoadBalancer - AWS NLB 인스턴스 유형
    • 인스턴스 NodePort를 활용 하기때문에 iptables를 조회해서 서비스하는 파드에 접속을 하게 된다

AWS with NLB

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

통신 흐름

요약 : 외부 클라이언트가 '로드밸런서' 접속 시 부하분산 되어 노드 도달 후 iptables 룰로 목적지 파드와 통신됨

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

부하분산 최적화 : 노드에 파드가 없을 경우 '로드밸런서'에서 노드에 헬스 체크(상태 검사)가 실패하여 해당 노드로는 외부 요청 트래픽을 전달하지 않는다

    3번째 인스턴스(Node3)은 상태 확인 실패로 외부 요청 트래픽 전달하지 않는다
    
  1. IP 유형 ⇒ 반드시 AWS LoadBalancer 컨트롤러 파드 및 정책 설정이 필요함!
    1. Proxy Protocol v2 비활성화 ⇒ NLB에서 바로 파드로 인입, 단 ClientIP가 NLB로 SNAT 되어 Client IP 확인 불가능
    2. Proxy Protocol v2 활성화 ⇒ NLB에서 바로 파드로 인입 및 ClientIP 확인 가능(→ 단 PPv2 를 애플리케이션이 인지할 수 있게 설정 필요)

실습

  • 스터디를 통해서 실습한 내용은 AWS VPC CNI와 NLB IP 모드를 연동한 서비스 구성이다
  • 파드 배포
kubectl apply -f ~/pkos/2/echo-service-nlb.yaml
  • 파드 생성 확인

  • pod ip와 NLB 대상 IP 확인

  • 접속 URL 확인

  • 웹 접속 확인
     
  • external-dns 등록후 접속 확인

  • 실제 NLB를 통해서 접속하는지 확인
    (hj-devstory:N/A) [root@kops-ec2 ~]# for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
         52 Hostname: deploy-echo-5c4856dfd6-m2pfq
         48 Hostname: deploy-echo-5c4856dfd6-j2srr
  • 파드를 줄이고 늘려서 실제로 NLB 대상에 정상적으로 제거되고 등록하는지 확인해보겠다

  • 이럴수가… 파드가 하나 줄어들자 마자 등록 대상에서 draining 되는걸 확인 할 수 있었다.

  • 파드의 갯수를 3개로 늘려보겠다

  • 등록 대상에 당연히 3개로 늘어나는 것을 기대하면서도 놀랍기 그지 없다.
    initial 상태를 거쳐서 정상 등록 되는 것을 확인 할 수 있고 요청도 3개의 파드에 분산되어서 동작하는 것을 확인 할 수 있다.

```jsx
(hj-devstory:N/A) [root@kops-ec2 ~]# for i in {1..100}; do curl -s --connect-timeout 1 nginx.$KOPS_CLUSTER_NAME | grep Hostname ; done | sort | uniq -c | sort -nr
     35 Hostname: deploy-echo-5c4856dfd6-j2srr
     35 Hostname: deploy-echo-5c4856dfd6-657mh
     30 Hostname: deploy-echo-5c4856dfd6-xnlh9

(hj-devstory:N/A) [root@kops-ec2 ~]# for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
     40 Hostname: deploy-echo-5c4856dfd6-657mh
     30 Hostname: deploy-echo-5c4856dfd6-xnlh9
     30 Hostname: deploy-echo-5c4856dfd6-j2srr
```
  • 실제로 파드와 svc, ep를 확인하면 다음과 같다
    (hj-devstory:N/A) [root@kops-ec2 ~]# kubectl get deploy,pod,svc,ep
    NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/deploy-echo   3/3     3            3           17m
    
    NAME                               READY   STATUS    RESTARTS   AGE
    pod/deploy-echo-5c4856dfd6-657mh   1/1     Running   0          80s
    pod/deploy-echo-5c4856dfd6-j2srr   1/1     Running   0          17m
    pod/deploy-echo-5c4856dfd6-xnlh9   1/1     Running   0          80s
    
    NAME                      TYPE           CLUSTER-IP      EXTERNAL-IP                                                                         PORT(S)        AGE
    service/kubernetes        ClusterIP      100.64.0.1      <none>                                                                              443/TCP        26m
    service/svc-nlb-ip-type   LoadBalancer   100.67.189.29   k8s-default-svcnlbip-1b0774e7de-c085c0594dd7698c.elb.ap-northeast-2.amazonaws.com   80:31462/TCP   17m
    
    NAME                        ENDPOINTS                                                  AGE
    endpoints/kubernetes        172.30.38.251:443                                          26m
    endpoints/svc-nlb-ip-type   172.30.60.147:8080,172.30.60.148:8080,172.30.91.178:8080   17m

이렇게 자동적으로 등록되는 원리는?

  • 다음 aws-load-balancer-controller가 NLB와 K8S 클러스터의 정보를 얻어와서 NLB에 등록 삭제를 하는것이다. 이 동작을 위해서 2가지 권한이 필요하다

    NAME                                            READY   STATUS    RESTARTS	AGE
    aws-cloud-controller-manager-nm8df              1/1     Running   0             35m
    aws-load-balancer-controller-54f484d865-gbzxh   1/1     Running   0             35m
    • AWS에서도 로드발랜서를 컨트롤 할 수 있는 권한

      aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME
      aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME
    • K8S 클러스터에서도 파드 정보와 상태, 기타 정보등을 볼 수 있는 권한이 필요한 것이다.
      노드에 직접 접속해서 정보를 얻는게 아닌 K8S API를 활용해서 정보들을 얻어오는 것이다.

      ```jsx
      (hj-devstory:N/A) [root@kops-ec2 ~]# kubectl describe clusterrolebindings.rbac.authorization.k8s.io aws-load-balancer-controller-rolebinding
      Name:         aws-load-balancer-controller-rolebinding
      Labels:       addon.kops.k8s.io/name=aws-load-balancer-controller.addons.k8s.io
                    app.kubernetes.io/managed-by=kops
                    app.kubernetes.io/name=aws-load-balancer-controller
                    k8s-addon=aws-load-balancer-controller.addons.k8s.io
      Annotations:  <none>
      Role:
        Kind:  ClusterRole
        Name:  aws-load-balancer-controller-role
      
      Subjects:
        Kind            Name                          Namespace
        ----            ----                          ---------
        ServiceAccount  aws-load-balancer-controller  kube-system
      ```
      
      ```jsx
      (hj-devstory:N/A) [root@kops-ec2 ~]# kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role
      Name:         aws-load-balancer-controller-role
      Labels:       addon.kops.k8s.io/name=aws-load-balancer-controller.addons.k8s.io
                    app.kubernetes.io/managed-by=kops
                    app.kubernetes.io/name=aws-load-balancer-controller
                    k8s-addon=aws-load-balancer-controller.addons.k8s.io
      Annotations:  <none>
      PolicyRule:
        Resources                                 Non-Resource URLs  Resource Names  Verbs
        ---------                                 -----------------  --------------  -----
        targetgroupbindings.elbv2.k8s.aws         []                 []              [create delete get list patch update watch]
        events                                    []                 []              [create patch]
        services                                  []                 []              [get list patch update watch]
        ingresses.extensions                      []                 []              [get list patch update watch]
        ingresses.networking.k8s.io               []                 []              [get list patch update watch]
        endpoints                                 []                 []              [get list watch]
        namespaces                                []                 []              [get list watch]
        nodes                                     []                 []              [get list watch]
        pods                                      []                 []              [get list watch]
        endpointslices.discovery.k8s.io           []                 []              [get list watch]
        ingressclassparams.elbv2.k8s.aws          []                 []              [get list watch]
        ingressclasses.networking.k8s.io          []                 []              [get list watch]
        pods/status                               []                 []              [patch update]
        services/status                           []                 []              [patch update]
        targetgroupbindings.elbv2.k8s.aws/status  []                 []              [patch update]
        ingresses.extensions/status               []                 []              [patch update]
        ingresses.networking.k8s.io/status        []                 []              [patch update]
      ```

결론

  • 클러스터를 구성 할 시에 필요한 CNI를 잘 선택해서 구성하는게 중요하다.
  • EC2 인스턴스에 클러스터를 구성 한 후 LB를 붙여야 하는 상황에서 검토하면 좋은 & 훌륭한 구성인 듯 하다.
  • LB와 인트턴스를 구성하는데 수작업을 하다보면 시룻와 빠지는 경우가 많이 있었는데 이러한 방식으로 자동 구성이 가능 하다면 운영의 효율이 정말 높아질 것 같다.
profile
인프라 운영하는 개발자

0개의 댓글