본문 바로가기
DevOps/Kubernetes

[7] 쿠버네티스 디플로이먼트

by 비어원 2022. 1. 23.
728x90

쿠버네티스는 파드를 생성하여 컨테이너 애플리케이션을 구동한다. 그런데 실제로 쿠버네티스 환경으로 운영할 때는 파드 자체를 생성하지 않고 디플로이먼트와 같은 워크로드 리소스를 생성하여 파드 집합을 관리한다. 이 워크로드 리소스는 원하는 파드의 종류와 갯수가 실행될 수 있도록 원하는 상태(desired state) 를 보장하는 컨트롤러를 구성한다.

이 장에서는 워크로드 리소스 중 하나인 디플로이먼트에 대해 알아보자.

 

디플로이먼트

디플로이먼트는 파드와 레플리카셋에 대한 선언적 업데이트를 제공한다. 디플로이먼트에서 원하는 상태(desired state)를 기술하며, 디플로이먼트 컨트롤러가 현재 상태를 원하는 상태로 변경한다. 디플로이먼트는 새로운 레플리카셋을 생성할지, 기존 디플로이먼트를 제거하고 제거 대상 모든 리소스들을 새로운 디플로이먼트에 적응할 것인지 정의할 수 있다.

아래는 일반적인 디플로이먼트 사용 예시이다.

  • 레플리카셋을 롤아웃 하기 위해 디플로이먼트를 생성한다. 레플리카셋은 백그라운드에서 파드를 생성한다.
  • 디플로이먼트의 PodTemplateSpec 를 업데이트 함으로써 파드의 새로운 상태를 정의한다. 새 레플리카셋이 생성되고 디플로이먼트는 기존 레플리카셋에서 새 레플리카셋으로 파드를 움직이도록 관리한다. 각 새 레플리카셋 마다 디플로이먼트 수정사항이 업데이트된다.
  • 최근 디플로이먼트 변경사항을 롤백한다. 각 롤백은 디플로이먼트의 수정본을 업데이트한다.
  • 디플로이먼트 확장
  • 디플로이먼트 일시중지로 podTemplateSpec 에 여러 수정사항을 적용하고 새로운 롤아웃의 시작을 재개한다.
  • 롤아웃이 막혀있는지를 나타내는 디플로이먼트 상태 이용
  • 더 이상 필요없는 이전 레플리카셋 정리

 

디플로이먼트 생성

아래는 디플로이먼트의 예시이다. 이 디플로이먼트는 3개의 nginx 파드를 가지는 레플리카셋을 생성한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment # 디플로이먼트 이름
  labels:
    app: nginx
spec:
  replicas: 3            # 파드 레플리케이션 개수
  selector:                # 디플로이먼트가 관리할 파드를 찾는 방식 정의 
    matchLabels:
      app: nginx    # app: nginx 라벨을 가지는 파드 관리
  template:                    # 파드 템플릿
    metadata:                    
      labels:                # 파드의 라벨 정의 
        app: nginx
    spec:                        # 파드 스펙. 컨테이너, 포트 등 파드의 정보가 들어있다.
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

해당 명세를 이용하여 디플로이먼트를 클러스터 내에 만들어보자.

 

먼저 디플로이먼트를 생성한다.

$ kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml

 

그 다음 디플로이먼트가 만들어졌는지 확인하기 위해 조회한다. 생성하자마자 조회하면 아직 만드는 중이라 actual이 0일 수도 있다.

$ kubectl get deployments
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1/1     1            1           5d23h
nginx-deployment      0/3     3            0           7s
  • READY: ready / desired 비율을 알려준다. 명세대로 desired = 3이다.
  • UP-TO-DATE: desired state로 도달하기 위해 업데이트 된 레플리카 개수
  • AVAILABLE: 현재 사용 가능한 레플리카 개수. 현재는 시간이 지나면 3이되는 것이 정상이다.

 

디플로이먼트가 만들어졌는지 확인하였다면 디플로이먼트 롤아웃 상태를 보기 위해 다음 명령어를 사용해보자.

$ kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out

 

