首页
/ kubernetes-the-hard-way 数据加密实战:生成 Encryption Key 与 Encryption Config,为 Secrets 开启静态加密

kubernetes-the-hard-way 数据加密实战:生成 Encryption Key 与 Encryption Config,为 Secrets 开启静态加密

2026-09-05 11:59:27作者:邵娇湘

本篇基于 kubernetes-the-hard-way 教程中的实验 Generating the Data Encryption Config and Key,讲解如何手工生成一个用于静态数据加密的密钥(Encryption Key),基于仓库中的模板 configs/encryption-config.yaml 渲染出 Encryption Config 文件,并最终通过 kube-apiserver--encryption-provider-config 参数为集群中的 Secrets 开启静态加密(Encryption at Rest)。读完本篇,你将掌握加密密钥的生成原理、Encryption Configuration 文件的字段结构,以及如何通过检查 etcd 中的实际存储数据来验证加密真正生效。

为什么需要静态数据加密

Kubernetes 会把大量数据——集群状态、应用配置以及 Secrets——持久化到 etcd 中。在 kubernetes-the-hard-way 的拓扑中(一台 server 承载全部控制平面组件,加 node-0node-1 两台工作节点,见 README),etcd 直接以明文形式落在 server 机器的磁盘上。如果攻击者拿到了 etcd 的数据文件或磁盘镜像,Secrets 中的凭据、令牌等内容将一览无余。

Kubernetes 支持静态数据加密(Encrypting data at rest)能力:由 kube-apiserver 在数据写入 etcd 之前完成加密、从 etcd 读取之后完成解密,客户端(kubectl 等)完全无感知。本实验就是整个教程中为这一步做准备的环节:生成一个加密密钥,并生成一份适合加密 Secrets 的 Encryption Config。

实验在教程中的位置

该实验位于 docs/06-data-encryption-keys.md,紧跟在 生成 kubeconfig 文件 之后、引导 etcd 集群 之前。之所以排在这个位置,是因为:

  1. 加密密钥和配置文件属于 server 机器上控制平面启动前必须就位的物料之一——后续 Bootstrapping the Kubernetes Control Plane 会把 encryption-config.yaml 移动到 /var/lib/kubernetes/ 目录;
  2. 密钥生成依赖 envsubst 做模板渲染,与证书、kubeconfig 一样都在 jumpbox 上完成,生成后再分发到目标机器。

教程使用的组件版本(见 downloads-amd64.txt)为 Kubernetes v1.32.3 与 etcd v3.6.x,运行环境为 Debian 12 (bookworm) 的 4 台 ARM64 或 AMD64 机器,要求见 docs/01-prerequisites.md

生成加密密钥(The Encryption Key)

实验的第一步是生成一个加密密钥,命令如下:

export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)

这条命令值得逐段拆解:

片段 作用
head -c 32 /dev/urandom 从操作系统的随机源读取 32 个随机字节(256 位)
| base64 将这 32 字节编码为 Base64 字符串(约 44 个字符)
export ENCRYPTION_KEY=... 导出为环境变量,供下一步的模板渲染读取

这里的 32 字节正是 AES-256 密钥的长度,与下一步配置文件中 aescbc(AES-CBC 模式)provider 对密钥的要求相吻合:aescbcsecret 字段要求填入 Base64 编码的 32 字节密钥。/dev/urandom 是内核提供的密码学安全随机源,保证每次执行生成的密钥都不同且不可预测。

注意:export 只在当前 shell 会话内有效。如果关闭了终端或切换了 shell,需要重新执行该命令生成新的 ENCRYPTION_KEY(或者沿用同一会话继续操作)。

解析 Encryption Config 模板文件

仓库中的 configs/encryption-config.yaml 是一份待渲染的模板,完整内容如下:

kind: EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: ${ENCRYPTION_KEY}
      - identity: {}

各字段含义如下:

  • kind: EncryptionConfigurationapiVersion: apiserver.config.k8s.io/v1:声明这是一份 API Server 的静态加密配置文件,采用 apiserver.config.k8s.io/v1 版本;
  • resources:定义加密规则,本教程只对 secrets 这一种资源启用静态加密。即只有 Secret 对象写入 etcd 时会被加密,其他资源仍按原样存储;
  • providers:按优先级排列的加密算法列表。第一条是 aescbc provider:
    • aescbc 表示使用 AES 算法的 CBC(Cipher Block Chaining)工作模式;
    • keys 是密钥列表,name: key1 是该密钥在数据中的标识名,secret: ${ENCRYPTION_KEY} 是一个占位符,等待模板渲染时替换为前面生成的 Base64 密钥;
  • identity: {} 作为兜底 provider:当数据无法(或无需)由前面的 provider 处理时(例如读取历史明文数据),按原样存取。

