[CKA] kubernetes Controller - Deployment
이번 시간에는 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
끝!