AI时代的Kubernetes教程36招-第28招-Secret静态加密、证书和API Server审计怎么保护控制面?

保护控制面与静态数据:Secret 静态加密、PKI 轮换与审计落地

etcd 落盘、证书到期、Exec 无痕,三处盲区一次补齐

[读者] 自建或托管 K8s 的平台工程师,集群上跑着数字人业务
[痛点] Secret 在 etcd 里明文可见、证书到期不可控、高危操作查不到人
[现在读] 三件事都要改 kube-apiserver 静态 Pod,改错就是控制面不可用
[读完] 能独立完成静态加密、证书轮换、审计策略的落地与自证
[旧方案] 默认 identity 加密 + 一年期证书 + 无审计策略
    |
    v
[新需求] 合规要求静态加密、证书可轮换、高危操作可追责
    |
    v
[冲突] 只配加密不重写等于没加密,审计全开又会把 Secret 写进日志
    |
    v
[后果] 备份泄露即全量凭据泄露,事故回溯时没人说得清谁 exec 过

我是老李,在一个做数字人业务的团队负责 K8s 平台。集群是 kubeadm 自建的,三台控制面,上面跑着推理服务、音色资产服务和一大片配置型 Secret——第三方模型 API Key、对象存储凭据、TTS 服务密钥。

之前我们对安全的默认假设很朴素:etcd 只有运维能碰、证书是 kubeadm 装好的、出问题翻 kubectl 的 history 就够了。这个假设在十个节点以内成立,一过合规评估立刻碎掉。

上个月安全评估给了三条结论:Secret 在 etcd 里是明文、证书没有到期巡检机制、Exec 和 PortForward 这类操作没有任何记录。三条结论指向同一个入口——kube-apiserver 的静态 Pod manifest,以及 /etc/kubernetes/pki 这棵证书树。

加密配置写进 manifest 就算合规了吗?

证书轮换是等快到期的前一周抢修,还是提前做成可重复、可回滚的流程?

如果审计只记录元数据,事故回溯时你真的能说清是谁 exec 进了那个 Pod 吗?

01、故事

数字人业务的特点是:模型推理本身不重,重的是素材和凭据。一次音色克隆要调三个外部服务,每个服务一把 Key,全部以 Secret 形式挂在命名空间里。这些 Secret 平时没人看,出事就是大事。

现场的约束很具体:集群正在服务线上流量,控制面不能停机做维护窗口;三台控制面共用一套 kubeadm 管理的 PKI;没有独立的 etcd 加密密钥托管系统,也没有 SIEM,审计日志暂时只能落本地文件。

任务是在不中断推理服务的前提下,给集群补上静态加密、证书巡检和审计三件事,并且每一件都要能自己证明它生效了。

变化来自一次合规要求:所有存储态敏感数据必须加密,控制面身份凭证必须有轮换记录,高权限操作必须可追溯。对照这三条,我们现有的方案是零——加密用的是默认的 identity provider,等于不加密;证书只在建集群时生成过一次;审计策略根本没开。

冲突点是:这三件事全部要在同一个对象上动手,也就是 kube-apiserver 的静态 Pod。改错一个 flag,apiserver 起不来,整个集群的 API 全部失效,包括你用来回滚的那条 kubectl。

所以我给这件事定的第一条纪律不是把配置写全,而是先保证可回滚。

集群跑得好
隐患藏得深
一张扫描单
三处盲区现

02、问题

旧方案失效的地方在于它的隐含前提:默认配置等于安全配置。Kubernetes 对 Secret 的默认处理是 identity provider,也就是对象被序列化后直接写进 etcd,只在 API 层做 base64 编码。base64 是编码不是加密,任何能读 etcd 数据目录或备份文件的人,都能拿到明文凭据。

业务影响是连锁的。一旦 etcd 快照被误传到一个不该去的存储桶,泄露的不是一份配置,而是推理服务、对象存储、第三方模型平台的全部调用凭据,攻击面直接从集群内部扩散到所有外部系统。

