Kubernetes Engine을 사용한 배포 관리(with Jenkins)


  • 2019 클라우드 스터디 잼 입문반에서 진행하는 Kubernetes in the Google Cloud 퀵랩을 듣고 정리한 내용입니다

Intro

  • 지속적 배포, Blue Green 배포, 카나리 배포 같은 배포 시나리오에 대해 배울 예정
  • kubectl 도구 연습
  • 배포 yaml 파일 생성
  • 배포 실행, 업데이트, 확장
  • 배포 및 배포 스타일 업데이트 연습

배포

  • 서로 다른 2개 이상의 인프라 환경, 지역을 연결해 기술, 운영상의 요구를 해결
  • 배포 세부 사항에 따라 하이브리드, 멀티 클라우드, 공개-비공개 배포라고도 부름
  • 배포가 단일 환경, 지역으로 제한될 경우 발생하는 이슈
    • 리소스 한도 도달
    • 제한된 지리적 범위
      • 단일 환경이면 멀리 떨어진 사용자들이 모두 하나의 배포에 액세스해야됨
    • 제한된 가용성
    • 제공업체 종속
    • 경직된 리소스
  • 일회성 배포가 아닌 절차를 가진 배포를 설계해야 함
    • 반복 가능하고 프로비저닝, 구성, 유지보수에 있어 검증된 방식을 사용해야 함
  • 시나리오는 대표적으로 멀티 클라우드 배포, 프론트엔드 내부 데이터, 지속적 통합/지속적 배포 프로세스

실습

  • 샘플 코드 clone

      git clone https://github.com/googlecodelabs/orchestrate-with-kubernetes.git
      cd orchestrate-with-kubernetes/kubernetes
    
  • 5개의 n1-standard-1 노드를 갖는 클러스터 생성

      gcloud config set compute/zone us-central1-a
      gcloud container clusters create bootcamp --num-nodes 5 --scopes "https://www.googleapis.com/auth/projecthosting,storage-rw"
    

배포 객체 알아보기

  • 배포 객체 살펴보기

      kubectl explain deployment
    
  • 모든 필드를 보려면 --recursive 옵션 추가

      kubectl explain deployment --recursive
    
  • 배포 객체의 구조와 개별 필드 이해

      kubectl explain deployment.metadata.name
    

