这篇文章已超过一年。较早的文章可能包含过时内容。请检查页面信息自发布以来是否已失效或不正确。

APIServer dry-run 和 kubectl diff

声明式配置管理,也称为配置即代码,是 Kubernetes 的主要优势之一。它允许用户提交集群的期望状态,跟踪不同版本,并通过 CI/CD 流水线改进审计和自动化。 Apply 工作组正致力于弥补一些空白,并高兴地宣布 Kubernetes 1.13 已将服务器端 dry-run 和 kubectl diff 提升至 Beta 状态。这两项特性是对 Kubernetes 声明式模型的重大改进。

挑战

为了获得无缝的 Kubernetes 声明式体验,仍缺少一些部分,我们尝试解决其中一些问题

  • 尽管编译器和 Linter 在检测代码拉取请求中的错误方面做得很好,但 Kubernetes 配置文件缺少良好的验证。现有的解决方案是运行 kubectl apply --dry-run,但这会运行一个不与服务器通信的本地 dry-run:它没有服务器验证,也不会通过 validating admission controller。例如,Custom Resource 名称仅在服务器上验证,因此本地 dry-run 没有帮助。
  • 由于多种原因,很难知道服务器将如何应用你的对象
    • 默认值可能会将某些字段设置为潜在的非预期值,
    • Mutating webhook 可能会设置字段或覆盖/更改某些值。
    • Patch 和合并可能会产生意想不到的效果并导致意外的对象。例如,合并后很难知道列表的排序方式。

工作组已尝试解决这些问题。

APIServer dry-run

实现APIServer dry-run 是为了解决这两个问题

  • 它允许将发送到 apiserver 的单个请求标记为 "dry-run",
  • apiserver 保证 dry-run 请求不会持久化到存储,
  • 请求仍然像典型请求一样被处理:字段会被默认赋值,对象会被验证,它会通过 validating admission 链和 mutating admission 链,然后最终对象会像正常情况一样返回给用户,而不会持久化。

尽管动态 admission controller 不应该对每个请求产生副作用,但只有当所有 admission controller 都明确声明它们没有 dry-run 副作用时,dry-run 请求才会被处理。

如何启用

服务器端 dry-run 通过一个 feature-gate 启用。由于该特性在 1.13 版本中是 Beta,它应该默认启用,但仍然可以通过使用 kube-apiserver --feature-gates DryRun=true 进行启用/禁用。

如果你有动态 admission controller,你可能需要修改它们以:

  • 当 webhook 请求中指定 dry-run 参数时,移除任何副作用,
  • admissionregistration.k8s.io/v1beta1.Webhook 对象的 sideEffects 字段中指定,表明该对象在 dry-run 时(或根本没有)没有副作用。

如何使用

你可以通过使用 kubectl apply --server-dry-run 从 kubectl 触发此特性,这会在请求中添加 dryRun 标志,并返回应用后对象的状态,如果失败则返回错误。

Kubectl diff

APIServer dry-run 很方便,因为它能让你看到对象将如何被处理,但如果对象很大,很难准确识别哪些地方发生了变化。kubectl diff 正是为你所想,它展示了当前“实时”对象与新的“dry-run”对象之间的差异。这使得只关注对象发生的变更、服务器如何合并这些变更以及 mutating webhook 如何影响输出变得非常方便。

如何使用

kubectl diff 旨在尽可能地与 kubectl apply 相似:kubectl diff -f some-resources.yaml 将显示 yaml 文件中资源的差异。甚至可以通过使用 KUBECTL_EXTERNAL_DIFF 环境变量来使用你选择的 diff 程序,例如

KUBECTL_EXTERNAL_DIFF=meld kubectl diff -f some-resources.yaml

未来展望

工作组仍在忙于改进其中一些内容

  • 服务器端 apply 正在尝试通过为字段添加所有者语义来改进 apply 场景!它还将改进对 CRD 和 unions 的支持!
  • kubectl diff 缺少一些 kubectl apply 的特性,但可能很有用,比如按标签过滤或显示被修剪的资源。
  • 最终,kubectl diff 将使用服务器端 apply!