DevOps/Kubernetes

[Kubernetes] Deployments (디플로이먼트)

TTOII 2022. 5. 29. 22:19
728x90

✔️ Deployment

디플로이먼트 | Kubernetes

Deployment는 ReplicaSet의 상위 오브젝트로 Deployment를 생성하면 해당 Deployment에 대응하는 ReplicaSet도 함께 생성된다. 따라서 Deployment를 사용하면 Pod, ReplicaSet을 직접 생성할 필요가 없다.

 

✔️ Deployment 사용 이유 ?

그렇다면 쿠버네티스는 ReplicaSet이 아닌 상위 개념인 Deployment를 사용해 간접적으로 ReplicaSet을 생성하는 것일까 ?

Deployment를 사용하는 핵심 이유어플리케이션의 업데이트와 배포를 더욱 편하게 만들기 위해서이다.

Deployment는 이름처럼 컨테이너 어플리케이션을 배포하고 관리하는 역할을 담당한다.

 

예를 들어 어플리케이션의 버전 업데이트를 할 때 ReplicaSet의 변경 사항을 저장하는 Revision을 남겨 Rollback를 가능하게 하고 무중단 서비스를 위해 Pod의 RollingUpdate 전략을 지정할 수도 있다. 

 

 vagrant@k8s-node1  ~  kubectl api-resources | grep deployment
deployments                       deploy       apps/v1                                true         Deployment

shortname은 deploy이며 apps 그룹이며 NS를 사용하고 kind는 Deployment이다.

 

 vagrant@k8s-node1  ~  kubectl explain deploy.spec

rs.spec과 유사하다.

 

myweb-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb
          ports:
            - containerPort: 8080
 vagrant@k8s-node1  ~/deploy  kubectl create -f myweb-deploy.yaml 
deployment.apps/myweb-deploy created

 vagrant@k8s-node1  ~/deploy  kubectl get deploy                 
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
myweb-deploy             3/3     3            3           6s

 vagrant@k8s-node1  ~/deploy  kubectl get rs              
NAME                                DESIRED   CURRENT   READY   AGE
myweb-deploy-7d649cccb8             3         3         3       35s

 vagrant@k8s-node1  ~/deploy  kubectl get po    
NAME                                      READY   STATUS    RESTARTS   AGE
myweb-deploy-7d649cccb8-476t8             1/1     Running   0          37s
myweb-deploy-7d649cccb8-jbfll             1/1     Running   0          37s
myweb-deploy-7d649cccb8-lnlnp             1/1     Running   0          37s

Deployment라는 리소스가 RS를 만들고 RS가 파드를 만든다.
우리는 Deploy만 선언했으나 알아서 RS도 만들고 파드도 만든다.
그래서 쿠버네티스에서는 파드를 만들때 Deployment를 사용하는 것이 일반적이다.

Deployment도 결국 복제본을 만들기 때문에 기본적인 기능은 RS와 유사하다.

 

myweb-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb:v1.0
          ports:
            - containerPort: 8080

myweb-svc-lb.yaml

apiVersion: v1
kind: Service
metadata:
  name: myweb-svc-lb
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080
 vagrant@k8s-node1  ~/deploy  kubectl get deploy,rs,po,svc,ep
NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/myweb-deploy             3/3     3            3           19s

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/myweb-deploy-7d649cccb8             3         3         3       19s

NAME                                          READY   STATUS    RESTARTS        AGE
pod/myweb-deploy-7d649cccb8-2g5zj             1/1     Running   0               19s
pod/myweb-deploy-7d649cccb8-89qf9             1/1     Running   0               19s
pod/myweb-deploy-7d649cccb8-cs2b9             1/1     Running   0               19s

NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGE
service/kubernetes     ClusterIP      10.233.0.1      <none>            443/TCP        42h
service/myweb-svc-lb   LoadBalancer   10.233.61.172   192.168.100.240   80:32154/TCP   19s

NAME                                                    ENDPOINTS                                                            AGE
endpoints/k8s-sigs.io-nfs-subdir-external-provisioner   <none>                                                               26h
endpoints/kubernetes                                    192.168.100.100:6443                                                 42h
endpoints/myweb-svc                                     10.233.90.79:8080,10.233.90.83:8080,10.233.92.120:8080 + 3 more...   5h44m
endpoints/myweb-svc-lb                                  10.233.90.79:8080,10.233.90.83:8080,10.233.92.120:8080 + 3 more...   19s

 

✔️ Rollout

 vagrant@k8s-node1  ~/deploy  kubectl rollout                                                        
Manage the rollout of a resource.

 Valid resource types include:

  *  deployments
  *  daemonsets
  *  statefulsets

Available Commands:
  history     View rollout history
  pause       Mark the provided resource as paused
  restart     Restart a resource
  resume      Resume a paused resource
  status      Show the status of the rollout
  undo        Undo a previous rollout

rollout으로 확인할 수 있는 리소스 타입은 deployments, daemonsets, statefulsets이다.
가능한 명령은 history, pause, restart, resume, status, undo이다.

 

