Kubernetes 定义Deployment控制器

编写 Deployment:

在所有的 Kubernetes 配置中,Deployment 也需要apiVersion,kind和metadata、 spec 这些配置项。

Pod Template:

deployment.spec.template 是 .spec中唯一必须的字段。

deployment.spec.template 是 pod template. 它跟 Pod有一模一样的结构有metadata、spec字段,除了它是嵌套的并且不需要apiVersion 和 kind字段。

另外为了划分Pod的范围,Deployment中的pod template必须指定适当的label(不要跟其他controller重复了,例如:在Deployments中定义了一个 labels是app = nginx,在Replica Set、Replication Controller 中都不来在定义app=nginx这个labels)和适当的重启策略。.spec.template.spec.restartPolicy 可以设置为 Always , 如果不指定的话这就是默认配置。

Replicas:

.spec.replicas 是可以选字段,指定期望的pod数量,默认是1。

Selector:

.spec.selector是可选字段,用来指定 label selector ,圈定Deployment管理的pod范围。

如果被指定, .spec.selector 必须匹配 .spec.template.metadata.labels,否则它将被API拒绝。如果 .spec.selector 没有被指定, .spec.selector.matchLabels 默认是 .spec.template.metadata.labels。

在Pod的template跟.spec.template不同或者数量超过了.spec.replicas规定的数量的情况下,Deployment会杀掉label跟selector不同的Pod。

注意: 您不应该再创建其他label跟这个selector匹配的pod,或者通过其他Deployment,或者通过其他Controller,例如ReplicaSet和ReplicationController。否则该Deployment会被把它们当成都是自己创建的。Kubernetes不会阻止您这么做。

如果您有多个controller使用了重复的selector,controller们就会互相打架并导致不正确的行为。

策略:

.spec.strategy 指定新的Pod替换旧的Pod的策略。 .spec.strategy.type 可以是”Recreate”或者是 “RollingUpdate”。”RollingUpdate”是默认值。

Recreate Deployment:

.spec.strategy.type==Recreate时,在创建出新的Pod之前会先杀掉所有已存在的Pod。

Rolling Update Deployment:

.spec.strategy.type==RollingUpdate时,Deployment使用rolling update 的方式更新Pod 。您可以指定maxUnavailable 和 maxSurge 来控制 rolling update 进程。

MAX UNAVAILABLE:

.spec.strategy.rollingUpdate.maxUnavailable 是可选配置项,用来指定在升级过程中不可用Pod的最大数量。该值可以是一个绝对值(例如5),也可以是期望Pod数量的百分比(例如10%)。通过计算百分比的绝对值向下取整。如果.spec.strategy.rollingUpdate.maxSurge 为0时,这个值不可以为0。默认值是1。

例如,该值设置成30%,启动rolling update后旧的ReplicatSet将会立即缩容到期望的Pod数量的70%。新的Pod ready后,随着新的ReplicaSet的扩容,旧的ReplicaSet会进一步缩容,确保在升级的所有时刻可以用的Pod数量至少是期望Pod数量的70%。

MAX SURGE:

.spec.strategy.rollingUpdate.maxSurge 是可选配置项,用来指定可以超过期望的Pod数量的最大个数。该值可以是一个绝对值(例如5)或者是期望的Pod数量的百分比(例如10%)。当MaxUnavailable为0时该值不可以为0。通过百分比计算的绝对值向上取整。默认值是1。

例如,该值设置成30%,启动rolling update后新的ReplicatSet将会立即扩容,新老Pod的总数不能超过期望的Pod数量的130%。旧的Pod被杀掉后,新的ReplicaSet将继续扩容,旧的ReplicaSet会进一步缩容,确保在升级的所有时刻所有的Pod数量和不会超过期望Pod数量的130%。

Revision History Limit:

Deployment revision history存储在它控制的ReplicaSets中。

