[쿠버네티스 실습] Blue-Green 배포

Jiwan Ahn·2023년 6월 6일
0

쿠버네티스

목록 보기
2/2

이전 글의 마지막에서 설명한 Blue-Green 배포를 하고, 웹사이트를 통해 직접 확인해보자

시작하기 전

  • 위 실습은 minikube로 실습하므로, 웹사이트 실습 부분에서 약간의 차이점이 존재한다.
  • minikube에서 가동하는 Kubernetes는 minikube VM 내에서 작동하므로 외부에서 접근하려면 별도의 방법이 필요하다. (minikube ssh)
  • Docker Desktop등, minikube를 사용하지 않는다면 NodePort로 Expose시 localhost:(포트번호)로 바로 접속할 수 있따.

블루-그린 배포란?

: 운영중인 구버전과 동일하게 신버전의 인스턴스를 구성한 후 로드밸런서를 통해 모든 트래픽을 한번에 신버전 쪽으로 전환하는 방식이다.

  • 구버전의 인스턴스가 그대로 남아있어, 손쉬운 롤백 가능

  • 구버전의 환경을 다음 배포에 재사용 가능

  • 운영환경에 영향을 주지 않고 새 버전 테스트 가능

  • 시스템 자원이 두 배로 필요하다

  • 새로운 환경에 대한 테스트가 전제가 되어야 한다.


Blue-Green 배포 실습

디플로이먼트 생성

: nginx1.11 (Blue)와 nginx1.12 (Green) 배포를 진행해보자.

  • nginx v1.11 디플로이먼트 생성
vi nginx11.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx11
spec:
  replicas: 3
  selector:
    matchLabels:
      app: deploy-nginx11
  template:
    metadata:
      labels:
        app: deploy-nginx11
    spec:
      containers:
      - name: deploy-nginx11
        image: nginx:1.11
kubectl apply -f nginx11.yaml
  • nginx v1.12 디플로이먼트 생성
vi nginx12.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx12
spec:
  replicas: 3
  selector:
    matchLabels:
      app: deploy-nginx12
  template:
    metadata:
      labels:
        app: deploy-nginx12
    spec:
      containers:
      - name: deploy-nginx11
        image: nginx:1.12
kubectl apply -f nginx12.yaml
  • nginx v1.11의 index.html 내용 변경
for pod in $(kubectl get pod -l app=deploy-nginx11 |awk 'NR>1 {print $1}'); do kubectl exec $pod -- /bin/sh -c "hostname > /usr/share/nginx/html/index.html; echo 'nginx:v1.11 END' >> /usr/share/nginx/html/index.html"; done
  • nginx v1.12의 index.html 내용 변경
for pod in $(kubectl get pod -l app=deploy-nginx12 |awk 'NR>1 {print $1}'); do kubectl exec $pod -- /bin/sh -c "hostname > /usr/share/nginx/html/index.html; echo 'nginx:v1.12 END' >> /usr/share/nginx/html/index.html"; done

⇒ curl을 통해 접속 시, 파드 이름과 버전, 그리고 END로 표시가 되도록 수정한다.

이제 nginx v1.11과 nginx v1.12가 제대로 생성되었는지 확인해보자.

kubectl get pod -o wide -l app=deploy-nginx11 |awk 'NR>1 {print $6}'
10.1.0.19
10.1.0.18
10.1.0.20
kubectl get pod -o wide -l app=deploy-nginx12 |awk 'NR>1 {print $6}'
10.1.0.23
10.1.0.21
10.1.0.22
minikube ssh

⇒ minkube를 사용하면 외부에서 curl을 통해 pod에 접속이 되지 않으므로, minikube의 VM에 직접 접속하여 curl을 시도해야 한다.

  • nginx v1.11의 podIP로 접속 시도
curl -s "위에서 nginx11 podIP 중 하나 선택"
deploy-nginx11-6489d4db8b-kbdj4
nginx:v1.11 END
  • nginx v1.12의 podIP로 접속 시도
curl -s "위에서 nginx12 podIP 중 하나 선택"
deploy-nginx12-b5c6679d6-dn5kc
nginx:v1.12 END
exit

서비스 생성

  • ClusterIP 서비스를 생성하여 nginx v1.11 파드들의 엔드포인트를 제공하자.
vi svc-nginx.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
spec:
  ports:
    - name: svc-nginx
      port: 9000
      targetPort: 80
  selector:
    app: deploy-nginx11

⇒ Type 지정을 하지 않을 시, 기본 Type은 ClusterIP가 된다.

kubectl apply -f svc-nginx.yaml
kubectl get service svc-nginx
kubectl get service svc-nginx -o jsonpath='{.spec.clusterIP}' ; echo

NAME        TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
svc-nginx   ClusterIP   10.108.8.47   <none>        9000/TCP   19s
10.108.8.47

⇒ 서비스 생성 확인 및 ClusterIP의 주소를 확인한다.

  • 현재 상황

⇒ 어떠한 딜레이 없이 모든 엔드포인트가 바로 오른쪽 그린 배포로 옮겨져야 한다.

  • ClusterIP에 연결된 엔드포인트를 확인한다.
kubectl get endpoints svc-nginx

NAME        ENDPOINTS                                AGE
svc-nginx   10.1.0.18:80,10.1.0.19:80,10.1.0.20:80   3m1s

⇒ 파드들의 IP와 비교한 결과 엔드포인트가 잘 연결되어있음을 알 수 있다.

