backend/kubernetes docs

[kubernetes docs] Replicaset, ReplicationController, Deployment

seul chan 2020. 6. 12. 19:10

Container

Replicasets

레플리카셋의 목적은 레플리카 파드 집합의 실행을 항상 안정적으로 유지하는 것이다. 이처럼 레플리카셋은 보통 명시된 동일 파드 개수에 대한 가용성을 보증하는데 사용

레플리카셋의 작동 방식

레플리카셋을 정의하는 필드

  • selector: 획득 가능한 pod를 식별
  • replica의 개수: 유지해야 하는 pod 개수
  • pod template: 신규 pod에 대한 데이터 명시

레플리카셋을 사용하는 시기

레플리카셋은 지정된 수의 파드 레플리카가 항상 실행되도록 보장한다.

그러나 디플로이먼트는 레플리카셋을 관리하고 다른 유용한 기능과 함께 파드에 대한 선언적 업데이트를 제공하는 상위 개념이다. 따라서 우리는 사용자 지정 오케스트레이션이 필요하거나 업데이트가 전혀 필요하지 않은 경우라면 레플리카셋을 직접적으로 사용하기 보다는 디플로이먼트를 사용하는 것을 권장한다.

kube 문서의 이 부분에서 예시를 직접 따라해볼 수 있다.

레플리카셋의 대안

책을 읽으면서 ReplicationController, Replicaset, Deployment 등 비슷한 개념에 헷갈렸는데 아래에 잘 정리되어 있다. -> 따로 블로그로 정리

  • Deployment (Recommended)
    • deployment는 replicaset을 소유하거나 관리
    • replicaset을 원한다면 deployment를 사용하는 것을 권장
  • Basic pod
    • 어떤 이유로 application이 단일 파드가 필요하더라도 replicaset을 이용하는 것을 권장
  • Job
    • 스스로 종료되는 것이 예상되는 pod의 경우에는 Job 사용 (batch job)
  • DaemonSet
    • machine monitoring, logging과 같은 machine-level의 기능을 가진 pod에 대해서는 daemonSet 사용
    • 이런 pod는 다른 pod가 시작되기 전에 실행되어야 함
  • ReplicationController
    • 레플리카셋은 레플리케이션 컨트롤러를 계승하였다. 이 두 개의 용도는 동일하고, 유사하게 동작하며, 레플리케이션 컨트롤러가 레이블 사용자 가이드에 설명된 설정-기반의 셀렉터의 요건을 지원하지 않는다는 점을 제외하면 유사하다. 따라서 레플리카셋이 레플리케이션 컨트롤러보다 선호된다.

ReplicationController

참고: ReplicaSet을 구성하는 Deployment가 현재 권장되는 설정방법이다.

레플리케이션 컨트롤러 는 언제든지 지정된 수의 파드 레플리카가 실행 중임을 보장

수동으로 생성된 pod와 달리 ReplicationController가 유지, 관리하는 pod는 실패, 삭제되는 경우 자동으로 교체된다.
따라서 하나의 pod만 필요한 경우에도 ReplicationController를 사용해야한다.

간단한 예제

apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
$ kubectl apply -f https://k8s.io/examples/controllers/replication.yaml
replicationcontroller/nginx created

$ kubectl describe replicationcontrollers/nginx
Name:        nginx
Namespace:   default
Selector:    app=nginx
Labels:      app=nginx
Annotations:    <none>
Replicas:    3 current / 3 desired
Pods Status: 0 Running / 3 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:       app=nginx
  Containers:
   nginx:
    Image:              nginx
    Port:               80/TCP
    Environment:        <none>
    Mounts:             <none>
  Volumes:              <none>
Events:
  FirstSeen       LastSeen     Count    From                        SubobjectPath    Type      Reason              Message
  ---------       --------     -----    ----                        -------------    ----      ------              -------
  20s             20s          1        {replication-controller }                    Normal    SuccessfulCreate    Created pod: nginx-qrm3m
  20s             20s          1        {replication-controller }                    Normal    SuccessfulCreate    Created pod: nginx-3ntk0
  20s             20s          1        {replication-controller }                    Normal    SuccessfulCreate    Created pod: nginx-4ok8v

$ kubectl delete rc nginx

ReplicationController의 Spec 작성

다른 config와 마찬가지로 apiVersion, kind, metadata 필요

  • pod template
  • label: 보통은 .spec.template.metadata.labels와 동일하게 설정, 없으면 그걸 씀
  • pod selector: .spec.selector는 label selector. 이와 일치하는 label을 가진 모든 pod를 관리함
    • pod selector가 지정되면 .spec.template.metadata.labels는 pod selector와 일치해야한다.
  • .spec.replicas: default는 1

Using ReplicationController

  • ReplicationController와 관리하는 모든 pod 삭제: kubectl delete 명령어 사용
  • ReplicationController만 삭제: kubectl delete 명령어에 --cascade=false flag 사용

일반적인 사용 패턴

  • reschedule: 노드 실패, 파드 종료등의 상황에 지정된 수의 pod가 존재하도록 보장
  • scaling: replicas field를 업데이트하여 쉽게 scaling 가능
  • rolling update: pod를 하나씩 교체함으로써 롤링 업데이트를 쉽게 가능
  • 다수의 릴리즈 트랙