배포 만들기

  • image 변경

      vi deployments/auth.yaml
      i
    	
      containers:
      - name: auth
        image: kelseyhightower/auth:1.0.0
    
  • 배포 객체 생성

      kubectl create -f deployments/auth.yaml
    
  • 배포 확인

      kubectl get deployments
    
  • 배포 복제본 생성

      kubectl get replicasets
    
  • 복제본 세트가 생성되면 단일 포드 생성

      kubectl get pods
    
  • 인증 배포 서비스 생성

      kubectl create -f services/auth.yaml
    
  • hello 배포 만들고 노출

      kubectl create -f deployments/hello.yaml
      kubectl create -f services/hello.yaml
    
  • fronted 배포 생성하고 노출

      kubectl create secret generic tls-certs --from-file tls/
      kubectl create configmap nginx-frontend-conf --from-file=nginx/frontend.conf
      kubectl create -f deployments/frontend.yaml
      kubectl create -f services/frontend.yaml
    
  • 외부 IP를 선택한 후 curl로 상호 작용

      kubectl get services frontend
      curl -ks https://<EXTERNAL-IP>
    
  • kubectl의 출력 템플릿을 사용해 curl을 한 줄로 사용할 수 있음

      curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`
    

배포 확장

  • spec.replicas 필드를 업데이트해 확장
  • 필드 설명 확인

      kubectl explain deployment.spec.replicas
    
  • kubectl scale 명령을 사용해 replicas 필드 업데이트 가능

      kubectl scale deployment hello --replicas=5
    
  • 실행 중인 인증 포드 5개인지 확인

      kubectl get pods | grep hello- | wc -l
    
  • 애플리케이션 축소 후 확인

      kubectl scale deployment hello --replicas=3
      kubectl get pods | grep hello- | wc -l
    

지속적 업데이트

  • 이미지가 새 버전으로 업데이트 되도록 지원
  • 배포가 새 버전으로 업데이트되면 새로운 복제본 세트가 생성되고 기존 복제본 세트의 복제본이 줄어들며 새 복제본 세트의 복제본 수가 서서히 늘어남
  • 배포 업데이트

      kubectl edit deployment hello
    
  • image를 kelseyhightower/hello:2.0.0로 변경
  • 편집기에서 저장하면 업데이트된 배포가 클러스터에 저장되고 쿠버네티스에서 지속적 업데이트 시작
  • 새 복제본 세트 조회

      kubectl get replicaset
    
  • 롤아웃 내역에서 확인

      kubectl rollout history deployment/hello
    

지속적 업데이트 일시중지

kubectl rollout pause deployment/hello
  • 롤아웃 현재 상태 확인

      kubectl rollout status deployment/hello
    
  • 포드에서 확인

      kubectl get pods -o jsonpath --template='{range .items[*]}{.metadata.name}{"\t"}{"\t"}{.spec.containers[0].image}{"\n"}{end}'
    

지속적 업데이트 재개

  • 롤아웃이 일시중지되면 일부만 새 버전이고 나머지는 기존 버전으로 유지(resume 명령 사용)

      kubectl rollout resume deployment/hello
    
  • 상태 확인

      kubectl rollout status deployment/hello
    

업데이트 롤백

  • 새 버전에서 버그가 발견된 경우 새로운 포드에 연결된 사용자들이 문제를 겪음
  • 이전 버전으로 롤백해 조사하고 다시 수정된 버전을 릴리즈
  • rollout 명령을 사용해 롤백

      kubectl rollout undo deployment/hello
    
  • 롤백 확인

      kubectl rollout history deployment/hello
    
  • 모든 포드가 이전 버전으로 롤백되었는지 확인

      kubectl get pods -o jsonpath --template='{range .items[*]}{.metadata.name}{"\t"}{"\t"}{.spec.containers[0].image}{"\n"}{end}'
    

카나리 배포(Canary Releases)

  • 설명 글
  • 사용자 하위 집합을 사용해 프러덕션의 새 배포를 테스트를 사용하고싶은 경우 선택하는 방법
  • 소수의 사용자에 변경 사항을 릴리즈

카나리 배포 만들기

  • 새 버전의 별도 배포와 안정적인 일반 배포 및 카나리 배포로 이루어짐
  • 새 버전에 해당하는 카나리 배포 생성

      cat deployments/hello-canary.yaml
      kubectl create -f deployments/hello-canary.yaml
    
  • 확인

      kubectl get deployments
    
  • curl

      curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version
    

Blue-Green 배포

  • 지속적 업데이트는 최소한 오버헤드, 성능 영향, 다운타임으로 천천히 배포할 수 있어서 이상적
    • 완전히 배포된 후 새 버전을 가리키도록 부하 분산기를 수정하는 편이 유용할 경우가 존재하는데, 이 경우 Blue-Green 배포 사용
  • 기존 Blue 버전과 새로운 Green 버전의 배포를 각각 하나씩 생성해 구현
    • 새로운 Green 버전이 실행되면 서비스를 업데이트해 이 버전을 사용하도록 전환
  • 단점
    • 클러스터의 리소스가 2배 이상 필요
  • 서비스 업데이트

      kubectl apply -f services/hello-blue.yaml
    
  • Green 배포 버전 라벨 및 이미지 경로 업데이트

      apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
    name: hello-green
    spec:
    replicas: 3
    template:
      metadata:
        labels:
          app: hello
          track: stable
          version: 2.0.0
      spec:
        containers:
          - name: hello
            image: kelseyhightower/hello:2.0.0
            ports:
              - name: http
                containerPort: 80
              - name: health
                containerPort: 81
            resources:
              limits:
                cpu: 0.2
                memory: 10Mi
            livenessProbe:
              httpGet:
                path: /healthz
                port: 81
                scheme: HTTP
              initialDelaySeconds: 5
              periodSeconds: 15
              timeoutSeconds: 5
            readinessProbe:
              httpGet:
                path: /readiness
                port: 81
                scheme: HTTP
              initialDelaySeconds: 5
              timeoutSeconds: 1
    
  • Green 배포 생성

      kubectl create -f deployments/hello-green.yaml
    
  • 현재 버전 사용하는지 확인

      curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version
    
  • 서비스 업데이트

      kubectl apply -f services/hello-green.yaml
    
  • 서비스가 업데이트되는 즉시 Green 배포가 사용됨

      curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version
    

Blue-Green 롤백

  • 기존 버전으로 업데이트

      kubectl apply -f services/hello-blue.yaml
    
  • 서비스를 업데이트하면 롤백 성공

      curl -ks https://`kubectl get svc frontend -o=jsonpath="{.status.loadBalancer.ingress[0].ip}"`/version
    

Kubernetes Engine에서 Jenkins를 사용한 지속적 통합(Conitnuous Delivery)

  • 젠킨스를 사용해 지속적 통합을 진행
    • 빌드, 테스트, 배포의 파이프라인을 통합
  • 미리 선행해야 하는 일
    • 쿠버네티스 엔진 클러스터에 젠킨스 Provision
    • 젠킨스에 Helm Package Manager 설정
    • Feature들 탐험
    • 젠킨스 파이프라인 생성하고 테스트
  • Kubernetes Engine
    • GCP의 Managed Kbernetes
  • Jenkins
    • 빌드, 테스트, 배포 파이프라인을 유연하게 조절할 수 있는 도구
    • 프로젝트를 신속하게 반복할 수 있도록 지원
  • Repo 준비

      gcloud config set compute/zone us-central1-f
      git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git
      cd continuous-deployment-on-kubernetes
    

Provisioning Jenkins

  • Kubernetes 클러스터 생성

      gcloud container clusters create jenkins-cd \
    --num-nodes 2 \
    --machine-type n1-standard-2 \
    --scopes "https://www.googleapis.com/auth/projecthosting,cloud-platform"
    
  • 완료된 Task 테스트

      gcloud container clusters list
      gcloud container clusters get-credentials jenkins-cd
      kubectl cluster-info
      >>> is running at ~
    
  • Helm 설치

      wget https://storage.googleapis.com/kubernetes-helm/helm-v2.9.1-linux-amd64.tar.gz
      tar zxfv helm-v2.9.1-linux-amd64.tar.gz
    cp linux-amd64/helm .
      # permission
      kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
      # cluster-admin role
      kubectl create serviceaccount tiller --namespace kube-system
    kubectl create clusterrolebinding tiller-admin-binding --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
      ./helm init --service-account=tiller
      ./helm update
      # version 확인
      ./helm version
    
  • 젠킨스 설정 및 설치
    • 설정 Deploy

        ./helm install -n cd stable/jenkins -f jenkins/values.yaml --version 0.16.6 --wait
      
    • 젠킨스 pod 확인

        kubectl get pods
      
    • 젠킨스 UI에서 클라우드 쉘로 포워딩 설정

        export POD_NAME=$(kubectl get pods -l "component=cd-jenkins-master" -o jsonpath="{.items[0].metadata.name}")
      kubectl port-forward $POD_NAME 8080:8080 >> /dev/null &
      
    • 젠킨스 서비스 확인

        kubectl get svc
        >>> cd-jenkins         ClusterIP   10.11.255.161   <none>        8080/TCP    4m
        cd-jenkins-agent   ClusterIP   10.11.251.179   <none>        50000/TCP   4m
        kubernetes         ClusterIP   10.11.240.1     <none>        443/TCP     27m
      
  • 젠킨스 마스터가 요청할 때 빌더 노드가 필요할 때 자동으로 실행되도록 쿠버네티스 플러그인을 사용
    • 작업이 완료되면 자동으로 해제되고 리소스가 클러스터 리소스 풀에 다시 추가됨

젠킨스 연결

  • 실행

      printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
    
  • 포트 8080 생성

    • ID : admin, PW : 위에서 나온 것을 복붙

배포

  • Production : Live
  • Canary : samller-capacity site

      cd sample-app
      kubectl create ns production
      kubectl apply -f k8s/production -n production
      kubectl apply -f k8s/canary -n production
      kubectl apply -f k8s/services -n production
    
  • Production 환경 scale up

      kubectl scale deployment gceme-frontend-production -n production --replicas 4
    
  • fronted 설정

      kubectl get pods -n production -l app=gceme -l role=frontend
    
  • backend 설정

      kubectl get pods -n production -l app=gceme -l role=backend
    
  • 외부 IP 노출

      kubectl get service gceme-frontend -n production
    
  • Export

      export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)
    
  • Curl

      curl http://$FRONTEND_SERVICE_IP/version
    

젠킨스 파이프라인 생성

  • gceme 복사하고 Cloud Source Repository에 Push

      gcloud alpha source repos create default
    
  • Init

      git init
      git config credential.helper gcloud.sh
      git remote add origin https://source.developers.google.com/p/$DEVSHELL_PROJECT_ID/r/default
    
  • config

      git config --global user.email "[EMAIL_ADDRESS]"
      git config --global user.name "[USERNAME]"
    
  • add, commit, push

      git add .
      git commit -m "Initial commit"
      git push origin master
    

Reference


카일스쿨 유튜브 채널을 만들었습니다. 데이터 분석, 커리어에 대한 내용을 공유드릴 예정입니다.

PM을 위한 데이터 리터러시 강의를 만들었습니다. 문제 정의, 지표, 실험 설계, 문화 만들기, 로그 설계, 회고 등을 담은 강의입니다

이 글이 도움이 되셨거나 의견이 있으시면 댓글 남겨주셔요.

Buy me a coffeeBuy me a coffee





© 2017. by Seongyun Byeon

Powered by zzsza