Kubernetes/05. 컨트롤러 종류 및 설명

[쿠버네티스] 디플로이먼트 업데이트 전략(RolliingUpdate, ReCreate, Blue/Green, Canary)

Jaden Park 2021. 6. 24. 16:38

들어가며: 디플로이먼트 란?

 

 

디플로이먼트의 전략

  • RollingUpdate
  • Recreate

 

디플로이먼트 생성 및 확인

디플로이먼트 롤아웃 상태 확인

디플로이먼트 롤링업데이트


 

들어가며: 디플로이먼트 란?

 

Deployment는 쿠버네티스에서 가장 널리 사용하는 오브젝트 중 한개입니다.

 

 

레플리카셋(ReplicaSet) 컨트롤러와 지금은 거의 사용하지않는 레플리케이션(Replication) 컨트롤러는 파드를 생성하고 관리합니다.

레플리케이션 컨트롤러보다 더 상위 수준의 컨트롤러 리소스가 있습니다. 그것이 디플로이먼트(Deployment) 리소스 입니다.

 

디플로이먼트애플리케이션(컨트롤러, 파드)을 배포하고 선언적으로 업데이트를 수행하는 리소스입니다. 디플로이먼트 리소스는 하위에 레플리카셋 컨트롤러를 제어하고 그리고 레플리카셋 컨트롤러가 하위 파드를 제어하는 구조 입니다.

 

 

디폴로이먼트 리소스가 관리하는 하위 레플리카셋 컨트롤러를 제어하고, 그리고 레플리카셋 컨트롤러가 하위 파드를 제어하는 구조입니다.

 

디플로이먼트 리소스를 이용해 전체를 제어하게 됩니다. 즉, 디플로이먼트 리소스가 관리하는 하위 레플리카셋 컨트롤러를 직접 관리하면 안됩니다.

 

디플로이먼트 개념에 대한 자세한 설명을 원한다면 이전 포스팅을 참고하세요.

 

 

 


 

디플로이먼트의 전략

 

 

우선, 리플로이먼트 리소스 오브젝트를 보겠습니다.

 

$ cat myapp-deploy-v1.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  labels:
    app: myapp-deploy
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  minReadySeconds: 20
  replicas: 3
  selector:
    matchLabels:
      app: myapp-deploy
  template:
    metadata:
      labels:
        app: myapp-deploy
    spec:
      containers:
      - image: ghcr.io/c1t1d0s7/go-myweb:v1.0
        name: myapp
        ports:
        - containerPort: 8080

 

 

디플로이먼트 리소스에만 적용할 수 있는 배포 전략 관련 필드는 아래와 같습니다.

(레플리카셋은 없는 필드입니다. 차이점이라고 할 수 있습니다)

타입은 rollingupdaterecreate 2가지가 있습니다.

spec:
  strategy:
    type: [RollingUpdate | Recreate]
    rollingUpdate:
      maxUnavailble: <정수 | 비율>
      maxSurge:

 

 

RollingUpdate: 롤링업데이트 방식(기본값)

 

롤링 업데이트란 새 버전을 배포하면서, 새 버전 파드를 하나씩 늘려가고 기존 버전의 파드를 하나씩 줄여나가는 방식입니다.

무중단 배포 라고도 합니다.

이전 버전과 새로운 버전이 공존하는 시간이 발생한다는 단점이 있습니다.

 

maxUnavailable

  • 롤링업데이트 프로세스 중에 사용할 수 없는 최대 파드의 수 (기본값: 25%).
  • 즉, 롤링 업데이트 중 동시에 삭제할 수 있는 파드의 최대 갯수를 의미
  • 퍼센트 및 직접 지정 가능
    • 정수 : ex) 3
    • 비율: ex) 10%
    • 위 예시라면 롤링 업데이트 시작 시 3개가 동시에 삭제되거나 10% 비율만큼 삭제됌

 

  • 값을 높게 설정하면 동시에 교체되는 파드가 늘어나므로 롤링 업데이트 시간은 줄어든다.
  • 하지만 롤링 업데이트 중에 남아 있는 파드의 요청 수가 몰릴 수 있다.
  • 따라서 1로 설정해 파드를 하나씩 교체하는 것이 안전할 수 있다.

 

 

