코알못

[CKA] kubernetes Controller - Deployment 본문

ETC

[CKA] kubernetes Controller - Deployment

코린이s 2023. 9. 3. 12:31
728x90

이번 시간에는 Controller 중에 하나인 Deployment 를 알아보자!
Deployment의 경우 배포를 위한 Controller로 ReplicaSet을 이용해서 Pod 수를 조절하는 방법을 사용한다.
그리고 Rolling Update(파드를 '점진적=하나씩'으로 새 버전으로 업데이트하여 서비스 중단없이 배포 한다.), RollBack 기능을 지원하여 배포를 원활하게 진행 할 수 있다.
Rolling Update, RollBack 기능을 이용하지 않으면 내부 문법은 ReplicaSet과 동일하게 이용할 수 있어 저번 시간에 사용한 ReplicaSet yaml 파일에 kind 부분만 ReplicaSet에서 Deployment로 변경하여 deploy-nginx.yaml 을 생성해보자!
# deploy-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webui
    matchExpressions:
    - {key: version, operator: Exists}
  template:
    metadata:
      name: pod-nginx
      labels:
        app: webui
        version: "1.0"
    spec:
      containers:
      - name: container-nginx
        image: nginx:1.14

해당 deploy 를 이제 생성해본다!

$ kubectl create -f deploy-nginx.yaml

이제 deploy, rs, pod 정보를 한번에 본다. (쉼표로 구분하여 나열하면 된다.)

$ kubectl get deploy,rs,pod
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-nginx   3/3     3            3           29s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/deploy-nginx-644d9f68db   3         3         3       29s

NAME                                READY   STATUS    RESTARTS   AGE
pod/deploy-nginx-644d9f68db-89g7t   1/1     Running   0          29s
pod/deploy-nginx-644d9f68db-q5pkq   1/1     Running   0          29s
pod/deploy-nginx-644d9f68db-wmkkq   1/1     Running   0          29s

생성된 NAME 부분을 보면 ReplicaSet은 deployment 가 만들었으니 deploy 명인 deploy-nginx 뒤에 해시 난수가 붙어 이름이 정해졌으며
파드의 경우 replicaSet 명인 [deploy명+hash난수]에 해시 난수가 붙어서 생성되었다.
이를 통해 deployment가 replicaset을 만들고 replicaset이 pod를 생성 했음을 알 수 있다.
그럼 pod 를 삭제하면 replicaset 이 파드를 생성할 것이고 replicaset을 삭제하면 deploy 가 replica 를 생성할까? 정답은 맞다!
이를 확인해보자!
우선 파드 하나를 제거하고 replicaset을 보면 다시 정상적으로 3개의 파드를 생성한것을 확인 할 수 있다.

$ kubectl delete pod deploy-nginx-XXX-XXX
$ kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
deploy-nginx-644d9f68db   3         3         3       118s

이제 replicaset 을 제거하고 deploy,rs,pod를 보면 정상적으로 rs, pod가 생성되는것을 볼 수 있다.

$ kubectl delete rs deploy-nginx-XXX
$ kubectl get deploy,rs,pod
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-nginx   3/3     3            3           3m16s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/deploy-nginx-644d9f68db   3         3         3       37s

NAME                                READY   STATUS    RESTARTS   AGE
pod/deploy-nginx-644d9f68db-66r25   1/1     Running   0          37s
pod/deploy-nginx-644d9f68db-cmkhc   1/1     Running   0          37s
pod/deploy-nginx-644d9f68db-ggfb5   1/1     Running   0          37s

이제 롤링 업데이트, 백의 기능을 이용해보자!
그전에 롤링 업데이트 방식을 알아보면 아래와 같이 이미지 변경 요청을 한다.

$ kubectl set image deployment [deploy name] [container name]=[new image name:version]

요청하게 되면 deployment 는 아래와 같이 변경된 이미지의 replicaset을 생성하며 파드를 하나 생성하며 (=replicas: 1) 이전 버전의 replica 수를 하나 줄여 파드를 제거 한다.

그 뒤에 새 replicaset의 replica를 하나 늘리고 이전 버전의 replica를 하나 줄여 점진적 배포를 진행한다.

이렇게 하나씩 replicaset의 replicas 수를 변경하여 점진적으로 파드가 새 버전으로 교체 하게 되며 마지막에는 새 버전만 남아 배포가 완료 되게 된다.

이렇게 모든 파드가 배포가 되는것이며  관련 실습을 진행해보자!
이전에 생성한 deploy의 경우 --record 옵션을 주지 않았기에 아래와 같이 확인 해보면 history가 남지 않는다.