技术表现有三个可观测信号:

第一,在控制面节点上直接读 etcd 中的 Secret 键值,内容是可读明文,而不是带加密前缀的密文。

第二,kubeadm 管理的证书有明确的有效期,但集群里没有任何机制告诉你还有多少天到期;直到某天 apiserver 与 kubelet 的 TLS 握手失败,你才知道过期这件事。

第三,审计没有开启时,谁执行过 kubectl exec、谁做过 RoleBinding 变更,在集群里不留痕迹,只能依赖外部的操作日志,而外部日志和实际 API 调用并不总是对得上。

可验证的完成标准我定成四条:新建 Secret 在 etcd 中以密文形式存储且带加密前缀;历史 Secret 经过重写后同样是密文;能用 kubeadm 自带的命令输出完整的证书有效期清单;审计日志中能检索到指定用户对 pods/exec 与 RBAC 变更的请求记录。

这四条都能用命令复现,不依赖任何人的口头确认。

明文落在盘上
证书逼近到期
高危操作无痕
合规不肯认账

03、原理

先把原理收敛到本篇真正需要的三块:加密的作用点、PKI 的信任链、审计的等级。

第一块是加密的作用点。kube-apiserver 在把对象写入 etcd 之前做序列化和加密,读出时解密。也就是说,EncryptionConfiguration 作用在写入路径上,读路径只是相应地多一层解密。

反直觉判断:加密配置生效不等于数据已经加密。它只影响之后写入的对象,etcd 里已经存在的历史对象不会因为你改了配置就自动变成密文。如果不做一次全量重写,你以为加密的那个 Secret,昨天就已经躺在磁盘上了,明天还是明文。

第二个反直觉的地方在 provider 的顺序。配置文件里的 providers 是一个有序列表,列表中的第一个 provider 用于加密,解密时按顺序尝试。identity 必须放在最后作为兜底,如果把 identity 放在第一位,新写入的数据依然是明文,配置看起来完全正确,行为却等于没配。

第二块是 PKI 的信任链。控制面组件之间的身份不是靠密码,而是靠证书里的 CN 和 O 字段映射到 RBAC 主体。apiserver 的客户端证书 CN 决定它是什么用户,O 决定它属于哪个组。证书轮换真正的风险不在生成新证书,而在新旧证书的信任链是否仍然指向同一套 CA,以及所有引用这份证书的组件是否同步换了。

第三块是审计的等级。审计策略有四个等级:None、Metadata、Request、RequestResponse。等级越高记录越全,代价也越大。Metadata 记录请求的用户、动作、资源、结果;Request 额外记录请求体;RequestResponse 连响应体一起记录。

反直觉判断:审计等级不是越高越安全。RequestResponse 会把响应体完整写进日志文件,而读取 Secret 的响应体就是明文凭据。你把审计开到最细的那一刻,等于在日志文件里复制了一份凭据备份,加密 etcd 的努力被审计日志从另一边抵掉了。

理解了这三点,后面的架构取舍才站得住:加密要配重写,PKI 要管信任链,审计要按资源分级而不是一刀切。

加密只管写入
旧账不会重算
审计是把双刃
证据也是风险

04、架构

[输入] 对 Secret 的读写请求、对 apiserver 的高危 API 调用
    |
    v
[模块] kube-apiserver(EncryptionConfiguration + AuditPolicy + PKI 证书)
    |
    v
[数据/状态] etcd 中的 Secret 密文、审计日志文件、/etc/kubernetes/pki 证书链
    |
    v
[处理] 写入路径加密 / 审计事件分级落盘 / TLS 握手与证书校验
    |
    v
[输出] 密文 Secret、可检索的审计记录、可信的控制面身份

这套结构的边界很清楚:所有三件事都挂在 kube-apiserver 这一个进程上,而它由 /etc/kubernetes/manifests/kube-apiserver.yaml 这个静态 Pod manifest 描述,由 kubelet 负责拉起和重建。改 manifest 就是改控制面的行为,影响面是整个集群。