maxSurge

  • 생성할 수 있는 최대 파드의 수(기본값: 25%)
  • 즉, 롤링 업데이트 중 동시에 생성하는 파드 갯수
    • 정수: ex) 3
    • 비율: ex) 10%

 

  • 위의 예시라면 롤링 업데이트 시작 시 새 버전의 파드가 3개 추가되거나 10% 비율만큼 추가 생성한다.
  • 값을 높게 설정하면 필요한 파드를 빨리 생성하므로 파드 교체 시간이 단축된다.
  • 하지만, 필요한 시스템 자원이 급증할 수 있다.

 

 

Recreate: 재성성(기존 파드는 모두 삭제되고, 새로운 파드 생성)

Recreate의 경우 기존 파드를 모두 삭제한 다음 새로운 파드를 생성하는 방법입니다.

무중단 방식이 아닙니다. 다운타임 발생합니다.

 

 

 

cf) RollingUpdate, Recreate 이외에도 추가적인 배포 업데이트 방식 소개

 

Blue/Green

구 버전과 신버전 2가지를 서버에 마련하고 한꺼번에 교체하는 방법입니다.

무중단 방식이며 롤백이 쉽고 RollingUpdate 의 단점(이전 버전과 새로운 버전이 공존하는 시간이 존재) 해결 가능합니다.

배포 시 시스템 자원을 2배로 사용한다는 단점이 있습니다.

 

Canary

구버전과 신버전을 구성하여 일부 트래픽을 신버전으로 분산시켜 테스트를 진행한 뒤 서서히 옮기는 방식

따른 위험감지를 하기 위한 배포 전략으로 성능 모니터링에 유용하다는 장점이 있습니다.

 

 

컨테이너 최소 대기 시간

롤링 업데이트를 수행할 때 새로운 파드가 배포되고 배포된 파드의 컨테이너가 실제 준비되기까지 대기 시간을 지정할 수 있습니다.

 

spec:
  minReadySeconds: <초>

minReadySeconds: 새로 배포된 컨테이너가 준비되기까지 대기할 시간 (기본값: 0초)

 

 


디플로이먼트 생성

$ cat myapp-svc-deploy.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-deploy
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-deploy

 

 

 

상단에서 작성한 디플로이먼트 리소스 myapp-deploy-v1.yaml 확인을 위한 서비스 myapp-svc-deploy.yaml 를 생성합니다.

//디플로이먼트 리소스 생성
$ kubectl create -f myapp-deploy.v1.yaml --record

// 로드밸런서 서비스 생성
$ kubectl create -f myapp-svc-deploy.yaml

 

--record 옵션을 사용하여 생성하면 롤아웃 히스토리에 변경 사유(CHANGE-CAUSE)에 해당 명령이 기록됩니다.

디플로이먼트의 리버전(REVISION)에 남게 되는데 이를 이용해 무엇 때문에 리소스가 변경되었는지, 필요하다면 롤백(ROLLBACK)을 할수도 있습니다.

 

추후 디플로이먼트 history 확인할 때 --record 명령을 더 살펴보겠습니다.

 

로드밸런서의 외부 IP 를 확인하겠습니다.

 

디플로이먼트 모니터링 준비를 위해 새로운 터미널을 추가로 열어 컨트롤러 및 파드의 상태를 확인합니다.

 

새로운 터미널을 추가로 열어 웹 요청 및 응답을 모니터링 합니다.

현재는 파드가 바뀌며 서비스가 되고 있는 것을 확인할 수 있습니다.

 


 

디플로이먼트 롤아웃 상태 확인

이제 디플로이먼트 롤아웃 상태를 확인해보겠습니다.

