6.5 Secret私密凭据
Secret的主要作用是保管私密数据,比如密码、OAuth Tokens、SSH Keys 等信息。将这些私密信息放在Secret对象中比直接放在Pod或Docker Image中更安全,也便便于使用和分发。
secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: dmFsdWUtMg0K
username: dmFsdWUtMQ0K
kubectl create -f secrets.yaml
例子中,data域的各子域的值必须为 BASE64 编码值,其中 password 域和 username 域 BASE64 编码值分别为 :value-1 和 value-2
一旦Secret被创建,就可以通过下面三种方式使用它。
- 在创建Pod时,通过为Pod指定ServiceAccount来自动使用该Secret。
- 通过挂载该Secret 到 Pod 来使用它。
- 在Docker镜像下载时使用,通过指定的Pod的spc.ImagePullSecrets 来引用它。
第1种使用方式主要用在API Server 鉴权方面,之前提到过。
第2种使用方式:将一个Secret通过挂载的方式,添加到Pod的Volume 中:
apiVersion: v1
kind: Pod
metadata:
name: mypod
namespace: myns
spec:
containers:
- name: mycontainers
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret

第3种使用方式的使用流程如下。
1、执行login 命令,登录私有Registry
docker login localhost:5000
输入用户名和密码,如果是第一次登录系统,则会创建新用户,相关信息被会写入~/.dockercfg 文件中。
2、用 BASE64 编码dockercfg 的内容
cat ~/.dockercfg | base64
3、将上步命令的输出结果作为secret的data.dockercfg域的内容,由此来创建一个Secret:
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
data:
.dockercfg: ewoJImF1dGhzIjogewoJCSJyZWcuYWxpYmFiYS5vcmciOiB7CgkJCSJhdXRoIjogIlpHOWphMlZ5T2tGc2FXSmhZbUVsTVRZNE9BPT0iCgkJfQoJfSwKCSJIdHRwSGVhZGVycyI6IHsKCQkiVXNlci1BZ2VudCI6ICJEb2NrZXItQ2xpZW50LzE5LjAzLjEgKGxpbnV4KSIKCX0KfQ0K
type: kubernetes.io/dockercfg
kubectl create -f image-pull-secret.yaml
4、创建Pod 时引用该Secret:
vpiVersion: v1
kind: Pod
meatadata:
name: mypod2
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey

每个单独的Secret大小不能超过1MB,Kubernetes 不鼓励建大的Secret,因为如果使用大的Secret,则将大量占用API Server 和 kubelet 的内存。当然,创建许多小的Secret也能耗尽API Server 和 kubelet 的内存。
在使用Mount 方式挂载Secret 时,Container 中Secret的data 域的各个域的Key 值作为目录中的文件,Value 值被 BASE64 编码后存储在相应的文件中。在前面的例子中创建的Secret ,被挂载到一个叫作mycontainer的Container 中,在该Container中可通过相应的查询命令查看所生成的文件和文件中的内容。如下所示:
root@mypod:/data# ls /etc/foo/
password username
root@mypod:/data# cat /etc/foo/username
value-1
root@mypod:/data# cat /etc/foo/password
value-2
root@mypod:/data#
例子可以看出,我们可以通过Secret保管其他系统的敏感信息(比如数据库的用户名和密码),并以Mount的方式将Secret挂载到Container中,然后通过访问目录中文件的方式获取敏感信息。当Pod 被API Server创建时,API Server 不会校验该Pod引用的Secret是否存在。一旦这个Pod 被调度,则kubelet 将试着获取Secret的值。如果Secret不存在或者暂时无法连接API Server ,则kubelet 按一定的时间间隔定期重试获取该Secret ,并发送一个Event 来解释Pod没有启动的原因。一旦Secret被Pod获取,则kubelet 将创建并挂载包含Secret的Volume。只有所有的Volume都挂载成功,Pod中的Container都会被启动。在kubelet 启动Pod中的Container后,Container 中的Secret相关的Volume将不会被改变,即使Secret本身被修改,为了使用更新后的Secret,必须删除旧Pod,并重新创建一个新Pod。