deployment
deployment基础
上一节试验了replicaset控制器,它可以保证设置的pod数量,但是在升级时,却做不到自动升级,kubectl apply -f xxxx,并不能实时生效。
今天看看deployment,一种比replicaset更高级的声明式资源。它具有滚动更新、平滑升级、蓝绿发布、金丝雀发布等优点。可以直接通过kubectl apply -f xxx完成所有操作。
Deployment控制器是建立在rs之上的一个控制器,定义一个deployment控制器就会增加一个replicaset,它可以管理多个rs,每次更新镜像版本,都会生成一个新的rs,把旧的rs替换掉,多个rs同时存在,但是只有一个rs运行。
deployment yaml文件语法
apiVersion: apps/v1
kind: Deployment
metadata:
name: first-deployment
labels:
func: test-deployment
spec:
replicas: 3 # deployment管理的POD数量
selector: # deployment管理哪些POD
matchLabels:
app: nginx
template: # pod的模板信息
metadata:
name: nginx-test
labels:
app: nginx
spec:
tolerations: # 配置容忍度
- effect: "NoSchedule"
key: "can-run-pods"
operator: "Equal"
value: "master-node"
- effect: "NoSchedule"
key: "node-role.kubernetes.io/control-plane"
operator: "Equal"
value:
containers:
- name: nginx-test
image: nginx:stable-alpine-perl # container所用镜像
imagePullPolicy: IfNotPresent # container镜像拉取策略
env:
- name: VERSION # 定义环境变量
value: 1.1.0
lifecycle: # POD声明周期,启动后钩子
postStart:
exec:
command: ["/bin/sh","-c","echo the version is $VERSION, this is a nginx server in container, and the ip is $(ip add show eth0 | grep -w inet | awk '{print $2}') > /usr/share/nginx/html/index.html" ] # 启动后钩子,生成定制的主页文件
startupProbe: # 启动探测
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
livenessProbe: # 存活探测
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
readinessProbe: # 就绪探测
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
生成了与replicas数量相等的POD
[root@master-worker-node-1 deployment]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-deployment-66494996ff-58x5z 1/1 Running 0 5m48s 10.244.54.58 only-worker-node-4 <none> <none>
first-deployment-66494996ff-clkwk 1/1 Running 0 5m48s 10.244.132.211 master-worker-node-2 <none> <none>
first-deployment-66494996ff-t7lc8 1/1 Running 0 5m48s 10.244.31.48 only-worker-node-3 <none> <none>
同时会创建一个replicaset资源
[root@master-worker-node-1 deployment]# kubectl get replicaset -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
first-deployment-66494996ff 3 3 3 7m16s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
[root@master-worker-node-1 deployment]# kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
first-deployment 3/3 3 3 8m53s nginx-test nginx:stable-alpine-perl app=nginx
pod的名字是以deployment名字+随机的RS编号+随机的POD编号组成
deployment的扩容和缩容
通过kubectl edit 修改或者通过修改deploy yaml文件后通过apply声明。
将deployment扩容为5
[root@master-worker-node-1 deployment]# diff deploy.yaml deploy-expansion.yaml
8c8
< replicas: 3
---
> replicas: 5
[root@master-worker-node-1 deployment]# kubectl apply -f deploy-expansion.yaml
deployment.apps/first-deployment configured
[root@master-worker-node-1 deployment]# kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
first-deployment 5/5 5 5 22m nginx-test nginx:stable-alpine-perl app=nginx
[root@master-worker-node-1 deployment]#
[root@master-worker-node-1 deployment]# kubectl get replicaset -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
first-deployment-66494996ff 5 5 5 22m nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
[root@master-worker-node-1 deployment]#
[root@master-worker-node-1 deployment]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-deployment-66494996ff-58x5z 1/1 Running 0 22m 10.244.54.58 only-worker-node-4 <none> <none>
first-deployment-66494996ff-clkwk 1/1 Running 0 22m 10.244.132.211 master-worker-node-2 <none> <none>
first-deployment-66494996ff-j78rp 1/1 Running 0 3m35s 10.244.31.49 only-worker-node-3 <none> <none>
first-deployment-66494996ff-t7lc8 1/1 Running 0 22m 10.244.31.48 only-worker-node-3 <none> <none>
first-deployment-66494996ff-w2fpc 1/1 Running 0 45s 10.244.54.59 only-worker-node-4 <none> <none>
将deployment缩容为2
[root@master-worker-node-1 deployment]# kubectl edit deployment first-deployment
deployment.apps/first-deployment edited
[root@master-worker-node-1 deployment]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-deployment-66494996ff-clkwk 1/1 Running 0 24m 10.244.132.211 master-worker-node-2 <none> <none>
first-deployment-66494996ff-t7lc8 1/1 Running 0 24m 10.244.31.48 only-worker-node-3 <none> <none>
[root@master-worker-node-1 deployment]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-deployment-66494996ff-bnfcq 1/1 Running 0 39s 10.244.54.7 only-worker-node-4 <none> <none>
first-deployment-66494996ff-f5257 1/1 Running 0 39s 10.244.132.221 master-worker-node-2 <none> <none>
first-deployment-66494996ff-vj49c 1/1 Running 0 39s 10.244.31.59 only-worker-node-3 <none> <none>
[root@master-worker-node-1 deployment]# kubectl scale deployment first-deployment --replicas 5
deployment.apps/first-deployment scaled
[root@master-worker-node-1 deployment]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-deployment-66494996ff-bnfcq 1/1 Running 0 115s 10.244.54.7 only-worker-node-4 <none> <none>
first-deployment-66494996ff-f5257 1/1 Running 0 115s 10.244.132.221 master-worker-node-2 <none> <none>
first-deployment-66494996ff-p44wx 1/1 Running 0 63s 10.244.31.61 only-worker-node-3 <none> <none>
first-deployment-66494996ff-spgc8 1/1 Running 0 63s 10.244.54.8 only-worker-node-4 <none> <none>
first-deployment-66494996ff-vj49c 1/1 Running 0 115s 10.244.31.59 only-worker-node-3 <none> <none>
[root@master-worker-node-1 deployment]#
使用的deployment实现滚动更新
deployment滚动升级涉及到升级策略:
kubectl explain deployment.spec.strategy
rollingUpdate:
type: Possible enum values:
- `"Recreate"` Kill all existing pods before creating new ones. 删除所有,再重建所有。
- `"RollingUpdate"` Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one. 删除一个,随之重建一个。
kubectl explain deployment.spec.strategy.rollingUpdate
maxSurge:The maximum number of pods that can be scheduled above the desired number of pods. 默认25%
maxUnavailable: The maximum number of pods that can be unavailable during the update. 默认25%
deployment升级过程中的POD数量取值范围:期望数量-maxUnavailable≤pod数量≤期望数量+maxSurge
不配置升级策略进行滚动升级
# 当前环境
[root@master-worker-node-1 deployment]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-deployment-66494996ff-clkwk 1/1 Running 0 52m 10.244.132.211 master-worker-node-2 <none> <none>
first-deployment-66494996ff-t7lc8 1/1 Running 0 52m 10.244.31.48 only-worker-node-3 <none> <none>
[root@master-worker-node-1 deployment]# kubectl get pods -o wide | awk '{print $6}'
IP
10.244.132.211
10.244.31.48
[root@master-worker-node-1 deployment]# kubectl get pods -o wide | awk '{print $6}' | grep -v IP
10.244.132.211
10.244.31.48
[root@master-worker-node-1 deployment]# kubectl get pods -o wide | awk '{print $6}' | grep -v IP | xargs curl
the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.132.211/32
the version is 1.1.0, this is a nginx server in container, and the ip is 10.244.31.48/32
# 修改一个版本号,模拟镜像变化
[root@master-worker-node-1 deployment]# diff deploy.yaml deploy-update.yaml
33c33
< value: 1.1.0
---
> value: 1.2.0
[root@master-worker-node-1 deployment]# kubectl apply -f deploy-update.yaml
deployment.apps/first-deployment configured
[root@master-worker-node-1 deployment]# kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
first-deployment 3/3 2 3 3m23s nginx-test nginx:stable-alpine-perl app=nginx
[root@master-worker-node-1 deployment]# kubectl get replicaset -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
first-deployment-66494996ff 0 0 0 3m54s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
first-deployment-7d6b98897d 3 3 3 83s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
[root@master-worker-node-1 deployment]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-deployment-7d6b98897d-t8vdf 1/1 Running 0 66s 10.244.54.6 only-worker-node-4 <none> <none>
first-deployment-7d6b98897d-w6lvc 1/1 Running 0 93s 10.244.31.57 only-worker-node-3 <none> <none>
first-deployment-7d6b98897d-wrxxc 1/1 Running 0 40s 10.244.132.219 master-worker-node-2 <none> <none>
# 主页已经更新到了version 1.2.0
[root@master-worker-node-1 deployment]# kubectl get pods -o wide | awk '{print $6}' | grep -v IP | xargs curl
the version is 1.2.0, this is a nginx server in container, and the ip is 10.244.54.6/32
the version is 1.2.0, this is a nginx server in container, and the ip is 10.244.31.57/32
the version is 1.2.0, this is a nginx server in container, and the ip is 10.244.132.219/32
完成上面的更新以后,发现pod对应的replicaset也发生的相应的变化。deployment进行了更新,同步的,也会产生一个对应的rs。既然如此就可以通过之前rs回复到之前的情况。
查看deployment的历史版本
[root@master-worker-node-1 ~]# kubectl rollout history deployment first-deployment
deployment.apps/first-deployment
REVISION CHANGE-CAUSE
1 <none>
2 <none>
回滚到对应的版本
[root@master-worker-node-1 ~]# kubectl rollout undo deployment first-deployment --to-revision=1
deployment.apps/first-deployment rolled back
升级过程中pod的变化情况
[root@master-worker-node-1 deployment]# kubectl get pods -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-deployment-7d6b98897d-t8vdf 1/1 Running 0 5m28s 10.244.54.6 only-worker-node-4 <none> <none>
first-deployment-7d6b98897d-w6lvc 1/1 Running 0 5m55s 10.244.31.57 only-worker-node-3 <none> <none>
first-deployment-7d6b98897d-wrxxc 1/1 Running 0 5m2s 10.244.132.219 master-worker-node-2 <none> <none>
first-deployment-66494996ff-47xhv 0/1 Pending 0 0s <none> <none> <none> <none>
first-deployment-66494996ff-47xhv 0/1 Pending 0 0s <none> only-worker-node-3 <none> <none>
first-deployment-66494996ff-47xhv 0/1 ContainerCreating 0 1s <none> only-worker-node-3 <none> <none>
first-deployment-66494996ff-47xhv 0/1 ContainerCreating 0 2s <none> only-worker-node-3 <none> <none>
first-deployment-66494996ff-47xhv 0/1 Running 0 3s 10.244.31.58 only-worker-node-3 <none> <none>
first-deployment-66494996ff-47xhv 0/1 Running 0 26s 10.244.31.58 only-worker-node-3 <none> <none>
first-deployment-66494996ff-47xhv 1/1 Running 0 26s 10.244.31.58 only-worker-node-3 <none> <none>
first-deployment-7d6b98897d-w6lvc 1/1 Terminating 0 8m28s 10.244.31.57 only-worker-node-3 <none> <none>
first-deployment-66494996ff-qhbfc 0/1 Pending 0 1s <none> <none> <none> <none>
first-deployment-66494996ff-qhbfc 0/1 Pending 0 1s <none> only-worker-node-4 <none> <none>
first-deployment-66494996ff-qhbfc 0/1 ContainerCreating 0 1s <none> only-worker-node-4 <none> <none>
first-deployment-7d6b98897d-w6lvc 1/1 Terminating 0 8m29s 10.244.31.57 only-worker-node-3 <none> <none>
first-deployment-66494996ff-qhbfc 0/1 ContainerCreating 0 3s <none> only-worker-node-4 <none> <none>
first-deployment-7d6b98897d-w6lvc 0/1 Terminating 0 8m31s 10.244.31.57 only-worker-node-3 <none> <none>
first-deployment-7d6b98897d-w6lvc 0/1 Terminating 0 8m31s 10.244.31.57 only-worker-node-3 <none> <none>
first-deployment-7d6b98897d-w6lvc 0/1 Terminating 0 8m31s 10.244.31.57 only-worker-node-3 <none> <none>
first-deployment-66494996ff-qhbfc 0/1 Running 0 4s 10.244.54.4 only-worker-node-4 <none> <none>
设置升级策略进行滚动升级
# 默认的升级策略,滚动式,最大最小均为25%
[root@master-worker-node-1 deployment]# kubectl get deployment first-deployment -o yaml | grep -A 5 strategy
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
[root@master-worker-node-1 deployment]# kubectl apply -f deploy-update-self.yaml
deployment.apps/my-deployment created
[root@master-worker-node-1 deployment]# kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
my-deployment 3/3 3 3 29s nginx-test nginx:stable-alpine-perl app=nginx
[root@master-worker-node-1 deployment]# kubectl get deployment my-deployment -o yaml | grep -A 5 strategy: -w
strategy:
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
type: RollingUpdate
template:
[root@master-worker-node-1 deployment]#
#在线更新deployment
[root@master-worker-node-1 deployment]# kubectl apply -f deploy-update-self-2.yaml
deployment.apps/my-deployment configured
[root@master-worker-node-1 deployment]# kubectl get deployment my-deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
my-deployment 3/3 3 3 4m10s nginx-test nginx:stable-alpine-perl app=nginx
# 观察rs的状态,更好的观察pod变化
[root@master-worker-node-1 ~]# kubectl get rs -o wide -w
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
my-deployment-66494996ff 3 3 3 3m9s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-7d6b98897d 2 0 0 0s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
my-deployment-66494996ff 2 3 3 3m24s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-7d6b98897d 2 0 0 1s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
my-deployment-7d6b98897d 2 2 0 1s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
my-deployment-66494996ff 2 3 3 3m25s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-7d6b98897d 3 2 0 2s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
my-deployment-66494996ff 2 2 2 3m25s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-7d6b98897d 3 2 0 3s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
my-deployment-7d6b98897d 3 3 0 3s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
my-deployment-7d6b98897d 3 3 1 27s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
my-deployment-66494996ff 1 2 2 3m50s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-7d6b98897d 3 3 2 28s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
my-deployment-66494996ff 1 2 2 3m51s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-66494996ff 1 1 1 3m51s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-66494996ff 0 1 1 3m51s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-66494996ff 0 1 1 3m51s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-66494996ff 0 0 0 3m51s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=66494996ff
my-deployment-7d6b98897d 3 3 3 29s nginx-test nginx:stable-alpine-perl app=nginx,pod-template-hash=7d6b98897d
# deployment的replicas为3,根据升级策略,maxSurge=2,表示最多可以比replicas多两个,maxUnavailable=1,表示最多比replicas小一个。
# 从rs的pod数量变化也能看出来,升级一开始,新的rs就创建了两个pod,然后停掉了原来rs的一个pod。
# 回滚操作
[root@master-worker-node-1 deployment]# kubectl rollout undo deployment my-deployment --to-revision 1
小结
deployment是建立在replicaset之上的一个控制器,它拥有比rs更多的优点,滚动升级、升级策略多样、蓝绿发布、金丝雀发布、回滚方便
deployment的扩容缩容方法很多,只要能触发副本数量变化的方法都可以。比如:通过yaml文件apply、通过kubectl edit、通过kubectl scale deployment、通过kubectl patch等等
deployment的滚动升级可以配置相应的升级策略。升级的触发也可以通过yaml文件kubectl apply、也可以通过kubectl set image deployment/完成