Secret主要作用是保管私密数据,比如密码、OAuth Tokens、SSH Keys等信息。将这些私密信息放在Secret对象中比直接放在Pod或Docker Image中要更安全,也便于使用和分发。
下面的例子用于创建一个Secret,命名为secret.yaml
:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: dmfsdWUtMg0k
username: dmfsdWUtMg0k
创建:
kubectl create -f secret.yaml
在上面的data域中的各子域的值必须为BASE64编码值,其中password域和username域BASE64编码前的值分别为value-1
和value-2
。
一旦Secret被创建,可以通过以下三个方式使用它:
- 在创建Pod时,通过为Pod指定
ServiceAccount
来自动使用该Seret; - 通过挂载该Secret到Pod来使用它;
- Docker镜像下载时使用,通过指定Pod的spec.ImagePullSecrets来引用它;
第一种方式主要用在 API Server 鉴权方面;下面的例子展示了第二种使用方式:将一个Secret通过挂载的方式添加到Pod的Volume中。
apiVersion:v1
kind:Pod
metadata:
name:mypod
namespace:myns
spec:
containers:
- name:mycontainer
image:redis
volumeMounts:
- name:foo
mountPath:“/etc/foo”
readOnly:true
volumes:
- name:foo
secret:
secretName:mysecret
第三种使用方式的使用流程如下:
(1)执行login命令,登录私有Registry
#docker login localhost:5000(输入账户及密码,如果是第1次登录则会创建新用户,并把相关信息写入~/.dockercfg文件中)
(2)用BASE64编码dockercfg的内容
#cat ~/.dockercfg|base64
(3)将上一步命令的输出结果作为Secret的“data.dockercfg”域的内容,由此来创建一个Secret
image-pull-secret.yaml:
apiVersion:v1
kind:Secret
metadata:
name:myregistrykey
data:
.dockercfg:oiu09joiu09ujlih8hkjh98...
type:kubernetes.io/dockercfg
# kubectl create -f image-pull-secret.yaml
(4)在创建Pod的时候引用该Secret
pods.yaml
apiVersion:v1
kind:Pod
metadata:
name:mypod2
spec:
containers:
- name:foo
image:janedoe/awexomeapp:v1
imagePullSecrets:
- name:myregistrykey
# kubectl create -f pods.yaml
每个单独的Secret大小不能超过1M,Kubernetes不鼓励创建大尺寸的Secret,因为如果使用大尺寸的Secret,则将大量占用API Server和kubelet的内存。当然创建许多小的Secret也能耗尽API Server和kubelet的内存。
在使用Mount方式挂载Secret时,Container中Secret的“data”域的各个域的key值作为目录中的文件,Value值被BASE64编码后存储在相应的文件中。前面的例子中创建的Secret,被挂载到一个叫做mycontainer的container中。
在该container中可以通过命令查看所生产的文件和文件中的内容:
# ls /etc/foo
username
password
# cat /etc/foo/username
value-1
# cat /etc/foo/password
value-2
关于Secret的一些知识点:
我们可以通过Secret保管其他系统的敏感信息(比如数据库用户名和密码),并以Mount的方式将Secret挂载到Container中,然后通过访问目录中的文件的方式获取该敏感信息。
当Pod被API Server创建时,API Server不会校验该Pod引用的Secret是否存在。
一旦这个Pod被调度,则Kubelet将试着获取Secret的值。如果Secret不存在或暂时无法连接到API Server,则kubelet将按一定的时间间隔定期重试获取该Secret,并发送一个Event来解释Pod没有启动的原因。一旦Secret被Pod获取,则Kubelet将创建并Mount包含Secret的Volume。
只有所有的Volume被Mount后,Pod中的Container才会被启动。
在kubelet启动Pod中container后,Container中和Secret相关的Volume将不会被改变,即使Secret本身被修改了。
为了使用更新后的Secret,必须删除旧的Pod,并重新创建一个新的Pod,因此更新Secret的流程和部署一个新的Image是一样的。