[Retry, k8s] 04. 워크로드 API - 디플로이먼트
카테고리: KUBERNETES
태그: kubernetes
[Retry, k8s] 04. 워크로드 API - 디플로이먼트
🔔 디플로이먼트
여러 레플리카셋을 관리하여 롤링 업데이트나 롤백 등을 구현하는 리소스, 디플로이먼트가 레플리카셋을 관리하고 레플리카셋이 파드를 관리하는 관계이다.
📜 디플로이먼트 생성
cat <<EOF > sample-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment
spec:
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx-container
image: nginx:1.16
EOF
🔔 디플로이먼트 업데이트(레플리카셋이 생성되는) 조건
디플로이먼트에서 파드 템플릿(spec.templat)을 변경하면 새로운 레플리카셋이 생성되고 롤링 업데이트가 진행되는데 이 때, 레플리카셋은 파드 템플릿의 해시값(pod-templat-hash)을 레이블(오브젝트를 식별하고 구별하는 메타데이터)로 사용하여 파드를 식별하고 관리한다. 만약 파드 템플릿을 이전 버전으로 되돌리면 해시값도 같아지므로 새로운 레플리카셋을 생성하지 않고 기존의 것을 사용한다.
# 디플로이먼트 확인 - 해시 값은 "845c7cc945"
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/sample-deployment-845c7cc945-jnt6s 1/1 Running 0 3s 10.44.0.1 k8s-node01 <none> <none>
pod/sample-deployment-845c7cc945-qq67w 1/1 Running 0 3s 10.36.0.2 k8s-node02 <none> <none>
pod/sample-deployment-845c7cc945-wq7c9 1/1 Running 0 3s 10.36.0.1 k8s-node02 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 45h <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/sample-deployment 3/3 3 3 3s nginx-container nginx:1.16 app=sample-app
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/sample-deployment-845c7cc945 3 3 3 3s nginx-container nginx:1.16 app=sample-app,pod-template-hash=845c7cc945
# 컨테이너 이미지 업데이트
$ kubectl set image deployment sample-deployment nginx-container=nginx:1.17 --record
# 다시 디플로이먼트 확인 - 해시 값이 "6c8bfc45d6" 변경된 것을 확인할 수 있다.
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/sample-deployment-6c8bfc45d6-fwnpv 1/1 Running 0 47s 10.44.0.2 k8s-node01 <none> <none>
pod/sample-deployment-6c8bfc45d6-ngpbb 1/1 Running 0 43s 10.44.0.1 k8s-node01 <none> <none>
pod/sample-deployment-6c8bfc45d6-p6vhn 1/1 Running 0 46s 10.36.0.3 k8s-node02 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 45h <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/sample-deployment 3/3 3 3 118s nginx-container nginx:1.17 app=sample-app
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/sample-deployment-6c8bfc45d6 3 3 3 47s nginx-container nginx:1.17 app=sample-app,pod-template-hash=6c8bfc45d6
replicaset.apps/sample-deployment-845c7cc945 0 0 0 118s nginx-container nginx:1.16 app=sample-app,pod-template-hash=845c7cc945
🔔 변경 롤백
디플로이먼트에서 제공하는 롤백 기능의 실체는 현재 사용 중인 레플리카셋의 전환과 같은 것은데, 디플로이먼트가 생성한 기존 레플리카셋은 레플리카 수가 0인 상태로 남아 있기 때문에 레플리카 수를 변경시켜 다시 사용할 수 있는 상태가 된다.
# 변경 이력 확인
$ kubectl rollout history deployment sample-deployment
# 초기 상태의 디플로이먼트
$ kubectl rollout history deployment sample-deployment --revision 1
deployment.apps/sample-deployment with revision #1
Pod Template:
Labels: app=sample-app
pod-template-hash=845c7cc945
Containers:
nginx-container:
Image: nginx:1.16
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
# 한 번 업데이트된 후의 디플로이먼트
$ kubectl rollout history deployment sample-deployment --revision 2
deployment.apps/sample-deployment with revision #2
Pod Template:
Labels: app=sample-app
pod-template-hash=6c8bfc45d6
Containers:
nginx-container:
Image: nginx:1.17
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
# 버전 번호를 지정하여 롤백하는 경우
$ kubectl rollout undo deployment sample-deployment --to-revision 1
# 바로 이전 버전으로 롤백하는 경우 (기본값인 --to-revision 0이 지정되어 바로 이전 버전으로 롤백)
$ kubectl rollout undo deployment sample-deployment
# 롤백한 후 이전 레플리카셋에서 파드가 기동됨
$ kubectl get replicasets
NAME DESIRED CURRENT READY AGE
sample-deployment-6c8bfc45d6 0 0 0 8m5s # 신규 레플리카셋
sample-deployment-845c7cc945 3 3 3 8m10s # 이전 레플리카셋
🔔 디플로이먼트 변경 일시 중지
디플로이먼트를 업데이트하면 바로 적용 되지만, 만약 안전을 위해 디플로이먼트에 대한 업데이트를 하더라도 바로 적용되지 않는 것을 원하는 경우를 위해 즉시 적용되지 않는 구조도 준비되어 있다. (먼저 kubectl rollout pause를 실행하고 다시 시작할 때는 kubectl rollout resume을 실행한다.)
# 업데이트 일시 정지
$ kubectl rollout pause deployment sample-deployment
# 업데이트 일시 정지 해제
$ kubectl rollout resume deployment sample-deployment
# 업데이트 일시 정지
$ kubectl rollout pause deployment sample-deployment
# pause 상태에서 컨테이너 이미지를 업데이트
$ kubectl set image deployment sample-deployment nginx-container=nginx:1.17
# 업데이트 대기 상태 확인
$ kubectl rollout status deployment sample-deployment
Waiting for deployment "sample-deployment" rollout to finish: 0 out of 3 new replicas have been updated...
# 업데이트 일시 정지 해제하면 업데이트가 진행된다.
$ kubectl rollout resume deployment sample-deployment
🔔 디플로이먼트 업데이트 전략
디플로이먼트를 업데이트 하면 롤링 업데이트가 실행되는데, 이것은 업데이트 전략을 지정하는 “spec.strategy.type”이라는 항목의 기본값이 RollingUpdate으로 되어 있어서 이며, 업데이트 전략은 Recreate와 RollingUpdate가 있다.
(a) Recreate
모든 파드를 한 번 삭제하고 다시 생성하기 때문에 다운타임이 발생하지만, 추가 리소스를 사용하지 않고 전환이 빠른 것이 장점이다.
cat <<EOF > sample-deployment-recreate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment-recreate
spec:
strategy:
type: Recreate
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx-container
image: nginx:1.16
EOF
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/sample-deployment-recreate-845c7cc945-248kj 1/1 Running 0 19s 10.44.0.2 k8s-node01 <none> <none>
pod/sample-deployment-recreate-845c7cc945-hmpth 1/1 Running 0 19s 10.44.0.1 k8s-node01 <none> <none>
pod/sample-deployment-recreate-845c7cc945-z5j5b 1/1 Running 0 19s 10.36.0.1 k8s-node02 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 47h <none>
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/sample-deployment-recreate 3/3 3 3 19s nginx-container nginx:1.16 app=sample-app
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/sample-deployment-recreate-845c7cc945 3 3 3 19s nginx-container nginx:1.16 app=sample-app,pod-template-hash=845c7cc945
# 컨테이너 이미지 업데이트
$ kubectl set image deployment sample-deployment-recreate nginx-container=nginx:1.17
# 레플리카셋 목록 표시(리소스 상태 변화가 있으면 계속 출력)
$ kubectget replicasets --watch
NAME DESIRED CURRENT READY AGE
sample-deployment-recreate-6c8bfc45d6 0 0 0 108s
sample-deployment-recreate-845c7cc945 3 3 3 3m13s
sample-deployment-recreate-6c8bfc45d6 0 0 0 112s
sample-deployment-recreate-845c7cc945 0 3 3 3m18s
sample-deployment-recreate-845c7cc945 0 3 3 3m18s
sample-deployment-recreate-845c7cc945 0 0 0 3m18s
sample-deployment-recreate-6c8bfc45d6 3 0 0 113s
sample-deployment-recreate-6c8bfc45d6 3 0 0 113s
sample-deployment-recreate-6c8bfc45d6 3 3 0 113s
sample-deployment-recreate-6c8bfc45d6 3 3 1 116s
sample-deployment-recreate-6c8bfc45d6 3 3 2 116s
sample-deployment-recreate-6c8bfc45d6 3 3 3 116s
(b) RollingUpdate
RollingUpdate는 업데이트 중에 동시에 정지 가능한 최대 파드 수(maxUnavailable)와 업데이트 중에 동시에 생성할 수 있는 최대 파드 수(maxSurge)를 설정이 가능하며, 이 설정을 사용하면 추가 리소스를 사용하지 않도록 하거나 많은 리소스를 소비하지 않고 빠르게 전환하는 등 업데이트를 하면서 동작을 제어할 수 있다. (maxUnavailable과 maxSurge 값을 모두 0으로 설정할 수 없다.)
cat <<EOF > sample-deployment-rollingupdate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment-rollingupdate
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx-container
image: nginx:1.16
EOF
# 컨테이너 이미지 업데이트
$ kubectl set image deployment sample-deployment-rollingupdate nginx-container=nginx:1.17
# 레플리카셋 목록 표시(리소스 상태 변화가 있으면 계속 출력)
# maxUnavailable=0/maxSurge=1 설정의 RollingUpdate에서는 maxSurge 수만큼 추가 레플리카 수를 늘려 파드를 이동시킨다.
$ kubectl get replicasets --watch
NAME DESIRED CURRENT READY AGE
sample-deployment-rollingupdate-845c7cc945 3 0 0 0s
sample-deployment-rollingupdate-845c7cc945 3 0 0 0s
sample-deployment-rollingupdate-845c7cc945 3 3 0 0s
sample-deployment-rollingupdate-845c7cc945 3 3 1 1s
sample-deployment-rollingupdate-845c7cc945 3 3 2 1s
sample-deployment-rollingupdate-845c7cc945 3 3 3 2s
sample-deployment-rollingupdate-6c8bfc45d6 1 0 0 0s
sample-deployment-rollingupdate-6c8bfc45d6 1 0 0 0s
sample-deployment-rollingupdate-6c8bfc45d6 1 1 0 0s
sample-deployment-rollingupdate-6c8bfc45d6 1 1 1 2s
sample-deployment-rollingupdate-845c7cc945 2 3 3 37s
sample-deployment-rollingupdate-6c8bfc45d6 2 1 1 2s
sample-deployment-rollingupdate-845c7cc945 2 3 3 37s
sample-deployment-rollingupdate-6c8bfc45d6 2 1 1 2s
sample-deployment-rollingupdate-845c7cc945 2 2 2 37s
sample-deployment-rollingupdate-6c8bfc45d6 2 2 1 2s
sample-deployment-rollingupdate-6c8bfc45d6 2 2 2 3s
sample-deployment-rollingupdate-845c7cc945 1 2 2 38s
sample-deployment-rollingupdate-6c8bfc45d6 3 2 2 3s
sample-deployment-rollingupdate-845c7cc945 1 2 2 38s
sample-deployment-rollingupdate-6c8bfc45d6 3 2 2 3s
sample-deployment-rollingupdate-845c7cc945 1 1 1 38s
sample-deployment-rollingupdate-6c8bfc45d6 3 3 2 3s
sample-deployment-rollingupdate-6c8bfc45d6 3 3 3 5s
sample-deployment-rollingupdate-845c7cc945 0 1 1 40s
sample-deployment-rollingupdate-845c7cc945 0 1 1 40s
sample-deployment-rollingupdate-845c7cc945 0 0 0 40s
# maxUnavailable=1/maxSurge=0 설정을 변경하고 RollingUpdate를 시작하면 maxUnavailable 수만큼 추가 레플리카 수를 감소시킨 후 파드를 이동시킨다.
$ kubectl get replicasets --watch
NAME DESIRED CURRENT READY AGE
sample-deployment-rollingupdate-845c7cc945 3 0 0 0s
sample-deployment-rollingupdate-845c7cc945 3 0 0 0s
sample-deployment-rollingupdate-845c7cc945 3 3 0 0s
sample-deployment-rollingupdate-845c7cc945 3 3 1 1s
sample-deployment-rollingupdate-845c7cc945 3 3 2 2s
sample-deployment-rollingupdate-845c7cc945 3 3 3 2s
sample-deployment-rollingupdate-6c8bfc45d6 0 0 0 0s
sample-deployment-rollingupdate-6c8bfc45d6 0 0 0 0s
sample-deployment-rollingupdate-845c7cc945 2 3 3 19s
sample-deployment-rollingupdate-6c8bfc45d6 1 0 0 0s
sample-deployment-rollingupdate-845c7cc945 2 3 3 19s
sample-deployment-rollingupdate-845c7cc945 2 2 2 19s
sample-deployment-rollingupdate-6c8bfc45d6 1 0 0 0s
sample-deployment-rollingupdate-6c8bfc45d6 1 1 0 0s
sample-deployment-rollingupdate-6c8bfc45d6 1 1 1 1s
sample-deployment-rollingupdate-845c7cc945 1 2 2 20s
sample-deployment-rollingupdate-6c8bfc45d6 2 1 1 1s
sample-deployment-rollingupdate-845c7cc945 1 2 2 20s
sample-deployment-rollingupdate-845c7cc945 1 1 1 20s
sample-deployment-rollingupdate-6c8bfc45d6 2 1 1 1s
sample-deployment-rollingupdate-6c8bfc45d6 2 2 1 1s
sample-deployment-rollingupdate-6c8bfc45d6 2 2 2 2s
sample-deployment-rollingupdate-845c7cc945 0 1 1 21s
sample-deployment-rollingupdate-6c8bfc45d6 3 2 2 2s
sample-deployment-rollingupdate-845c7cc945 0 1 1 21s
sample-deployment-rollingupdate-6c8bfc45d6 3 2 2 2s
sample-deployment-rollingupdate-845c7cc945 0 0 0 21s
sample-deployment-rollingupdate-6c8bfc45d6 3 3 2 2s
sample-deployment-rollingupdate-6c8bfc45d6 3 3 3 4s
🔔 상세 업데이트 파라미터
(a) minReadySeconds(최소 대기 시간(초))
파드가 Ready 상태가 된 다음부터 디플로이먼트 리소스에서 파드 기동이 완료되었다고 파단(다음 파드의 교체가 가능하다고 판단)하기까지의 최소 시간(초)
(b) revisionHistoryLimit(수정 버전 기록 제한)
디플로이먼트가 유지할 레플리카셋 수, 롤백이 가능한 이력 수
(c) progressDeadlineSeconds(진행 기한 시간(초))
Recreate/RollingUpdate 처리 타임아웃 시간, 타임 아웃 기간이 경과하면 자동으로 롤백
cat <<EOF > sample-deployment-params.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-deployment-params
spec:
minReadySeconds: 0
revisionHistoryLimit: 2
progressDeadlineSeconds: 3600
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx-container
image: nginx:1.16
EOF
🔔 디플로이먼트 스케일링
디플로이먼트가 관리하는 레플리카셋의 레플리카 수는 레플리카셋과 같은 방법으로 kubectl apply -f 또는 kubectl scale을 사용하여 스케일할 수 있다.
# 레플리카 수를 3에서 4로 변경한 매니페스트를 apply
$ sed -i -e 's|replicas: 3|replicas: 4|' sample-deployment.yaml
$ kubectl apply -f sample-deployment.yaml
# kubectl scale 명령어를 사용한 스케일링
$ kubectl scale deployment sample-deployment --replicas=5
댓글 남기기