본문 바로가기
Tech/Kubernetes

[PKOS_2기] 2주차 (네트워크)

by 구름_쟁이 2023. 3. 17.

본 시리즈는 가시다님의 PKOS(Production Kubernetes Online Study) 2기 진행 내용입니다.

스터디에 사용된 서적은 이정훈님의 24단계 실습으로 정복하는 쿠버네티스 입니다.

도서 링크 : http://www.yes24.com/Product/Goods/115187666

 

 

들어가기에 앞서
[AWS kOps 원클릭 배포 + AddOn 배포]

1주차에서 진행한 kops create cluster 와 기타 AddOn 배포 작업을 CloudFormation만으로 프로비저닝되도록 코드화(가시다님 작품)
앞으로의 실습은 원클릭 배포로 쿠버네티스 클러스터 구성을 진행할 예정

 

 

목차

     


    쿠버네티스 네트워크

     

     

     

    1. CNI (Container Network Interface)

    쿠버네티스는 컨테이너를 오케스트레이션하는 툴이다.

    그럼 쿠버네티스는 컨테이너의 네트워크 환경을 어떻게 구성할까?

    이것을 다루는 주제가 오늘의 CNI (Container Network Interface)이다.

    여러 애드온이 있지만, Calico가 가장 많이 쓰이고 Cilium 역시 성능에 대한 강점으로 많이 사용되고 있다.

    그 외에도 Flannel, WeaveNet 등이 있지만 개인적으로 Flannel은 쿠버네티스를 공부하는 단계에서는 비추천한다.

    Network Policy를 적용할 수 없기 때문이다.

     

    우리가 지금 실습하고 있는 환경은 AWS 이고, AWS에서는 자사 네트워크 시스템에 친화적인 CNI를 제공한다.

    그것이 바로 AWS VPC CNI 이다. 아래는 Calico CNI와 AWS VPC CNI의 비교표이다.

    AWS VPC CNI가 노드의 IP와 Pod의 IP가 같은 대역으로 구성되어, hop 수가 줄어 좀더 빠른 통신이 가능하다.

     

    일반적인 CNI의 경우 Pod간 통신 시 오버레이(VXLAN, IP-IP 등) 통신을 하고, AWS VPC CNI는 동일 대역으로 직접 통신한다.

     

    2. 워커 노드에 생성 가능한 최대 Pod 개수

    오버레이없이 AWS VPC IP대역을 점유하는 순간부터는 Pod 배포 개수에 대한 문제에서 자유로워질 수 없다.

    이것은 비단 kops에서 할당하는 Pod의 IP 대역 설정과는 별개로, 워커 노드의 Spec에 따라 결정되는 요소가 있다.

    쉽게 설명해서 원클릭 kOps 배포를 통해 Pod IP 대역을 172.30.0.0/16 로 설정했다면 Pod는 최대 65,534개 배포가 가능하다. (물론 기본적으로 배포되는 Pod를 제외한다면 그 수는 더 줄어들겠지만)

    백문이 불여일견, 80개의 Pod를 배포해보자.

    cat <<EOF | kubectl apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
    spec:
      selector:
        matchLabels:
          app: nginx
      replicas: 80
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: public.ecr.aws/nginx/nginx:1.21
            ports:
            - containerPort: 80
    EOF

    정상적으로 Running인 Pod의 수가 33개밖에 되지 않는다.

    제대로된 실습을 하기 전에 아래 명령어를 실행하여 컨테이너의 최소 보장 cpu 설정을 삭제한다.

    # (옵션) LimitRanges 기본 정책 삭제
    kubectl describe limitranges # LimitRanges 기본 정책 확인 : 컨테이너는 기본적으로 0.1CPU(=100m vcpu)를 최소 보장(개런티)
    kubectl delete limitranges limits
    kubectl get limitranges

    물론 이걸 삭제해도 당장에 아까 배포한  80개의 pod들의 Running Pod 개수가 33개에서 늘어나진 않는다.

     

     

    왜그럴까?
    그 이유는 AWS VPC CNI를 사용하는 경우 Pod를 생성할 때 노드의 
    kops 설정을 변경한 뒤에는 Node의 IP(Public/Private)가 변경된다.

     

    확인 시작.

    각 노드당 pod 개수가 100개 제한인데 현재 제대로 반영이 안되어 Pod 80대 중 33대만 Running인 것으로 보임
    kops edit cluster를 통해 maxPods 값을 100 -> 200 변경.

     

    # 적용을 위해서 반드시 노드 롤링업데이트 필요 : 삭제 -> 재생성, 이 과정에서 master node 의 IP(Public, Private) 가 자동으로 변경됨 >> 10분 정도 소요
    kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster --yes

     

    각 노드당 Pod 개수 제한이 200으로 변경됨
    80대 Pod가 모두 Running

    추가로 150까지 Pod 개수 증가

     

    수 분내로 150개까지 전부 Running 상태 확인

    순서가 꼬여서 제대로 검증이 안되는 것 같지만, 정리하자면 아래와 같다.

    Pod 배포 제한이 되는 항목

    1. 기본 limitranges limits = 컨테이너당 100m vcpu 보장

    2. 노드당 배포 가능한 Pod 개수 = kops 상 maxPods 100 설정

    3. 워커노드(EC2)의 유형에 따라 할당가능한 보조 프라이빗 IP 개수가 다름

    결론

    위 3가지 사항을 고려하면 원하는 만큼 Pod IP를 배포하거나 클러스터 구성에 대한 설계를 할 수 있다.

     


     

     

    Ingress

     

    2048 게임을 배포하고 AWS 로드밸런서에 어떻게 나타나는지 확인

    pod개수 조정 (3개)

    Pod개수 조정(3개->1개)

    2개의 대상이 draining 중

    보유한 도메인을 활용하여 최상위 루트(path)에서 2048 게임 플레이되도록 ingress 연동

     

     

    과제

    [도전] 목표 : Ingress(with 도메인, 단일 ALB 사용)에 PATH /mario 는 mario 게임 접속하게 설정하고, /tetris 는 tetris 게임에 접속하게 설정하고, SSL(https strip) 적용 해보세요

     

    결과 영상

     

    설정 확인

    로드밸런서

    443에 연결된 인증서

     

    HTTP:80 규칙

    HTTP:443 규칙

     

    인증서 상태

     

    작업 1 - 테트리스,마리오 앱 배포 및 Ingress 배포

    apiVersion: v1
    kind: Namespace
    metadata:
      name: games
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: deployment-tetris
      namespace: games
      labels:
        app: tetris
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: app-tetris
      template:
        metadata:
          labels:
            app: app-tetris
        spec:
          containers:
          - name: app-tetris
            image: bsord/tetris
    ---
    apiVersion: v1
    kind: Service
    metadata:
       name: service-tetris
       namespace: games
       annotations:
         alb.ingress.kubernetes.io/healthcheck-path: /tetris/index.html
    spec:
      selector:
        app: app-tetris
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      type: NodePort
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      namespace: games
      name: deployment-mario
      labels:
        app: mario
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: app-mario
      template:
        metadata:
          labels:
            app: app-mario
        spec:
          containers:
          - name: app-mario
            image: pengbai/docker-supermario
    ---
    apiVersion: v1
    kind: Service
    metadata:
      namespace: games
      name: service-mario
      annotations:
        alb.ingress.kubernetes.io/healthcheck-path: /mario/index.html
    spec:
      selector:
        app: app-mario
      ports:
      - port: 80
        targetPort: 8080
        protocol: TCP
      type: NodePort
      externalTrafficPolicy: Local
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      namespace: games
      name: ingress-games
      annotations:
        alb.ingress.kubernetes.io/scheme: internet-facing
        alb.ingress.kubernetes.io/target-type: ip
    spec:
      ingressClassName: alb
      rules:
        - host: ${WEBDOMAIN}
          http:
            paths:
            - path: /tetris
              pathType: Prefix
              backend:
                service:
                  name: service-tetris
                  port:
                    number: 80
            - path: /mario
              pathType: Prefix
              backend:
                service:
                  name: service-mario
                  port:
                    number: 80

    작업 2 - 테트리스,마리오 실행 경로 수정

    [테트리스]

    k exec -it $(kubectl get pod -n games| grep tetris | awk '{print $1}') -n games -- bash -c "mkdir -p /usr/share/nginx/html/tetris && mv /usr/share/nginx/html/* /usr/share/nginx/html/tetris"
    k exec -it $(kubectl get pod -n games| grep tetris | awk '{print $1}') -n games -- ls /usr/share/nginx/html
    k exec -it $(kubectl get pod -n games| grep tetris | awk '{print $1}') -n games -- ls /usr/share/nginx/html/tetris

    [마리오]

    k exec -it $(kubectl get pod -n games| grep mario | awk '{print $1}') -n games -- bash -c "mkdir -p /usr/local/tomcat/webapps/ROOT/mario && mv /usr/local/tomcat/webapps/ROOT/* /usr/local/tomcat/webapps/ROOT/mario"
    k exec -it $(kubectl get pod -n games| grep mario | awk '{print $1}') -n games -- ls /usr/local/tomcat/webapps/ROOT/
    k exec -it $(kubectl get pod -n games| grep mario | awk '{print $1}') -n games -- ls /usr/local/tomcat/webapps/ROOT/mario

    작업 편의성을 위하여 Deployment의 replicas는 1로 설정할 것

     

    작업 3 -  SSL 인증서 (ACM) 적용

    # ACM ARN 불러오기
    CERT_ARN=`aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn[]' --output text`
    echo $CERT_ARN
    # ACM ARN 적용하여 어노테이션 추가
    cat<<EOF | k apply -f -
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      namespace: games
      name: ingress-games
      annotations:
        alb.ingress.kubernetes.io/scheme: internet-facing
        alb.ingress.kubernetes.io/target-type: ip
        alb.ingress.kubernetes.io/certificate-arn: ${CERT_ARN}
        alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
        alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
        alb.ingress.kubernetes.io/healthcheck-port: traffic-port
        alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15'
        alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
        alb.ingress.kubernetes.io/success-codes: '200'
        alb.ingress.kubernetes.io/healthy-threshold-count: '2'
        alb.ingress.kubernetes.io/unhealthy-threshold-count: '2'
    spec:
      ingressClassName: alb
      rules:
        - host: ${WEBDOMAIN}
          http:
            paths:
            - path: /tetris
              pathType: Prefix
              backend:
                service:
                  name: service-tetris
                  port:
                    number: 80
            - path: /mario
              pathType: Prefix
              backend:
                service:
                  name: service-mario
                  port:
                    number: 80
    EOF

     

    과제 그 이후

    보통 http(80)으로 접속하게 되는 경우 https(443)으로 Redirection 해주는 것을 기본으로 하는데 이 부분도 개별 학습해야겠다.

     

    댓글