본문 바로가기

About/Kubernetes

[k8s] 디플로이먼트(Deployment)

디플로이먼트

디플로이먼트(Deployment)는 쿠버네티스에서 상태가 없는(stateless) 앱을 배포할 때 사용하는 가장 기본적인 컨트롤러입니다. 쿠버네티스가 처음 등장했을 때는 Replication Controller에서 앱을 배포했는데 최근에는 디플로이먼트를 기본적적인 앱 배포에 사용합니다.

Stateless Application이란?
클라이언트와 서버의 연결 구조에서 불필요한 상태의 반영을 위한 데이터나 리소스가 사용되지 않는 형태의 서비스 구조

 

파드와 레플리카셋은 '이력'이라는 개념이 없기 때문에 릴리스 후에 변경이 없는 애플리케이션을 관리하는데 적합합니다.

디플로이먼트는 이름처럼 배포 기능을 세분화 한 것으로 파드와 레플리카셋에 버전 관리 기능을 추가한 것이라고 생각하면 이해가 쉽습니다. 단순히 실행시켜야 할 파드 개수를 유지하는 것 뿐만 아니라 앱을 배포할 때 롤링 업데이트 하거나, 앰 배포 도중 잠시 멈췄다가 다시 배포할 수 있습니다. 또한 앱 배포 후 이전 버전으로 롤백할 수도 있습니다.

레플리카셋과 완전히 다른 기능이라고 보기는 어렵고, 디플로이먼트가 레플리카셋을 관리하며 앱 배포를 더 세밀하게 관리하는 것이라고 할 수 있습니다.

Deployment

디플로이먼트를 사용하면 다음과 같은 일이 가능합니다.
- 포드의 롤아웃/롤백
- 롤아웃 방식의 지정
- 롤아웃 조건이나 속도 제어

디플로이먼트는 컨테이너 이미지 버전업 등 업데이트가 있을 때 새로운 사양의 레플리카셋을 작성하고 순서대로 새로운 파드로 대체하여 롤아웃을 수행합니다. 디플로이먼트는 레플리카셋과 달리 이력을 관리하기 때문에 1세대 이전으로 되돌리는 롤백을 할 수 있습니다.

또한 디플로이먼트를 이용하여 애플리케이션을 업데이트 하는 방식은 다음과 같은 방식이 있습니다.
- ReCreate
- Rolling Update
- Blue/Green
- Canary 
이것에 대해서는 다음 번에 포스팅해보도록 하겠습니다.


디플로이먼트 매니페스트 파일 작성

디플로이먼트의 매니페스트 파일을 작성하는 방법은 레플리카셋과 거의 비슷합니다. 다음은 디플로이먼트 구성 예시 입니다.

# deployment-nginx.yaml
# [1] 기본 항목
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment

#  [2] Deployment 스펙
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-deployment

 # [3] Pod 템플릿
  template:
    metadata:
      labels:
        app: nginx-deployment
    # [4] Pod 스펙
    spec:
      containers:
        - name: nginx-deployment
          image: nginx # 컨테이너 이미지 위치
          ports:
            - containerPort: 80 # 포트 번호

[1] 매니페스트 기본 항목

먼저 API 버전이나 파드명과 같은 기본 항목을 설정합니다.

필드 데이터형 설명 예시
apiVersion 문자열 API 버전, 존재하지 않는 값을 설정하면 오류가 발생 apps/v1
kind 문자열 쿠버네티스 리소스의 종류 Deployment
metadata Object 레플리카셋의 이름이나 Label과 같은 메타데이터 name: nginx-deployment
spec PodSpec 레플리카셋의 상세 정보를 설정 -

[2] 디플로이먼트 스펙

.spec 필드에는 디플로이먼트의 내용을 설정합니다. 클러스터 안에서 실행시키고 싶은 파드의 수를 replicas로 설정합니다. 또 만일 실제로 클러스터 안에서 파드의 수가 부족할 때 어떤 파드를 새로 시작시킬지 그 템플릿을 정합니다.

필드 데이터형 설명
replicas 정수 클러스터 안에서 가동시킬 파드의 수, 기본값은 1
selector LabelSelector 어떤 파드를 가동시킬지에 대한 셀렉터, 파드의 Template에 설정된 라벨과 일치해야 한다.
template PodTemplateSpec 실제로 클러스터 안에서 움직이는 파드의 수가 replicas에 설정된 파드의 수를 만족시키지 않을 때 새로 작성되는 파드의 템플릿

 

.spec 필드 작성 시 유의 사항

[3] Pod 템플릿

[template] 필드에는 레플리카셋이 어떤 파드를 실행할지에 관한 정보를 설정합니다. 따라서 template 필드 하위에 다시 spec, metadata를 설정하는 필드가 존재합니다. 앞에서도 얘기했지만 [2]의 Selector에서 지정한 조건과 맞는 것을 만들 필요가 있습니다.

필드 데이터형 설명
metadata Object 템플릿의 이름이나 Label과 같은 데이터
spec PodSpec 파드의 상세 정보를 설정

[4] Pod 스펙