${ENCRYPTION_KEY} 是标准的 shell 变量占位符,这正是下一步使用 envsubst 的原因。

渲染配置文件并分发到 Controller 机器

jumpbox 上执行模板渲染,生成真正包含密钥的 encryption-config.yaml

envsubst < configs/encryption-config.yaml \
  > encryption-config.yaml

envsubst 会读取当前 shell 环境变量中的 ENCRYPTION_KEY,替换模板中的占位符,输出到当前目录的 encryption-config.yaml。渲染完成后,可用 cat encryption-config.yaml 确认 secret: 字段已经是真实的 Base64 密钥字符串。

然后把配置文件复制到每台 controller 实例(本教程即 server 机器):

scp encryption-config.yaml root@server:~/

后续 Bootstrapping the Kubernetes Control Plane 实验中会执行以下操作,把 encryption-config.yaml 与其他 TLS 证书、Service Account 密钥一起移入 kube-apiserver 的配置目录:

{
  mkdir -p /var/lib/kubernetes/

  mv ca.crt ca.key \
    kube-api-server.key kube-api-server.crt \
    service-accounts.key service-accounts.crt \
    encryption-config.yaml \
    /var/lib/kubernetes/
}

kube-apiserver 如何消费这份配置

配置文件生效的入口在 units/kube-apiserver.service 这个 systemd 单元文件中,其 ExecStart 一行的第 18 行明确挂载了该文件:

ExecStart=/usr/local/bin/kube-apiserver \
  ...
  --etcd-servers=http://127.0.0.1:2379 \
  --encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \
  ...

从源码结构看,整条链路是:kube-apiserver 启动时加载 --encryption-provider-config 指定的文件,按照其中的 resources 规则匹配资源类型,对命中的对象(本例为 secrets)使用 providers 列表中第一个可用的 provider(aescbc/key1)做 AES-CBC 加密后写入 etcd;读取时再按数据头部携带的 provider 与密钥标识反向解密。etcd 本身不需要感知加密,数据加密完全发生在 API Server 进程内——这也解释了为什么本教程中 etcd 以 http://127.0.0.1:2379 的本地明文方式运行,而 Secrets 在磁盘上依然不是明文。

验证加密真正生效:检查 etcd 中的实际数据

教程在最后的 Smoke Test 实验("Data Encryption" 一节)中给出了验证方法。先创建一个 generic secret:

kubectl create secret generic kubernetes-the-hard-way \
  --from-literal="mykey=mydata"

再登上 server 机器,直接查看 etcd 中该 Secret 的原始字节:

ssh root@server \
    'etcdctl get /registry/secrets/default/kubernetes-the-hard-way | hexdump -C'

输出形如:

00000000  2f 72 65 67 69 73 74 72  79 2f 73 65 63 72 65 74  |/registry/secret|
00000010  73 2f 64 65 66 61 75 6c  74 2f 6b 75 62 65 72 6e  |s/default/kubern|
00000020  65 74 65 73 2d 74 68 65  6d 68 61 72 64 2d 77 61  |etes-the-hard-wa|
00000030  79 0a 6b 38 73 3a 65 6e  63 3a 61 65 73 63 62 63  |y.k8s:enc:aescbc|
00000040  3a 76 31 3a 6b 65 79 31  3a 4f 1b 80 d8 89 72 f4  |:v1:key1:O....r.|
...

判断加密生效的依据是数据值的前缀 k8s:enc:aescbc:v1:key1,它逐段声明了存储形态:

  • k8s:enc: —— 该值经过 API Server 静态加密处理后存储;
  • aescbc —— 使用的 provider 类型是 AES-CBC;
  • v1 —— 该 provider 的版本;
  • key1 —— 使用的是密钥列表中名为 key1 的密钥。

前缀之后的字节即为密文,mydata 等明文内容不会出现在 etcd 数据中。

密钥管理与后续演进注意事项

基于本实验的产物,有几点值得在实际操作中留意:

  1. 配置文件本身包含明文密钥。渲染后的 encryption-config.yaml${ENCRYPTION_KEY} 替换结果的形式保存了密钥的 Base64 值,因此应严格控制其文件权限(例如 chmod 600),避免 server 机器上的其他账户读取。这是由"密钥内嵌于配置文件"这一静态加密方案的结构特点决定的运维要求;
  2. 密钥轮转的扩展方式aescbc provider 的 keys 是一个列表,从配置结构看,可以推断向列表中添加新的密钥项(如 key2)后,新的写入与解密将引用新密钥,而旧数据仍按数据头部携带的 key1 标识找到对应密钥解密——这是该配置结构天然支持轮转能力的原因;
  3. 加密范围有限:当前配置只对 secrets 资源生效,集群状态中的其他对象(如 Deployment、ConfigMap 等)在 etcd 中依然是明文,这是本教程为聚焦教学而做的取舍。

相关资源索引

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384