跟k8s工作负载Deployments的缘起缘灭
跟k8s工作负载Deployments的缘起缘灭
考点之简单介绍一下什么是Deployments吧?
考点之怎么查看 Deployment 上线状态?
考点之集群中能不能设置多个Deployments控制器具有重叠的标签选择器?
考点之可以自定义Pod-template-hash 标签嘛?如果可以,有什么好处?如果不可以,有什么危害?
考点之什么场景下会触发Deployments上线动作?
考点之Deployments在更新时会关闭所有Pod嘛?如果不是,默认关闭最大比例是多少?
考点之你能不能简单描述一下Deployments更新时RS和Pod是如何滚动更新的?
考点之如何判定Deployment上线过程是否出现停滞?有哪些原因会造成停滞?如何解决配额不足的问题?
考点之保存修订历史会消耗 etcd 中的资源,并占用 `kubectl get rs` 的输出,如果给修订历史限制值设置为0是不是就能有效解决这个问题?
囧么肥事-胡说八道
考点之简单介绍一下什么是Deployments吧?
Deployments
是k8s内置的工作负载之一,主要作用是帮助我们管理无状态Pod。
一个 Deployment
为 Pods 和 ReplicaSets
提供了声明式的更新能力,我们只需要负责描述 Deployment
中的RS和Pod需要达到的目标状态,那么DM就会以一种受控速率去帮助我们更改RS和Pod的实际状态, 使其变为我们期望出现的状态。
Deployment
很适合用来管理你的集群上的无状态应用,Deployment
认为所有的 Pod
都是相互等价的,在需要的时候都是可以替换的。
Deployment: "小Pod 们,都给我听话"
DM: "你们都不是唯一的"
DM: "不听话,闹事的Pod"
DM: "随时可以让你走人"
DM: "大把的Pod可以替换你们"
Pods: "是是是,我们一定听话"
Deployment 是一个实干主义者,你如果好好工作,不闹事,那么一切OK,但是如果你有小心思,敢闹事,那它随时可以赶你走人,随时随地可以招新人。
考点之怎么查看 Deployment 上线状态?
Deployment 的生命周期中会有许多状态。上线新的 ReplicaSet 期间可能处于Progressing
(进行中),可能是 Complete
(已完成),也可能是Failed
(失败)进入阻塞停滞无法继续进行。
利用kubectl rollout status
命令可以监视 Deployment
的进度。
假设创建了一个Nginx的DM,查看DM进度。
kubectl rollout status deployment/nginx-deployment
哪些场景会让Deployment 进入这三种状态呢?
为了方便,后续DM均代表Deployment
进行中(Progressing)
当Deployment
执行下面的任务期间,Kubernetes
将其标记为进行中(Progressing):
- DM创建新的 `ReplicaSet`
- DM正在为最新的 `ReplicaSet` 执行扩容操作
- DM 正在为旧的 `ReplicaSet`执行缩容操作
- 新的 Pods 已经就绪或者可用(就绪至少持续了 `MinReadySeconds` 秒)
完成(Complete)
当 Deployment
具有以下特征时,Kubernetes
将其标记为 完成(Complete):
- 与 DM 关联的所有副本都已更新到指定的最新版本,这意味着之前请求的所有更新都已完成。
- 与 DM 关联的所有副本都可用。
- 未运行 DM 的旧副本。
失败的(Failed)
当Deployment
在尝试部署其最新的 ReplicaSet
受挫时,会一直处于未完成状态。 造成此情况可能因素如下:
- 配额(Quota)不足
- 就绪探测(Readiness Probe)失败
- 镜像拉取错误
- 权限不足
- 限制范围(Limit Ranges)问题
- 应用程序运行时的配置错误
考点之集群中能不能设置多个Deployments控制器具有重叠的标签选择器?
首先答案肯定是不能的。
如果这样做,后果是什么呢?如果有多个控制器的标签选择器发生重叠,则控制器之间会因冲突而无法正常工作。
另一篇已经讨论类似问题:线上预警k8s集群循环创建、删除Pod副本,一直无法稳定指定目标副本数量?如果排除了是Pod内部发生了故障,从RS角度你猜测可能是什么原因?
上一篇主要说明的是多个ReplicaSets 配置了相同的标签选择符,使用相同的标签选择器创建多个ReplicaSet
,则多个RS无法识别哪个Pod是自己创建的,都会认为是归属于自己管理的Pod。这样做的后果就是会造成Pod被竞争接管的情况,导致Pod副本数量一直无法稳定。
我们知道 Deployment
为 Pods
和 ReplicaSets
提供了声明式的更新能力,主要管控的是RS和Pods。
Kubernetes 不会阻止你去给设置重叠的标签选择器,但是既然RS和Pods会出现因为竞争克制引发的管理冲突情况,那么身为他们俩的管理者DM肯定是不能独善其身,一定会受到影响的。
那么为了不出现管理冲突,我们应该怎么做呢?
必须在 Deployment 中指定适当的标签选择器和 Pod 模板标签,同时标签或者标签选择器不要与其他控制器(包括其他 Deployment
和 StatefulSet
)重叠。
考点之可以自定义Pod-template-hash 标签嘛?如果可以,有什么好处?如果不可以,有什么危害?
k8s官方说明: 不要更改此标签
k8s官方直接明确的告诉我们,不要自定义Pod-template-hash
标签,那么为什么呢?凭什么就不能自定义?
Deployment
控制器会将自己创建或者管理的每一个ReplicaSet
身上都标注Pod-template-hash 标签。
唯一的目的就是利用这个标签确保 Deployment 的子 ReplicaSets 不重叠。
注意Deployment
中 ReplicaSet
的名称始终被格式化为[Deployment名称]-[随机字符串]
。
其中随机字符串是使用 pod-template-hash 作为种子随机生成的。
通过对 ReplicaSet 的 PodTemplate
进行哈希处理,所生成的哈希值被添加到 ReplicaSet 的标签选择器、Pod 模板标签,以及RS中的每个Pod身上。
疑问来了,自定义有什么危害呢?
上面说了,这个标签主要是作为名称随机,确保不重叠,随机到每一个Pod和RS上,可以避免出现多个Deployments
控制器具有重叠的标签选择器。也就是上面说的那个竞争排斥问题。
考点之什么场景下会触发Deployments上线动作?
仅当 Deployment Pod 模板(即 .spec.template
)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。
其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。
考点之Deployments在更新时会关闭所有Pod嘛?如果不是,默认关闭最大比例是多少?
Deployment 可确保在更新时仅关闭一定数量的 Pod。
默认情况下,它确保至少所需 Pods 75% 处于运行状态(maxUnavailable
最大不可用比例为 25%)。
如果有100个Pod,在更新时,最多关闭25个Pod
DM 保证至少会有75个Pod能正常提供服务
Deployment 还确保所创建 Pod 数量只可能比期望 Pods 数高一点点。
默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 25%(最大峰值 25%)。
DM 更新会出现两种操作
1、销毁老版本Pod
2、创建新版本Pod
无论是销毁还是创建
默认峰值都是25%
销毁时,最多同时销毁25%Pod
保证有75%的Pod可以继续提供服务
创建时,最多运行比预期副本数多出25%
也就是说如果预期存活Pod副本是100个
那么最多允许同时在运行125个旧版副本+新版副本
考点之你能不能简单描述一下Deployments更新时RS和Pod是如何滚动更新的?
如果不去更改默认的最大不可用比例和最大运行峰值比例,那么DM更新时,会创建新版本RS,并将其进行扩容,控制到Pod副本数量满足最大运行峰值比例。
达到比例后,DM会停止新版RS扩容,不会再创建新版Pod,直到DM杀死足够多的旧版Pod
接下来对旧版本RS进行缩容操作,控制去除Pod副本数量满足最大不可用比例。
同样,达到比例后,DM会停止旧版RS删除,不会再继续删除旧版Pod,直到DM创建到足够多的新版Pod
此为一轮更新,DM不断的进行滚动更新上述操作,直到旧版RS,旧版Pod副本数为0,新版副本数稳定,停止滚动更新。
考点之如何判定Deployment上线过程是否出现停滞?有哪些原因会造成停滞?如何解决配额不足的问题?
Deployment
可能会在尝试部署最新的 ReplicaSet
时出现故障,一直处于未完成的停滞状态。
造成此情况一些可能因素如下:
- 配额(Quota)不足
- 就绪探测(Readiness Probe)失败
- 镜像拉取错误
- 权限不足
- 限制范围(Limit Ranges)问题
- 应用程序运行时的配置错误
如何判定Deployment上线过程是否出现停滞?
检测此状况的一种方法是在 Deployment
规约中指定截止时间参数.spec.progressDeadlineSeconds
。
一旦超过 Deployment 进度限期,Kubernetes
将更新DM状态和进度状况的原因:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate
通过 Deployment
状态,就能知道是否出现停滞。你可以使用 kubectl rollout status
检查 Deployment 是否未能取得进展。 如果 Deployment
已超过进度限期,kubectl rollout status
返回非零退出代码。
判断停滞,这时候我们可以在上线过程中间安全地暂停 Deployment ,对其进行上线修复。
假设排查出停滞原因是配额不足,直接在命名空间中增加配额 来解决配额不足的问题。
配额条件满足,Deployment 控制器完成了 Deployment
上线操作, Deployment 状态会更新为成功状况(Status=True
and Reason=NewReplicaSetAvailable
)
考点之保存修订历史会消耗 etcd 中的资源,并占用 kubectl get rs
的输出,如果给修订历史限制值设置为0是不是就能有效解决这个问题?
.spec.revisionHistoryLimit
是一个可选字段,用来设定为回滚操作所备份保留的旧 ReplicaSet
数量。
这些旧 ReplicaSet
会消耗 etcd 中的资源,并占用 kubectl get rs
的输出。
每个 Deployment
修订版本的配置都存储在其 ReplicaSets
中;
因此,一旦删除了旧的 ReplicaSet
, 将失去回滚到 Deployment
的对应修订版本的能力。
默认情况下,系统保留 10 个旧 ReplicaSet
,但其理想值取决于新 Deployment
的频率和稳定性。
如果给修订历史限制值设置为0,将导致 Deployment
的所有历史记录被清空。没有了历史备份,因此 Deployment
将无法回滚,无法撤消新的 Deployment 上线。
总结:虽然可以减少etcd
的资源消耗,但是不利于k8s集群实现故障容错、高可用。为了节约一些资源,而放弃容错,高可用性质,只能说,非常非常非常,不值得。