.spec.revisionHistoryLimit 是一个可选配置项,用来指定可以保留的旧的ReplicaSet数量。该理想值取决于心Deployment的频率和稳定性。如果该值没有设置的话,默认所有旧的Replicaset或会被保留,将资源存储在etcd中,是用kubectl get rs查看输出。每个Deployment的该配置都保存在ReplicaSet中,然而,一旦您删除的旧的RepelicaSet,您的Deployment就无法再回退到那个revison了。

如果您将该值设置为0,所有具有0个replica的ReplicaSet都会被删除。在这种情况下,新的Deployment rollout无法撤销,因为revision history都被清理掉了。

Paused:

.spec.paused是可以可选配置项,boolean值。用来指定暂停和恢复Deployment。Paused和没有paused的Deployment之间的唯一区别就是,所有对paused deployment中的PodTemplateSpec的修改都不会触发新的rollout。Deployment被创建之后默认是非paused。

revision清理策略:

您可以通过设置.spec.revisonHistoryLimit项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision;如果将该项设置为0,Deployment就不允许回退了。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ye #deployments资源名称
namespace: kube-system #定义所在的名称空间
labels:
app: myapp #deployments的标签
spec:
replicas: 5 #Pod副本数
selector:
matchLabels: #标签选择器
app: nginx #匹配的标签
template:
metadata:
labels:
app: nginx #Pod的标签,这里的标签要和上面的matchLabels保持一致deployments将根据这个标签来匹配那些Pod是属于同一个deployments资源。
spec: #Pod容器资源定义
containers:
- name: myapp-container
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
livenessProbe: #存活检查
httpGet:
path: /index.html
port: http
initialDelaySeconds: 1
periodSeconds: 3

查看定义的deployments资源:

注释:查看当前有哪些deployment
deployment

deployments管理的rs:

注释:一个deployment可以管理多个rs,但是处于运行状态的只有一个。例如:nginx-ye-5ddd85887。说明当前已经更新了三个版本了其中RS (nginx-ye-5b5d8d5794 、nginx-ye-5d6cc588fd)已经没用了,但是回滚的时候会用到。您可能会注意到 ReplicaSet 的名字总是<Deployment的名字>-<pod 模板的hash值>,只要模板不同后面的HASH值就不同,就表示不同的RS。

rs

deployments资源详细信息:

deployments-info

Deployment为Pod和Replica Set(升级版的 Replication Controller)提供声明式更新。

你只需要在 Deployment 中描述您想要的目标状态是什么,Deployment controller 就会帮您将 Pod 和ReplicaSet 的实际状态改变到您的目标状态。您可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。

注意:您不该手动管理由 Deployment 创建的 Replica Set,否则您就篡越了 Deployment controller 的职责!下文罗列了 Deployment 对象中已经覆盖了所有的用例。如果未有覆盖您所有需要的用例,请直接在 Kubernetes 的代码库中提 issue。

典型的用例如下:

  • 使用Deployment来创建ReplicaSet。ReplicaSet在后台创建pod。检查启动状态,看它是成功还是失败。
  • 然后,通过更新Deployment的PodTemplateSpec字段来声明Pod的新状态。这会创建一个新的ReplicaSet,Deployment会按照控制的速率将pod从旧的ReplicaSet移动到新的ReplicaSet中。
  • 如果当前状态不稳定,回滚到之前的Deployment revision。每次回滚都会更新Deployment的revision。
  • 扩容Deployment以满足更高的负载。
  • 暂停Deployment来应用PodTemplateSpec的多个修复,然后恢复上线。
  • 根据Deployment 的状态判断上线是否hang住了。
  • 清除旧的不必要的 ReplicaSet。

Deployments滚动升级过程:

Deployment直接使用kubectl edit deployment/deploymentName 或者kubectl set方法就可以直接升级(原理是Pod的template发生变化,例如更新label、更新镜像版本等操作会触发Deployment的滚动升级):

将nginx的版本进行升级,从1.7.9升级到1.8。第一种方法,直接set镜像:

1
2
$ kubectl set image deployment/nginx-deployment2 nginx=nginx:1.8
deployment "nginx-deployment2" image updated

第二种方法,直接edit:

