Deployment
에서는 pod에 대한 replicas를 관리하여, 재시작, versioning 등을 제공한다고 하였다. 여기서 versioning으로 pod의 version을 올리고 내릴 수 있는데, rollout
이 바로 version을 올리는 작업을 말하고, rollback
이 version을 되돌리는 일을 한다.
Revision1: [Pod1-nginx:1.7.0] , [Pod2-nginx:1.7.0]
(Rollout)
Revision2: [Pod1-nginx:1.7.1] , [Pod2-nginx:1.7.1]
위의 예제와 같이 Revision
이라는 것을 Deployment
에서 갖게되어 version을 rollout, rollback함에 따라 pod의 version이 달라지는 것이다.
kubectl rollout status deployment/myapp-deployment
rollout status
를 실행하면 지금의 rollout
현황을 볼 수 있다.
만약, 현재까지의 revision이나 version history를 보고 싶다면 아래의 명령어를 쓰면 된다.
kubectl rollout history deployment/myapp-deployment
deployment
에서 rollout, rollback을 실행하는데 있어서, 두 가지 배포 전략이 있다.
Recreate
strategy라고 한다.Revision1: [Pod1-nginx:1.7.0] , [Pod2-nginx:1.7.0]
rollout
시에 먼저 pod1
, pod2
를 죽이고
(Rollout)
Revision2: [Pod1-nginx:1.7.1] , [Pod2-nginx:1.7.1]
다음 새로운 version의 pod들로 새로올리는 것이다.
문제는 이러한 방식을 사용하면 잠시 동안 application이 down되는 문제가 발생한다는 것이다. 따라서 사용자에게 좋지못한 사용자 경험을 줄 수 밖에 없다.
다행이도 restart strategy는 default strategy가 아니기 때문에 문제가 되지 않는다.
Rolling Update
strategy라고 하며, 이 방식이 default이다.Revision1: [Pod1-nginx:1.7.0] , [Pod2-nginx:1.7.0]
rollout
시에 먼저 pod1
을 죽이고 새로운 버전의 pod1
을 올린다. pod2
는 여전이 이전 버전이다.
Revision1: [Pod2-nginx:1.7.0]
(Rollout)
Revision2: [Pod1-nginx:1.7.1]
다음으로 pod2
를 죽이고 pod2
의 새로운 버전을 올린다. 이전에 이미 pod1
은 새로운 버전의 pod이다.
(Rollout)
Revision2: [Pod1-nginx:1.7.1] , [Pod2-nginx:1.7.1]
방식을 사용하면 application의 다운없이 사용자에게 지속적인 경험을 시켜줄 수 있어 굉장히 좋다.
지금까지 update
전략에 대해서 알아봤는데, 그런데 어떻게 update
를 할 수 있는가?? 여러 방법들이 있는데, kubectl apply
를 사용하여 deployment를 업데이트하는 방법이 대표적이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
labels:
app: myapp
type: front-end
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
replicas: 3
selector:
matchLabels:
type: front-end
다음의 file에서 원하는 부분만 바꾸는 것이다. 이렇게 바꾸면 rollout이 발생하고 새로운 pod가 생길 것이다.
그런데, 만약 image
만 바꾸고 싶은 경우는 kubectl set image
를 사용해도 된다.
kubectl set image deployment/myapp-deployment nginx-container=nginx:1.9.1
사실 rollout
방식은 실제로 내부적으로는 그렇게 어려울 것이 없는데, deployment
내부가 ReplicaSet
으로 이루어졌다는 것만 기억하면 쉽다.
현재 deployment에 해당하는 ReplicaSet1
이 있다고 하자.
-----ReplicaSet 1-----
|pod1, pod2, pod3 |
----------------------
새로운 deployment로 rollout되면 새로운 ReplicaSet 2
를 만드는 것이다. 단, 이 경우 순차적인 rolling update를 해야하기 때문에 다음과 같은 순서로 업데이트된다.
-----ReplicaSet 1----- -----ReplicaSet 2-----
|pod2, pod3 | |pod1 |
---------------------- ----------------------
먼저 ReplicaSet 1
의 pod1
이 죽고, ReplicaSet 2
의 pod1
이 생긴다.
-----ReplicaSet 1----- -----ReplicaSet 2-----
| pod3 | |pod1, pod2 |
---------------------- ----------------------
이 다음도 마찬가지인데, ReplicaSet 1
의 pod2
가 죽고, ReplicaSet 1
의 pod2
가 생긴다.
-----ReplicaSet 1----- -----ReplicaSet 2-----
| | |pod1, pod2, pod3 |
---------------------- ----------------------
이제 모든 pod들이 ReplicaSet 2
에 의해서 생성되고 ReplicaSet 1
은 텅비어지게 된다.
그러나 ReplicaSet 1
이 텅비었다고 해서 사라지는 것은 아니다. kubectl get replicasets
로 확인해보면 ReplicaSet 1
이 있는 것을 볼 수 있을 것이다.
kubectl get replicasets
NAME DESIRED CURRENT READY AGE
replicaset1 0 0 0 22m
replicaset2 5 5 5 20m
만약 rollback을 하고 싶다면 다음의 명령어를 사용하면 된다.
kubectl rollout undo deployment/myapp-deployment
rollback시에 우리가 삭제하지 않았던 ReplicaSet 1
이 힘을 발휘한다. ReplicaSet 1
이 남아있으므로, 이를 사용하여 이전 old version의 pod들을 다시 올리고, 새로운 버전의 pod들은 ReplicaSet 2
의 replicas 수를 0으로 만들어 rollback을 진행하는 것이다.
kubectl create -f deployment-definition.yaml
kubectl get deployments
kubectl apply -f deployment-definition.yaml
kubectl set image deployment/myapp-deployment nginx=nginx:1.9.1
kubectl rollout status deployment/myapp-deployment
kubectl rollout history deployment/myapp-deployment
kubectl rollout undo deployment/myapp-deployment
참고로 kubectl edit
으로는 rolling update 이력을 남길 수 없다. 따라서 kubectl set ... --record
를 통해서 이력을 남기는 것이 좋다.
다음은 nginx-deploy
deployment의 nginx
container에 대해서 image를 nginx:1.17
로 바꾸고, rolling update history를 남기기 위해 --record
를 넣은 것이다.
kubectl set image deployment/nginx-deploy nginx=nginx:1.17 --record