$ kubectl rollout history deployment deploy-nginx
REVISION  CHANGE-CAUSE
1         <none>

그렇기에 이전에 생성한 deploy를 삭제하고

$ kubectl delete deploy deploy-nginx
deployment.apps "deploy-nginx" deleted
$ kubectl get deploy,rs,pod
No resources found in default namespace.

다시  기록 옵션을 주어 생성 한다.

$ kubectl create -f deploy-nginx.yaml deploy-nginx --record

다시 히스토리를 보면 기록 된것을 확인 할 수 있다.

$ kubectl rollout history deployment deploy-nginx
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy-nginx.yaml --record=true

이제 1.14 이미지 버전을 1.15 버전으로 변경한다.

$ kubectl set image deployment deploy-nginx container-nginx=nginx:1.15 --record

아래와 같이 status 를 입력하면 rollout 되는것을 모니터링 할 수 으며

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

완료 된 후 deploy, rs, pod 정보를 확인하면 이전 replicaset은 0개가 되고 새 replicaset 이 생성되어 배포 된것을 알 수 있다.

$ kubectl get deploy,rs,pod
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-nginx   3/3     3            3           23s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/deploy-nginx-644d9f68db   0         0         0       23s
replicaset.apps/deploy-nginx-85fd7d4579   3         3         3       8s

NAME                                READY   STATUS    RESTARTS   AGE
pod/deploy-nginx-85fd7d4579-48kfr   1/1     Running   0          6s
pod/deploy-nginx-85fd7d4579-97xhp   1/1     Running   0          5s
pod/deploy-nginx-85fd7d4579-gskkl   1/1     Running   0          8s

파드 정보를 확인해보면 해당 파드가 1.15 이미지의 파드 인것을 알 수 있다.

$ kubectl describe pod deploy-nginx-XXX-XXX
..
    Image:          nginx:1.15

이제 rollout 중에 pause 명령어를 입력하여 롤 아웃을 중간에 중단하도록 한다.
우선 다른 버전인 1.16으로 변경하고

$ kubectl set image deployment deploy-nginx container-nginx=nginx:1.16 --record

변경 하는 중간에 아래 명령어로 중단한다.

$ kubectl rollout pause deployment deploy-nginx
deployment.apps/deploy-nginx paused

중단된 상태에서 다시 중단을 입력하면 이미 중단 되었다고 안내 메세지가 나온다.

$ kubectl rollout pause deployment deploy-nginx
error: deployments.apps "deploy-nginx" is already paused

저자의 경우 너무 늦게 pause 해서 이미 배포가 모두 되어 버렸다.

[node1 ~]$ kubectl get deploy,rs,pod
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-nginx   3/3     3            3           69s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/deploy-nginx-644d9f68db   0         0         0       69s
replicaset.apps/deploy-nginx-78d868d86d   3         3         3       19s
replicaset.apps/deploy-nginx-85fd7d4579   0         0         0       54s

NAME                                READY   STATUS    RESTARTS   AGE
pod/deploy-nginx-78d868d86d-28z4r   1/1     Running   0          19s
pod/deploy-nginx-78d868d86d-88m54   1/1     Running   0          8s
pod/deploy-nginx-78d868d86d-jff5p   1/1     Running   0          10s

다시 재개를 하고 (만약 재개 하지 않은 상태에서 추가 변경 요청시 진행 되지 않는다.)

$ kubectl rollout resume deployment deploy-nginx
deployment.apps/deploy-nginx resumed

1.17로 시도 해보자!

$ kubectl set image deployment deploy-nginx container-nginx=nginx:1.17 --record

중단하고

$ kubectl rollout pause deployment deploy-nginx

이상태에서 파드를 확인해보면 중간 해시 값인 replicaSet 난수가 다른 파드가 섞여 있으며 이는 배포 중간에 중단이 정상적으로 됐음을 알 수 있다.

$ kubectl get deploy,rs,pod
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-nginx   4/3     1            4           103s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/deploy-nginx-644d9f68db   0         0         0       103s
replicaset.apps/deploy-nginx-78d868d86d   3         3         3       53s
replicaset.apps/deploy-nginx-84bf46c47c   1         1         1       6s
replicaset.apps/deploy-nginx-85fd7d4579   0         0         0       88s

NAME                                READY   STATUS    RESTARTS   AGE
pod/deploy-nginx-78d868d86d-28z4r   1/1     Running   0          53s
pod/deploy-nginx-78d868d86d-88m54   1/1     Running   0          42s
pod/deploy-nginx-78d868d86d-jff5p   1/1     Running   0          44s
pod/deploy-nginx-84bf46c47c-jnfwm   1/1     Running   0          6s