1
2
$ kubectl edit deployment/nginx-deployment -n kube-system
deployment "nginx-deployment2" edited

deployments-1

deployments可以同时控制多个RS控制器。在滚动升级的时候先创建一个RS,然后deploymen在删除V1版本的Pod后在创建一个另个RS里创建一个V2版本。但是只有一个是处于活动状态的。Deployment可以控制更新粒度,例如5个Pod的时候,可以设置最大允许6个Pod,最少允许4个。那么在滚动更新的时候会先更新一个新版本然后在删掉一个老版本,直到更新完成。如果你允许最大是7个Pod那么就是两个Pod一起更新。 如果设置只允许少不允许多,最少允许4个。那么就先删除一个然后在更新一个, 直到更新完成。

最后介绍下Deployment的一些基础命令。

1
$ kubectl describe deployments  #查询详细信息,获取升级进度
1
$ kubectl rollout pause deployment/nginx-deployment2  #暂停升级
1
$ kubectl rollout resume deployment/nginx-deployment2  #继续升级
1
$ kubectl rollout undo deployment/nginx-deployment2  #升级回滚
1
$ kubectl scale deployment nginx-deployment --replicas 10  #弹性伸缩Pod数量

Deploymentsce层级关系:

deployments-2

deloyments-annotations

在上述输出中,可以看到自动添加到注解中的“deployment.kubernetes.io/revision=2”字段,新建Deployment的revision是1,2表示这是更新过的第二版,前缀“deployment.kubernetes.io”表示这是系统保留的供deployment使用的关键字,用户不可以使用引种类型的注解。(注释:revision在回滚到某一个指定版本的时候需要用到)

关于更新失败:

如果在新版本中指定了错误的image名称,那么更新注定会失败。在本例中如果发生这种情况,首先Deployment会创建新的ReplicaSet,新ReplicaSet在创建每个pod实例就会因为取不到image而失败,整个更新过程会被卡住不再进行下去。即使失败也会产生一个新的修订版本号,并且新创建的ReplicaSet、因无法取到image而失败的pod仍存在于系统中。当然目前对外提供服务的仍然是旧版本的pod。如果发生这种情况就要乃至回滚功能,回到上一个正确的版本。

Rolling Back a Deployment:

Deployment会记录修订历史,当然对能记录的修订历史个数有限制(可以通过.spec.revisionHistoryLimit参数设置),因此Deployment能回滚到记录在案的以前的历史版本中。注意只有rollout操作才会触发修订历史记录,也就是只有.spec.template发生变更才被认为产生了新的版本。其它的变更,比如修改标签选择器、通过kubectl scalling命令扩缩容、被HPA自动扩缩容等不会被认为是新的版本。只回滚.spec.template部分,比如当前的副本数量是5,回滚的版本副本数量是3,回滚后副本数量不变仍然是5,但副本的内容变回以前。

查看修定历史记录,注意后边的CHANGE-CAUSE,需要在kubectl creae创建Deployment时指定–record=true才会有:(–record=false在资源注释中记录当前的kubectl命令。如果设置为false,则不要记录)

1
2
3
4
5
6
$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 kubectl create -f https://k8s.io/examples/controllers/nginx-deployment.yaml --record
2 kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3 kubectl set image deployment/nginx-deployment nginx=nginx:1.91

通过指定REVISION号码查看特定修订记录:

1
[root@master app]# kubectl rollout history deployment/nginx-ye -n kube-system --revision=4

rollout

回滚到前一个版本:

1
2
$ kubectl rollout undo deployment/nginx-deployment
deployment "nginx-deployment" rolled back

通过revision号回滚到任意版本:

1
2
$ kubectl rollout undo deployment/nginx-ye --to-revision=4 -n kube-system
deployment "nginx-deployment" rolled back

升级或创建(如果该资源还不存在,将创建它)

1
kubectl apply -f xxx.yaml --record

Kubernetes 定义Deployment控制器
https://system51.github.io/2019/08/23/Kubernetes-Deployment/
作者
Mr.Ye
发布于
2019年8月23日
许可协议