[Kubernetes in action] chapter 9. Deployment

4 minute read

서론

  • 파드를 최신 버전으로 교체
  • 관리되는 파드 업데이트
  • 이플로이먼트 리소스로 파드의 선언적 업데이트
  • 롤링 업데이트 수행
  • 잘못된 버전의 롤아웃 자동 차단
  • 롤아웃 속도 제어
  • 이전 버전으로 파드 되돌리기

애플리케이션은 변경될 것이다. 쿠버네티스트에서 실행되는 애플리케이션을 업데이트하는 방법과 무중단 업데이트를 어떻게 하는지 설명할 것이다.

이 작업은 레플리케이션 컨트롤러 또는 레플리카셋을 사용해서 수행할 수 있지만 디플로이는 레플리카셋 기능을 활용해서 선언적으로 업데이트를 가능하게 한다.

파드에서 실행중인 애플리케이션 업데이트

기본 버전 v1을 태그로 가지는 애플리케이션을 외부에서 접근할 수 있다. 그런 상태에서 우리는 새로운 버전인 v2를 배포하고 싶다. 그러기 위해서는 우리는 기존 파드를 삭제하고 새로운 파드를 실행해야한다. 두가지 방법이 있다고 할 수 있다.

  1. 기존 파드를 한번에 모두 삭제한 다음 새 파드를 실행
    • 일시적으로 서비스 접근이 불가능하다.
  2. 새로운 파드를 실행하고 기존 파드를 삭제. 새로운 파드를 모두 띄우고 삭제하거나 그 중간 중간에 삭제와 배포를 같이 한다.
    • 두가지 버전이 동시에 실행되어야 하기 때문에 서비스가 같은 기능을 제공하지 못할수도 있으며 데이터 저장소 같은 경우 새 버전이 이전 버전을 손상 시킬 수 있어서 데이터 스키마나 데이터 수정을 해서는 안된다.

롤링 업데이트

과정

rolling

레플리케이션컨트롤러와 kubectl을 이용한 rolling update

이전에 hoon:v1이라는 이미지를 활용해서 컨테이너를 만들다고 가정할 때.

새로운 버전인 hoon:v2를 배포하고 싶다.

$ k rolling-update <이전버전 이름> <새로운버전 이름> <업데이트 내용>

$ k rolling-update hoon-v1 hoon-v2 --image=hoon:v2

지금은 사용하지 않는 이유

  1. 운영자가 아닌 쿠버네티스가 자원에 대해서 수정을 진행. (쿠버네티스 내부적으로 라벨을 변경함.)
  2. k8s client가 이 과정을 진행. 네트워크 이슈로 클라이언트와 연결이 끊어지면 큰일.
  3. 명령을 나타난다. 쿠너베티스는 상태를 선언하고 그것을 달성하는 것이 베스트라고 생각하기에.

deployment

애플리케이션을 배포하고 선언적으로 업데이트하기 위한 높은 수준의 리소스 <-> 레플리케이션컨트롤러 또는 레플리카셋과 같은 낮은 수준의 개념

deployment

deployment -> 레플리카셋 -> pods

형식

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: kubia
spec:
  replicas: 3
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v1
        name: nodejs

레플리케이션컨트롤러를 만드는 것과 다르지 않다.

Q. apiVersion apps/v1beta1 vs apps/v1beta2 vs v1

파드 생성 방식 이해

이름에 숫자가 들어감. 그 값은 디플로이먼트와 파드 텟플릿의 해시값. 그것을 통해서 해당 리소스 이름과 합쳐져서 레플리카셋 이름이 만들어짐.

추후 여러 리플리카셋이 나오게 되는데 이런 것을 통해서 어떤 레플리카셋의 파드인지 알 수 있음. 그리고 관리됨. -> 지정한 버전에 대한 해시값을 통해서 특정 버전 실행 가능

$ kubectl get po
NAME                     READY     STATUS    RESTARTS   AGE
kubia-1506449474-otnnh   1/1       Running   0          14s
kubia-1506449474-vmn7s   1/1       Running   0          14s
kubia-1506449474-xis6m   1/1       Running   0          14s

---
$ kubectl get replicasets
NAME               DESIRED   CURRENT   AGE
kubia-1506449474   3         3         10s

deployment를 통한 업데이트

왜 사용?

레플리카셋, 컨트롤러로도 충분히 배포는 가능.

하지만 아까 보여준 것 처럼 두개의 레플리카셋을 만들고 관리해야 되기 때문에 그것보다 상위 개념이 존재해야 됨.

레플리케이션 컨트롤러 업데이트

  • 레플리케이션컨트롤러은 명시적으로 하라면 명령도 내리고 새로운 레컨 이름도 지정해줘야했음.
  • 업데이트가 끝나면 이전 레플리케이션컨트롤러을 삭제함.
  • 터미널을 열어두고 끝날 때까지 기달려야 했음.

