在 Kubernetes 中,Secret 是一种资源对象,用于存储敏感信息,如密码、OAuth 令牌和 SSH 密钥。Secret 可以用来向 Pod 传递敏感信息,而无需明文在 Pod 规约中暴露它们。
Kubernetes 如何保证 Secret 的安全?主要有以下几点:
- Secret 数据加密存储:Secret 中的数据是 base64 编码并存储在 Etcd 中,Etcd 支持对保存的数据进行加密,所以 Secret 数据是加密存储的。
- Secret 只有在明确被引用时才会被传播到节点上:Secret 不会被默认传播到所有节点上。只有在 Pod 的规约中明确引用了某个 Secret,该 Secret 才会被传播到运行该 Pod 的节点上。
- Secret 传播到节点上的方式是通过临时文件:Secret 传播到节点上时,会被保存在一个临时目录中,并设置 0600 权限,只有 root 用户才能读取。Pod 要使用该 Secret,需要通过 Volume 方式挂载该临时文件。
- 每次 Secret 被使用时,其被挂载的临时文件名称都是随机生成的:这可以避免多个 Pod 共享一个 Secret 文件,增加了安全性。
- 节点上的临时 Secret 文件在Pod 被删除后也会被删除:这可以避免 Secret 数据遗留在节点上。
Secret 的工作流程:
- 创建一个 Secret 对象,将敏感数据 base64 编码后存储在数据字段中。
- 在 Pod 的 Volume 中引用该 Secret。
- 当调度 Pod 到节点上时,kubelet 会获取 Pod 使用到的 Secret 对象。
- kubelet 将 Secret 数据随机写入一个临时文件,并设置 0600 权限。
- kubelet 将临时文件作为 Volume 挂载到 Pod 中。
- Pod 中的容器可以读取挂载的 Secret Volume 以获取敏感数据。
- Pod 删除后,临时 Secret 文件也同时被删除。
示例:
yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
- 创建一个 Secret 对象,data 字段编码了 username 和 password。
- Pod 规约引用了该 Secret,将其作为 Volume 挂载。
- Pod 调度到节点后,kubelet 获取 mysecret Secret 对象。
- kubelet 将 Secret 数据写入一个随机文件名的临时文件,设置 0600 权限。
- 将临时文件作为 Volume 挂载到 Pod 的 /etc/foo 路径。
- Pod 里的容器可以读取 /etc/foo 路径获取 username 和 password。
- Pod 删除后,临时 Secret 文件也被 kubelet 删除。
所以总结来说,Secret 的安全性主要来源于:
- 数据加密存储
- 只有被引用时才传播到节点
- 以临时文件形式挂载,随机文件名,0606权限
- 随Pod一起删除
- 需要挂载才能被Pod使用