약간의 시간이 지난 후 kubectl get deployments 를 다시 입력하여 ready = 3이 되었는지 확인하자.

 

그리고 레플리카셋을 조회해보자.

$ kubectl get rs
NAME                             DESIRED   CURRENT   READY   AGE
kubernetes-bootcamp-57978f5f5d   1         1         1       5d23h
nginx-deployment-66b6c48dd5      3         3         3       5m12s

 

그 다음 파드를 조회해보자. --show-lables 플래그를 추가하면 파드가 가진 라벨을 볼 수 있다.

$ kubectl get pods --show-labels
NAME                                   READY   STATUS    RESTARTS       AGE     LABELS
kubernetes-bootcamp-57978f5f5d-72dmd   1/1     Running   1 (7m5s ago)   5d22h   app=kubernetes-bootcamp,pod-template-hash=57978f5f5d
nginx-deployment-66b6c48dd5-5fzzh      1/1     Running   0              5m57s   app=nginx,pod-template-hash=66b6c48dd5
nginx-deployment-66b6c48dd5-wjslw      1/1     Running   0              5m57s   app=nginx,pod-template-hash=66b6c48dd5
nginx-deployment-66b6c48dd5-xb46h      1/1     Running   0              5m57s   app=nginx,pod-template-hash=66b6c48dd5

디플로이먼트는 desired 개수만큼의 파드가 유지될 수 있도록 파드를 지속적으로 관찰한다. 만약 파드를 하나 삭제하면 디플로이먼트가 자동으로 파드를 다시 생성할 것이다.

pod-template-hash 레이블

pod-template-hash 레이블은 디플로이먼트 컨트롤러에 의해 디플로이먼트가 생성하거나 채택한 모든 레플리카셋에 추가된다.

이 레이블은 디플로이먼트의 자식 레플리카셋이 오버랩되지 않음을 보장한다. 레플리카셋의 PodTemplate을 해싱하고 해시 결과를 레플리카셋 셀렉터, 파드 템플릿, 및 레플리카셋이 가질 수 있는 기존의 모든 파드에 레이블 값으로 추가해서 사용하도록 생성한다.

 

디플로이먼트 업데이트

디플로이먼트 업데이트를 사용하여 nginx:1.14.2 버전의 이미지를 사용하는 파드를 nginx:1.16.1 버전의 이미지를 사용하도록 업데이트 해보자.

디플로이먼트를 업데이트하는 방법은 아래 명령어 중 하나를 사용하면 된다. (또는 매니페스트 파일을 수정하여 kubectl apply -f 명령어를 사용하면 된다.)

$ kubectl deployment.apps/nginx-deployment set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
deployment.apps/nginx-deployment image updated
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
deployment.apps/nginx-deployment image updated

디플로이먼트를 업데이트 한 후 롤아웃 상태를 확인해보자.

$ kubectl rollout status deployment/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 old replicas are pending termination...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-deployment" successfully rolled out

롤아웃을 성공적으로 끝냈다면 디플로이먼트가 구동중인지 확인하자.

$ kubectl get deployment
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment      3/3     3            3           6d1h

그리고 레플리카셋을 조회해보자. 롤아웃을 한 디플로이먼트는 새 레플리카셋을 생성하여 이를 최대 3개 복제본으로 확장하고 이전 레플리카셋을 0개 복제본으로 축소한 후 이전 레플리카셋이 0이되면 레플리카셋을 삭제하는 작업을 거친다.

$ kubectl get rs
NAME                             DESIRED   CURRENT   READY   AGE
nginx-deployment-559d658b74      3         3         3       7m16s
nginx-deployment-66b6c48dd5      0         0         0       6d1h

그리고 새로운 파드가 떠있는지 확인하자 (AGE 참조)

$ kubectl get po
NAME                                   READY   STATUS    RESTARTS      AGE
kubernetes-bootcamp-57978f5f5d-72dmd   1/1     Running   2 (18m ago)   11d
nginx-deployment-559d658b74-k7wjn      1/1     Running   0             5m26s
nginx-deployment-559d658b74-mrtxw      1/1     Running   0             5m24s
nginx-deployment-559d658b74-ttcwn      1/1     Running   0             5m27s

