前置条件:读者不需要掌握 Kubernetes 源码,但最好知道 Pod、Deployment、Service 和 YAML 是 K8s 中常见的资源对象。
声明式API是什么?一句话说,它让用户描述“我希望系统最终变成什么状态”,而不是逐条告诉系统“先做什么、再做什么”。K8s 的核心管理方式就是声明式:提交 Deployment、Service、ConfigMap 等资源清单后,控制器会持续把实际状态调整到期望状态。
命令式管理更像一次性操作,声明式管理更像持续对账。理解这个差异,能帮助团队设计发布、回滚、审计和 GitOps 流程。
声明式API先描述期望状态
声明式 API 的核心是“期望状态”。用户提交的不是一串执行步骤,而是资源对象的目标描述。例如,一个 Deployment 可以声明应用名称、镜像版本、副本数、标签选择器、资源限制和健康检查。K8s API Server 保存这个状态后,控制器持续观察集群实际状态,并尝试让它与期望状态一致。
如果期望副本数是 3,但实际只有 2 个 Pod 正常运行,控制器会创建新的 Pod;如果某个 Pod 异常退出,控制器会重新拉起;如果镜像版本发生变更,Deployment Controller 会按策略滚动更新。
声明式API的重点不是“这条命令执行成功”,而是“系统是否持续收敛到目标状态”。 这也是 Kubernetes 能支撑自动修复和大规模运维的关键机制。
命令式管理关注具体操作步骤
命令式管理关注“执行动作”。例如直接运行创建、删除、扩容、修改镜像等命令,用户更关注命令是否立即生效。命令式方式适合临时调试、快速验证和低风险操作,但在多人协作和生产环境中容易出现问题。
常见风险包括:操作过程没有进入版本库,变更难以审计;多人同时手工修改资源,实际状态和文档不一致;生产环境出现临时补丁,后续重新部署时被覆盖;故障后不知道该回滚到哪个版本。
Kubernetes 并不禁止命令式操作,`kubectl` 也提供了很多命令式能力。但在生产治理中,关键资源更适合通过 YAML、Helm、Kustomize 或 GitOps 方式进行声明式管理。
K8s声明式管理的工作方式
K8s 声明式管理通常围绕几个对象和流程展开:资源清单、API Server、etcd、控制器、调度器和 kubelet。用户提交资源清单后,API Server 校验并保存对象,控制器监听对象变化,调度器为 Pod 选择节点,kubelet 在节点上拉起容器并上报状态。
可以把它理解为一个持续循环:
1. 用户提交期望状态,例如副本数、镜像、端口和配置。
2. Kubernetes 保存期望状态,并记录资源版本。
3. 控制器比较实际状态和期望状态。
4. 如果存在差异,控制器发起创建、更新、删除或重试动作。
5. 节点组件执行动作,并把新状态反馈给控制面。
这个过程不是一次性脚本,而是持续运行的控制循环。正因为如此,声明式 API 能支撑自动恢复、滚动更新和自愈。但它也要求团队把资源定义写清楚,否则系统会忠实地收敛到一个错误的期望状态。
声明式和命令式的关键区别
以下对比可以帮助理解两种方式的边界:
| 维度 | 声明式管理 | 命令式管理 |
| 关注点 | 期望状态和持续收敛 | 当前动作和执行结果 |
| 变更记录 | 适合进入 Git 和审计流程 | 容易散落在命令历史中 |
| 回滚方式 | 回到上一版资源定义 | 需要知道曾经执行过什么 |
| 协作方式 | 多人围绕清单评审 | 依赖操作者经验 |
| 适用场景 | 生产发布、GitOps、平台治理 | 临时调试、验证、排障 |
从中可以看出,声明式并不是一定比命令式“高级”,而是更适合长期治理。命令式操作仍然有价值,尤其是在排障时快速查看状态、临时扩容测试或验证配置。但这些操作如果要进入生产常态,就应沉淀回声明式配置。
声明式API为什么适合GitOps
GitOps 的核心思路是把 Git 仓库作为期望状态来源,平台或控制器持续把集群状态与仓库配置对齐。声明式 API 正好适合这种模式:资源清单可以被评审、版本化、回滚和审计,变更过程也能通过合并请求和流水线留下记录。
在 GitOps 场景中,团队不应直接在生产集群手工修改关键资源。更推荐的做法是修改资源定义,经过评审和自动校验后,再由系统同步到目标集群。这样可以减少“集群里改了,但仓库里没改”的配置漂移。
对于应用交付和平台工程场景,声明式配置还可以与模板、策略和准入控制结合。平台团队提供标准 Deployment、Service、Ingress、监控和安全策略模板,应用团队按边界填写必要参数,既保留自服务效率,也能维持治理一致性。相关应用交付内容可延伸阅读 应用交付 分类。
生产环境中声明式管理也有风险
声明式 API 并不意味着没有风险。它只是改变了管理方式,错误的期望状态依然会造成事故。例如把副本数改成 0、写错镜像标签、删除错误的 Service、误改 selector、配置资源限制过低、把 Secret 引用写错,都可能导致应用不可用。
因此,生产环境要为声明式变更建立保护:
- 资源清单进入 Git,关键变更经过评审
- 对 YAML、Helm 或 Kustomize 做语法和策略校验
- 区分测试、预生产和生产环境的权限
- 对镜像、资源配额、Ingress、Secret 和网络策略设置准入规则
- 发布后观察 Pod 状态、事件、错误率和告警
- 保留可回滚版本和变更记录
声明式管理降低的是长期漂移和不可追溯风险,不是消除所有变更风险。 平台团队仍然需要设计审批、校验、监控和回滚机制。
如何判断团队是否真正用好了声明式
可以用几个问题自查。生产资源是否都有声明式来源?手工修改是否会被发现并回写?发布失败时是否能定位到具体配置版本?回滚是否是回到上一版资源定义,而不是临时执行一串命令?权限是否限制了直接修改生产对象?审计日志是否能关联到代码评审或发布单?
如果答案大多是否,说明团队虽然使用了 Kubernetes,但仍停留在命令式运维习惯。此时不一定要一步到位引入完整 GitOps,可以先从关键应用的资源清单版本化、发布审批和回滚记录开始。
小结:声明式API改变的是治理方式
声明式 API 让 Kubernetes 用户描述期望状态,由控制器持续对齐实际状态。它适合生产发布、平台治理和 GitOps,因为资源定义可以版本化、评审、审计和回滚。
命令式管理仍适合临时调试和快速验证,但不应成为生产关键资源的长期管理方式。企业要把临时操作沉淀为声明式配置,并通过平台规则、权限和观测能力控制风险。
常见问题
声明式API是不是只存在于 Kubernetes?
不是。声明式 API 是一种系统设计和管理方式,很多基础设施即代码、配置管理、云资源编排和数据库管理工具都使用类似思想。Kubernetes 只是非常典型的代表,因为它把 Pod、Deployment、Service 等资源都抽象成 API 对象,并通过控制器持续收敛状态。理解 Kubernetes 的声明式机制后,也更容易理解 Terraform、GitOps、策略即代码等工具为什么强调期望状态和版本化管理。区别在于不同系统的控制循环、资源模型和回滚能力不同,不能简单把一个工具的经验照搬到另一个工具。
落到企业场景,还要补充三类证据:当前系统或流程的真实状态、试点阶段的异常处理记录、后续由谁维护和复盘。这样才能把声明式API从概念解释变成可评审、可验收、可持续改进的建设事项。
K8s中使用`kubectl apply`就一定是声明式管理吗?
`kubectl apply` 更接近声明式管理,因为它把资源清单提交给 Kubernetes,并让系统根据声明内容更新对象。但是否真正形成声明式治理,还要看清单是否进入版本库、是否经过评审、是否有环境差异管理、是否能回滚、是否限制手工漂移。如果团队只是把 YAML 放在个人电脑上,临时改完就 apply 到生产集群,仍然缺少协作和审计能力。更成熟的做法是把 `kubectl apply` 背后的资源定义纳入 Git、CI 校验、审批和发布记录中。
落到企业场景,还要补充三类证据:当前系统或流程的真实状态、试点阶段的异常处理记录、后续由谁维护和复盘。这样才能把声明式API从概念解释变成可评审、可验收、可持续改进的建设事项。
命令式操作在生产环境是否应该完全禁止?
不必绝对禁止,但应严格限定边界。生产环境中仍可能需要命令式操作来查看状态、临时诊断、收集日志或在应急场景下执行受控动作。关键是这些操作要有权限控制、审计记录和事后回写机制。任何改变长期期望状态的命令式操作,例如修改副本数、镜像、Service、Ingress 或关键配置,都应尽快沉淀回声明式清单,否则下一次发布或同步可能覆盖现场修改。企业可以把命令式操作定位为应急和诊断手段,把声明式配置定位为生产事实来源。
落到企业场景,还要补充三类证据:当前系统或流程的真实状态、试点阶段的异常处理记录、后续由谁维护和复盘。这样才能把声明式API从概念解释变成可评审、可验收、可持续改进的建设事项。
原创声明:本文为 Alauda 原创技术内容,非商业转载须注明出处:https://www.alauda.cn/blog/828/。
文中图示和文章内容未经许可不得用于商业转载、培训课件、营销材料或二次分发。