加密模块的边界是存储介质。它能保证的是:拿到 etcd 数据文件或快照的人无法直接读出凭据。它管不了的是:通过 API 合法读取 Secret 的人。加密不改变 RBAC,也不改变谁能 get secret。

PKI 模块的边界是身份。证书在 /etc/kubernetes/pki 下按用途分目录,根 CA 与叶子证书分离,etcd 有自己独立的一套 CA。收益是组件间通信可验证、可追责;代价是证书成了单点,CA 私钥泄露等于整个集群的信任基座失效。

审计模块的边界是记录而不阻断。审计默认是记录行为,不是拦截行为。它能让高危操作可追溯,但不会阻止一次恶意的 exec。收益是可追责、可做异常基线;代价是日志体积、敏感信息外溢风险和 apiserver 的额外开销。

适用条件也要说清:这套方案适用于 kubeadm 自建集群和能改 apiserver 静态 Pod 的托管形态;如果你的集群完全不允许接触控制面 manifest,加密和审计就只能走云厂商托管能力,本文的实操部分不适用。

三事同一入口
一改全集群动
边界先划清楚
回滚要留后手

05、实战一次

先跑通最小可用的 V1:只做 Secret 静态加密,不做审计,不做证书轮换,把加密这条路走通再谈别的。

环境与依赖:kubeadm 部署的自建集群,控制面节点可登录,/etc/kubernetes/pki 与 /etc/kubernetes/manifests 就位;工具需要 kubectl、etcdctl、base64。--encryption-provider-config-automatic-reload 的可用版本与默认值随 Kubernetes 版本变化,需按当前官方文档核验。

第一步,生成 32 字节密钥。aescbc 与 aesgcm 都要求密钥长度是 32 字节,长度不对 apiserver 会拒绝启动:

head -c 32 /dev/urandom | base64

第二步,把输出写进加密配置文件 /etc/kubernetes/enc/encryption-config.yaml。注意 providers 的顺序,aescbc 在前,identity 在最后:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <上一步生成的 base64 字符串>
      - identity: {}

第三步,修改 kube-apiserver 静态 Pod manifest。只新增必要内容,其余 flag 与 volume 保持原样,任何一处删改都可能导致 apiserver 无法启动:

apiVersion: v1
kind: Pod
metadata:
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
    - name: kube-apiserver
      command:
        - kube-apiserver
        - --encryption-provider-config=/etc/kubernetes/enc/encryption-config.yaml
        # 其余原有 flag 保持不变
      volumeMounts:
        - name: encryption-config
          mountPath: /etc/kubernetes/enc
          readOnly: true
        # 其余原有 volumeMounts 保持不变
  volumes:
    - name: encryption-config
      hostPath:
        path: /etc/kubernetes/enc
        type: DirectoryOrCreate
    # 其余原有 volumes 保持不变

第四步,等待 kubelet 检测到 manifest 变化并重建静态 Pod,观察 apiserver 是否正常起来:

kubectl -n kube-system get pod -l component=kube-apiserver -o wide
kubectl -n kube-system logs kube-apiserver-<node> --tail=50

第五步,写入一个新 Secret 并验证。这是 V1 唯一必须通过的验收点:

kubectl -n demo create secret generic demo-secret --from-literal=token=hello-v1

然后直接读 etcd 中的存储值:

ETCDCTL_API=3 etcdctl \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  get /registry/secrets/demo/demo-secret | head -c 200

未在当前环境实测,以下为预期结果:

k8s:enc:aescbc:v1:key1:\x0e...

只要开头出现 k8s:enc:aescbc:v1:key1 这一段前缀,就说明写入路径上的加密已经生效。

V1 到这里就跑通了,但它留下两个明显的问题:老 Secret 还是明文,而且这套配置一旦要换密钥,你没有任何成型的流程可用。

密钥先备好
挂载再改参
新写看前缀
老对象留问号

06、排查

诊断链一:新对象是密文,老对象还是明文。

