首页 / Kubernetes (k8s) 入门教程 / 声明式 vs 命令式管理对象

Kubernetes (k8s) 入门教程

声明式 vs 命令式管理对象

本教程共 65 篇 · 第 10 篇 · 更新于 2026-08-14 · 约 13 分钟阅读

Kubernetes声明式命令式kubectl applyYAML对象管理

本节目标:分清 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 是”整体替换”,会把文件里没写的字段全部清掉。所以官方明确说:别把 applycreate/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 建的对象,想转成声明式管理,可以这样做:

  1. 把运行中的对象导成 YAML:
    kubectl get deployment hello-node -o yaml > hello-node.yaml
  2. 手动删掉导出的 status 段(那是集群填的运行态,不该你管)。
  3. kubectl apply -f hello-node.yaml 接管它。

之后就只用 YAML + apply 管理这个对象,别再混用 create/replace

Note

导出的 YAML 里常常带一大堆默认字段和 status,看着眼花。别怕,真正需要你关心的往往只有 apiVersionkindmetadata.name、和 spec 那几块。其余大多是系统维护的,可以先忽略。

10-8 给初学者的实践建议

最后给三条可落地的建议:

  • 所有”正式”资源都用 YAML 文件写,哪怕只有几行。文件进 Git,环境可复现。
  • 改之前先 kubectl diff,看清会动哪些字段,再 apply
  • 一个对象只用一种方式管,声明式或命令式二选一,别混着来。
Tip

本书后续所有”建资源”的示例,都会给你 YAML + apply 的写法,而不是一条 kubectl run。跟着这个节奏走,你自然会养成”环境即代码”的习惯。

小结

命令式下指令、声明式给蓝图;生产首选 apply + YAML,临时试手才用命令式;别把 applycreate/replace 混用;改动前先 diff。到这章,入门与快速开始这十章就走完了。你已经知道 k8s 是什么、为什么用、核心概念、整体架构、本地环境、第一个应用、常用命令和管理对象的思维方式。接下来,教程会进入更深的 Pod、工作负载、网络等专题。基础打牢,后面才不慌。