✔️ status

 vagrant@k8s-node1  ~/deploy  kubectl rollout status deploy myweb-deploy 
deployment "myweb-deploy" successfully rolled out

status로 배포가 완료된 상태임을 확인할 수 있다. 

 

✔️ history

 vagrant@k8s-node1  ~/deploy  kubectl rollout history deploy myweb-deploy 
deployment.apps/myweb-deploy 
REVISION  CHANGE-CAUSE
1         <none>

history 정보를 볼 수 있다.

kubectl rollout history deployment/nginx-deployment --revision=2

상세 정보를 보려면 --revision 옵션으로 번호를 지정하면 된다.

 

 

📌 Tip : 다양한 이미지 교체 방법
replace, apply, edit, patch + set

 vagrant@k8s-node1  ~/deploy  kubectl set      
Configure application resources.

 These commands help you make changes to existing application resources.

Available Commands:
  env            Update environment variables on a pod template
  image          Update the image of a pod template
  resources      Update resource requests/limits on objects with pod templates
  selector       Set the selector on a resource
  serviceaccount Update the service account of a resource
  subject        Update the user, group, or service account in a role binding or cluster role binding

set을 사용한 이미지 업데이트 방법

 

 vagrant@k8s-node1  ~  kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v2.0 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/myweb-deploy image updated

 vagrant@k8s-node1  ~  kubectl rollout status deploy myweb-deploy
 ...
 deployment "myweb-deploy" successfully rolled out 

rollout 과정을 확인할 수 있다.

 

===Version 2.0===
Hello World!
myweb-deploy-59b4f448d5-fdq2n

모두 2.0으로 rollout되었다.

 

 vagrant@k8s-node1  ~  kubectl rollout history deploy myweb-deploy
deployment.apps/myweb-deploy 
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v2.0 --record=true

다음과 같이 변경의 사유가 출력되는데 이는 set 명령 실행 시 --record 옵션을 붙일때만 출력된다. --record 옵션을 붙이지 않으면 None이 출력된다.

 

✔️ undo

 vagrant@k8s-node1  ~  kubectl rollout undo deploy myweb-deploy   
deployment.apps/myweb-deploy rolled back

 vagrant@k8s-node1  ~  kubectl rollout history deploy myweb-deploy
deployment.apps/myweb-deploy 
REVISION  CHANGE-CAUSE
2         kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v2.0 --record=true
3         <none>

2.0에서 1.0으로 undo, 되돌리는 것이지만 표기에서는 3.0으로 표기된다.

즉 다시 되돌아간 상태를 1.0이 아닌 3.0으로 본다.

 

===Version 1.0===
Hello World!
myweb-deploy-7d649cccb8-9r7sj

버전이 변경되었다.

 

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/myweb-deploy-59b4f448d5             0         0         0       10m
replicaset.apps/myweb-deploy-7d649cccb8             3         3         3       25m

rollback을 위해 1.0 버전인 myweb-deploy-7d649cccb8를 지우지 않는다. DESIRED만 0으로 설정해놓는다.

 

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/myweb-deploy-59b4f448d5             3         3         3       14m
replicaset.apps/myweb-deploy-7d649cccb8             0         0         0       29m

여기서 다시 2.0 버전으로 rollout을 실행하면 myweb-deploy-59b4f448d5DESIREDCURRENT가 3 / 3으로 변경된다. 그리고 history를 살펴보면 4.0으로 표기된다.

 

 vagrant@k8s-node1  ~/deploy  kubectl apply -f myweb-deploy.yaml --record
Flag --record has been deprecated, --record will be removed in the future
Warning: resource deployments/myweb-deploy is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
deployment.apps/myweb-deploy configured

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/myweb-deploy-59b4f448d5             0         0         0       17m
replicaset.apps/myweb-deploy-744cb77cb6             3         3         3       16s
replicaset.apps/myweb-deploy-7d649cccb8             0         0         0       31m

myweb-deploy.yaml에서 이미지를 v1.0 → v3.0으로 수정한뒤 apply 명령으로 변경하면 3.0 이므로 새로운 myweb-deploy-744cb77cb6가 생성된다.

 

===Version 3.0===
Hello World!
myweb-deploy-744cb77cb6-6bcfk

트래픽을 확인하면 모두 3.0 버전으로 rollout됐음을 확인할 수 있다.

 

 vagrant@k8s-node1  ~/deploy  kubectl rollout history deploy myweb-deploy
deployment.apps/myweb-deploy 
REVISION  CHANGE-CAUSE
3         kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v1.0 --record=true
4         kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v2.0 --record=true
5         kubectl apply --filename=myweb-deploy.yaml --record=true

그리고 history를 확인하면 5.0으로 표기된다.

 

kubectl rollout undo deployment/nginx-deployment --to-revision=2

--to-revision 옵션으로 번호를 지정하면 해당 버전으로 undo한다.
번호를 지정하지 않으면 바로 직전 버전으로 undo한다.

 

