静态加密 Secret 数据
你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:
To check the version, enter .
需要 etcd v3 或者更高版本
配置并确定是否已启用静态数据加密
kube-apiserver
的参数 --experimental-encryption-provider-config
控制 API 数据在 etcd 中的加密方式。 下面提供一个配置示例。
每个 resources
数组项目是一个单独的完整的配置。 resources.resources
字段是要加密的 Kubernetes 资源名称(resource
或 resource.group
)的数组。 providers
数组是可能的加密 provider 的有序列表。 每个条目只能指定一个 provider 类型(可以是 identity
或 aescbc
,但不能在同一个项目中同时指定)。
列表中的第一个 provider 用于加密进入存储的资源。 当从存储器读取资源时,与存储的数据匹配的所有 provider 将按顺序尝试解密数据。 如果由于格式或密钥不匹配而导致没有 provider 能够读取存储的数据,则会返回一个错误,以防止客户端访问该资源。
Caution: 重要: 如果通过加密配置无法读取资源(因为密钥已更改),唯一的方法是直接从底层 etcd 中删除该密钥。 任何尝试读取资源的调用将会失败,直到它被删除或提供有效的解密密钥。
每个 provider 都支持多个密钥 - 在解密时会按顺序使用密钥,如果是第一个 provider,则第一个密钥用于加密。
在 EncryptionConfig 中保存原始的加密密钥与不加密相比只会略微地提升安全级别。 请使用 kms
驱动以获得更强的安全性。 默认情况下,identity
驱动被用来对 etcd 中的 Secret 提供保护, 而这个驱动不提供加密能力。 EncryptionConfiguration
的引入是为了能够使用本地管理的密钥来在本地加密 Secret 数据。
使用本地管理的密钥来加密 Secret 能够保护数据免受 etcd 破坏的影响,不过无法针对 主机被侵入提供防护。 这是因为加密的密钥保存在主机上的 EncryptionConfig YAML 文件中,有经验的入侵者 仍能访问该文件并从中提取出加密密钥。
加密你的数据
创建一个新的加密配置文件:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
providers:
- aescbc:
keys:
- name: key1
secret: <BASE 64 ENCODED SECRET>
- identity: {}
遵循如下步骤来创建一个新的 secret:
生成一个 32 字节的随机密钥并进行 base64 编码。如果你在 Linux 或 Mac OS X 上,请运行以下命令:
head -c 32 /dev/urandom | base64
将这个值放入到 secret 字段中。
- 设置
kube-apiserver
的--experimental-encryption-provider-config
参数,将其指向 配置文件所在位置。 - 重启你的 API server。
Caution: 你的配置文件包含可以解密 etcd 内容的密钥,因此你必须正确限制主控节点的访问权限, 以便只有能运行 kube-apiserver 的用户才能读取它。
数据在写入 etcd 时会被加密。重新启动你的 kube-apiserver
后,任何新创建或更新的密码在存储时都应该被加密。 如果想要检查,你可以使用 etcdctl
命令行程序来检索你的加密内容。
创建一个新的 secret,名称为
secret1
,命名空间为default
:使用 etcdctl 命令行,从 etcd 中读取 secret:
ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C
这里的
[...]
是用来连接 etcd 服务的额外参数。验证存储的密钥前缀是否为
k8s:enc:aescbc:v1:
,这表明aescbc
provider 已加密结果数据。-
kubectl describe secret secret1 -n default
其输出应该是
mykey: bXlkYXRh
, 数据是被加密过的,请参阅 了解如何完全解码 Secret 内容。
确保所有 Secret 都被加密
由于 Secret 是在写入时被加密,因此对 Secret 执行更新也会加密该内容。
上面的命令读取所有 Secret,然后使用服务端加密来更新其内容。
Note: 如果由于冲突写入而发生错误,请重试该命令。 对于较大的集群,你可能希望通过命名空间或更新脚本来对 Secret 进行划分。
在不发生停机的情况下更改 Secret 需要多步操作,特别是在有多个 kube-apiserver
进程正在运行的 高可用环境中。
- 重新启动所有
kube-apiserver
进程以确保每台服务器都可以使用新密钥进行解密 - 将新密钥设置为
keys
数组中的第一个条目,以便在配置中使用其进行加密 - 重新启动所有
kube-apiserver
进程以确保每个服务器现在都使用新密钥进行加密 - 运行
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
以用新密钥加密所有现有的秘密 - 在使用新密钥备份 etcd 后,从配置中删除旧的解密密钥并更新所有密钥
如果只有一个 kube-apiserver
,第 2 步可能可以忽略。
解密所有数据
要禁用 rest 加密,请将 identity
provider 作为配置中的第一个条目:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- identity: {}
- aescbc:
keys:
- name: key1
secret: <BASE 64 ENCODED SECRET>
并重新启动所有 kube-apiserver
进程。然后运行:
kubectl get secrets -all-namespaces -o json | kubectl replace -f -`
以强制解密所有 secret。
最后修改 January 05, 2022 at 10:56 PM PST: [zh] synchronize translate encrypt-data.md (875bb06af)