当前位置 博文首页 > RtxTitanV的博客:Kubernetes控制器之Deployment
Deployment为Pod和ReplicaSet提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController来方便的管理应用。只需要在Deployment中描述一个期望状态,Deployment控制器以受控速率更改实际状态以达到期望状态。
本文主要Kubernetes的Deployment控制器进行简单总结。
本文所使用的环境如下:
Deployment为Pod和ReplicaSet提供声明式的更新方式。只需要在Deployment中描述一个期望状态,Deployment控制器以受控速率更改实际状态以达到期望状态。可以定义Deployment以创建新的ReplicaSet,或删除现有的Deployment并通过新的Deployment使用其所有资源。注意不要手动管理Deployment创建的ReplicaSet,否则逾越了Deployment控制器职责。下面是关于Deployment的典型用例:
可以通过以下命令查看Deployment资源清单规则:
kubectl explain deployment
kubectl explain deployment.spec
kubectl explain deployment.spec.template
也可以通过官方Kubernetes API手册进行查找。这里主要总结一下资源清单中重要的字段:
字段 | 类型 | 说明 |
---|---|---|
apiVersion | string | api版本定义 |
kind | string | 资源类型定义 |
metadata | object | 元数据定义 |
spec | object | Deployment的Spec定义 |
spec.replicas | integer | Pod副本的期望数目,默认值为1。为可选字段 |
spec.selector | object | 标签选择器,定义匹配Pod的标签。spec.selector 必须匹配spec.template.metadata.labels ,否则请求会被API拒绝。为必要字段 |
spec.selector.matchLabels | object | {key,value}对的映射 |
spec.template | object | Pod模板定义,除了它是嵌套的并且没有apiVersion 和kind 之外,与Pod资源清单的语法几乎完全一致。为必要字段 |
spec.template.metadata | object | Pod的元数据定义 |
spec.template.metadata.name | string | 定义Pod的名称 |
spec.template.metadata.labels | object | 定义Pod的标签,必须与spec.selector 匹配(可以多出其他标签),否则它将被API拒绝 |
spec.template.spec | object | Pod的Spec定义 |
spec.strategy | object | 指定可用于用新Pod替换旧Pod的策略 |
spec.strategy.type | string | 指定Deployment的策略类型,可以是Recreate或RollingUpdate,RollingUpdate是默认值。当spec.strategy.type==Recreate 时,在创建新Pod之前,所有现有的Pod都将被杀死。当spec.strategy.type==RollingUpdate 时,Deployment会以滚动更新方式更新Pod,可以指定maxUnavailable 和maxSurge 来控制滚动更新过程 |
spec.strategy.rollingUpdate | object | 滚动更新配置参数,仅在spec.strategy.type==RollingUpdate 时生效 |
spec.strategy.rollingUpdate.maxSurge | 指定在期望的Pod副本数的基础之上再创建的最大Pod数量。该值可以是绝对数字(例如,5)或所需Pod的百分比(例如,10%)。如果spec.strategy.rollingUpdate.maxUnavailabl 为0,则该值不能为0。绝对数字通过四舍五入从百分比中得出的。默认值为25%。例如:当此值设置为30%时,滚动更新开始时会立即按比例扩展新的ReplicaSet,以使新旧Pod的总数不超过所需Pod的130%。一旦旧Pod被杀死,就可以进一步扩展新的ReplicaSet,以确保更新期间任何时间运行的Pod总数最多为所需Pod数的130% | |
spec.strategy.rollingUpdate.maxUnavailable | 指定更新期间不可用的Pod的最大数量。该值可以是绝对数字(例如,5)或所需Pod的百分比(例如,10%)。绝对数字是通过四舍五入从百分比中得出的。 如果spec.strategy.rollingUpdate.maxSurge 为0,则该值不能为0。默认为25%。例如:当此值设置为30%时,滚动更新开始时会立即将旧ReplicaSet向下缩减到期望Pod的70%。新Pod准备就绪后,可以进一步向下缩减旧ReplicaSet,然后向上扩展新的ReplicaSet,确保可用的Pod总数在更新期间的任何时候都至少为期望Pod数的70% | |
spec.progressDeadlineSeconds | integer | 在Deployment失败之前,部署进行的最长时间,以秒为单位。Deployment制器将继续处理失败的部署,并且在部署状态中将显示带有ProgressDeadlineExceeded原因的条件。在部署暂停期间不会估计进度。默认为600s。如果指定,此字段需要大于spec.minReadySeconds 。为可选字段 |
spec.minReadySeconds | integer | 指定新创建的Pod在没有任何容器崩溃情况下的最小就绪时间,以便将其视为可用。默认值为0(Pod在准备就绪后将立即被视为可用)。为可选字段 |
spec.revisionHistoryLimit | integer | 指定要保留的旧ReplicaSet的数量以允许回滚。这些旧ReplicaSet消耗etcd中的资源,并占用kubectl get rs 的输出。每个Deployment修改版的配置都存储在其ReplicaSet中,一旦删除了旧的ReplicaSet,将失去回滚到旧的Deployment版本的能力。默认值为10。将此字段设置为0意味着将清理所有具有0个Pod副本的旧ReplicaSet,这种情况下,无法撤消新的Deployment展开,因为它的修改历史被清除了。为可选字段 |
spec.paused | boolean | 用于暂停和恢复Deployment的可选布尔字段。暂停的Deployment和未暂停的Deployment唯一的区别就是,只要暂停Deployment处于暂停状态,PodTemplateSpec的任意修改都不会触发新的展开。默认Deployment在创建时是不会被暂停的 |
注意:
- 在API
apps/v1
版本中,spec.selector
和.metadata.labels
不会被默认设置为.spec.template.metadata.labels
,如果没有设置需要明确进行设置。同时在apps/v1
版本中,Deployment创建后spec.selector
是可变的。- 当Pod的标签和选择器匹配时,若此类Pod的模板和
spec.template
不同,或者此类Pod的总数超过spec.replicas
, Deployment会终止这些Pod。如果Pod总数达不到期望值,会用spec.template
创建新的Pod。- 不应直接通过创建另一个Deployment或创建另一个诸如ReplicaSet或ReplicationController的控制器来创建其标签与该选择器匹配的其他Pod。如果这样做,第一个Deployment会认为是它创建了这些其他的Pod。如果有多个具有重叠选择器的控制器,则控制器之间会因冲突而故障。
创建Deployment会展开(rollout)ReplicaSet,ReplicaSet会在后台创建Pod。一个简单的Deployment示意图如下:
首先准备一个镜像,创建一个名为mynginx1
的Dockerfile
文件:
FROM nginx:alpine
RUN echo 'mynginx:v1' > /usr/share/nginx/html/index.html
构建mynginx:v1
镜像:
docker build -t mynginx:v1 -f mynginx1 .
创建Deployment
资源清单文件mynginx-deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mynginx-deployment
labels:
app: mynginx
env: test
spec:
replicas: 3
selector:
matchLabels:
app: mynginx
env: test
template:
metadata:
labels:
app: mynginx
env: test
spec:
containers:
- name: nginx
image: mynginx:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
执行以下命令创建Deployment
:
kubectl apply -f mynginx-deployment.yaml --record
注意:可以指定
--record
选项来写入在资源注释(annotation)kubernetes.io/change-cause
中执行的命令。它对以后的检查很有用。例如,查看在每个Deployment修订历史(revision)中执行的命令。
查看Deployment
展开状态,为成功状态:
kubectl rollout status deployment.v1.apps/mynginx-deployment
查看Deployment
,发现Deployment
已创建了所有的三个最新且可用的副本:
kubectl get deployment
Deployment的输出显示的字段解释如下:
NAME
:列出名称空间中Deployment的名称。READY
:显示用户可以使用多少个应用程序副本。它遵循准备/期望的模式。UP-TO-DATE
:显示已更新以实现期望状态的副本数。AVAILABLE
:显示应用程序可供用户使用的副本数。AGE
:显示应用程序运行的时间。查看Deployment
创建的ReplicaSet
,发现ReplicaSet
的名称格式为[DEPLOYMENT-NAME]-[RANDOM-STRING]
,其中随机字符串是以pod-template-hash
为基础随机生成的:
kubectl get rs
ReplicaSet的输出显示的字段的解释如下:
NAME
:列出名称空间中ReplicaSet的名称。DESIRED
:显示应用程序的期望副本数,这些副本是在创建展开时定义的,这只是期望的状态。CURRENT
:显示当前正在运行的副本数。READY
:显示用户可以使用多少个应用程序副本。AGE
:显示应用程序运行的时间。查看每个Pod
及其标签,发现创建的ReplicaSet
确保总是有3个nginx
的Pod
存在,Pod
的名字为ReplicaSet
的名字加上5位随机字符:
kubectl get pod -o wide --show-labels
注意有一个名为pod-template-hash
的标签,不要更改。此标签将被Deployment控制器添加到Deployment创建或使用的每个ReplicaSet中,可确保Deployment的子ReplicaSet不重复。它是通过对ReplicaSet的PodTemplate
进行哈希处理并使用生成的哈希值添加到ReplicaSet选择器、Pod模板标签以及ReplicaSet可能具有的任何现有Pod中的标签而生成的。最后执行以下命令清理之前创建的资源对象:
kubectl delete all -l app=mynginx
仅当Deployment的Pod模板即spec.template
更改时,例如模板的标签或容器镜像已更新,才会触发Deployment的展开(rollout)。其他更新,如Deployment扩容,则不会触发Deployment的展开。首先准备一个mynginx:v2
镜像用于更新,创建一个名为mynginx2
的Dockerfile
文件:
FROM nginx:alpine
RUN echo 'mynginx:v2' > /usr/share/nginx/html/index.html
构建mynginx:v2
镜像:
docker build -t mynginx:v2 -f mynginx2 .
Deployment控制器支持两种更新策略:
Deployment控制器的滚动更新并非在同一个ReplicaSet控制器对象下删除并创建Pod,会先创建一个新的ReplicaSet控制器,然后新控制器的Pod数量不断增加,旧控制器的Pod相应不断减少,直到旧控制器不再拥有Pod,而新控制器的Pod副本数量达到期望值为止。如下图所示:
滚动更新可以指定spec.strategy.rollingUpdate.maxSurge
和spec.strategy.rollingUpdate.maxUnavailable
来控制滚动更新过程。其功能如下:
maxSurge
:指定在期望的Pod副本数的基础之上再创建的最大Pod数量。该值可以是绝对数字(例如,5)或所需Pod的百分比(例如,10%)。如果spec.strategy.rollingUpdate.maxUnavailabl
为0,则该值不能为 0。绝对数字通过四舍五入从百分比中得出的。默认值为25%。maxUnavailable
:指定更新期间不可用的Pod的最大数量。该值可以是绝对数字(例如,5)或所需Pod的百分比(例如,10%)。绝对数字是通过四舍五入从百分比中得出的。 如果spec.strategy.rollingUpdate.maxSurge
为0,则该值不能为0。默认为25%。先创建资源清单mynginx-deploy-recreate.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mynginx-deploy-recreate
labels:
app: mynginx
env: test
spec:
replicas: 3
selector:
matchLabels:
app: mynginx
env: test
strategy:
type: Recreate
template:
metadata:
labels:
app: mynginx
env: test
spec:
containers:
- name: nginx
image: mynginx:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
创建Deployment
并查看Deployment
、ReplicaSet
和Pod
,然后访问其中一个Pod
可知更新前使用的mynginx:v1
镜像:
将Deployment
的spec.template.spec.containers[0].image
从mynginx:v1
改为mynginx:v2
:
kubectl edit deployment.v1.apps/mynginx-deploy-recreate
之后马上查看Pod
的状态,由于删除得太快,这里只截到有两个旧Pod
已经被删除,只剩一个旧的Pod
处于正在终止状态,并且3个Pod
都被删除后才开始创建新的Pod
:
同时新开三个终端查看Deployment
、ReplicaSet
和Pod
变化过程:
kubectl get deployment mynginx-deploy-recreate -w
kubectl get rs -w
kubectl get pod -o wide -w
查看Deployment
和ReplicaSet
:
再次查看Pod
,发现旧Pod
已全部被新创建的Pod
取代:
查看Deployment
描述信息:
然后访问其中一个Pod
,发现使用了mynginx:v2
镜像,说明更新成功:
最后清理之前创建的资源对象。
先通过之前的Deployment
示例的清单文件mynginx-deployment.yaml
创建Deployment
,然后在此基础上进行滚动更新操作。在更新之前先查看Deployment
、ReplicaSet
和Pod
,然后访问其中一个Pod
可知更新前使用的mynginx:v1
镜像:
下面更新nginx
的Pod
,可以执行以下命令更新:
kubectl --record deployment.apps/mynginx-deployment set image deployment.v1.apps/mynginx-deployment nginx=mynginx:v2
也可以使用edit
将Deployment
的spec.template.spec.containers[0].image
从mynginx:v1
改为mynginx:v2
:
kubectl edit deployment.v1.apps/nginx-deployment
之后马上查看Pod
的状态,可以发现旧的pod
正在被终止,而一个新的ReplicaSet
也在创建新的pod
:
查看展开状态,新ReplicaSet
已成功展开:
同时新开三个终端查看Deployment
、ReplicaSet
和Pod
变化过程:
查看Deployment
和ReplicaSet
:
再次查看Pod
,发现旧Pod
已全部被新创建的Pod
取代:
查看Deployment
描述信息:
访问其中一个Pod
,发现使用了mynginx:v2
镜像,说明更新成功:
最后清理之前创建的资源对象。
每次Deployment控制器观察新Deployment时,都会创建一个ReplicaSet以启动所期望的Pod。如果更新了Deployment ,则已存在的 ReplicaSet控制其标签spec.selector
匹配但其模板与spec.template
不匹配的Pod缩容。最终,新的ReplicaSet将会扩容出spec.replicas
指定数目的Pod,旧的ReplicaSet会缩容到0。
如果更新了一个的已存在并正在进行中的Deployment,每次更新Deployment都会创建一个新的ReplicaSet并扩容它,同时回滚之前扩容的ReplicaSet——将它添加到旧的ReplicaSet列表中并开始缩容。例如,假设创建一个Deployment以创建5个nginx:1.7.9
的副本,然后更新Deployment以创建5个 nginx:1.9.1
的副本,而此时只有3个nginx:1.7.9
的副本已创建。在这种情况下, Deployment会立即开始杀死3个nginx:1.7.9
的Pod,并开始创建nginx:1.9.1
的Pod。它不会等到5个nginx:1.7.9
的副本都创建完成之后才改变任务。
默认情况下,所有Deployment历史记录都保留在系统中,以便可以随时回滚。
首先通过资源清单文件mynginx-deployment.yaml
创建Deployment
,然后更新镜像为v2版。更新后的Pod
信息如下:
查看Deployment修改历史:
kubectl rollout history deployment.v1.apps/mynginx-deployment
查看修改历史的详细信息:
kubectl rollout history deployment.v1.apps/mynginx-deployment --revision=2
回滚到上一版本:
kubectl rollout undo deployment.v1.apps/mynginx-deployment
然后立马查看Pod
:
查看Deployment
和ReplicaSet
:
查看Deployment
描述信息:
访问其中一个Pod
,发现使用了mynginx:v1
镜像,说明回滚到上一版本成功:
回滚到版本2:
kubectl rollout undo deployment.v1.apps/mynginx-deployment --to-revision=2
然后立马查看Pod
:
查看Deployment
和ReplicaSet
:
查看Deployment
描述信息:
访问其中一个Pod
,发现使用了mynginx:v2
镜像,说明回滚到版本2成功:
在Deployment中设置spec.revisionHistoryLimit
,以指定此Deployment要保留的旧ReplicaSet的数量以允许回滚,多余的ReplicaSet将在后台进行垃圾回收,默认值为10。如果显式将此字段设置为0将会清理Deployment的所有历史记录,因此Deployment将无法回滚。
扩容到10个副本:
kubectl scale deployment.v1.apps/mynginx-deployment --replicas=10
查看Deployment
和Pod
:
缩容到3个副本:
kubectl scale deployment.v1.apps/mynginx-deployment --replicas=3
查看Deployment
和Pod
:
如果集群中启用了HPA,可以为Deployment设置autoscale,基于现有Pod的CPU利用率进行自动缩放,当CPU利用率超过80%,Pod最多不超过15个,当CPU利用率低于80%,Pod最低不少于10个:
kubectl autoscale deployment.v1.apps/mynginx-deployment --min=10 --max=15 --cpu-percent=80
最后清理之前创建的资源对象。
可以在触发一个或多个更新之前暂停Deployment,然后再恢复它。这允许在Deployment暂停和恢复之间修复应用多个程序,而不会触发不必要的展开(rollout)。首先通过资源清单文件mynginx-deployment.yaml
创建Deployment
,然后查看Deployment
和ReplicaSet
信息:
执行以下命令暂停Deployment
:
kubectl rollout pause deployment.v1.apps/mynginx-deployment
然后更新Deployment
中Pod
使用的镜像:
kubectl set image deployment.v1.apps/mynginx-deployment nginx=mynginx:v2
查看Deployment
修改历史,发现没有新的展开:
可以进行任意多次更新,例如更新使用到的资源:
kubectl set resources deployment.v1.apps/mynginx-deployment -c