Kubernetes Engine을 사용한 배포 관리(with Jenkins)
in Development on Kubernetes
- 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
카일스쿨 유튜브 채널을 만들었습니다. 데이터 사이언스, 성장, 리더십, BigQuery 등을 이야기할 예정이니, 관심 있으시면 구독 부탁드립니다 :)
PM을 위한 데이터 리터러시 강의를 만들었습니다. 문제 정의, 지표, 실험 설계, 문화 만들기, 로그 설계, 회고 등을 담은 강의입니다
이 글이 도움이 되셨거나 다양한 의견이 있다면 댓글 부탁드립니다 :)