现象:demo-secret 读完前缀正确,但业务实际使用的 auth-secret 读出来仍是明文。

怀疑:加密配置没生效,或者 apiserver 没重启成功。

检查:分别读取两个对象的 etcd 存储值做对比;同时检查 apiserver 进程的启动参数里是否真的带上了 encryption-provider-config。

证据:新对象带 k8s:enc:aescbc:v1:key1 前缀,老对象没有;apiserver 参数确实已生效。

根因:加密只作用在写入路径,配置生效前写入 etcd 的历史对象不会被回溯加密,这与配置是否正确无关。

修复:对所有 Secret 做一次全量重写,让它们以密文重新落盘:

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

错误尝试: 我们最初的判断是重启 apiserver 就会重新加密数据,于是反复重建静态 Pod 并重启 kubelet。这个方向是错的,原因在于加密发生在 write path 上,重启只是重新加载配置,不会触发任何对象的重新写入,老数据自然不会变。判断数据是否加密,唯一可靠的证据是 etcd 里的实际字节,不是配置文件和进程参数。

诊断链二:审计策略配了,但日志里搜不到 exec 记录。

现象:执行 kubectl exec 进入一个业务 Pod,审计日志里能查到其他请求,就是没有这条。

怀疑:策略文件没挂载成功,或者 --audit-log-path 指向的目录没有写权限。

检查:确认 apiserver 启动参数中 audit-policy-file 与 audit-log-path 同时存在;确认 policy 与日志目录都已挂载进静态 Pod;查看日志文件是否有新增内容。

证据:日志文件确实在增长,说明审计后端是通的,缺的是特定事件。问题出在规则匹配上。

根因:exec 和 portforward 在 API 层是 Pod 的子资源,规则里若只写 resources 为 pods,并不会匹配到 pods/exec;另外如果前面存在一条宽泛的 catch-all 规则,它会把请求提前命中并落到低等级处理,后面的细粒度规则永远不生效。

修复:在高危子资源上单独写规则,并保证它的顺序在宽泛规则之前。

诊断链三:证书续期后控制面组件起不来。

现象:kubeadm certs renew 之后,apiserver 容器反复重启,kubectl 大量超时。

怀疑:新证书与 etcd 或 kubelet 的信任链不一致。

检查:kubeadm certs check-expiration 看有效期,crictl logs 或 journalctl -u kubelet 看容器退出原因,重点找 x509 相关报错。

证据:报错集中在证书校验失败,而不是端口或资源问题。

错误尝试: 我们试过用 openssl 手工重新签发并覆盖 /etc/kubernetes/pki 下的证书文件。这个方向错在两处:一是手工签发的证书 SAN 很难和 kubeadm 的预期完全一致,apiserver 的 service IP、节点名、cluster.local 相关名称漏一个就会握手失败;二是手工覆盖会破坏 kubeadm 对证书的管理状态,后续 renew 和 check-expiration 的结果不再可信。正确路径是始终用 kubeadm 自己的证书子命令管理这套 PKI。

现象先对齐
证据不靠猜
错路走一遍
根因才露头

07、优化

V2 的改动严格来自上一章三条证据,不做任何没有依据的加固。

改动一,把全量重写变成加密上线的固定第二步。根因是写入路径加密不影响历史对象,所以流程上必须紧跟一条重写动作。修改方式是固定顺序:改配置、验证新对象前缀、全量 replace、再次验证老对象前缀。原因是重写会触发每个 Secret 的更新,从而走一遍加密写入。新行为是集群内所有 Secret 在 etcd 中均为密文。验证方式是对同一批对象做前后对比,观察前缀是否出现。

改动二,把密钥从单钥改成可轮换的多钥列表。根因是单个 key1 无法安全更换,直接替换会导致老数据无法解密。修改方式是把新密钥追加到 keys 列表最前面,因为列表第一位才是加密用密钥,重写全量数据,确认无误后再从列表末尾移除旧密钥。原因是这样在任一时刻都保留了解密历史数据的能力。新行为是密钥更换不需要停机,也不需要一次性删掉旧钥。验证方式是轮换后读一个重写前创建的 Secret,仍能正常解密。

