개발강의정리/DevOps

[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심 개념-애플리케이션 롤링 업데이트와 롤백

nineDeveloper 2020. 12. 4.
728x90

애플리케이션 롤링 업데이트와 롤백

기존 모든 포드를 삭제 후 새로운 포드 생성

  • 잠깐의 다운 타임 발생

새로운 포드를 실행시키고 작업이 완료되면 오래된 포드를 삭제

  • 새버전을 실행하는동안구버전포드와연결
  • 서비스의 레이블셀렉터를 수정하여 간단하게 수정가능

레플리케이션컨트롤러가 제공하는 롤링 업데이트

  • 이전에는 kubectl을 사용해 스케일링을 사용하여 수동으로 롤링 업데이트 진행 가능
  • kubectl 중단되면 업데이트는 어떻게 될까?
  • 레플리케이션컨트롤러 또는 레플리카셋을 통제할 수 있는 시스템이 필요

디플로이먼트 생성

  • 레이블 셀렉터, 원하는 복제본 수, 포드 템플릿
  • 디플로이먼트의 전략을 yaml에 지정하여 사용 가능
  • 먼저 업데이트 시나리오리를 위해 3개의 도커 이미지를 준비
    • gasbugs/http-go:v1
    • gasbugs/http-go:v2
    • gasbugs/http-go:v3
FROM golang:1.11
WORKDIR /usr/src/app
COPY main /usr/src/app
CMD ["/usr/src/app/main"]

디플로이먼트 생성 YAML 만들기

  • 버전을 이름에 넣을 필요가 없음 (업데이트 되어도 동일한 디플로이먼트를 사용)
$ kubectl create -f http-go-deployment.yaml --record=true
deployment.apps/http-go created

$ kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE  AVAILABLE   AGE
http-go   3         3         3           3           18m

$ kubectl get rs
NAME                       DESIRED   CURRENT   READY   AGE
http-go-5bf4b7b6c9         3         3         3       15m

$ kubectl get pod
NAME                       READY   STATUS    RESTARTS   AGE
http-go-764d477998-c2hvv   1/1     Running   7          13m
http-go-764d477998-g5m8t   1/1     Running   7          13m
http-go-764d477998-w22b4   1/1     Running   7          13m

rollout을 통해서도 상태 확인 가능

$ kubectl rollout status deployment http-go
deployment "http-go" successfully rolled out

디플로이먼트 업데이트 전략(StrategyType)

spec:
  strategy:
    type: RollingUpdate
  • Rolling Update(기본값)
    • 오래된 포드를 하나씩 제거하는 동시에 새로운 포드 추가
    • 요청을 처리할 수 있는 양은 그대로 유지
    • 반드시 이전 버전과 새 버전을 동시에 처리 가능하도록 설계한 경우에만 사용해야 함
  • Recreate
    • 새 포드를 만들기 전에 이전 포드를 모두 삭제
    • 여러 버전을 동시에 실행 불가능
    • 잠깐의 다운 타임 존재
  • 업데이트 과정을 보기 위해 업데이트 속도 조절

업데이트가 10초정도 준비가 되었다가 실행되게 함

$ kubectl patch deployment http-go -p '{"spec": {"minReadySeconds": 10}}'
deployment.extensions/http-go patched

디플로이먼트 업데이트 실행 준비

  • 디플로이먼트를 모니터하는 프로그램 실행
$ while true; curl <ip>; sleep 1; done
Welcome! http-go:v1
Welcome! http-go:v1
Welcome! http-go:v1
Welcome! http-go:v1
Welcome! http-go:v1
Welcome! http-go:v1
...

디플로이먼트 업데이트 실행

  • 새로운 터미널을 열어 이미지 업데이트 실행
$ kubectl set image deployment http-go http-go=gasbugs/http-go:v2
deployment.extensions/http-go image updated
  • 모니터링하는 시스템에서 관찰
$ while true; curl <ip>; sleep 1; done
Welcome! http-go:v1
Welcome! http-go:v1
Welcome! http-go:v1
Welcome! http-go:v1
Welcome! http-go:v1
Welcome! http-go:v1
...
Welcome! http-go:v1
Welcome! http-go:v2
Welcome! http-go:v2
Welcome! http-go:v1

디플로이먼트 업데이트 실행 결과

  • 업데이트한 이력을 확인
    • 리비전의 개수는 디폴트로 10개까지 저장
$ kubectl rollout history deployment http-go
deployment.extensions/http-go REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deployment http-go http-go=gasbugs/http-go:v2

롤백 실행하기

  • 롤백을 실행하면 이전 업데이트 상태로 돌아감
  • 롤백을 하여도 히스토리의 리비전 상태는 이전 상태로 돌아가지 않음
$ kubectl set image deployment http-go http-go=gasbugs/http-go:v3
deployment.extensions/http-go image updated

$ kubectl rollout undo deployment http-go
deployment.extensions/http-go

$ kubectl exec http-go-7dbcf5877-d6n6p curl 127.0.0.1:8080
Welcome! http-go:v2

$ kubectl rollout undo deployment http-go --to-revision=1
deployment.extensions/http-go

롤링 업데이터 전략 세부 설정

  • maxSurge
    • 기본값 25%, 개수로도 설정이 가능
    • 최대로 추가 배포를 허용할 개수 설정
    • 4개인 경우 25%이면 1개가 설정 (총 개수 5개까지 동시 포드 운영)
  • maxUnavailable
    • 기본값 25%, 개수로도 설정이 가능
    • 동작하지 않는 포드의 개수 설정
    • 4개인 경우 25%이면 1개가 설정(총 개수 4-1개는 운영해야 함)

spec:
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnvailable: 1
    type: RollingUpdate

롤아웃 일시중지와 재시작

  • 업데이트 중에 일시정지하길 원하는 경우
    • $ kubectl rollout pause deployment http-go
  • 업데이트 일시중지 중 취소
    • $ kubectl rollout undo deployment http-go
  • 업데이트 재시작
    • $ kubectl rollout resume deployment http-go

업데이트를 실패한 경우

  • 업데이트를 실패하는 케이스
    • 부족한 할당량(Insufficient quota)
    • 레디네스 프로브 실패(Readiness probe failures)
    • 이미지 가져오기 오류(Image pull errors)
    • 권한 부족(Insufficient permissions)
    • 제한 범위(Limit ranges)
    • 응용 프로그램 런타임 구성 오류(Application runtime misconfiguration)
  • 업데이트를 실패하는 경우에는 기본적으로 600초 후에 업데이트를 중지한다
spec:
  processDeadlineSeconds: 600

실습

  1. http-go-deployment.yaml 파일 작성

    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: http-go
     labels:
       app: http-go
    spec:
     replicas: 3
     selector:
       matchLabels:
         app: http-go
     template:
       metadata:
         labels:
           app: http-go
       spec:
         containers:
         - name: http-go
           image: gasbugs/http-go:v1
           ports:
           - containerPort: 8080
  2. 디플로이먼트 생성

    $ kubectl create -f http-go-deployment.yaml --record=true
    deployment.apps/http-go created
    
    # rollout을 통해 상태 확인
    $ kubectl rollout status deployment http-go
    deployment "http-go" successfully rolled out
    
    # history 확인
    $ kubectl rollout history deploy http-go
    deployment.apps/http-go
    REVISION  CHANGE-CAUSE
    1         kubectl create --filename=http-go-deployment.yaml --record=true
  3. 디플로이먼트 정보 확인

  • 디플로이먼트 상세 정보 확인
    • $ kuberctl describe deploy http-go
  • 디플로이먼트 배포 yaml 파일 정보 확인
    • $ kubectl get deploy http-go -o yaml
  1. 업데이트가 10초정도 준비가 되었다가 실행되게 함

    $ kubectl patch deployment http-go -p '{"spec": {"minReadySeconds": 10}}'
    deployment.extensions/http-go patched
  2. 로드밸런싱 생성

    $ kubectl expose deploy http-go
    service/http-go exposed
    
    # IP 확인
    $ kubectl get svc
    NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
    http-go      ClusterIP   10.100.238.9   <none>        8080/TCP   7s
    kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP    3m53s
  3. busybox 이미지를 kubectl 명령으로 생성해 요청 테스트

    $ kubectl run -it --rm --image busybox -- bash
    If you don't see a command prompt, try pressing enter.
    / # wget -O- -q 10.100.238.9:8080
    Welcome! v1
  4. 디플로이먼트 모니터링 프로그램 실행

    $ while true; do wget -O- -q 10.100.238.9:8080; sleep 1; done
    Welcome! v1
  5. 새탭에서 업데이트 실행

    $ kubectl set image deployment http-go http-go=gasbugs/http-go:v2 --record=true
    deployment.extensions/http-go image updated
    
    # v1 에서 v2로 순차적으로 업데이트 됨
    $ kubectl get pod -w
    NAME                       READY   STATUS    RESTARTS   AGE
    bash                       1/1     Running   0          12m
    http-go-6c4d9d5989-whbs4   1/1     Running   0          16s
    http-go-ccb794f48-57q7q    1/1     Running   0          14m
    http-go-ccb794f48-qht4p    1/1     Running   0          14m
    http-go-ccb794f48-qxffh    1/1     Running   0          14m
    http-go-ccb794f48-qxffh    1/1     Terminating   0          14m
    http-go-6c4d9d5989-825fj   0/1     Pending       0          0s
    http-go-6c4d9d5989-825fj   0/1     Pending       0          0s
    http-go-6c4d9d5989-825fj   0/1     ContainerCreating   0          0s
    http-go-ccb794f48-qxffh    0/1     Terminating         0          14m
    http-go-6c4d9d5989-825fj   1/1     Running             0          5s
    http-go-ccb794f48-qxffh    0/1     Terminating         0          14m
    http-go-ccb794f48-qxffh    0/1     Terminating         0          14m
    http-go-ccb794f48-qht4p    1/1     Terminating         0          14m
    http-go-6c4d9d5989-w9cf4   0/1     Pending             0          0s
    http-go-6c4d9d5989-w9cf4   0/1     Pending             0          0s
    http-go-6c4d9d5989-w9cf4   0/1     ContainerCreating   0          0s
    http-go-ccb794f48-qht4p    0/1     Terminating         0          14m
    http-go-6c4d9d5989-w9cf4   1/1     Running             0          1s
    http-go-ccb794f48-57q7q    1/1     Terminating         0          14m
    http-go-ccb794f48-57q7q    0/1     Terminating         0          14m
    http-go-ccb794f48-qht4p    0/1     Terminating         0          14m
    http-go-ccb794f48-qht4p    0/1     Terminating         0          14m
    http-go-ccb794f48-57q7q    0/1     Terminating         0          14m
    http-go-ccb794f48-57q7q    0/1     Terminating         0          14m
    
    # history 확인
    $ kubectl rollout history deploy http-go
    deployment.apps/http-go
    REVISION  CHANGE-CAUSE
    1         kubectl create --filename=http-go-deploy-v1.yaml --record=true
    2         kubectl set image deployment http-go http-go=gasbugs/http-go:v2 --record=true
  6. edit로 수정

    $ kubectl edit deploy http-go --record=true

    v3로 수정

    spec:
     containers:
     - image: gasbugs/http-go:v3

    신규 ReplicaSet 생성확인

    $ kubectl get all
    ...
    NAME                                 DESIRED   CURRENT   READY   AGE
    replicaset.apps/http-go-6c4d9d5989   3         3         3       8m35s
    replicaset.apps/http-go-855b9bcff4   1         1         1       8s
    replicaset.apps/http-go-ccb794f48    0         0         0       22m

    history 확인

    kubectl rollout history deploy http-go
    deployment.apps/http-go
    REVISION  CHANGE-CAUSE
    1         kubectl create --filename=http-go-deployment.yaml --record=true
    2         kubectl set image deployment http-go http-go=gasbugs/http-go:v2 --record=true
    3         kubectl edit deploy http-go --record=true
  7. 롤백 실행

    $ kubectl rollout undo deploy http-go
    deployment.apps/http-go rolled back

    history 2가 사라지고 4가 추가되면서 v3가 v2로 롤백됨을 확인

    kubectl rollout history deploy http-go
    deployment.apps/http-go
    REVISION  CHANGE-CAUSE
    1         kubectl create --filename=http-go-deployment.yaml --record=true
    3         kubectl edit deploy http-go --record=true
    4         kubectl set image deployment http-go http-go=gasbugs/http-go:v2 --record=true

    버전을 지정하여 롤백하기

    $ kubectl rollout undo deploy http-go --to-revision=1
    deployment.apps/http-go rolled back
    
    $ kubectl rollout history deploy http-go
    deployment.apps/http-go
    REVISION  CHANGE-CAUSE
    3         kubectl edit deploy http-go --record=true
    4         kubectl set image deployment http-go http-go=gasbugs/http-go:v2 --record=true
    5         kubectl create --filename=http-go-deploy-v1.yaml --record=true

연습문제

  • 다음 alpine 이미지를 사용하여 업데이트와 롤백을 실행하라
    모든 revision 내용은 기록돼야 한다
    • alpine:3.4 이미지를 사용하여 deployment를 생성하라
      • Replicas: 10
      • maxSurge: 50%
      • maxUnavailable: 50%
  1. alpine-deploy.yaml 생성

    apiVersion: apps/v1
    kind: Deployment
    metadata:
     creationTimestamp: null
     labels:
       app: alpine-deploy
     name: alpine-deploy
    spec:
     replicas: 10
     selector:
       matchLabels:
         app: alpine-deploy
     strategy:
       type: RollingUpdate
       rollingUpdate:
         maxSurge: 50%
         maxUnavailable: 50%
     template:
       metadata:
         creationTimestamp: null
         labels:
           app: alpine-deploy
       spec:
         containers:
         - image: alpine:3.4
           name: alpine
           resources: {}
    status: {}
  2. 디플로이 먼트 생성

    $ kubectl create -f alpine-deploy.yaml --record=true
    deployment.apps/alpine-deploy created
    
    $ kubectl rollout history deploy alpine-deploy
    deployment.apps/alpine-deploy
    REVISION  CHANGE-CAUSE
    1         kubectl create --filename=alpine-deploy.yaml --record=true
  • alpine:3.5 롤링 업데이트를 수행하라

    edit 명령으로 업데이트

    $ kubectl edit deploy alpine-deploy --record=true

    alpine:3.5 로 변경 후 저장

    spec:
      containers:
      - image: alpine:3.5

    확인

    $ kubectl get rs
    NAME                       DESIRED   CURRENT   READY   AGE
    alpine-deploy-5bf4b7b6c9   10        10        0       27m
    alpine-deploy-8659f8ff96   4         4         0       32m

    alpine:3.6 롤링 업데이트

    $ kubectl edit deploy alpine-deploy --record=true

    alpine:3.6 으로 변경 후 저장

    spec:
      containers:
      - image: alpine:3.6

    확인

    $ kubectl get rs
    NAME                       DESIRED   CURRENT   READY   AGE
    alpine-deploy-5bf4b7b6c9   4         4         0       3m51s
    alpine-deploy-764d477998   10        10        0       77s
    alpine-deploy-8659f8ff96   0         0         0       6m39s
    
    $ kubectl rollout history deploy alpine-deploy
    deployment.apps/alpine-deploy
    REVISION  CHANGE-CAUSE
    1         kubectl create --filename=alpine-deploy.yaml --record=true
    2         kubectl edit deploy alpine-deploy --record=true
    3         kubectl edit deploy alpine-deploy --record=true
  • alpine:3.4로 롤백을 수행하라

    $ kubectl rollout undo deploy alpine-deploy --to-revision=1
    deployment.apps/http-go rolled back
    
    $ kubectl rollout history deploy alpine-deploy
    deployment.apps/alpine-deploy
    REVISION  CHANGE-CAUSE
    2         kubectl edit deploy alpine-deploy --record=true
    3         kubectl edit deploy alpine-deploy --record=true
    4         kubectl create --filename=alpine-deploy.yaml --record=true

명령어가 잘되는지만 확인 --dry-run=client

$ kubectl create deploy --image alpine:3.4 alpine-deploy --dry-run=client

명령어가 잘되는지만 확인하는 yaml 파일로 출력

$ kubectl create deploy --image alpine:3.4 alpine-deploy --dry-run=client -o yaml
728x90

댓글

💲 추천 글