2. 声明式模型基础:声明式 vs 指令式配置、期望状态与实际状态、Kubernetes声明式API
声明式模型是 GitOps 和 Kubernetes 的核心理念。理解声明式与指令式的本质区别,以及期望状态与实际状态之间的闭环调和机制,是掌握安全权限与 RBAC 设计的前提。本章从概念对比、状态机模型和 Kubernetes API 实现三个层面展开。
2.1 声明式 vs 指令式:两种配置哲学的对比
指令式配置关注“如何做”,声明式配置关注“做什么”。在基础设施和权限管理场景中,这种差异直接影响安全模型的复杂度。
| 维度 | 指令式(Imperative) | 声明式(Declarative) |
|---|---|---|
| 操作对象 | 过程与步骤 | 最终状态 |
| 典型命令 | kubectl run、kubectl create、kubectl delete |
kubectl apply -f manifest.yaml |
| 幂等性 | 非幂等,重复执行可能产生不同结果 | 幂等,重复执行结果一致 |
| 权限粒度 | 通常需要执行权限(动词级) | 需要写入权限(资源级),更易审计 |
| 变更历史 | 依赖操作日志,难以回滚 | 依赖版本控制(Git),天然可追溯 |
| 安全风险 | 临时提权、越权操作难以拦截 | 所有变更通过 PR/MR 审查,权限收敛 |
关键洞察: 声明式模型将“谁可以做什么”从运行时命令转移到版本控制中的 YAML 文件。这意味着 RBAC 策略的审核点从终端日志前移到代码审查阶段,安全左移成为可能。
2.2 期望状态与实际状态:闭环调和模型
声明式系统的核心是一个永不停止的调和循环(Reconciliation Loop)。控制器持续比较“期望状态”(存储在 Git 或 API 中的声明)与“实际状态”(集群中运行的资源),并采取行动消除差异。
安全视角: 调和循环中的“差异检测”是安全控制的关键点。如果实际状态被恶意篡改(例如攻击者直接修改了 Deployment),控制器会立即检测到差异并自动恢复为期望状态。这是 GitOps 提供“自愈”安全能力的基础。
2.3 Kubernetes 声明式 API 的实现机制
Kubernetes 本身就是一个声明式 API 平台。用户通过 kubectl apply 提交资源清单(YAML/JSON),API Server 将其持久化到 etcd,然后各个控制器(Controller)负责调和。
2.3.1 声明式 API 的核心组件
- API Server(kube-apiserver): 所有声明式请求的入口,负责认证、鉴权、准入控制和数据持久化。
- etcd: 存储期望状态(即用户提交的资源定义)的键值数据库。
- 控制器(Controller): 运行在 kube-controller-manager 中,持续监视 etcd 中的期望状态和集群实际状态,执行调和逻辑。
- kubelet: 节点上的代理,负责将 Pod 的期望状态转化为容器运行时实际状态。
2.3.2 声明式 API 的权限模型
Kubernetes 的 RBAC 系统与声明式 API 深度绑定。每一次 kubectl apply 操作都会触发以下安全链路:
- 认证(Authentication): 验证请求者身份(证书、、OIDC 等)。
- 鉴权(Authorization): 检查请求者是否对目标资源具有
create、update、patch或delete权限。 - 准入控制(Admission Control): 在持久化之前,通过 MutatingWebhook 和 ValidatingWebhook 对声明进行修改或校验。
- 持久化: 将声明写入 etcd,成为期望状态。
常见误区: 很多团队认为声明式模型下只需要“写权限”。实际上,
kubectl apply 在底层会转换为对资源的 patch 或 update 操作。如果 RBAC 策略只授予了 create 权限,而资源已存在,则 apply 会失败。正确的做法是授予 get、list、patch、update 的组合权限。
2.4 声明式模型在 GitOps 中的安全优势
| 安全维度 | 指令式模型 | 声明式模型(GitOps) |
|---|---|---|
| 变更审计 | 依赖 kubectl 日志,易丢失 | Git commit 历史,不可篡改 |
| 权限最小化 | 用户需要 kubectl 执行权限 | 用户只需 Git 仓库写入权限 |
| 回滚能力 | 手动逆向操作,易出错 | git revert 一键回滚 |
| 合规证明 | 难以证明“谁在何时做了什么” | 每个变更关联 PR/MR 和审批记录 |
| 配置漂移 | 无法自动检测 | 调和循环自动修复漂移 |
2.5 实践要点:从指令式迁移到声明式
对于正在从传统运维模式向 GitOps 转型的团队,以下迁移路径可以降低安全风险:
- 禁止直接使用
kubectl run、kubectl create deployment等指令式命令。 改为编写 YAML 文件并通过kubectl apply -f提交。 - 将 YAML 文件纳入 Git 仓库管理。 所有变更必须通过 Pull Request 提交,并启用分支保护规则。
- 配置准入控制器(Admission Controller) 强制校验所有资源必须包含
app.kubernetes.io/managed-by: gitops标签,否则拒绝创建。 - 使用
kubectl diff预览变更。 在 apply 之前,通过kubectl diff -f manifest.yaml查看期望状态与实际状态的差异。 - RBAC 策略收紧: 只允许 GitOps 控制器(如 Argo CD、Flux)的 ServiceAccount 拥有对集群资源的
patch、update、delete权限;普通开发者只拥有 Git 仓库的写入权限。
安全基线: 在 Kubernetes 集群中,通过
kubectl auth can-i 命令定期审计哪些用户或 ServiceAccount 拥有 create 或 patch 权限。理想状态下,除了 GitOps 控制器和集群管理员外,不应有任何主体拥有直接修改集群状态的权限。
2.6 本章小结
- 声明式模型关注“是什么”,指令式模型关注“怎么做”。
- 期望状态存储在 Git 或 etcd 中,实际状态由控制器持续调和。
- Kubernetes 声明式 API 通过 API Server、etcd、控制器和 kubelet 实现闭环。
- 声明式模型天然支持变更审计、权限最小化、自动回滚和配置漂移修复。
- 从指令式迁移到声明式,核心是“先审查,后执行”的安全左移策略。