업데이트 전략

  • (default) RollingUpdate: 이전에 보여준 것처럼 하나씩 하나씩. 이전 버전과 현재 버전이 동시에 동작하는 것이 가능한 경우.
  • Recreate: 한번에 모두 삭제한 다음 새로운 파드를 만듬. 이전 버전을 완전히 싸그리 없애버리고 새로 만듬. 짧은 다운타임이 생김

파드 템플릿을 변경하지 않은 경우에 디플로이먼트는 배포를 하지 않는다.

Pod에 대한 정보가 바뀐 것이 아니기 때문에 image나 다른 정보가 바뀌는 경우에는 배포가 진행됨.

파드 템플릿이 컨피그맵(또는 시크릿)을 참고하고 있고 해당 컨피그맵이 업데이트된다고해서 배포가 되지는 않는다. 실제 configmap은 적용됨.

업데이트 과정

$ k set image deployment kubia nodejs=luksa/kubia:v3
deployment "kubia" image updated
  • Pod template 정보 변경 -> deployment trigger

과정은 전에 설명한 레플리케이션컨트롤러 롤링 업데이트 과정에서 발생하는 이벤트와 매우 유사. 하지만 우리가 어떤 다른 명령어를 하지 않아도 된다.

그리고 추가적으로 이전 버전에 대한 레플리카셋을 그냥 나둔다. (k rolling-update는 삭제해버림)

롤백

배포 이후에 문제가 있다고 판단되는 경우 이전 버전으로 롤백할 수가 있다.

$ k rollout undo deployment kubia // 직전 버전으로 롤백

$ $ k rollout history deployment kubia // 이력 확인 => 이력을 보기 위해서 --record를 통해서 배포를 진행해야 됨

$ k rollout undo deployment kubia --to-revision=1 // 특정 버전으로 롤백

롤아웃 프로세스가 진행 중에도 중단하고 실행을 취소하는 명령어가 있다.

kubectl rollout document

롤아웃 속도 제어

spec:
  replicas: 3
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate

maxSurge

해당 숫자만큼 추가적으로 인스턴스를 가질 수 있다. (replicas + maxSurge)

replicas: 3, maxSurge: 1 이라고 과정했을 때 롤링 업데이트 과정에서 최대 4개까지의 인스턴스가 동작할 수 있다.

maxUnavailable

해당 숫자를 뺀 나머지 인스턴스는 동작하는 것을 보장해야 된다. (replicas - maxUnavailable)

replicas: 3, maxUnavailable: 1 이라고 과정했을 때 롤링 업데이트 과정에서 최대 2개의 인스턴스는 동작을 보장해야된다.

롤아웃 프로세스 일시 정지

$ k set image deployment kubia nodejs=luksa/kubia:v4

$ k rollout pause deployment kubia

$ k rollout resume deploymnet kubia

변경을 하자마자 deployment는 롤아웃을 진행할 것이고 그러면서 생긴 새로운 버전에 v4 파드가 만들어질 것이다.

그 과정에서 중간에 멈추게 되면 해당 v4 파드에 트래픽이 들어가게 할 수 있다. 이런 방식으로 카나리 배포가 가능함.

잘못된 버전의 롤아웃 방지

  • minReadySecond

파드를 사용 가능한 것으로 취급하기 전에 새로 만든 파드에 준비 시간을 줌.

minReadySecond가 지나기 전에 새 파드가 제대로 작동하지 않고 레디니스 프로브가 실패하기 시작하면 롤아웃이 효과적으로 차단된다.

실제 트래픽을 수신하기 시작한 후 파드가 준비 상태를 계속 보고할 수 있도록 minReadySecond를 널널하게 설정해야 된다.

spec:
  minReadySecond: 10
  ...
  template:
    ...
    spec: 
      containers:
      - image: kubia:v3
        name: kubia
        readinessProbe: 
          periodSeconds: 5
            httpGet:
              path: /
              port: 8080

주의사항

만약 minReadySecond은 설정하지 않고 readinessProbe만 설정하는 경우 readinessProbe의 첫번째가 성공하면 배포가 가능한 것으로 판단해서 나머지도 모두 배포하게 된다.

그러니 올바르게 적절한 값으로 설정하는 것을 추천한다.

롤아웃 데드라인

ProgressDeadlineSeconds라는 것을 설정할 수 있음.

spec:
  progressDeadlineSeconds: 600 // (단위는 초)

만약 데드라인을 넘어서면 디플로이먼트 컨트롤러는 디플로이먼트의 .status.conditions 속성에 다음의 디플로이먼트 컨디션(DeploymentCondition)을 추가한다.

Type=Progressing
Status=False
Reason=ProgressDeadlineExceeded

쿠버네티스는 Reason=ProgressDeadlineExceeded 과 같은 상태 조건을 보고하는 것 이외에 정지된 디플로이먼트에 대해 조치를 취하지 않는다. 더 높은 수준의 오케스트레이터는 이를 활용할 수 있으며, 예를 들어 디플로이먼트를 이전 버전으로 롤백할 수 있다.

deployment 실패

Leave a comment