Kubernetes 中的 Secret 是如何保证安全的?

在 Kubernetes 中,Secret 是一种资源对象,用于存储敏感信息,如密码、OAuth 令牌和 SSH 密钥。Secret 可以用来向 Pod 传递敏感信息,而无需明文在 Pod 规约中暴露它们。

Kubernetes 如何保证 Secret 的安全?主要有以下几点:

  1. Secret 数据加密存储:Secret 中的数据是 base64 编码并存储在 Etcd 中,Etcd 支持对保存的数据进行加密,所以 Secret 数据是加密存储的。
  2. Secret 只有在明确被引用时才会被传播到节点上:Secret 不会被默认传播到所有节点上。只有在 Pod 的规约中明确引用了某个 Secret,该 Secret 才会被传播到运行该 Pod 的节点上。
  3. Secret 传播到节点上的方式是通过临时文件:Secret 传播到节点上时,会被保存在一个临时目录中,并设置 0600 权限,只有 root 用户才能读取。Pod 要使用该 Secret,需要通过 Volume 方式挂载该临时文件。
  4. 每次 Secret 被使用时,其被挂载的临时文件名称都是随机生成的:这可以避免多个 Pod 共享一个 Secret 文件,增加了安全性。
  5. 节点上的临时 Secret 文件在Pod 被删除后也会被删除:这可以避免 Secret 数据遗留在节点上。

Secret 的工作流程:

  1. 创建一个 Secret 对象,将敏感数据 base64 编码后存储在数据字段中。
  2. 在 Pod 的 Volume 中引用该 Secret。
  3. 当调度 Pod 到节点上时,kubelet 会获取 Pod 使用到的 Secret 对象。
  4. kubelet 将 Secret 数据随机写入一个临时文件,并设置 0600 权限。
  5. kubelet 将临时文件作为 Volume 挂载到 Pod 中。
  6. Pod 中的容器可以读取挂载的 Secret Volume 以获取敏感数据。
  7. 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
  1. 创建一个 Secret 对象,data 字段编码了 username 和 password。
  2. Pod 规约引用了该 Secret,将其作为 Volume 挂载。
  3. Pod 调度到节点后,kubelet 获取 mysecret Secret 对象。
  4. kubelet 将 Secret 数据写入一个随机文件名的临时文件,设置 0600 权限。
  5. 将临时文件作为 Volume 挂载到 Pod 的 /etc/foo 路径。
  6. Pod 里的容器可以读取 /etc/foo 路径获取 username 和 password。
  7. Pod 删除后,临时 Secret 文件也被 kubelet 删除。

所以总结来说,Secret 的安全性主要来源于:

  1. 数据加密存储
  2. 只有被引用时才传播到节点
  3. 以临时文件形式挂载,随机文件名,0606权限
  4. 随Pod一起删除
  5. 需要挂载才能被Pod使用