目录
一、Secret 概述
1.1 Secret 的使用
1.2 secret 可选参数有三种
1.3 Secret 类型
二、使用 Secret
2.1 以环境变量的方式使用 Secret
2.2 Pod 以数据卷的形式挂载 Secret
一、Secret 概述
Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 使用 Secret 意味着你不需要在应用程序代码中包含机密数据。
由于创建 Secret 可以独立于使用它们的 Pod, 因此在创建、查看和编辑 Pod 的工作流程中暴露 Secret(及其数据)的风险较小。 Kubernetes 和在集群中运行的应用程序也可以对 Secret 采取额外的预防措施, 例如避免将机密数据写入非易失性存储。
上一篇文章写的 ConfigMap 一般是用来存放明文数据的,如配置文件。但对于一些敏感数据,如密码、私钥等数据时,要用 secret 类型。
Secret 类似于 ConfigMap 但专门用于保存机密数据。Secret 解决了密码、token、秘钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec 中。Secret 可以以Volume 或者环境变量的方式使用。
1.1 Secret 的使用
要使用 secret,pod 需要引用 secret。Pod 可以用三种方式之一来使用 Secret:
- 作为挂载到一个或多个容器上的卷 中的文件。(常用)
- 作为容器的环境变量。(常用)
- 由 kubelet 在为 Pod 拉取镜像时使用。
Kubernetes 控制面也使用 Secret; 例如,引导令牌 Secret 是一种帮助自动化节点注册的机制。
secret 概述:Secret | Kubernetes
1.2 secret 可选参数有三种
- generic:通用类型,通常用于存储密码数据。
- tls:此类型仅用于存储私钥和证书。
- docker-registry:若要保存 docker 仓库的认证信息的话,就必须使用此种类型来创建。
1.3 Secret 类型
创建 Secret 时,你可以使用 Secret 资源的 type
字段,或者与其等价的 kubectl
命令行参数(如果有的话)为其设置类型。 Secret 类型有助于对 Secret 数据进行编程处理。
Kubernetes 提供若干种内置的类型,用于一些常见的使用场景。 针对这些类型,Kubernetes 所执行的合法性检查操作以及对其所实施的限制各不相同。
- Service Account:用于被 serviceaccount 引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。
- base64 编码格式的 Secret:用来存储密码、秘钥等。可以通过 base64 --decode 解码获得原始数据,因此安全性弱。
- kubernetes.io/dockerconfigjson:用来存储私有 docker registry 的认证信息。
Secret 的类型:Secret | Kubernetes
二、使用 Secret
Secret 可以以数据卷的形式挂载,也可以作为环境变量 暴露给 Pod 中的容器使用。Secret 也可用于系统中的其他部分,而不是一定要直接暴露给 Pod。 例如,Secret 也可以包含系统中其他部分在替你与外部系统交互时要使用的凭证数据。
Kubernetes 会检查 Secret 的卷数据源,确保所指定的对象引用确实指向类型为 Secret 的对象。因此,如果 Pod 依赖于某 Secret,该 Secret 必须先于 Pod 被创建。
如果 Secret 内容无法取回(可能因为 Secret 尚不存在或者临时性地出现 API 服务器网络连接问题),kubelet 会周期性地重试 Pod 运行操作。kubelet 也会为该 Pod 报告 Event 事件,给出读取 Secret 时遇到的问题细节。
2.1 以环境变量的方式使用 Secret
如果需要在 Pod 中以环境变量的形式使用 Secret:
- 创建 Secret(或者使用现有 Secret)。多个 Pod 可以引用同一个 Secret。
- 更改 Pod 定义,在要使用 Secret 键值的每个容器中添加与所使用的主键对应的环境变量。 读取 Secret 主键的环境变量应该在
env[].valueFrom.secretKeyRef
中填写 Secret 的名称和主键名称。 - 更改你的镜像或命令行,以便程序读取环境变量中保存的值。
# 把 mysql 的 root 用户的 password 创建成 secret
[root@k8s-master01 secret]# kubectl create secret generic mysql-password --from-literal=password=123456
secret/mysql-password created
[root@k8s-master01 secret]# kubectl get secrets
NAME TYPE DATA AGE
mysql-password Opaque 1 55s
[root@k8s-master01 secret]# kubectl describe secrets mysql-password
Name: mysql-password
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 6 bytes
# password 的值是加密的,但 secret 的加密是一种伪加密,它仅仅是将数据做了 base64 的编码。
# 创建 pod,引用 secret
[root@k8s-master01 secret]# vim pod-secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-secret
labels:
app: myapp
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
env:
- name: MYSQL_ROOT_PASSWORD # 它是 Pod 启动成功后,Pod 中容器的环境变量名.
valueFrom:
secretKeyRef:
name: mysql-password # 这是 secret 的对象名
key: password # 它是 secret 中的 key 名
[root@k8s-master01 secret]# kubectl apply -f pod-secret.yaml
[root@k8s-master01 secret]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod-secret 1/1 Running 0 2m2s
# 通过环境变量使用 Secret 值
[root@k8s-master01 secret]# kubectl exec -it pod-secret -- sh
/ # echo "$MYSQL_ROOT_PASSWORD"
123456
/ # printenv
MYSQL_ROOT_PASSWORD=123456
以环境变量的方式使用 Secret:Secret | Kubernetes
2.2 Pod 以数据卷的形式挂载 Secret
- 如果你希望在 Pod 中访问 Secret 内的数据,一种方式是让 Kubernetes 将 Secret 以 Pod 中一个或多个容器的文件系统中的文件的形式呈现出来。
要配置这种行为,你需要:
- 创建一个 Secret 或者使用已有的 Secret。多个 Pod 可以引用同一个 Secret。
- 更改 Pod 定义,在
.spec.volumes[]
下添加一个卷。根据需要为卷设置其名称, 并将.spec.volumes[].secret.secretName
字段设置为 Secret 对象的名称。 - 为每个需要该 Secret 的容器添加
.spec.containers[].volumeMounts[]
。 并将.spec.containers[].volumeMounts[].readOnly
设置为true
, 将.spec.containers[].volumeMounts[].mountPath
设置为希望 Secret 被放置的、目前尚未被使用的路径名。 - 更改你的镜像或命令行,以便程序读取所设置的目录下的文件。Secret 的
data
映射中的每个主键都成为mountPath
下面的文件名。
#1. 手动加密,基于 base64 加密
[root@k8s-master01 secret]# echo -n 'admin' | base64
YWRtaW4=
[root@k8s-master01 secret]# echo -n 'root123456' | base64
cm9vdDEyMzQ1Ng==
# 解密方法:
[root@k8s-master01 secret]# echo cm9vdDEyMzQ1Ng== | base64 -d
root123456
#2. 创建 secret 资源文件
[root@k8s-master01 secret]# vim secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4= # 根据实际情况填写
password: cm9vdDEyMzQ1Ng==
[root@k8s-master01 secret]# kubectl apply -f secret.yaml
secret/mysecret created
[root@k8s-master01 secret]# kubectl describe secrets mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 10 bytes
username: 5 bytes
#3. 创建 pod,将 Secret 挂载到 Volume 中
[root@k8s-master01 secret]# vim pod_secret_volume.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-secret-volume
spec:
containers:
- name: myapp
image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1
imagePullPolicy: IfNotPresent
volumeMounts:
- name: secret-volume
mountPath: /etc/secret
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: mysecret
[root@k8s-master01 secret]# kubectl apply -f pod_secret_volume.yaml
pod/pod-secret-volume created
[root@k8s-master01 secret]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod-secret 1/1 Running 0 24m
pod-secret-volume 1/1 Running 0 5s
# 使用来自卷中的 Secret 值
[root@k8s-master01 secret]# kubectl exec -it pod-secret-volume -c myapp -- sh
/ # cd /etc/secret/
/etc/secret # ls
password username
/etc/secret # cat password
root123456
/etc/secret # cat username
admin
# 由上可见,在 pod 中的 secret 信息实际已经被解密。
在 Pod 中以文件形式使用 Secret:Secret | Kubernetes