다른 해시를 각각 확인해보면 하나는 1.16 하나는 1.17 버전이 있다. 

$ $ kubectl describe pod deploy-nginx-78d868d86d-28z4r
    Image:          nginx:1.16
$ kubectl describe pod deploy-nginx-84bf46c47c-jnfwm
    Image:          nginx:1.17

 
rs 정보를 보고자 하면 아래와 같이 입력하여 확인 가능하다.

$ kubectl describe rs deploy-nginx-78d868d86d
..
    Image:        nginx:1.16
$ kubectl describe rs deploy-nginx-78d868d86d
    Image:        nginx:1.17

이제 다시 재개를 해서 배포를 완료 시켜 보자!

$ kubectl rollout resume deployment deploy-nginx
deployment.apps/deploy-nginx resumed

이제 배포 완료가 되었고 rollout 히스토리를 확인해보면 어떻게 배포가 이뤄졌는지 알 수 있다.

$ kubectl rollout history deployment deploy-nginx
deployment.apps/deploy-nginx 
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy-nginx.yaml --record=true
2         kubectl set image deployment deploy-nginx container-nginx=nginx:1.15 --record=true
3         kubectl set image deployment deploy-nginx container-nginx=nginx:1.16 --record=true
4         kubectl set image deployment deploy-nginx container-nginx=nginx:1.17 --record=true

이러한 히스토리의 경우 디폴트로 10개가 보여지며 아래와 같은 설정을 통해 replicaset 보관수를 변경 할 수 있다. 

spec:
  revisionHistoryLimit: 10

또 다른 배포 관련 설정 확인 가능하며 edit를 통해 보면 여러가지 옵션을 볼 수 있고 

$ kubectl edit deployment deploy-nginx

progressDeadlineSeconds는 기본값 600s(=10분) 이며 10분안에 배포가 완료되지 않으면 롤백된다.

spec:
  progressDeadlineSeconds: 600

strategy의 경우 배포 방식 설정으로

spec:
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate

maxSurge의 경우 최대 이용가능한 파드수로 
현재 떠있는 3개 파드의 25%(=3*0.25=0.75 반올림=1)인 1개의 파드를 더해서 최대 4개의 파드가 이용가능한 상태일 수 있다.
롤링 업데이트로 배포 한다고 하면 이미 3개거 떠있으니 최대 4개 이므로 새 버전의 replica로 파드가 1개 추가로 뜰 수 있게 된다.
maxUnavailable의 경우 최대 이용불가능한 파드수로 즉, 최소 떠있어야 하는 파드수 이며
현재 떠있는 3개의 파드의 25% 이므로 최대 2(3-1)개의 파드가 최소 떠있어야 한다.
그럼 현재 설정으로는 파드가 2개 ~ 4개 떠있을수 있는 것이다.
만약에 롤백을 하고 싶다면 어떻게 해야 할까?
우선 히스토리를 보면 Revision이라는 번호를 보게 되며

$ kubectl rollout history deployment deploy-nginx
deployment.apps/deploy-nginx 
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy-nginx.yaml --record=true
2         kubectl set image deployment deploy-nginx container-nginx=nginx:1.15 --record=true
3         kubectl set image deployment deploy-nginx container-nginx=nginx:1.16 --record=true
4         kubectl set image deployment deploy-nginx container-nginx=nginx:1.17 --record=true

아래와 같이 undo를 사용하면 바로 한단계 이전(3)으로 가게 되며 undo 된 이전(3)번호가 새 번호인 5를 부여 받는다. 

$ kubectl rollout undo deployment deploy-nginx
deployment.apps/deploy-nginx rolled back
$ kubectl rollout history deployment deploy-nginx
deployment.apps/deploy-nginx 
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy-nginx.yaml --record=true
2         kubectl set image deployment deploy-nginx container-nginx=nginx:1.15 --record=true
4         kubectl set image deployment deploy-nginx container-nginx=nginx:1.17 --record=true
5         kubectl set image deployment deploy-nginx container-nginx=nginx:1.16 --record=true

그럼 현재 revision은 5이며 replicaset이 현재 1.16 인지 확인 해보면 1.16으로 정상적으로 롤백된것을 확인 할 수 있다.