改动三,把审计规则从单条 catch-all 改成分层策略。根因是宽泛规则会提前命中请求,且高等级规则会放大敏感信息外溢风险。修改方式是按资源分层:默认级别用 Metadata 覆盖全量请求;对 RBAC 变更类资源提高等级;对 pods/exec、pods/portforward、pods/attach 这类子资源单独写规则,且放在宽泛规则之前。原因是高危操作真正需要的是主体、时间、目标对象这些元数据,而不是完整的请求响应体。新行为是 exec 与 RBAC 变更可检索,Secret 响应体不会成片进入日志。验证方式是实际执行一次 exec 与一次 RoleBinding 变更,然后在日志尾部确认两条记录都存在且等级符合预期。

改动四,把证书巡检接进日常巡检。根因是证书风险来自缺少可见性,而不是来自续期命令本身。修改方式是定期执行 kubeadm certs check-expiration 并把输出纳入巡检记录,续期走 kubeadm certs renew,之后按顺序重启控制面组件。原因是让到期时间变成可观测数据,而不是一个突然发生的事件。新行为是能提前看到每张证书的剩余天数。验证方式是巡检输出中每张证书都有明确的到期时间。

加钥再重写
删旧留新序
审计分三层
证书入巡检

08、演进

[同一输入]
    |
    +--[V1] aescbc 单钥加密 / 代价:老数据仍明文、换钥无流程
    |
    +--[V2] 多钥轮换 + 分层审计 + 证书巡检 / 代价:配置复杂度与运维流程成本上升
    |
[Trade-off]
{得到什么 / 失去什么 / 适用边界}

正确性上,V1 只对增量数据正确,V2 对增量与存量都正确,代价是多了一条必须执行的重写动作,流程少一步就会留下明文残留。

稳定性上,V1 的风险集中在改 manifest 那一次,后续几乎不动;V2 增加了密钥轮换和证书续期两个周期性动作,换句话说,V2 把一次性的高风险改成了持续的低风险运维,前提是流程被真正执行。

复杂度上,V1 只有一个配置文件;V2 增加了多钥列表、审计策略文件和证书巡检,这三者的变更都会影响控制面,任何一次修改都建议配合 etcd 快照。

成本上,V2 的额外开销主要来自两处:审计日志的写入与轮转占用的磁盘,以及高等级审计规则带来的 apiserver 处理开销。这两项都不宜拍脑袋定数值,应当先用 Metadata 级别观察一段时间的日志量与增长速率,再决定哪些资源提升等级。

适用范围上,V1 适合先验证加密链路是否打通;V2 适合需要长期运营、需要过合规的集群。如果你的集群不允许修改 apiserver 静态 Pod,这两个版本都无从落地,只能换成托管控制面提供的对应能力。

遗留问题也要写清楚:密钥目前仍然以文件形式保存在控制面节点上,拿到了节点文件系统的人依然能拿到密钥;审计日志是本地文件,没有集中采集,日志文件本身缺少访问控制。这两条是后一阶段要解决的对象,而不是本篇已经解决的问题。

版本一先跑通
版本二再收敛
得到的要认账
失去的也要认

09、洞见

9.1 加密的边界是介质,不是权限

反直觉判断:给 Secret 配好 at-rest encryption 之后,能读 etcd 备份的人拿不到凭据,但能 get secret 的人依然能读到明文。加密改变的是数据在磁盘上的形态,它不改变任何一条 RBAC 规则。所以把加密当成一个数据泄露问题的终点是危险的,它只是把攻击面从磁盘挪回了 API。真正的凭据收敛要靠最小权限、命名空间隔离和更短生命周期的凭据形式,加密只是最后一道兜底。

9.2 审计的价值在元数据,不在正文

