前言

Secret 可以用来保存密码、密钥等敏感信息,避免密钥直接放在 Pod 的YAML定义文件或容器镜像中导致的泄露问题。

密钥使用 Base64 编码形式存储于 Secret 对象中,Pod 挂载后自动解码为明文。

更新历史

通过 kubectl 创建 Secret

创建用户名/密码文件

echo -n 'username' > ./username.txt
echo -n 'password' > ./password.txt

写入 Secret 对象中

# kubectl create secret generic db-info --from-file=./username.txt --from-file=./password.txt
secret/db-info created

检查 Secret

# kubectl get secret
NAME                  TYPE                                  DATA   AGE
db-info               Opaque                                2      106s

查看刚写入的 db-info 的详细信息

# kubectl describe secret db-info
Name:         db-info
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
username.txt:  8 bytes
password.txt:  8 bytes

查看密钥的值

# kubectl get secret db-info -o yaml  

通过 YAML 创建 Secret

先将要保存的值进行 Base64 编码

# echo -n 'username' | base64 
dXNlcm5hbWU=
# echo -n 'password' | base64
cGFzc3dvcmQ=

#cat secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: base64编码
  password: base64编码

创建 secret

# kubectl apply -f secret.yaml 
secret/mysecret created

查看

# kubectl get secret
NAME                  TYPE                                  DATA   AGE
mysecret              Opaque                                2      2m5s

查看密钥的值

# kubectl get secret mysecret -o yaml  

编辑 secret

kubectl edit secrets mysecret

在 Pod 中使用 Secret

  1. 将 Secret 以卷的形式挂载到 Pod 中
  2. 卷中每一个文件名对应 Secret 中的一个 key 名称
  3. Secret 的值以 base64 解码后明文形式存储于卷文件中
  4. 支持实时动态更新
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

以上示例中,

将名为 mysecret 的 secret 对象映射为卷,卷名为 foo,

将名为 foo 的卷挂载到 Pod 中的路径 /etc/foo 下面,

mysecret 中username/password两个key,分别映射为文件。

多个 Pod 可以共享一个卷。

可以进入 Pod 中查看这两个文件内容

# kubectl exec -it mypod -- ls /etc/foo/
password  username

# kubectl exec -it mypod -- cat /etc/foo/username
admin

# kubectl exec -it mypod -- cat /etc/foo/password
password

结束语

Secret 对象将重要性高的秘钥和 Pod 进行了解耦处理。

它有如下特点:

  1. Secret 对象需先于引用它的 Pod 创建。
  2. Secret 对象和引用它的 Pod 必须位于同一命名空间。
  3. Secret 对象单个大小限制为 1M。
  4. Secret 对象中数据以纯文本的方式存储在 etcd 中。
  5. 除了以卷形式挂载外,还可以环境变量形式用于 Pod 中。
  6. 使用环境变量形式的问题是,secret无法动态实时更新。

官方安全建议:

  1. 管理员应该为集群数据开启静态加密(v1.13 以上版本)。
  2. 管理员应该限制只有 admin 用户能访问 etcd。
  3. API 服务器中的 Secret 数据位于 etcd 使用的磁盘上;应该在不再使用时擦除/粉碎 etcd 使用的磁盘。
  4. 如果 etcd 运行在集群内,管理员应该确保 etcd 之间的通信使用 SSL/TLS 进行加密。
  5. secret 的YAML中包含的 base64 编码为可逆编码,不要将其加入代码库或公开。
  6. 防止应用程序读取 secret 中数据后写入日志导致泄露。
  7. 所有可以运行该 Pod 的用户均可读取到挂载卷中的 secret 值。
  8. 任何节点的 root 用户都可以通过模拟 kubelet 来读取 API 服务器中的任何 Secret。 仅向实际需要 Secret 的节点发送 Secret 数据才能限制节点的 root 账号漏洞的影响, 该功能还在计划中。

联系我

微信公众号:zuolinux_com

微信扫码关注