声明式 vs 命令式管理对象
本教程共 65 篇 · 第 10 篇 · 更新于 2026-08-14 · 约 13 分钟阅读
本节目标:分清 k8s 管理对象的两种思路——命令式和声明式,知道各自适合什么场合,并养成用 YAML 管集群的习惯。
kubectl 能管对象(Pod、Deployment 这些)的方式,官方分成三类:命令式命令、命令式对象配置、声明式对象配置。听起来绕,本质上就是”你下指令”和”你给蓝图”的区别。
10-1 命令式:我一步步告诉你怎么做
命令式(Imperative)是你直接下指令,告诉 k8s “现在执行某动作”。
比如前面第 8、9 章我们用的:
kubectl create deployment hello-node --image=nginx
kubectl expose deployment hello-node --port=80 --type=NodePort
kubectl scale deployment hello-node --replicas=3
每一条都是一个”动作”。你脑子得清楚下一步干什么,按顺序敲。这就像你站在工人旁边,一步步喊:“起一个、暴露端口、扩到三个”。
Note命令式又分两种:一种是纯命令(像上面这样),一种是”命令式对象配置”——用
kubectl create -f/kubectl replace -f读文件,但语义上仍是”按我给的当前内容,创建/替换”。
10-2 声明式:我只给你蓝图,你自行抵达
声明式(Declarative)是你给一份 YAML 蓝图,描述”最终要长什么样”,k8s 自己想办法逼近它。
kubectl apply -f my-app.yaml
你不需要说”先建再改”。你只给目标状态,kubectl 计算当前状态和目标的差异,自己动手补齐。这就像你把设计图交给施工队,过程不用你操心。
一个最小的 YAML 蓝图长这样:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-node
spec:
selector:
matchLabels:
app: hello-node
template:
metadata:
labels:
app: hello-node
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
Tip第一次看 YAML 可能头大。先别钻字段含义,记住它的结构:
apiVersion(用哪套 API)、kind(什么资源)、metadata(名字标签)、spec(你期望的状态)。后面章节会反复见到这四块。
10-3 核心区别在哪
说个最直观的差异,关于”保留现场修改”。
假设你用 apply 建了上面的 Deployment(YAML 里没写副本数,默认 1 个)。然后你手滑,用命令式直接改了运行时:
kubectl scale deployment hello-node --replicas=5
这时集群里实际是 5 个副本。接着你改了 YAML 里的 image,再 apply 一次。会发生什么?
k8s 会:把镜像更新成新的,同时保留你手动扩到的 5 个副本——因为 YAML 里没写 replicas,它不会去改这个值。
这就是声明式的精髓:你只描述关心的字段,没写的字段,它尊重现状里的其它来源(比如你手动 scale 的值)。
Warning反过来,命令式对象配置的
kubectl replace -f是”整体替换”,会把文件里没写的字段全部清掉。所以官方明确说:别把apply和create/replace混着用,否则apply赖以计算差异的注解会丢失,行为会变得不可预期。
10-4 各自优缺点,怎么选
命令式优点: 快、直观,适合临时试手、排错时改一个值。
命令式缺点: 没法版本化管理,步骤散落在你的历史命令里,别人复现不了,久了自己也忘了。
声明式优点:
- 蓝图是文件,能存进 Git,可评审、可回滚、可复现(环境即代码)。
- 多个对象放一个目录,
kubectl apply -f ./dir一把梭。 - 适合团队协作和生产环境。
声明式缺点: 要学 YAML 写法,初期上手比敲命令慢一点。
Note一句话结论:临时探索用命令式,正经管理用声明式。 本书后续所有示例,凡是建资源的,都会优先给你 YAML +
apply的写法。
10-5 apply 背后的一点原理
kubectl apply 之所以聪明,是因为它会在对象上记一个注解:kubectl.kubernetes.io/last-applied-configuration,把”上次 apply 时的内容”存进去。
下次再 apply,它拿”上次内容、这次文件、集群现状”三者做对比,算出该加哪些字段、清哪些字段。所以:
- 你删了 YAML 里某字段 → apply 后集群里那个字段也被清掉。
- 你加了字段 → 被设置。
- 你没动、但别人手动改了的字段 → 被保留(除非你显式把它置空)。
Tip想看 apply 到底会改什么,先跑
kubectl diff -f my-app.yaml预览。改动前先 diff,是个能救命的习惯。
10-6 删除也要讲方式
删除资源两种方式都常见:
kubectl delete -f my-app.yaml # 声明式配合:按文件删,最明确
kubectl delete deployment hello-node # 命令式:按名字删
官方建议:声明式管理时,删除也用 kubectl delete -f,语义最清楚,不容易误删。
Warning切换管理方式要谨慎。一个对象最好只用一种方式长期管理(声明式或命令式二选一),混用容易让”现状”和”文件”对不上,改出幺蛾子。
10-7 从命令式迁移到声明式
如果你一开始是用命令式 create 建的对象,想转成声明式管理,可以这样做:
- 把运行中的对象导成 YAML:
kubectl get deployment hello-node -o yaml > hello-node.yaml - 手动删掉导出的
status段(那是集群填的运行态,不该你管)。 - 用
kubectl apply -f hello-node.yaml接管它。
之后就只用 YAML + apply 管理这个对象,别再混用 create/replace。
Note导出的 YAML 里常常带一大堆默认字段和
status,看着眼花。别怕,真正需要你关心的往往只有apiVersion、kind、metadata.name、和spec那几块。其余大多是系统维护的,可以先忽略。
10-8 给初学者的实践建议
最后给三条可落地的建议:
- 所有”正式”资源都用 YAML 文件写,哪怕只有几行。文件进 Git,环境可复现。
- 改之前先
kubectl diff,看清会动哪些字段,再apply。 - 一个对象只用一种方式管,声明式或命令式二选一,别混着来。
Tip本书后续所有”建资源”的示例,都会给你 YAML +
apply的写法,而不是一条kubectl run。跟着这个节奏走,你自然会养成”环境即代码”的习惯。
小结
命令式下指令、声明式给蓝图;生产首选 apply + YAML,临时试手才用命令式;别把 apply 和 create/replace 混用;改动前先 diff。到这章,入门与快速开始这十章就走完了。你已经知道 k8s 是什么、为什么用、核心概念、整体架构、本地环境、第一个应用、常用命令和管理对象的思维方式。接下来,教程会进入更深的 Pod、工作负载、网络等专题。基础打牢,后面才不慌。