디플로이먼트에 의해 생성된 파드에 대한 정보를 변경하고 싶다면 디플로이먼트의 파드 템플릿을 업데이트하는 방법만 사용해야 한다. 디플로이먼트는 파드 템플릿(spec.template)이 변경된 경우에만 디플로이먼트 롤아웃이 트리거되기 때문이다. 그리고 디플로이먼트는 파드가 업데이트될 때 일부 개수의 파드만 다운되는 것이 보장된다. 기본적으로 적어도 desired 개수의 75% 정도의 파드가 떠있도록 보장한다. 또한 디플로이먼트는 desired 수의 이상으로 특정 수의 파드만 생성되도록 한다. 기본적으로 최대 desired의 125% 정도의 파드가 떠있도록 보장한다. (0.75 * desired <= num <= 1.25 * desired)

Rollover

디플로이먼트 컨트롤러는 매 시간마다 새로운 디플로이먼트에서 레플리카셋이 원하는 상태의 파드를 생성하고 띄우는 것을 관찰한다. 만약 디플로이먼트가 업데이트되면 레이블이 .spec.selector 와 일치하지만 템플릿이 .spec.template 와 일치하지 않는 파드를 제어하는 기존 레플리카셋은 0으로 스케일 다운된다. 그리고 새로운 레플리카셋은 .spec.replicas 만큼 스케일링되어 롤오버가 진행된다.

기존 롤아웃이 진행되는 동안 디플로이먼트를 업데이트한다면, 디플로이먼트는 업데이트에 따라 새 레플리카셋을 생성하고 그 레플리카셋을 스케일링하기 시작한다. 그리고 기존 레플리카셋은 이전 레플리카셋 목록에 추가하고 스케일 다운하기 시작하여 기존 레플리카셋을 롤오버한다. 결국 최근에 업데이트된 내용으로 디플로이먼트가 업데이트된다.

 

 

마무리

이번 장에서는 파드의 레플리카를 관리하고 레플리카의 버전을 관리하여 파드 레플리카를 배포 및 롤백을 수행하는 디플로이먼트에 대하여 알아보았다. 하지만 디플로이먼트만으로는 애플리케이션을 완전히 서비스하는 것이 불가능하다. 이유로는 여러가지가 있다.

1. 파드가 죽고 다시 살아나면 IP가 변경된다. 그렇기 때문에 클라이언트는 변경된 파드의 IP를 알지 못한다.

2. 파드의 IP는 쿠버네티스 클러스터 내부 IP이기 때문에 쿠버네티스 클러스터 외부에서 접근이 불가능하다.

 

이와 같은 이유로 디플로이먼트만으로는 애플리케이션을 완전히 서비스하는 것이 불가능하다. 이를 보완하기 위해 쿠버네티스에서는 서비스라는 오브젝트를 통해 쿠버네티스 파드들을 쿠버네티스 클러스터 외부로 노출시키고, 변경된 파드의 IP를 감지하는 서비스 디스커버리 및 파드 레플리카를 로드밸런싱하는 기능을 제공한다. 

 

다음 장에서는 서비스에 대하여 알아보자.

2022.02.09 - [DevOps/Kubernetes] - [7] 쿠버네티스 서비스

 

[7] 쿠버네티스 서비스

지금까지는 파드로 컨테이너 기반 애플리케이션을 띄우고 디플로이먼트로 파드의 레플리카 수와 버전을 관리하였다. 하지만 이것만으로는 파드로 띄운 웹 애플리케이션을 쿠버네티스 클러스

beer1.tistory.com

 

728x90

'DevOps > Kubernetes' 카테고리의 다른 글

[9] 쿠버네티스 볼륨  (0) 2022.02.20
[8] 쿠버네티스 서비스  (0) 2022.02.09
[6] 쿠버네티스 파드  (0) 2022.01.05
[5] 쿠버네티스 오브젝트 (2)  (0) 2022.01.02
[4] 쿠버네티스 오브젝트 (1)  (0) 2021.11.24

댓글