들어가기에 앞서...
- 본 글은 쿠버네티스 시리즈 중의 하나로, kubernetes 실습을 위한 기본 환경 세팅이 이루어져 있지 않은 분은 시리즈 1편을 확인해주시길 바란다.
- 쿠버네티스 실습 시리즈는 아래 학습 자료를 참고하고 있다.
0. 블로깅 목적
- Deployment 정의, 주요 기능 및 배포전략을 이해한다.
- Deployment의 기본적인 생성 및 조회 방법을 이해할 수 있다.
- Deployment의 롤링 업데이트 적용 및 흐름을 이해할 수 있다.
1. Deployment 정의, 주요 기능 및 배포전략을 이해한다.
1) Deployment의 정의 및 주요 기능
(1) Deployment?
- 서비스 버전이 업데이트 되어 Pod를 새로운 버전의 이미지 Pod로 교체해야 한다면? 새 버전에 이슈가 발견되어 롤백을 진행해야 한다면?
=> 즉, 업데이트와 롤백 2가지 과정에 관여하는 게 바로 Deployment라고 할 수 있다.
(2) Deployment 기능
- Pod의 이미지 버전이 갱신될 때 배포 전략을 설정한다.
- 배포 전략을 지원해주는 게 2가지가 있는데, Recreate 전략과 RollingUpdate 전략이다.
- Deployment 오브젝트를 생성하면 이에 대응되는 ReplicaSet과 Pod는 자동으로 생성된다. (Deployment를 쓰는 것만으로 ReplicaSet과 Pod을 사용자가 직접 다룰 필요가 없는 것)
=> 사용자는 특수한 목적이 아니라면 Pod와 ReplicaSet이 아닌 Deployment로 워크로드를 관리한다.
2) Deployment 배포 전략
(1) Recreate 전략
- 기존 ReplicaSet의 Pod를 모두 종료 후, 새 ReplicaSet의 Pod를 새로 생성한다.
- 다만 운영환경에서는 배포된 서비스의 다운타임이 발생하기 때문에, 어지간하면 안 쓰는 게 좋다. (트래픽이 적으면 고려해볼 수 있을 것)
(2) RollingUpdate 전략
- 주로 사용되는 전략이다.
- 세부 설정에 따라 기존 ReplicaSet에서 새로운 ReplicaSet으로 점진적으로 이동하는 전략이다.
- maxSurge: 업데이트 과정에서 spec.replicas 수 기준 최대 새로 추가되는 파드 수
- maxUnavailable: 업데이트 과정에 spec.replicas 수 기준 최대 이용 불가능 파드 수
1. [새 파드 생성] => [기존 파드 삭제] 반복 전략:
- 가령 spec.replicas가 10인데 maxSurge 옵션이 1이면 최대 Pod 수가 11개까지 가능하다는 것이다. 그럼 롤링 업데이트 시에 새로운 레플리카에 Pod를 1개 만든 이후에, 기존 레플리카의 Pod를 1개씩 지워가는 방식으로 이동하게 된다.
- 참고로 maxUnavailable 옵션은 0으로 고정해야 가능한 전략이다.
- 장점: 노드 자원의 수가 기본 spec 설정값 미만으로 떨어질 일이 없다.
- 단점: 노드 자원의 수가 간혹 기본 spec 설정값을 초과하여 클러스터에 부담을 줄 수 있다.
2. [기존 파드 삭제] => [새 파드 생성] 반복 전략:
- 가령 spec.replicas가 10인데 maxUnavailable이 1이면 최대 Pod 수가 9까지 가능하다는 것이다. 그럼 롤링 업데이트 시에 기존 레플리카의 Pod를 1개를 삭제한 이후에, 새로운 레플리카에 Pod를 1개씩 만드는 방식으로 이동하게 된다.
- 참고로 maxSurge 옵션은 0으로 고정해야 가능한 전략이다.
- 장점: 노드 자원의 수가 기본 spec 설정값을 초과할 일이 없다.
- 단점: 노드 자원의 수가 간혹 기본 spec 설정값 미만으로 떨어져 트래픽 대응 레벨이 떨어질 수 있다.
2. Deployment의 기본적인 생성 및 조회 방법을 이해할 수 있다.
- yml 파일을 준비하고 실습을 통해 이해해보자.
deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
replicas: 3
selector:
matchLabels:
app: hello
template:
metadata:
name: hello
labels:
app: hello
spec:
containers:
- name: nginx
image: nginxdemos/hello:plain-text
ports:
- name: http
containerPort: 80
protocol: TCP
- 이전 시리즈의 replicaSet.yml 파일과 kind 부분빼고는 다른 게 없다.
- cat deployment.yml
- 간단히 파일을 확인부터 시작해본다.
- kubectl apply -f deployment.yml
- 생성을 진행한다.
- kubectl get deploy
- 간단히 deployment를 조회해본다. deploy는 축약어이다.
- kubectl get rs
- rs(replicaSet의 축약어)을 조회하였다. hello 뒤에 prefix값이 랜덤으로 붙은 걸 볼 수 있다.
- kubectl get pod
- pod도 조회하였다. 모든 pod가 동일한 replicaSet prefix값이 붙고, 그뒤에 pod 각각의 식별값이 랜덤하게 붙은 걸 볼 수 있다. 이렇게 deployment를 생성하면 Pod와 ReplicarSet이 같이 생성이 된다.
- watch kubectl get pod --show-labels
- 새로운 터미널을 열고 watch 모드로도 관찰해보자.
- 그리고 kubectl delete -f deployment.yml 한다.
3. Deployment의 롤링 업데이트 적용 및 흐름을 이해할 수 있다
- yml 파일을 준비하고 실습을 통해 이해해보자.
rolling-update.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: rolling
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
minReadySeconds: 5
revisionHistoryLimit: 5
replicas: 5
selector:
matchLabels:
app: rolling
template:
metadata:
name: rolling
labels:
app: rolling
spec:
containers:
- name: nginx
image: nginxdemos/hello:plain-text
ports:
- name: http
containerPort: 80
protocol: TCP
- deployment.yml에서 전반적인 이름이 hello -> rolling으로 바뀌고, spec 부분의 strategy ~ revisionHistoryLimit이 새로 추가된 파일이다.
- strategy가 없으면 Recreate 전략이 디폴트로 실행된다. RollingUpdate 전략을 적용하려면 strategy.type에 RollingUpdate를 추가해야 한다.
- 앞서 설명했듯이 rollingUpdate 옵션도 줄 수 있다. 옵션은 maxSurge와 maxUnavailable을 잘 사용한다.
- minReadySeconds는 새로운 Pod를 생성한 뒤의 최소 대기 시간을 설정하는 옵션이다.
- revisionHistoryLimit은 이미지 버전이 업데이트 될때마다 revision을 만든다. 그 revision을 몇개까지 가지고 있을 건지를 설정하는 옵션이다.
- cat rolling-update.yml
- 간단히 파일을 확인부터 시작해본다.
- kubectl apply -f rolling-update.yml
- 생성이 잘 되었다.
- kubectl rollout history deployment rolling
- 기본적으로는 kubectl이 어떤 CHANGE-CAUSE 명령어로 발생한 revision인지 기록하지 않는다.
- record 옵션을 통해서 만들면 기록을 남길 수 있다.
- 아래 명령어를 순서대로 입력하면
- kubectl delete -f rolling-update.yml
- kubectl apply -f rolling-update.yml --record
- kubectl rollout history deployment rolling
- revision 1이 만들어 질때 사용됐던 CHANGE-CAUSE가 확인됨을 알 수 있다.
- 이제 새로운 터미널을 열어 watch 모드를 실행시키고 아래 과정을 진행해보자.
- kubectl set image deployment rolling nginx=nginxdemos/hello:latest --record
- 롤링 업데이트 입력을 진행하기 전의 출력 상태다.
- 새로운 rs에 새로운 Pod를 만들고, 기존 rs의 Pod를 삭제하는 모습이다. 이와 같은 과정이 한바퀴 돌때까지 반복된다.
- 롤링 업데이트 완료 후 상태이다. 롤링 업데이트 전과 비교하면 Pod 식별값이 전부 바뀐 것을 알 수 있다.
- kubectl rollout history -f rolling-update.yml
- 2번 revision과 CHANGE-CAUSE가 기록되어 있음을 알 수 있다.
- kubectl rollout history deployment rolling도 되지만 이렇게 yml을 통해 history를 볼수도 있다.
- kubectl rollout undo deployment rolling --to-revision=1
- undo 를 통해 이전 revision 시점으로 돌아가는 방법이다.
- 과정은 생략했지만 이것도 롤링 업데이트 처럼 점진적으로 돌아간다.
- kubectl rollout status deployment rolling
- 동시에 해당 롤링 업데이트 중에 rollout status를 입력하면, 상태를 확인할 수도 있다. 1 -> 2 -> 3 몇번째 replica가 새롭게 만들어지고 있는 지 보인다.
- kubectl rollout history -f rolling-update.yml
- 완료 후 마지막으로 한번더 확인해보자.
- revision 1은 사라지고 revision 3가 revision 1의 구문을 동일하게 대체하여 만들어졌음을 알 수 있다.
- 즉, 당연히 복구라고는 해도 Pod를 새롭게 만들면서 돌아간 것이기 때문에 식별자는 처음 revision 1의 Pod들과는 다르며 새로운 revision이 만들어진 것이나 다름 없는 것이다.
- 다만 undo로 이전 시점과 완전히 동일한 구문을 실행한거나 다름 없으므로, 중복되는 revision 1은 필요가 없어져 삭제된 것이다.