反直觉判断:审计等级越高,日志本身越可能成为新的泄露面。RequestResponse 会把响应体完整记录下来,而读取 Secret 的响应体就是明文凭据;等于你花力气给 etcd 上了锁,又亲手把钥匙抄了一份放在旁边的文件里。对 exec、portforward 这类操作,追责需要的是谁、何时、对哪个 Pod,Metadata 已经完全够用。把高等级留给真正需要正文的资源,是审计设计里最容易被忽略的取舍。

9.3 证书风险来自可见性,不来自续期本身

反直觉判断:证书轮换翻车,绝大多数不是因为轮换命令用错了,而是因为集群里没人知道证书什么时候到期。一旦到期时间不可观测,所有轮换动作都变成事故现场的抢救,而抢救时最容易被采用的就是手工签发的捷径,那条路会把 PKI 的管理状态彻底破坏。把 check-expiration 放进巡检,比写好一份轮换手册更重要。

9.4 控制面加固的第一原则是可回滚

反直觉判断:控制面加固的难点不是配置写不出来,而是配置写错之后你没法用集群自己的工具去修。三件事都挂在 kube-apiserver 这一个进程上,它挂了,kubectl 也一起挂。所以顺序永远是先做快照、再做单点变更、再验证、再继续。把最激进的改动放在最后一步一步来,比一次性把三件事全配齐要安全得多。

加密防的是介质
防不住有权限的人
审计越写越详细
日志就越像雷区

10、系统落地

原来有什么:一个默认配置的 kubeadm 集群,Secret 明文落 etcd,证书只在建集群时生成过一次,审计未开启,控制面所有行为都不可追溯。

本篇新增了什么:一份放在 /etc/kubernetes/enc 下的加密配置文件,通过静态 Pod manifest 挂载给 apiserver;一套支持多密钥的轮换流程,配套一次全量重写动作;一份分层的审计策略,把默认等级压到 Metadata,对 exec、portforward 和 RBAC 变更单独提级;一条基于 kubeadm 证书子命令的巡检路径。

现在能做什么:能证明集群里的 Secret 在磁盘上是密文而不只是声称加密;能在不停机的情况下更换加密密钥;能检索到谁在什么时候对哪个 Pod 执行了 exec、谁修改了 RoleBinding;能提前看到每张控制面证书还有多久到期。

还缺什么:加密密钥仍然以文件形式存在控制面节点上,没有接入外部密钥管理服务,密钥的保护级别没有高于节点本身;审计日志是本地文件,没有集中采集与访问控制,日志轮转策略也需要单独设计,否则高危记录可能先被轮转掉;Secret 的读取权限仍然按原样存在,RBAC 层面没有做收敛;etcd 备份的加密与访问控制也还没有覆盖。

下一步演进的方向很明确:加密侧把 provider 从 aescbc 换成外部密钥管理方案,让密钥本体不落在节点磁盘上;审计侧把日志接进集中采集,并对高危事件做基线告警;权限侧对 Secret 的 get 和 list 做一次面向业务的最小化收敛。这三步做完,控制面加固才算从能过检查走到能扛事故。

原来只有默认配置
现在有三件套
尚缺外部密钥托管
下一步接入 KMS

11、小结

Q1 → 配了加密只是第一步,历史对象必须全量重写才算真的加密
Q2 → 轮换靠 kubeadm 证书子命令巡检与续期,别手改 CA,改完按顺序重启控制面
Q3 → 审计按资源分层,exec 与 portforward 单独成规则,默认等级压在 Metadata
状态 → 三件套可落地、可验证、可回滚,且各自的边界已经说清

Q1 的答案落在一句提醒上:配置文件生效和数据已加密是两件不同的事,中间隔着一次全量重写。判断标准不看你改了什么,只看 etcd 里的字节长什么样。

Q2 的答案落在工具的选择上:PKI 交给 kubeadm 的证书子命令管理,巡检在前、续期在后、重启收尾,手工 openssl 覆盖是必须避开的路径。

