ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쿠버네티스 컨트롤러 : 디플로이먼트(Deployments)
    Kubernetes 2018. 6. 18. 09:30
    반응형
    디플로이먼트는 쿠버네티스에서 일반적인 상태가 없는(stateless)앱을 배포할때 사용하는 가장 기본적인 컨트롤러입니다. 쿠버네티스가 처음 나왔을때는 이 역할을 복제 컨트롤러가 했지만 이제는 디플로이먼트가 기본적인 배포방법으로 사용되고 있습니다. 디플로이먼트는 복제세트를 관리하면서 앱의 배포를 보다 세밀하게 관리할 수 있게 합니다. 디플로이먼트라는 이름에서 알수 있듯이 배포에 대한 기능이 세분화되어 있습니다. 단순히 실행시켜야할 포드의 개수를 유지 하는 것만이 아니라 배포할때 롤링업데이트가 가능한 것은 물론,  배포도중 멈췄다가 다시 배포하는것도 가능합니다. 배포후 이전 버전으로 롤백도 할 수 있습니다.
    다음 내용을 deployments-nginx.yaml이란 이름으로 저장하고 kubctl apply -f deployments-nginx.yaml 명령어를 사용해서 쿠버네티스 클러스터에 띄울 수 있습니다.
    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
            ports:
            - containerPort: 80
    늘 있는 apiVersion은 apps/v1이고 kind는 Deployment인걸 확인할 수 있습니다. metadata.name부분을 보면 이름이 nginx-deployment인걸 알 수 있습니다. 라벨은 app: nginx로 지정했습니다. 포드를 몇개 띄울것인지는 복제컨트롤러나 복제세트와 마찬가지로 spec.replicas에 지정하고 여기서는 3으로 했습니다. 스펙의 셀렉터를 보면 matchLabels에서 app: nginx으로 라벨에 지정된 것과 동일하게 지정된걸 확인할 수 있습니다. spec.template 부분에는 포드의 template에 대한 정보가 있고, spec.template.spec.containers에 보면 실제 사용하려는 컨테이너의 이름(name)과 이미지(image)에 대한 정보가 있습니다. 여기서는 nginx를 실행해 봅니다. 디플로이먼트가 제대로 실행됐는지는 kubectl get deploy,rs,rc,pods로 확인할 수 있습니다.


    앞의 명령어에서 deploy는 디플로이먼트, rs는 복제세트, pods는 포드를 의미합니다. 실제 실행결과를 보면 디플로이먼트가 있고, 이 디플로이먼트가 관리하는 복제세트가 디플로이먼트 이름뒤에 679dc9c764라는 해시문자들이 붙어서 보이고 마지막으로 이 복제세트가 관리하는 포드들이 복제세트 이름뒤에 다시 구분하는 해시문자들이 붙어서 보입니다. 
    이 상태에서 nginx-deployment를 업데이트 해보겠습니다. 업데이트는 kubectl set 명령어로 직접 이미지를 지정해서 할수도 있고, kubectl edit로 현재 spec을 연 다음에 그걸 편집해서 할수도 있습니다. 그리고 처음 제출했던 yaml파일의 내용을 다시 편집한 다음에 kubectl apply를 이용해서 변경할수도 있습니다. 
    먼저 kubectl set을 이용해서 실행중인 디플로이먼트에서 아래처럼 image만 변경하는것이 가능합니다.
    kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

    kubectl get deploy -o jsonpath='{.items[0].spec.template.spec.containers[0].image}{"\n"}'
    명령어를 이용하면 kubectl set 실행 전후에 이미지가 변경된걸 확인할 수 있습니다.



    kubectl edit deploy nginx-deployment를 이용해서 현재 실행중인 디플로이먼트를 실행한 다음에 컨테이너 이미지 부분을 찾아서 변경할수도 있습니다. 



    마지막으로 처음 사용했던 deployment-nginx.yaml 파일의 내용을 편집해서 kubectl apply -f deployment-nginx.yaml을 실행해서 컨테이너 이미지가 변경되는걸 확인할 수 있습니다.

    배포 롤백하기
    이렇게 컨테이너 이미지명을 변경한 내역을 kubectl rollout history deploy nginx-deployment를 이용해서 확인할 수 있습니다. 버전(REVISION)이 여러개 보이는걸 알 수 있습니다. 현재 버전은 6입니다.



    버전의 상세 내용을 보려면 --revision=6 이런식으로 옵션을 주면 됩니다.
    이미지 버전이 변경된걸 확인할 수 있습니다.



    이 상태에서 직전 버전으로 돌아가려면 다음처럼 rollout undo를 하면 됩니다.
    kubectl rollout undo deploy nginx-deployment

    그리고 특정 버전으로 돌아가려면 --to-revision옵션을 줘서 지정된 버전으로 실행중인 포드를 되돌릴 수 있습니다.
    kubectl rollout undo deploy nginx-deployment --to-revision=3 

    되돌릴수 있는 revision 개수는 .spec.revisionHistoryLimit 옵션을 이용해서 조정할수 있습니다. 기본값은 10입니다.

    포드 개수 조정하기
    실행중인 디플로이먼트의 포드 개수를 조정하려면 scale명령을 사용하면 됩니다. --replicas 옵션에 포드 개수를 입력하면 됩니다.
    kubectl scale deploy nginx-deployment --replicas=5

    배포 중지/재시작하기
    kubectl rollout 명령을 이용해서 진행중인 배포를 잠시 멈췄다가 다시 시작할 수 있습니다. 

    우선 업데이트를 멈춥니다.
    kubectl rollout pause deployment/nginx-deployment

    그리고나서 이미지를 변경해 봅니다. 하지만 이미 업데이트를 정지(pause) 시켜놨기 때문에 배포작업이 진행되지 않습니다.
    kubectl set image deploy/nginx-deployment nginx=nginx:1.10

    history를 이용해서 확인해 보면 배포가 진행되지 않았다는걸 알 수 있습니다.
    kubectl rollout history deploy/nginx-deployment

    이 상태에서 다시 resume을 해주면 미뤄졌던 배포가 진행됩니다.
    kubectl rollout resume deploy/nginx-deployment

    여기서는 정지를 해둔 다음에 배포를했지만 배포를 하는 중간에도 pause를 이용해서 배포를 멈출 수 있습니다. 멈췄던 배포는 resume을 이용해서 다시 진행시킬 수 있습니다.

    배포 상태
    배포를 하게 되면 배포 상태(status)에 변화가 있게 됩니다. 우선 진행(Progressing)으로 넘어갔다가 성공이면 완료(complete), 실패면 실패(failed)상태로 넘어가게 됩니다.

    다음 작업들을 하고 있는 동안에는 진행(progressing)으로 상태가 표시됩니다.
    • 디플로이먼트가 새로운 리플리카세트를 만들고 있을때
    • 디플로이먼트가 새로운 리플리카세트의 포드 개수를 늘리고 있을때
    • 디플로이먼트가 예전 리플리카세트의 포드 개수를 줄이고 있을때
    • 새로운 포드가 준비상태가 되거나 이용가능한 상태가 됐을때

    kubectl rollout status 명령을 통해서 배포 진행 상태를 확인할 수 있습니다.

    배포가 이상없이 끝나면 배포 상태는 완료(complete)가 됩니다. 다음 조건들을 확인해서 완료로 표시합니다. 종료 코드가 0으로 표시됩니다.
    • 디플로이먼트가 관리하는 모든 리플리카세트가 업데이트 완료 되었을때
    • 모든 리플리카세트가 사용가능해 졌을때
    • 예전 리플리카가 모두 종료되었을때


    배포중 이상이 있으면 실패(fail)로 표시가 됩니다. 보통 다음과 같은 이유 때문에 실패하게 됩니다.
    • 쿼터 부족
    • Readiness probe 실패
    • 이미지 가져오기 에러
    • 권한 부족
    • 제한 범위 초과
    • 앱 실행 조건을 잘못 지정

    yaml 설정에 .spec.progressDeadlineSeconds 항목을 추가하면 지정된 시간이 지났을때 상태를 False로 바꿉니다. 일부러 실패를 시키기 위해서 설정을 2초로 짧게 해보겠습니다.
    kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":2}}'

    그런다음 배포를 다시 해보면 status.conditions항목에서 다음같은 결과를 볼수 있습니다.
    message: ReplicaSet "nginx-deployment-5f54cfb85" has timed out progressing.
    reason: ProgressDeadlineExceeded
    status: "False"
    type: Progressing

    ststus가 False로 실패한걸 확인할 수 있습니다. reason에도 데드라인이 지나서 실패했다는걸 확인할 수 있습니다.



    반응형

    댓글

Designed by Tistory.