디플로이먼트에서는 모든 배포 및 롤링업데이트를 롤아웃(Rollout)이라고 합니다.

 

 

$ kubectl rollout status deployment myapp-deploy

myapp-deploy 디플로이먼트가 정상적으로 배포된 것을 확인할 수 있습니다.

 

 

 

$ kubectl rollout history deployment myapp-deploy

롤아웃 히스토리를 확인해보겠습니다.

앞서 디플로이먼트 리소스 생성 시 --record 옵션을 사용하여 생성하면 변경사유(CHANGE-CAUSE)에 해당 명령이 기록됩니다.

그리고 디플로이먼트의 리비전이 남게 되는데 이를 이용해 무엇 때문에 변경되었는지, 필요하다면 롤백 할수도 있습니다.

 

디플로이먼트 롤링업데이트

롤링업데이트 명령 형식은 다음과 같습니다

kubectl set image deployment <디플로이먼트 이름> <컨테이너 이름>=<새 이미지>
kubectl set image deployment -f <디플로이먼트 파일> <컨테이너 이름>=<새 이미지>

 

버전 1 -> 버전 2

버전 1에서 버전 2로 업데이트해보겠습니다.

kubectl set image deployment myapp-deploy myapp=ghcr.io/c1t1d0s7/go-myweb:v2.0

 

롤 아웃 상태를 확인해보겠습니다.

일정 시간을 기다리면 롤아웃이 정상적으로 완료됐다는 메시지를 확인할 수 있습니다.

 

롤아웃 히스토리를 확인해보겠습니다.

kubectl set image 명령으로 업데이트 할 때 --record 옵션을 사용하지 않아 변경 기록이 되어있지 않습니다. 이는 나중에 추적을 어렵게 만들 수 있습니다.

 

참고

리소스를 수정하는 방법

kubectl edit: 편집기를 이용해 오브젝트 수정

kubectl patch: 리소스의 개별 속성 수정

kubectl replace: 리소스를 새로운 오브젝트로 변경

kubectl apply: 리소스 생성 및 변경

kubectl set image: 리소스의 이미지만 변경

 

 

버전2 -> 버전3

버전2에서 버전3으로 --record 옵션을 사용해서 업데이트 해보겠습니다.

 

 

롤아웃 히스토리를 보면 변경 사유가 기록된 것을 확인할 수 있습니다.

 

 

버전3 -> 버전2

버전3에서 버전2로 롤백을 해보겠습니다.

$ kubectl rollout undo deployment myapp-deploy --to-revision=2

 

 

롤아웃 히스토리를 확인해보겠습니다.

 

리비전 2는 없어졌고, 리비전 2의 상태가 현재 리비전 4로 반영되었습니다.

 

 

버전2 -> 버전3

이번에는 새로 디플로이먼트 오브젝트를 생성해서 롤링업데이트를 수행해보겠습니다.

 

$ cat myapp-deploy-v3.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  labels:
    app: myapp-deploy
  annotations:
    kubernetes.io/change-cause: My Golang Web App Version 3
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  minReadySeconds: 20
  replicas: 3
  selector:
    matchLabels:
      app: myapp-deploy
  template:
    metadata:
      labels:
        app: myapp-deploy
    spec:
      containers:
      - image: ghcr.io/c1t1d0s7/go-myweb:v3.0
        name: myapp
        ports:
        - containerPort: 8080
        readinessProbe:
          periodSeconds: 1
          httpGet:
            path: /
            port: 8080

 

롤아웃 상태를 확인해보고 히스토리를 확인해보겠습니다.

변경 사유에 명령이 아닌 어노테이션의 문자열이 기록된 것을 확인할 수 있습니다.

 

 

롤백과 레플리카셋 컨트롤러

디플로이먼트는 이전 버전의 레플리카셋 컨트롤러를 삭제하지 않습니다.

이는 롤백 하기 위한 롤아웃 히스토리 목록과 같으며, 롤백 시 다시 이전 레플리카셋을 그대로 사용하기 위함입니다.