目录
一、Secret概述
二、Secret 三种类型
2.1、Opaque
2..2、kubernetes.io/dockerconfigjson
2.3、kubernetes.io/service-account-token
三、Secret创建
3.1、命令行方式创建 Secret
3.2、yaml方式创建 Secret
四、Secret解码
五、Secret使用
5.1、将 Secret 挂载到 Volume 中
5.2、将 Secret 设置为环境变量
5.3、通过volume挂载和设置为环境变量的区别
六、Secret删除
一、Secret概述
Secret 解决了密码、令牌、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec 中,它把 Pod 想要访问的加密数据存放到 Etcd 中,然后用户就可以通过在 Pod 的容器里挂载 Volume 的方式或者环境变量的方式访问到这些 Secret 里保存的信息。
二、Secret 三种类型
2.1、Opaque
使用 base64 编码存储信息,手动加密,用来存储密码、密钥等,可以通过 base64 --decode 解码获得原始数据,因此安全性弱。
# base64编码
$ echo "root" | base64
cm9vdAo=# base64解码
$ echo "cm9vdAo=" | base64 --decode
root
2..2、kubernetes.io/dockerconfigjson
用于存储私有docker registry认证的Secret。
下面是一个示例:
# 使用kubectl create secret命令创建Secret,指定docker私有仓库地址,用户名、密码等
kubectl create secret docker-registry habor-registry-secret --docker-server=xxx --docker-username=xxx --docker-password=xxx
如果我们需要拉取私有仓库中的docker镜像的话,在Pod的资源清单中就需要引用前面定义好的habor-registry-secret这个Secret,例如:
apiVersion: v1
kind: Pod
metadata:name: order-service
spec:containers:- name: order-serviceimage: 192.168.1.33:5000/order-service:v1.2imagePullSecrets:- name: habor-registry-secret
2.3、kubernetes.io/service-account-token
用于被 serviceaccount 引用,serviceaccout 创建时 Kubernetes 会默认创建对应的 Secret。Pod 如果使用了 serviceaccount,对应的 Secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。
下面是一个示例:
$ kubectl run nginx --image nginx
pod/nginx created$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 12s# 进入nginx容器
$ kubectl exec -it nginx bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.root@nginx:/# ls -l /run/secrets/kubernetes.io/serviceaccount
ca.crt namespace token
三、Secret创建
Secret的创建一般有两种方式,一种是通过命令行方式【 kubectl create secret命令】,另外一种是使用yaml资源清单方式创建。
3.1、命令行方式创建 Secret
首先需要准备Secret数据的来源,然后使用 kubectl create secret 命令将这些文件打包成一个 Secret 并在 API 服务器上创建Secret对象,生成Secret后会自动加密,而非明文存储。
假如某个Pod要访问数据库,需要用户名密码,分别存放在2个文件中:username.txt,password.txt。
# -n参数确保生成的txt文件在文本末尾不包含额外的换行符,因为当 kubectl 读取文件并将内容编码为 base64 字符串时,多余的换行符也会被编码。
$ echo -n "admin" > ./username.txt
$ echo -n "123456" > ./password.txt# 使用 kubectl create secret 命令将这些文件打包成一个 Secret 并在 API 服务器上创建Secret对象
$ kubectl create secret generic db-account-secret --from-file=./username.txt --from-file=./password.txt
secret/db-account-secret created# 查看secret,为了防止Secret被意外暴露,默认不显示Secret的内容
$ kubectl get secret
NAME TYPE DATA AGE
db-account-secret Opaque 2 8s# 通过yaml查看secret详细信息
$ kubectl get secret db-account-secret -o yaml
apiVersion: v1
data: # secret中的key默认就是txt文件名称,可以看到这里是password.txt、password.txtpassword.txt: MTIzNDU2 #secret保存的是base64加密后的数据: 123456password.txt: YWRtaW4= #secret保存的是base64加密后的数据: admin
kind: Secret
metadata:creationTimestamp: "2023-01-05T02:21:18Z"name: db-account-secretnamespace: defaultresourceVersion: "3212"uid: a11caa2c-e7d7-4234-a20a-453cc05d565b
type: Opaque# base64加密之后的数据
$ echo -n 'admin' | base64
YWRtaW4=
$ echo -n '123456' | base64
MTIzNDU2
注意,Secret中的key默认就是文件名称,可以看到这里是password.txt、password.txt。可以使用 --from-file=[key=]source 来设置密钥名称,例如:kubectl create secret generic db-account-secret --from-file=username=./username.txt --from-file=password=./password.txt。
我们还可以使用 --from-literal=<key>=<value> 标签提供 Secret 数据。 可以多次使用 --from-literal标签,提供多个键值对。 请注意,特殊字符(例如:$,\,*,= 和 !)由shell 解释执行,而且需要转义,最简便的方法是用单引号括起来。 比如,如果你的密码是$#123456=,可以像下面一样执行命令:
$ kubectl create secret generic db-secret-test --from-literal=username=admin --from-literal=password='$#123456='
secret/db-secret-test created
3.2、yaml方式创建 Secret
因为Secret保存的是base64加密后的数据,所以使用yaml方式创建Secret的时候,我们需要准备好base64加密之后的数据,然后放到Secret的资源清单中。
# base64加密之后的数据
$ echo -n 'admin' | base64
YWRtaW4=
$ echo -n '123456' | base64
MTIzNDU2
创建Secret资源清单文件: vim custom-db-account-secret.yaml
apiVersion: v1
kind: Secret
metadata:name: custom-db-account-secret
type: Opaque
data:username: YWRtaW4=password: MTIzNDU2
创建Secret:
$ kubectl apply -f custom-db-account-secret.yaml
secret/custom-db-account-secret created$ kubectl get secret/custom-db-account-secret
NAME TYPE DATA AGE
custom-db-account-secret Opaque 2 22s# 查看Secret描述信息,为了防止Secret被意外暴露,默认不显示Secret的内容
$ kubectl describe secret/custom-db-account-secret
Name: custom-db-account-secret
Namespace: default
Labels: <none>
Annotations: <none>Type: OpaqueData
====
password: 6 bytes
username: 5 bytes
四、Secret解码
为了防止Secret被意外暴露,默认不显示Secret的内容,要查看我们创建的 Secret 的内容,可以通过下面的方式。
$ kubectl get secret custom-db-account-secret -o jsonpath=‘{.data}’
‘{"password":"MTIzNDU2","username":"YWRtaW4="}’$ echo "YWRtaW4=" | base64 -d
admin$ echo "MTIzNDU2" | base64 -d
123456
五、Secret使用
Secret使用有两种方式,一种是将Secret挂载到存储卷volume中,另外一种是将Secret中的值,设置为Pod中的环境变量。
5.1、将 Secret 挂载到 Volume 中
创建Pod资源清单文件: vim secret-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:containers:- name: nginximage: nginxvolumeMounts:- name: secret-volumemountPath: "/etc/foo" # 将secret的数据挂载到pod容器中/etc/foo目录下readOnly: truevolumes:- name: secret-volumesecret: # volume存储卷的类型为secretsecretName: custom-db-account-secret # 引用前面定义好的secret的名称:custom-db-account-secret
创建Pod,然后进入Pod中查看custom-db-account-secret中的数据是否挂载进去。
$ kubectl apply -f secret-pod.yaml
pod/nginx created$ kubectl get pod/nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 27s 192.168.1.3 node01 <none> <none>$ kubectl exec -it nginx sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# cd /etc/foo/
# ls
password username
# cat username
admin
# cat password
123456
可以看到,custom-db-account-secret中我们定义的username、password已经成功挂载到pod容器中/etc/foo目录下,并且数据也是解密之后的数据。
5.2、将 Secret 设置为环境变量
创建Pod资源清单文件: vim secret-env-pod.yaml
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:containers:- name: nginximage: nginxenv: - name: DB_USERNAME # 声明环境变量DB_USERNAMEvalueFrom:secretKeyRef: # 指定数据来源是custom-db-account-secret这个secret的username字段name: custom-db-account-secretkey: username - name: DB_PASSWORD # 声明环境变量DB_PASSWORDvalueFrom:secretKeyRef: # 指定数据来源是custom-db-account-secret这个secret的password字段name: custom-db-account-secretkey: passwordrestartPolicy: Never
创建Pod,并进入Pod查看环境变量的值。
$ kubectl apply -f secret-env-pod.yaml
pod/nginx created$ kubectl get pod/nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 14s 192.168.1.4 node01 <none> <none>$ kubectl exec nginx -it sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
# env | grep -E "USERNAME|PASSWORD"
DB_USERNAME=admin
DB_PASSWORD=123456
# echo $DB_USERNAME
admin
# echo $DB_PASSWORD
123456
如上可以看到,进入Pod之后,已经成功将custom-db-account-secret这个secret的username、password,对应生成了$DB_USERNAME、$DB_PASSWORD两个环境了,这样在Pod中就可以使用这两个环境变量了。
5.3、通过volume挂载和设置为环境变量的区别
通过Volume挂载到容器内部时,当该Secret的值发生变化时,容器内部具备自动更新的能力,但是通过环境变量设置到容器内部该值不具备自动更新的能力。所以一般推荐使用Volume挂载的方式使用Secret。
六、Secret删除
使用【kubectl delete secret xxx】命令即可,xxx指定Secret的名称。
$ kubectl get secret
NAME TYPE DATA AGE
custom-db-account-secret Opaque 2 44m
db-account-secret Opaque 2 54m
db-secret-test Opaque 2 12m$ kubectl delete secret db-secret-test
secret "db-secret-test" deleted$ kubectl get secret
NAME TYPE DATA AGE
custom-db-account-secret Opaque 2 44m
db-account-secret Opaque 2 55m