kubectl get pod -o wide -l app=deploy-nginx11 |awk 'NR>1 {print $6}'
10.1.0.19
10.1.0.18
10.1.0.20
  • 터미널 하나를 별도로 열어 Blue 배포에 있는 파드의 로그를 실시간으로 확인해보자.
kubectl logs -l 'app in (deploy-nginx11)' -f --max-log-requests 8
  • 또 하나의 터미널을 열어 Green 배포에 있는 파드의 로그를 실시간으로 확인한다.
kubectl logs -l 'app in (deploy-nginx12)' -f --max-log-requests 8
  • minikube bash에서 ClusterIP를 통해 curl -s를 반복적으로 실행한다.
minikube ssh
SVC="서비스의 ClusterIP를 넣어주세요. 큰 따옴표 지워주셔야 합니다."
for i in {1..100}; do curl -s $SVC:9000 ; done | sort | uniq -c | sort -nr
while true; do curl -s --connect-timeout 1 $SVC:9000 ; echo "--------------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done

2023-05-24 04:43:00
deploy-nginx11-6489d4db8b-rnmb9
nginx:v1.11 END
--------------
2023-05-24 04:43:01
deploy-nginx11-6489d4db8b-vwzj8
nginx:v1.11 END
--------------
2023-05-24 04:43:02
deploy-nginx11-6489d4db8b-vwzj8
nginx:v1.11 END
--------------
2023-05-24 04:43:03
deploy-nginx11-6489d4db8b-kbdj4
nginx:v1.11 END
--------------
2023-05-24 04:43:04
deploy-nginx11-6489d4db8b-rnmb9
nginx:v1.11 END

⇒ Blue 배포 파드의 로그는 기록되는 반면 Green 배포의 로그는 기록되지 않음을 알 수 있다.

=> Blue 배포 로그

=> Green 배포 로그

그럼 이제 Green 배포로 바꿔보자.

kubectl get svc svc-nginx -o yaml | sed -e "s/app: deploy-nginx11/app: deploy-nginx12/" | kubectl apply -f -
minikube ssh
SVC="서비스의 ClusterIP를 넣어주세요. 큰 따옴표 지워주셔야 합니다."
e
2023-05-24 04:51:25
deploy-nginx12-b5c6679d6-jf9zh
nginx:v1.12 END
--------------
2023-05-24 04:51:26
deploy-nginx12-b5c6679d6-j2qdp
nginx:v1.12 END
--------------
2023-05-24 04:51:27
deploy-nginx12-b5c6679d6-jf9zh
nginx:v1.12 END
--------------
2023-05-24 04:51:28
deploy-nginx12-b5c6679d6-dn5kc
nginx:v1.12 END
--------------
2023-05-24 04:51:29
deploy-nginx12-b5c6679d6-dn5kc
nginx:v1.12 END

⇒ 이번엔 Blue 배포의 로그는 기록되지 않고 Green 배포가 출력되고 있음을 확인할 수 있다.

  • 이전 Blue 버전으로 롤백을 하려면 다음과 같이 명령어를 실행한다.
kubectl get svc svc-nginx -o yaml | sed -e "s/app: deploy-nginx12/app: deploy-nginx11/" | kubectl apply -f -

NodePort를 통한 웹사이트 확인

더 확실하게 표시하기 위해 NodePort를 통해 외부로 노출시켜 보자.

  • svc-nginx 서비스의 종류를 NodePort로 변경한다.
kubectl edit svc svc-nginx
...
ports:
  - name: svc-nginx
    port: 9000
    protocol: TCP
    targetPort: 80
  selector:
    app: deploy-nginx11
  sessionAffinity: None
  type: ClusterIP # NodePort로 변경
:wq

service/svc-nginx edited
kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          24h
svc-nginx    NodePort    10.99.240.247   <none>        9000:30653/TCP   92s

minikube로 쿠버네티스를 실행 시, minikube 가상 머신 안에서 돌아가기 때문에 여전히 외부로 접속이 불가능하므로, minikube 자체에서 서비스를 노출시켜야 한다.

minikube service svc-nginx

|-----------|-----------|----------------|---------------------------|
| NAMESPACE |   NAME    |  TARGET PORT   |            URL            |
|-----------|-----------|----------------|---------------------------|
| default   | svc-nginx | svc-nginx/9000 | http://192.168.49.2:30653 |
|-----------|-----------|----------------|---------------------------|
🏃  svc-nginx 서비스의 터널을 시작하는 중
|-----------|-----------|-------------|------------------------|
| NAMESPACE |   NAME    | TARGET PORT |          URL           |
|-----------|-----------|-------------|------------------------|
| default   | svc-nginx |             | http://127.0.0.1:53653 |
|-----------|-----------|-------------|------------------------|
🎉  Opening service default/svc-nginx in default browser...
❗  Because you are using a Docker driver on darwin, the terminal needs to be open to run it.

⇒ 터미널을 계속 열어야 하므로, 새로운 터미널 창을 열어 마저 실습한다.

  • Green 배포 전환
kubectl get svc svc-nginx -o yaml | sed -e "s/app: deploy-nginx11/app: deploy-nginx12/" | kubectl apply -f -

  • Blue 배포 전환
kubectl get svc svc-nginx -o yaml | sed -e "s/app: deploy-nginx12/app: deploy-nginx11/" | kubectl apply -f -

다 끝난 후에는 모두 종료하자.

kubectl delete deploy --all
kubectl delete svc svc-nginx
profile
Engineer, to be a Pioneer.

0개의 댓글