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 中的声明)与“实际状态”(集群中运行的资源),并采取行动消除差异。

期望状态 vs 实际状态 — 调和循环 期望状态 Git 仓库 / YAML 声明 实际状态 集群运行时资源 差异检测 Diff → 是否需要调和? 调和动作 Apply / Create / Delete 循环持续运行:控制器不断比较期望状态与实际状态,直到两者完全一致
安全视角: 调和循环中的“差异检测”是安全控制的关键点。如果实际状态被恶意篡改(例如攻击者直接修改了 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 操作都会触发以下安全链路:

  1. 认证(Authentication): 验证请求者身份(证书、、OIDC 等)。
  2. 鉴权(Authorization): 检查请求者是否对目标资源具有 create、update、patch 或 delete 权限。
  3. 准入控制(Admission Control): 在持久化之前,通过 MutatingWebhook 和 ValidatingWebhook 对声明进行修改或校验。
  4. 持久化: 将声明写入 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 和审批记录
配置漂移 无法自动检测 调和循环自动修复漂移
指令式 vs 声明式:安全链路对比 指令式链路(高风险) 用户执行 kubectl run / create API Server 即时鉴权(动词级) 直接修改集群状态(无审查) 变更仅记录在操作日志中 声明式链路(低风险) 用户提交 PR/MR 到 Git 仓库 代码审查 + CI 策略检查 GitOps 控制器 apply 到集群 变更永久记录在 Git commit 中 声明式模型通过 Git 引入“审查层”,将安全控制点从运行时前移到代码提交阶段

2.5 实践要点:从指令式迁移到声明式

对于正在从传统运维模式向 GitOps 转型的团队,以下迁移路径可以降低安全风险:

  1. 禁止直接使用 kubectl run、kubectl create deployment 等指令式命令。 改为编写 YAML 文件并通过 kubectl apply -f 提交。
  2. 将 YAML 文件纳入 Git 仓库管理。 所有变更必须通过 Pull Request 提交,并启用分支保护规则。
  3. 配置准入控制器(Admission Controller) 强制校验所有资源必须包含 app.kubernetes.io/managed-by: gitops 标签,否则拒绝创建。
  4. 使用 kubectl diff 预览变更。 在 apply 之前,通过 kubectl diff -f manifest.yaml 查看期望状态与实际状态的差异。
  5. 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 实现闭环。
  • 声明式模型天然支持变更审计、权限最小化、自动回滚和配置漂移修复。
  • 从指令式迁移到声明式,核心是“先审查,后执行”的安全左移策略。