spec.template 하위의 [spec] 필드에는 Pod의 상세 정보를 설정합니다. 특히 .spec.template.spec.containers[] 필드의 하위에 .name, .image, .ports[], .containerPort 필드를 이용해 컨테이너의 구체적인 명세를 설정합니다.

위의 예시에서는 컨테이너의 이름을 nginx-deployment, 사용할 컨테이너 이미지는 nginx, 해당 컨테이너의 포트 번호는 80번으로 설정했습니다.


디플로이먼트 사용해보기

디플로이먼트 생성

위의 코드를 deployment-nginx.yaml로 저장합니다. 그리고 다음 명령으로 클러스터에 적용합니다.

kubectl apply -f deployment-nginx.yaml

실행 결과

이 후 디플로이먼트가 제대로 실행됐는 지를 확인하기 위해 다음과 같이 명령어를 입력합니다. 명령어에서 deploy는 디플로이먼트, rs는 레플리카셋, pods는 파드를 의미합니다.

kubectl get deploy,rs,pods

실행 결과

실행 결과를 살펴보면 nginx-deployment라는 디플로이먼트가 있고, 이 디플로이먼트가 관리하는 nginx-deployment-69cfdf5bc7라는 레플리카셋도 생성되었습니다. 69cfdf5bc7는 레플리카셋을 구분하는 UUID 해시 문자 입니다.

마지막으로 레플리카셋이 관리하는 nginx-deployment-69cfdf5bc7-xxxxx 형식의 파드들이 생성되었습니다.

디플로이먼트 수정

이 상태에서 nginx-deployment의 컨테이너 이미지 설정 정보를 업데이트해보겠습니다. 업데이트하는 방법은 크게 세 가지가 있습니다.

1. kubectl set 명령으로 직접 컨테이너 이미지를 지정
2. kubectl edit 명령으로 현재 파드의 설정 정보를 연 다음 컨테이너 이미지 정보를 수정
3. 처음 적용했던 템플릿의 컨테이너 이미지 정보를 수정한 다음 kubectl apply 명령을 실행해서 변경

1번 방식을 사용하여 실행 중인 디플로이먼트에서 image 필드를 nginx:1.9.1 버전으로  변경해보겠습니다.

kubectl set image deployment/nginx-deployment nginx-deployment=nginx:1.9.1

실행 결과

kubecdtl get deploy,rs,pods 명령어를 여러번 입력하여 중간 과정을 여러 번 출력해보면 다음과 같습니다.

컨테이너 이미지를 업데이트하여 nginx-deployment-7b779c9596이라는 새로운 레플리카셋이 생성되었고, 기존의 파드는 해당 레플리카셋이 관리하는 nginx-deployment-7b779c9596-xxxxx로 변경되었습니다. 디플로이먼트를 변경할 때 마다 이렇게 새로운 레플리카셋이 생성되고 그에 맞게 파드가 변경됩니다.

디플로이먼트 롤백

컨테이너 이미지를 변경한 내역을 보기위하여 다음과 같이 명령어를 입력합니다.

kubectl rollout history deploy [디플로이먼트 이름]

위에서 이미지를 한 번 변경하였기 때문에 두 개의 리비전이 보이며, 현재 리비전은 2입니다. 특정 리비전의 상세 내용을 확인하려면 --revision=리비전번호 옵션을 사용합니다.

kubectl rollout history deploy [디플로이먼트 이름] --revision=2

실행 결과

 

이 상태에서 컨테이너 이미지를 수정하기 전인 리비전 #1로 롤백해보겠습니다. 디플로이먼트를 롤백하기 위한 명령어는 다음과 같습니다.

kubectl rollout undo deploy [디플로이먼트명] --to-revision=[리비전번호]

따라서 다음과 같이 입력합니다.

kubectl rollout undo deploy nginx-deployment --to-revision=1

실행 결과

kubectl get deploy,rs,pods 명령어로 디플로이먼트 상태를 확인하면 다음과 같습니다.

리비전#2의 레플리카셋인 7b779c9598에 있던 파드들이 삭제되고 다시 리비전#1의 레플리카셋인 69cfdf4bc에 파드들이 생성된 것을 확인할 수 있습니다.

롤아웃 히스토리를 다시 확인하면 다음과 같습니다.

kubectl rollout history deploy nginx-deployment

리비전 #1이 없어지고 #3이 생겼는데 리비전 #1이 리비전 #3으로 변경된 것입니다.

실습은 여기까지하고 다음번에 디플로이먼트를 활용한 예제를 더 자세히 다루어보도록 하겠습니다.


쿠버네티스의 디플로이먼트에 대하여 알아보았습니다.

참고

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

[k8s] Job/CronJob  (0) 2022.01.13
[k8s] 데몬셋(Daemonset)  (0) 2022.01.13
[k8s] RelicaSet(레플리카셋) 정리  (0) 2022.01.11
[k8s] Namespace, ResourceQuota, LimitRange  (0) 2022.01.07
[k8s] Volume - (emptyDir, hostPath, PV/PVC)  (0) 2022.01.06