Deployment

deployment는 pod와 replicaset에 대한 선언적 업데이트를 제공한다.

Usecase

deployment의 일반적인 유스케이스

  • 레플리카셋을 롤아웃 할 디플로이먼트 생성. 레플리카셋은 백그라운드에서 파드를 생성한다. 롤아웃 상태를 체크해서 성공 여부를 확인한다.
  • 디플로이먼트의 PodTemplateSpec을 업데이트해서 파드의 새로운 상태를 선언한다. 새 레플리카셋이 생성되면, 디플로이먼트는 파드를 기존 레플리카셋에서 새로운 레플리카셋으로 속도를 제어하며 이동하는 것을 관리한다. 각각의 새로운 레플리카셋은 디플로이먼트의 수정 버전에 따라 업데이트한다.
  • 만약 디플로이먼트의 현재 상태가 안정적이지 않은 경우 디플로이먼트의 이전 버전으로 롤백한다. 각 롤백은 디플로이먼트의 수정 버전에 따라 업데이트한다.
  • 더 많은 로드를 위해 디플로이먼트의 스케일 업.
  • 디플로이먼트 일시 중지로 PodTemplateSpec에 여러 수정 사항을 적용하고, 새로운 롤아웃의 시작을 재개한다.
  • 롤아웃이 막혀있는지를 나타내는 디플로이먼트 상태를 이용.
  • 더 이상 필요 없는 이전 레플리카셋 정리.

Create deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
  1. 아래 명령어로 deployment 생성

--record flag를 지정하면 실행 명령을 kubernetes.io/change-cause resource annotation에 작성이 가능하다.

kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
  1. kubectl get deployments로 생성되었는지 확인
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   0/3     3            0           3s
  1. kubectl rollout status deployment deployment.v1.apps/nginx-deployment로 deployment의 롤아웃 상태 확인 가능
  2. deployment로 생성된 ReplicaSet(rs)를 보려면 kubectl get rs로 확인 가능

    replicaSet의 이름은 [deployment_name]-[random-string]이다. 무작위 문자열은 pod-template-hash를 시드로 사용

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-574b87c764   3         3         3       2m55s
  3. 각 파드에 자동으로 생성된 label을 보려면 kubectl get pods --show-labels 실행

Pod-template-hash label은 deployment controller에 의해서 생성, 선택된 모든 replicaSet에 추가된다. 이들이 겹치지 않도록 보장. 변경하면 안 됨

Update deployment

deployment의 pod template (.spec.template)이 변경된 경우에만 rollout이 trigger된다.

다음 단계에 따라 deployment를 업데이트

  1. nginx:1.14.2 대신 nginx:1.16.1 이미지를 사용하도록 pdo template을 업데이트
$ kubectl --record deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
# 혹은 아래 명령어 사용
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
deployment.apps/nginx-deployment image updated

# 또는 deployment를 edit 할 수도 있다.
$ kubectl edit deployment.v1.apps/nginx-deployment
  1. 롤아웃 상태를 보려면 다음을 실행
$ kubectl rollout status deployment.v1.apps/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
# 혹은 이미 완료되었다면
deployment.apps/nginx-deployment successfully rolled out

replicaSet이 새로 생성되었는지 볼 수 있다.

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-574b87c764   0         0         0       7m53s
nginx-deployment-5d66cc795f   3         3         3       62s

Rollback deployment

디플로이먼트를 업데이트하는 동안 이미지 이름을 nginx:1.16.1 이 아닌 nginx:1.161 로 입력해서 오타를 냈다고 가정한다.

$ kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.161 --record=true
deployment.apps/nginx-deployment image updated

# rollout이 잘 되지 않는것 확인
$ kubectl rollout status deployment.v1.apps/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-574b87c764   0         0         0       11m
nginx-deployment-5d66cc795f   3         3         3       4m31s
nginx-deployment-7cf8977f4c   1         1         0       30s

# 새로 만들어진 pod의 ImagePullBackOff 에러를 볼 수 있음
$ kubectl get po
NAME                                               READY   STATUS             RESTARTS   AGE
nginx-deployment-5d66cc795f-4tp8d                  1/1     Running            0          4m33s
nginx-deployment-5d66cc795f-sq4mb                  1/1     Running            0          4m50s
nginx-deployment-5d66cc795f-v48fh                  1/1     Running            0          4m36s
nginx-deployment-7cf8977f4c-gnzfn                  0/1     ImagePullBackOff   0          49s

이 문제를 해결하기 위해 안정적인 이전 수정 버전으로 롤백해보자.

  1. 먼저 이 deployment의 수정사항 확인
$ kubectl rollout history deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=nginx-deployment.yaml --record=true
2         kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true
3         kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.161 --record=true

위의 CHANGE-CAUSEkubernetes.io/change-cause에서 복사해옴

  • deployment에 kubectl annotate deployment.v1.apps/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1"로 주석 추가
  • kubectl 명령어 이용시 --record flag 추가
  • 수동으로 resource manifest 편집