📌 annotation 활용하기

set 명령을 사용하면 이미지가 어떻게 변경됐는지 알수 있지만 apply 명령은 어떻게 변경됐는지 알기 힘들다.

파일을 수정할 때는 다른 방법을 사용하는 것을 권장한다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-deploy
  annotations:
    kubernetes.io/change-casue: "Change Go Myweb version from 3 to 4"
    ...

다음과 같이 annotations을 지정한다.

 

 vagrant@k8s-node1  ~/deploy  kubectl apply -f myweb-deploy.yaml         
deployment.apps/myweb-deploy configured

 vagrant@k8s-node1  ~/deploy  kubectl rollout history deploy myweb-deploy
deployment.apps/myweb-deploy 
REVISION  CHANGE-CAUSE
3         kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v1.0 --record=true
6         kubectl set image deployments myweb-deploy myweb=ghcr.io/c1t1d0s7/go-myweb:v2.0 --record=true
7         kubectl apply --filename=myweb-deploy.yaml --record=true
8         Change Go Myweb version from 3 to 4

annotations을 지정했을 때는 apply 명령에 --record 옵션을 붙이지 않는다.
Change Go Myweb version from 3 to 4 해당 문구가 변경 사유에 출력된다.

 

✔️ Max Surge & Max Unavailable

  • maxSurge : 롤링 업데이트 도중 전체 파드의 개수가 Deployreplicas 값보다 얼마나 더 많이 존재할 수 있는지 설정한다.
  • maxUnavailable : 롤링 업데이트 도중 사용 불가능한 상태가 되는 파드의 최대 개수를 설정한다.
 vagrant@k8s-node1  ~/deploy  kubectl explain deploy.spec.strategy                  
FIELDS:
   rollingUpdate        <Object>
     Rolling update config params. Present only if DeploymentStrategyType =
     RollingUpdate.

   type <string>
     Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
     RollingUpdate.

 vagrant@k8s-node1  ~/deploy  kubectl explain deploy.spec.strategy.rollingUpdate

FIELDS:
   maxSurge     <string>
   maxUnavailable       <string>

maxSurgemaxUnavailable는 absolute number 또는 percentage로 표기할 수 있다.
기본 maxSurge, maxUnavailable는 모두 25%이다.
만약 Deploy의 replicas가 3개라면 3 * 0.25 = 0.75의 올림 수인 1개가 된다.

 

myweb-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-deploy
  annotations:
    kubernetes.io/change-casue: "Change Go Myweb version from 3 to 4"
spec:
  strategy:
  type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb:v4.0
          ports:
            - containerPort: 8080

  • Deployment의 replicas에 설정된 파드 개수 : 4개
  • maxUnavailable : 1 (전체 파드 개수가 3개 이하로 떨어지지 않음)
  • maxSurge : 2 (전체 파드 개수는 4 + 2 = 6개를 넘을 수 없음)
  • t0 : 롤링 업데이트 전 v1, 4개의 포드가 있다.
  • t1 : maxUnavailable의 값이 1이기 때문에 최대 1개의 파드까지는 사용 불가능한 상태가 허용된다. 따라서 적어도 4 - 1 = 3개의 파드는 실행 중이어야 하며, 이에 따라 1개의 v1 파드가 삭제된다.
  • t2 : maxSurge의 값이 2이기 때문에 파드의 개수는 4 + 2 = 6개까지 존재할 수 있다. 따라서 t1에서 v1 파드가 삭제됨과 동시에, v2 버전의 파드가 전체 파드 개수의 상한선까지 생성된다. 이때, v1 파드가 아직 3개 존재하기 때문에 새롭게 생성될 수 있는 파드의 개수는 6 - 3 = 3개이며, 이에 따라 v2 파드는 3개만 생성된다.
  • t3 : 전체 파드의 최소 개수인 3개를 벗어나지 않는 선에서 v1 파드를 삭제한다. 남아있는 v1 파드 3개를 모두 삭제해도 최소 개수를 벗어나지 않기 때문에, v1 파드를 모두 삭제한다.
  • t4 : 원래 replicas에 설정된 파드 개수만큼 v2 파드르 생성해 롤링 업데이트를 마무리한다.

 

📌 그 밖의 다른 필드

deploy.spec.minReadySeconds : Ready 상태가 될 때까지 조금 기다린다.
기본 값은 0이다. RS에 의해 파드가 만들어질 때 Ready 상태가 되어야 다음 파드를 만들 수 있는데 값을 60초라고 지정하면 Ready 상태가 될 때까지 최대 60초를 기다린다.


프로브를 사용하면 minReadySeconds는 사용할 필요가 없으면 프로브를 사용할 수 없을 때 대신해서 사용한다.

deploy.spec.revisionHistoryLimit : rollback을 허용하기 위해 보유할 이전 ReplicaSet의 수다.

rollout history는 기본적으로 10개까지만 나온다.

728x90