Kubernetes 的声明式 API (Declarative API) 与命令式 API 的区别
在 Kubernetes 中,理解命令式 API (Imperative API) 和 声明式 API (Declarative API) 的区别,是掌握 K8s 核心设计哲学的关键。
简单来说:
- 命令式关注“怎么做”(过程)。
- 声明式关注“要什么”(结果)。
以下是详细的对比解析:
1. 生活中的类比
为了方便理解,我们可以用打车和做菜来类比:
命令式 (打车 - 指挥司机):
- “师傅,前面左转。”
- “直走 500 米。”
- “在那个红绿灯右转。”
- “停车。”
- 你必须全程关注每一步,如果一步错了,结果就错了。
声明式 (打车 - 给目的地):
- “师傅,我要去机场。”
- 你不需要管司机走哪条路,只要最终到达机场即可。如果中间修路(环境变化),司机自动换路(系统自我修复)。
2. 具体操作对比
命令式 API (Imperative)
你告诉 Kubernetes 具体的动作。通常使用 kubectl 的动词命令(create, run, expose, scale, edit 等)。
操作方式: 面向过程,一步步执行。
例子:
- 创建一个 Nginx Pod:
kubectl run nginx --image=nginx - 将副本数调整为 3:
kubectl scale deployment nginx --replicas=3 - 修改镜像版本:
kubectl set image deployment/nginx nginx=nginx:1.19
- 创建一个 Nginx Pod:
缺点:
- 不可重复性:如果网络中断,你不知道命令是否执行成功。
- 非幂等性:
kubectl create执行两次会报错(因为资源已存在)。 - 难以维护:没有文档记录集群当前的状态,只能靠记忆或翻历史命令。
声明式 API (Declarative)
你告诉 Kubernetes 期望的状态 (Desired State)。通常使用 YAML 文件配合 kubectl apply。
操作方式: 面向结果,提交配置文件。
例子:
- 编写一个
nginx.yaml文件:yamlapiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 3 # 我期望有3个副本 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.19 # 我期望镜像是 1.19 - 应用配置:
kubectl apply -f nginx.yaml
- 编写一个
Kubernetes 的工作: 系统会对比“当前状态”和“期望状态”。如果当前没有 Nginx,它就创建;如果当前有 1 个副本,它就再加 2 个;如果镜像不对,它就更新镜像。
3. 核心区别深度解析
| 特性 | 命令式 API (Imperative) | 声明式 API (Declarative) |
|---|---|---|
| 关注点 | 过程 (How) | 结果/状态 (What) |
| 典型命令 | create, run, scale, edit |
apply |
| 数据源 | 命令行参数 | 配置文件 (YAML/JSON) |
| 幂等性 | 弱 (重复执行可能报错或产生副作用) | 强 (重复执行 apply 结果一致) |
| 事务处理 | 一次性操作 (Fire and forget) | 持续调谐 (Continuous Reconciliation) |
| 审计与协作 | 困难 (命令记录在个人终端) | 容易 (YAML 文件可存入 Git 进行版本控制) |
| 复杂性 | 简单直观,适合临时调试 | 学习曲线稍高,适合生产管理 |
4. 为什么 Kubernetes 推崇声明式 API?
Kubernetes 的核心是 控制器模式 (Controller Pattern),它依赖于声明式 API 来实现自动化运维。
A. 只有声明式才能实现“GitOps”
通过声明式 API,我们可以将 YAML 文件存放在 Git 仓库中。
- Infrastructure as Code (IaC):基础设施即代码。
- 版本控制:可以回滚到上一个版本的 YAML。
- 审计:谁修改了 YAML,Git 都有记录。
B. 自动修复 (Self-Healing)
这是声明式 API 最强大的地方。
- 场景:你定义了
replicas: 3。 - 命令式:如果你手动删除了一个 Pod,系统不会自动补齐,因为命令已经执行完了。
- 声明式:Kubernetes 的控制器会不断循环检查(Reconciliation Loop)。它发现“期望是 3,实际只有 2”,于是自动创建一个新的 Pod 来补齐。
C. 智能合并 (Merge Patch)
kubectl apply 不仅仅是覆盖。它会计算 YAML 文件与集群内现有配置的差异(Diff)。
- 如果有人手动给 Pod 加了一个 Label,而你的 YAML 更新了镜像。
apply会更新镜像,但保留那个手动加的 Label(除非发生冲突)。
5. 总结
- 如果你只是想快速测试、临时起一个容器看看日志,用命令式 (
kubectl run)。 - 如果你是在管理生产环境、部署应用、需要长期维护,必须使用声明式 (
kubectl apply -f yaml)。
Kubernetes 的强大之处在于它不仅仅是一个执行命令的工具,而是一个维持状态的系统,这完全归功于声明式 API 的设计。
右滑查看面试常问