$ kubectl get rs -o wide
NAME                      DESIRED   CURRENT   READY   AGE     CONTAINERS        IMAGES       SELECTOR
deploy-nginx-644d9f68db   0         0         0       10m     container-nginx   nginx:1.14   app=webui,pod-template-hash=644d9f68db,version
deploy-nginx-78d868d86d   3         3         3       9m35s   container-nginx   nginx:1.16   app=webui,pod-template-hash=78d868d86d,version
deploy-nginx-84bf46c47c   0         0         0       8m48s   container-nginx   nginx:1.17   app=webui,pod-template-hash=84bf46c47c,version
deploy-nginx-85fd7d4579   0         0         0       10m     container-nginx   nginx:1.15   app=webui,pod-template-hash=85fd7d4579,version

 
만약 원하는 버전으로 가고 싶다면 history의 버전을 가지고 이동 할 수 있다.
1.15 이미지로 가고 싶다면 revision 2로 가면 된다!

$ kubectl rollout history deployment deploy-nginx
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy-nginx.yaml --record=true
2         kubectl set image deployment deploy-nginx container-nginx=nginx:1.15 --record=true
4         kubectl set image deployment deploy-nginx container-nginx=nginx:1.17 --record=true
5         kubectl set image deployment deploy-nginx container-nginx=nginx:1.16 --record=true

아래와 같이 --to-revision 옵션을 사용하면 되며

$ kubectl rollout undo reployment deploy-nginx --to-revision=[ROLLBACK REVISION]

2로 가려면 2를 적으면 된다.

$ kubectl rollout undo deployment deploy-nginx --to-revision=2
deployment.apps/deploy-nginx rolled back

이와 같이 입력시 이전 이미지의 revision인 2가 사라지고 새 Revision 번호인 6을 부여받게 된다.

$ kubectl rollout history deployment deploy-nginx
deployment.apps/deploy-nginx 
REVISION  CHANGE-CAUSE
1         kubectl create --filename=deploy-nginx.yaml --record=true
4         kubectl set image deployment deploy-nginx container-nginx=nginx:1.17 --record=true
5         kubectl set image deployment deploy-nginx container-nginx=nginx:1.16 --record=true
6         kubectl set image deployment deploy-nginx container-nginx=nginx:1.15 --record=true

그리고 deploy 를 삭제하면 history는 물론 모든 deploy, replicaset, pod 모두 제거 된다.

$ kubectl delete deploy deploy-nginx
deployment.apps "deploy-nginx" deleted
$ kubectl get deploy,rs,pod
No resources found in default namespace.
$ kubectl rollout history deployment deploy-nginx
Error from server (NotFound): deployments.apps "deploy-nginx" not found

그리고 k8s의 경우 annotations를 이용하여 기존 history 메세지를 수정할 수 있다.
아래와 같이 kubernetes.io/change-cause 어노테이션을 사용하면 되며 해당 값에 원하는 메세지를 넣는다.
추가로 revision 보관수를 최대 3개 가능 하도록 한다.
# deploy-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  annotations:
    kubernetes.io/change-cause: version 1.14
spec:
  replicas: 3
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: webui
    matchExpressions:
    - {key: version, operator: Exists}
  template:
    metadata:
      name: pod-nginx
      labels:
        app: webui
        version: "1.0"
    spec:
      containers:
      - name: container-nginx
        image: nginx:1.14

적용 한다.

$ kubectl create -f deploy-v2.yaml

그리고 1.15로 어노테이션과 이미지 버전을 수정한다.
# deploy-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
  annotations:
    kubernetes.io/change-cause: version 1.15
spec:
  replicas: 3
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: webui
    matchExpressions:
    - {key: version, operator: Exists}
  template:
    metadata:
      name: pod-nginx
      labels:
        app: webui
        version: "1.1"
    spec:
      containers:
      - name: container-nginx
        image: nginx:1.15

적용 한다.

$ kubectl apply -f deploy-v2.yaml

히스토리를 보면 이전과 달리 깔끔하게 표기 되며 관리하기 좋게 된다.

$ kubectl rollout hisory deployment deploy-nginx
deployment.apps/deploy-nginx 
REVISION  CHANGE-CAUSE
1         version 1.14
2         version 1.15

롤백 가능한 replicaset이 최대 3개가 맞는지 확인을 위해 버전 여러개를 배포 해본다.
현재 revision은 6이며 최대 이전 3개(3,4,5)의 revision 으로 롤백 가능한것을 확인 할 수 있다.

$ kubectl rollout history deployment deploy-nginx
deployment.apps/deploy-nginx 
REVISION  CHANGE-CAUSE
3         version 1.16
4         version 1.17
5         version 1.18
6         version 1.19

이제 모든 deploy 를 삭제 한다.

$ kubectl delete deploy deploy-nginx

끝!

728x90
Comments