Q3 的答案落在分层的取舍上:高危操作的追责靠元数据就够,把正文级审计留给真正必要的资源,避免审计日志自己变成泄露面。

本篇最终交付的能力是一个能过合规检查、也能自己证明生效的控制面加固基线,以及一套可以继续叠加外部密钥托管与集中审计日志的演进路径。

一问对应一答
三问形成闭环
能力可以交付
边界已经说清

12、作业

12.1 理解题:为什么按官方步骤配好了 aescbc,用 etcdctl 仍能看到某些 Secret 是明文?

参考答案:因为加密只作用在写入路径上,kube-apiserver 的加密发生在对象写入 etcd 之前。配置生效之前就已经存在的对象不会被回溯加密,必须通过一次全量读取再写回的操作,让这些对象走一遍加密写入流程。验证时必须区分新建对象与历史对象,分别取样对比。

12.2 实战题:请给出一个可回滚的 Secret 静态加密上线步骤。

参考答案:第一步备份 etcd 快照并保留原 manifest 副本;第二步生成 32 字节密钥,写入独立目录的加密配置文件,注意 provider 顺序为加密算法在前、identity 在最后;第三步在静态 Pod manifest 中新增 flag 与只读挂载,其余 flag 与 volume 保持原样;第四步等待静态 Pod 重建,确认 apiserver 正常并检查参数生效;第五步新建一个测试 Secret,直接用 etcdctl 确认密文前缀;第六步执行全量重写;第七步再次抽样确认历史对象已变为密文。若任一步失败,用 etcd 快照与备份 manifest 回到初始状态。

12.3 排障题:审计策略已经配置,但日志中完全找不到 pods/exec 的记录,排查顺序是什么?

参考答案:先确认 apiserver 启动参数里审计策略文件与日志路径同时存在,且两者都已挂载进静态 Pod;再确认日志文件确实在增长,排除后端未生效;然后检查策略规则中是否用子资源形式匹配 pods/exec,只写 pods 不会命中;接着检查是否存在顺序更靠前的宽泛规则把请求提前命中并降级;最后检查日志轮转配置,确认记录不是已被轮转覆盖。用一次真实的 exec 操作触发,直接看日志尾部验证。

12.4 架构判断题:为什么建议给 exec、portforward 单独设规则,而不是统一用 RequestResponse?

参考答案:RequestResponse 会完整记录请求与响应体,对 Secret 这类资源而言,响应体就是明文凭据,等于把敏感数据复制进另一个文件,抵消了静态加密的部分价值,同时显著放大日志体积与 apiserver 开销。exec 与 portforward 的追责价值集中在主体、时间、目标对象这三个维度,Metadata 级别已经足够,把高等级审计留给真正必须看正文的资源,才是合理取舍。

理解要能落地
实战要能闭环
排障要讲证据
判断要讲取舍

13、思考

这篇的核心冲突不是加密、证书、审计三件事谁更重要,而是它们共用一个控制面入口,而这个入口本身不能出错。三件事里最容易犯的错误也不是配置写错,而是把配置生效误当成问题解决:加密配了不等于数据加密了,审计开了不等于记录查得到,证书续了不等于信任链一致。

可复用的工程判断有三条。第一,凡是要动控制面 manifest 的加固,先问自己一句话:如果这次改动让 apiserver 起不来,我用什么命令回滚。第二,任何加密与审计的设计都要先明确边界:加密负责介质,权限负责访问,审计负责追溯,三者不能互相替代,把其中一项当成全部,迟早会在另一端漏掉。第三,判断生效的证据只认底层形态,不认配置文件;etcd 里的字节、日志里的记录、证书里的到期时间,这三样才是唯一可信的验收标准。

下一次面对类似的控制面加固需求,先画清楚改哪个对象、影响哪些组件、怎么验证、怎么回滚,再动手改第一个 flag。

一念辨边界
一证定根因
一改知取舍
一役见真章

posted @ 2026-10-12 09:41  李福春  阅读(2)  评论(0)    收藏  举报