kubectl apply 是什么
kubectl apply 做声明式提交:把本地 YAML 或 JSON 清单发给集群,对象不存在就创建,已存在就按三方合并更新。它把上一次提交的清单记录在对象的 last-applied-configuration 注解里,于是能算出「本次清单、上次清单、现网状态」三者之间的差异,只改动清单里明确出现过的字段。这是 GitOps 与日常发布的基础命令。
三方合并怎么工作
提交时 kubectl 会先读取注解里的旧清单,与本次清单做比较得出「本次删除了哪些字段」,再把这些字段从现网对象上移除,同时把新增与修改的字段打上去。现网中既不在旧清单、也不在本次清单里的字段会保留,这也是它和 replace 的关键差别:replace 会用新对象整体替换,未写到的字段会被清空。
基本信息
| 适用环境 | 任何 Kubernetes 发行版,kubectl 1.14 以上行为一致 |
|---|---|
| 语法 | kubectl apply -f <文件|目录|URL> [-n 命名空间] |
| 是否幂等 | 是,同一份清单重复执行结果一致 |
| 记录位置 | 对象注解 kubectl.kubernetes.io/last-applied-configuration |
| 删除语义 | apply 不会删除对象,删除要显式执行 delete |
| 权限要求 | 对目标资源具备 create 与 patch 权限 |
典型使用场景
- 发布新版本:修改镜像标签后提交,触发控制器的滚动更新
- 批量下发:一个目录放多份清单,用 -f 指向目录一次提交
- 补齐字段:在原清单上补充探针、资源请求等生产字段并重新提交
- 接管手工创建的对象:核对现网字段后纳管,后续变更统一走清单
- 配置漂移修正:发现有人手工改过对象,重新提交让配置回到声明状态
- 配合 Kustomize:用 -k 处理多环境差异化,apply 只负责最终提交
- 状态核对:用 diff 在提交前预览将要发生的变更
常用示例
常用示例
kubectl apply -f deploy.yaml # 单文件提交
kubectl apply -f ./manifests/ -n prod # 整个目录批量提交
kubectl apply -k ./overlays/prod # Kustomize 入口
kubectl apply -f deploy.yaml --dry-run=server # 只做服务端校验,不落库
kubectl apply view-last-applied deploy/web # 查看上次提交的清单内容
kubectl diff -f deploy.yaml # 提交前预览差异
kubectl apply -f deploy.yaml --server-side # 服务端应用,避免注解过大三个提交命令对照
| 命令 | 语义 | 对象已存在时的行为 |
|---|---|---|
| apply | 声明式,自带历史记录 | 按三方合并只更新清单中出现的字段 |
| create | 命令式,只创建 | 直接报 AlreadyExists 失败 |
| replace | 整对象覆盖 | 用新对象整体替换,未写字段会被清空 |
| apply 加 --server-side | 服务端合并 | 由 API Server 维护字段归属,避免客户端注解过大 |
提交前的检查清单
- 用 diff 或 dry-run 确认只有预期字段变化,特别注意副本数与镜像标签
- 确认命名空间正确,避免把测试清单提交到生产
- 清单里不要写 status、resourceVersion、uid 等运行态字段
三方合并会清掉「之前由 apply 设置、本次清单已删除」的字段,但不会删除整个对象;批量对齐遗留资源需要单独的清理流程。
对象被 kubectl edit 手工改过时,旧注解与现网状态不一致,apply 可能覆盖掉手改内容,排查前先看 view-last-applied。
配合发布流程的用法
- 清单进版本库,发布时由流水线执行提交,保证集群状态可追溯
- 提交后用 rollout status 观察发布是否完成,再决定放量或回滚
- 变更前保留旧清单,出问题时用旧清单重新提交即可回到上一版声明
- 多环境用同一套模板加差异化覆盖,避免手工改生产清单造成漂移