CKA 자격 시험 준비를 위한 Kubernetes 정리5-Deployment
오늘은 인프런 강의 대세는 쿠버네티스 강의 중 Deployment 관련 내용을 실습해 보면서 정리 할 예정이다.
Deployment - https://kubetm.github.io/k8s/04-beginner-controller/deployment/
Controller - Deployment 설명
아래 설명들은 Deployment로 Pod 2개를 운영하고 있다고 가정한다.
Recreate
v1 Pod를 v2로 업그레이드시 v1 Pod Downtime이 생기고 v2 Pod가 생성된다. 일시적인 정지가 가능한 서비스일 때 사용한다.
Pod가 2대(v1)->0대->2대(v2)로 변경된다.
Rolling Update
일시적으로 Pod가 3대까지 증가한다. 배포 중간 추가적인 자원을 필요로 한다. Downtime도 없다.
Pod가 2대(v1)->3대(v1:2대, v2:1대)->2대(v1:1대,v1:1대)->2대(v1:1대,v1:2대)->2대(v1:2대)
Blue/Green
Service의 Label 설정을 통한 배포방법이다. 운영 중인 v1 Pod 2대 외에 v2 Pod 2대를 더 띄운다. 일시적으로 4대의 Pod의 자원이 필요하게 되고 Service에 설정된 v1 Pod를 바라보게 설정한 Label을 v2 Pod를 바라보는 Label로 변경한다. 많이 사용되는 배포 방법이고 Downtime이 없고 Rollback이 용이하다. Pod가 2대(v1)->4대(v1:2대,v2:2대)->서비스 정상확인->2대(v2:2대)
Canary
카나리아라는 새의 이름에서 유래된다. 카나리아는 유독가스에 굉장히 민감한 동물로 석탄 광산에서 유독가스 누출의 위험을 알리는 용도로 사용되었다.
Service에 v1 Pod 2대에 v2 Pod 1대를 추가로 설정해서 불특정 유저의 유입으로 v2 Pod가 문제가 없는지 확인하고 확인이 되었다면 v1 Pod를 v2로 전환한다.
Pod가 2대(v1)->3대(v1:2대,v2:1대)->2대(v2:2대)
Deployment
Deployment는 selector,replicas,template 값을 갖고 있고 직접 Pod를 만들지 않고 ReplicaSet을 만들기 위한 값이다. ReplicaSet이 Pod를 만들게 된다.
1. Recreate
spec.strategy.type: Recreate로 설정, spec.strategy.revisionHistoryLimit: 1은 ReplicaSet의 replicas의 숫자값이 0인 History를 1개만 남기겠다는 의미이고 Optional 값으로 default 값은 10이다.
1-1. Deployment(Recreate)
Deployment, ReplicaSet으로 Pod를 생성하게 되면 내부적으로 pod-template-hash라는 label이 생성되어 기존에 사용중이던 Pod와의 구분값으로 사용된다.
$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-01
spec:
selector:
matchLabels:
type: app
replicas: 2
strategy:
type: Recreate
revisionHistoryLimit: 1
template:
metadata:
labels:
type: app
spec:
containers:
- name: container
image: coolguy239/app:v4
terminationGracePeriodSeconds: 10
EOF
deployment.apps/deploy-01 created
$ kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
deploy-01-67b6f8695b-bx5jw 1/1 Running 0 4m18s pod-template-hash=67b6f8695b,type=app
deploy-01-67b6f8695b-h5x2r 1/1 Running 0 4m18s pod-template-hash=67b6f8695b,type=app
1-2. Service(Recreate)
라벨이 type=app인 pod를 조회해서 Service와 연결이 되었는지 확인한다. Endpoints를 보면 두개의 Pod IP가 연결된 것을 확인할 수 있다.
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: svc-01
spec:
selector:
type: app
ports:
- port: 8080
protocol: TCP
targetPort: 8080
EOF
service/svc-01 created
$ kubectl get pod -l type=app -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deploy-01-67b6f8695b-bx5jw 1/1 Running 0 7m57s 20.100.194.73 k8s-worker1 <none> <none>
deploy-01-67b6f8695b-h5x2r 1/1 Running 0 7m57s 20.100.194.76 k8s-worker1 <none> <none>
$ kubectl describe svc svc-01
Name: svc-01
Namespace: default
Labels: <none>
Annotations: <none>
Selector: type=app
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.108.136.144
IPs: 10.108.136.144
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
Endpoints: 20.100.194.73:8080,20.100.194.76:8080
Session Affinity: None
Events: <none>
1-3. Service의 Cluster IP를 반복호출
Service를 반복호출 하고 Deployment의 version 정보를 Edit한다.(coolguy239/app:v3 -> coolguy239/app:v4)
$ while true; do curl 10.108.136.144:8080/version; sleep 1; done
v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3...
$ kubectl edit deployment deployment-01
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"deployment-01","namespace":"default"},"spec":{"replicas":2,"revisionHistoryLimit":1,"selector":{"matchLabels":{"type":"app"}},"strategy":{"type":"Recreate"},"template":{"metadata":{"labels":{"type":"app"}},"spec":{"containers":[{"image":"coolguy239/app:v3","name":"container"}],"terminationGracePeriodSeconds":10}}}}
creationTimestamp: "2021-09-13T15:16:47Z"
generation: 1
name: deployment-01
namespace: default
resourceVersion: "109771"
uid: ebcb978b-cd79-41e7-8e95-147c7e921f9d
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 1
selector:
matchLabels:
type: app
strategy:
type: Recreate
template:
metadata:
creationTimestamp: null
labels:
type: app
spec:
containers:
- image: coolguy239/app:v4
imagePullPolicy: IfNotPresent
name: container
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
deployment.apps/deployment-01 edited
1-4. Deployment 결과확인
strategy가 Recreate로 설정을 했기 때문에 중간에 Downtime이 발생하는 것을 확인할 수 있다.
v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
curl: (7) Failed connect to 10.108.136.144:8080; Connection refused
v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4
1-5. 배포 History 확인 및 Undo
버전을 v4에서 v5 올려서 배포하고 다시 history 조회하면 revisionHistoryLimit: 1 설정을 했기 때문에 현재 revision 이외에 하나만 남는 것을 확인 할 수 있다.
$ kubectl rollout history deployment deployment-01
deployment.apps/deployment-01
REVISION CHANGE-CAUSE
1 <none>
2 <none>
# kubectl edit를 통해 v4->v5 변경 후 History 조회
$ kubectl rollout history deployment deployment-01
deployment.apps/deployment-01
REVISION CHANGE-CAUSE
2 <none>
3 <none>
$ kubectl rollout undo deployment deployment-01 --to-revision=2
deployment.apps/deployment-01 rolled back
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-01-7c894b6dd4-782db 1/1 Terminating 0 6m16s
deployment-01-7c894b6dd4-wnz8c 1/1 Terminating 0 6m16s
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-01-5788495b4c-mvqgh 1/1 Running 0 21s
deployment-01-5788495b4c-np2xw 1/1 Running 0 20s
2. RollingUpdate
spec.strategy.type: RollingUpdate - type만 Recreate에서 RollingUpdate로 변경하고 동일하게 진행한다.
spec.strategy.minReadySeconds: 10 - v1, v2에 Pod가 추가되고 삭제되는 시간(sec)이다.
revisionHistoryLimit을 명시하지 않았기 때문에 default 10으로 생성된다.
2-1. Deployment(RollingUpdate)
$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-02
spec:
selector:
matchLabels:
type: app2
replicas: 2
strategy:
type: RollingUpdate
minReadySeconds: 10
template:
metadata:
labels:
type: app2
spec:
containers:
- name: container
image: coolguy239/app:v1
terminationGracePeriodSeconds: 0
EOF
2-2. Service
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: svc-02
spec:
selector:
type: app2
ports:
- port: 8080
protocol: TCP
targetPort: 8080
EOF
2-3. Service의 Cluster IP를 반복호출
Service를 반복호출 하고 Deployment의 version 정보를 Edit한다.(coolguy239/app:v3 -> coolguy239/app:v4)
$ while true; do curl 10.109.238.1:8080/version; sleep 1; done
v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3v3...
$ kubectl edit deployment deployment-01
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "2"
kubectl.kubernetes.io/last-applied-configuration: |
creationTimestamp: "2021-09-15T14:53:20Z"
generation: 2
name: deployment-02
namespace: default
resourceVersion: "115332"
uid: e3d79735-39cc-4ede-bd0b-81a714205e17
spec:
minReadySeconds: 10
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
type: app2
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
type: app2
spec:
containers:
- image: coolguy239/app:v4
imagePullPolicy: IfNotPresent
name: container
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 0
status:
availableReplicas: 2
conditions:
- lastTransitionTime: "2021-09-15T14:53:50Z"
lastUpdateTime: "2021-09-15T14:53:50Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2021-09-15T14:53:20Z"
lastUpdateTime: "2021-09-15T14:56:27Z"
message: ReplicaSet "deployment-02-54bb6fbf67" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 2
readyReplicas: 2
replicas: 2
updatedReplicas: 2
deployment.apps/deployment-02 edited
2-4. Deployment 결과확인
v3에서 v4로 버전업 edit를 하고 나면 일시적으로 v3,v4의 요청이 같이 들어오다가 배포가 완료되면 v4 요청만 들어오게 된다.
$ while true; do curl 10.109.238.1:8080/version; sleep 1; done
v3v4v3v3v4v3v3v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4
3. Blue/Green
3-1. ReplicaSet 생성
v3, v4 ReplicaSet 두개를 생성하고 v3 ReplicaSet으로 생성된 Pod에만 Service를 연결한다.
$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replica-03
spec:
replicas: 2
selector:
matchLabels:
ver: v3
template:
metadata:
name: bg-pod
labels:
ver: v3
spec:
containers:
- name: container
image: coolguy239/app:v3
terminationGracePeriodSeconds: 0
EOF
replicaset.apps/replica-03 created
$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replica-04
spec:
replicas: 2
selector:
matchLabels:
ver: v4
template:
metadata:
name: bg-pod
labels:
ver: v4
spec:
containers:
- name: container
image: coolguy239/app:v4
terminationGracePeriodSeconds: 0
EOF
replicaset.apps/replica-04 created
3-2. Service 생성
$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: svc-03
spec:
selector:
ver: v3
ports:
- port: 8080
protocol: TCP
targetPort: 8080
EOF
service/svc-03 created
3-3. Service 반복 호출
$ while true; do curl 10.101.0.145:8080/version; sleep 1; done
v3v3v3v3v3v3v3v3 ...
3-4. Service label 수정
spec.selector 의 Label을 v3에서 v4 변경을 하게 되면 Downtime 없이 배포를 할 수 있다.
$ kubectl edit svc/svc-03
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
kind: Service
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"svc-03","namespace":"default"},"spec":{"ports":[{"port":8080,"protocol":"TCP","targetPort":8080}],"selector":{"ver":"v1"}}}
creationTimestamp: "2021-09-15T15:27:46Z"
name: svc-03
namespace: default
resourceVersion: "117350"
uid: 609d018e-fae1-4b44-8524-408117d3e54f
spec:
clusterIP: 10.101.0.145
clusterIPs:
- 10.101.0.145
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
ver: v4
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
service/svc-03 edited
$ while true; do curl 10.101.0.145:8080/version; sleep 1; done
3v3v3v3v3v3v3v3v3v3v3v3v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4v4 ...