跟k8s工作负载Deployments的缘起缘灭

跟k8s工作负载Deployments的缘起缘灭

考点之简单介绍一下什么是Deployments吧?

考点之怎么查看 Deployment 上线状态?

考点之集群中能不能设置多个Deployments控制器具有重叠的标签选择器?

考点之可以自定义Pod-template-hash 标签嘛?如果可以,有什么好处?如果不可以,有什么危害?

考点之什么场景下会触发Deployments上线动作?

考点之Deployments在更新时会关闭所有Pod嘛?如果不是,默认关闭最大比例是多少?

考点之你能不能简单描述一下Deployments更新时RS和Pod是如何滚动更新的?

考点之如何判定Deployment上线过程是否出现停滞?有哪些原因会造成停滞?如何解决配额不足的问题?

考点之保存修订历史会消耗 etcd 中的资源,并占用 `kubectl get rs` 的输出,如果给修订历史限制值设置为0是不是就能有效解决这个问题?

跟k8s工作负载Deployments的缘起缘灭
文章图片

囧么肥事-胡说八道


考点之简单介绍一下什么是Deployments吧?
Deployments是k8s内置的工作负载之一,主要作用是帮助我们管理无状态Pod。
一个 Deployment 为 Pods 和 ReplicaSets 提供了声明式的更新能力,我们只需要负责描述 Deployment 中的RS和Pod需要达到的目标状态,那么DM就会以一种受控速率去帮助我们更改RS和Pod的实际状态, 使其变为我们期望出现的状态。
跟k8s工作负载Deployments的缘起缘灭
文章图片

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副本数量一直无法稳定。
我们知道 DeploymentPodsReplicaSets 提供了声明式的更新能力,主要管控的是RS和Pods。
Kubernetes 不会阻止你去给设置重叠的标签选择器,但是既然RS和Pods会出现因为竞争克制引发的管理冲突情况,那么身为他们俩的管理者DM肯定是不能独善其身,一定会受到影响的。
那么为了不出现管理冲突,我们应该怎么做呢?
必须在 Deployment 中指定适当的标签选择器和 Pod 模板标签,同时标签或者标签选择器不要与其他控制器(包括其他 DeploymentStatefulSet)重叠。
跟k8s工作负载Deployments的缘起缘灭
文章图片

考点之可以自定义Pod-template-hash 标签嘛?如果可以,有什么好处?如果不可以,有什么危害?
k8s官方说明: 不要更改此标签
k8s官方直接明确的告诉我们,不要自定义Pod-template-hash 标签,那么为什么呢?凭什么就不能自定义?
Deployment 控制器会将自己创建或者管理的每一个ReplicaSet 身上都标注Pod-template-hash 标签。
唯一的目的就是利用这个标签确保 Deployment 的子 ReplicaSets 不重叠。
注意DeploymentReplicaSet 的名称始终被格式化为[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个PodDM 保证至少会有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: TypeStatusReason ---------------- AvailableTrueMinimumReplicasAvailable ProgressingFalseProgressDeadlineExceeded ReplicaFailureTrueFailedCreate

通过 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集群实现故障容错、高可用。为了节约一些资源,而放弃容错,高可用性质,只能说,非常非常非常,不值得。
【跟k8s工作负载Deployments的缘起缘灭】跟k8s工作负载Deployments的缘起缘灭
文章图片

    推荐阅读