文章目录
一、Secret 概述
1.1、Secret 是什么?
Secret是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在Pod规约中或者镜像中。 使用Secret意味着你不需要在应用程序代码中包含机密数据。
由于创建Secret可以独立于使用它们的Pod, 因此在创建、查看和编辑Pod的工作流程中暴露 Secret(及其数据)的风险较小。 Kubernetes 和在集群中运行的应用程序也可以对 Secret 采取额外的预防措施, 例如避免将机密数据写入非易失性存储。
Secret 类似于ConfigMap但专门用于保存机密数据。
总结:对于一些敏感数据,如密码、私钥等数据时,要用secret类型。
1.2、Secret类型
创建Secret时,你可以使用Secret资源的type字段或者与其等价的kubectl命令行参数(如果有的话)为其设置类型。 Secret的type有助于对不同类型机密数据的编程处理。
Kubernetes提供若干种内置的类型,用于一些常见的使用场景。 针对这些类型,Kubernetes所执行的合法性检查操作以及对其所实施的限制各不相同。
通过为Secret对象的type字段设置一个非空的字符串值,你也可以定义并使用自己Secret类型。如果type值为空字符串,则被视为Opaque类型。 Kubernetes并不对类型的名称作任何限制。不过,如果你要使用内置类型之一, 则你必须满足为该类型所定义的所有要求。
二、创建Secret
2.1、通过命令行创建
如下图所示,secret 可选参数有三种
generic: 通用类型,通常用于存储密码数据。
tls:此类型仅用于存储私钥和证书。
docker-registry: 若要保存 docker 仓库的认证信息的话,就必须使用此种类型来创建。
如下图所示:
通过–from-literal可实现命令行创建secret如下图所示:
总结:使用–from-literal== 标签提供Secret 数据。 可以多次使用此标签,提供多个键值对。特殊字符(例如:$,\,*,= 和 !)需要进行转义,转义密码最简便的方法是用单引号括起来。如下所示:
kubectl create secret generic db-user-pass \
--from-literal=username=root \
--from-literal=password='S!B\*d$zDsb='
如上图所示,password 的值是加密的,但secret的加密是一种伪加密,它仅仅是将数据做base64的编码
解码Secret
[root@k8s-client-17 secret]# kubectl get secrets
NAME TYPE DATA AGE
default-token-7nx4h kubernetes.io/service-account-token 3 43d
mysql-secret Opaque 2 9m46s
nfs-client-provisioner-token-q2x5d kubernetes.io/service-account-token 3 10d
[root@k8s-client-17 secret]# kubectl get secrets mysql-secret -o jsonpath='{.data}'
{"mysql_passwd":"MTIzNDU2","mysql_user":"cm9vdA=="}[root@k8s-client-17 secret]# echo 'cm9vdA==' | base64 -d
root[root@k8s-client-17 secret]# echo 'MTIzNDU2' | base64 -d
123456[root@k8s-client-17 secret]#
2.2、通过文件创建
通过----from-file可实现文件创建secret如下图所示:
总结:不需要对文件中包含的密码字符串中的特殊字符进行转义。
如上图所示,password和username的值是加密的,但secret的加密是一种伪加密,它仅仅是将数据做base64的编码
解码Secret
[root@k8s-client-17 secret]# kubectl get secrets
NAME TYPE DATA AGE
db-user-pass Opaque 2 6m9s
default-token-7nx4h kubernetes.io/service-account-token 3 43d
mysql-secret Opaque 2 25m
nfs-client-provisioner-token-q2x5d kubernetes.io/service-account-token 3 11d
[root@k8s-client-17 secret]# kubectl get secrets db-user-pass -o jsonpath='{.data}'
{"password.txt":"MTIzNDU2","username.txt":"cm9vdA=="}[root@k8s-client-17 secret]# echo 'cm9vdA==' | base64 -d
root[root@k8s-client-17 secret]# echo 'MTIzNDU2' | base64 -d
123456[root@k8s-client-17 secret]#
2.3、通过YAML配置文件
字段详解
[root@k8s-client-17 secret]# kubectl explain secret
KIND: Secret
VERSION: v1
DESCRIPTION:
Secret holds secret data of a certain type. The total bytes of the values
in the Data field must be less than MaxSecretSize bytes.
FIELDS:
apiVersion <string>
data <map[string]string> #"key:value" 格式的数据、通产格式敏感信息、数据格式需要是以Base64格式编码的字符串、因此需要用户实现完成编码
immutable <boolean>
kind <string>
metadata <Object>
stringData <map[string]string> #以明文格式(非Base64编码)定义的"key:value" 数据;无须用户实现对数据进行Base64编码
type <string>
一般数据加密使用base64编码,所以可以先使用base64编码对用户名和密码进行加密:
[root@k8s-client-17 secret]# echo -n 'admin' | base64
YWRtaW4=
[root@k8s-client-17 secret]# echo -n 'root' | base64
cm9vdA==
2.3.1、data
编写一个Secret配置文件,如下所示:
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
data: #data字段以key/value的方式存储base64编码的任意数据,key必须由字母、数字、-,_ 或 . 组成
username: cm9vdA== #username是key
password: MTIzNDU2 #password是key
type: Opaque #内置类型,用户定义的任意数据
如下图所示,password和username的值是加密的,但secret的加密是一种伪加密,它仅仅是将数据做base64的编码
解码Secret
[root@k8s-client-17 secret]# kubectl get secrets
NAME TYPE DATA AGE
db-mysql-secret Opaque 2 2m56s
db-user-pass Opaque 2 54m
default-token-7nx4h kubernetes.io/service-account-token 3 43d
mysql-secret Opaque 2 73m
nfs-client-provisioner-token-q2x5d kubernetes.io/service-account-token 3 11d
[root@k8s-client-17 secret]# kubectl get secrets db-mysql-secret -o jsonpath='{.data}'
{"password.txt":"MTIzNDU2","username.txt":"cm9vdA=="}[root@k8s-client-17 secret]# echo 'cm9vdA==' | base64 -d
root[root@k8s-client-17 secret]# echo 'MTIzNDU2' | base64 -d
123456[root@k8s-client-17 secret]#
2.3.2、stringData
方式一:
编写一个Secret配置文件,如下所示:
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
stringData: #stringData字段提供了明文格式的键值数据,从而免去了事先进行手动编码的麻烦
username: 'root'
password: '123456'
type: Opaque #内置类型,用户定义的任意数据
其使用stringData提供了明文格式的键值数据、从而免去了事先进行手动编码的麻烦,如下图所示:
总结:以明文格式(非Base64编码)定义的"key:value" 数据;无须用户实现对数据进行Base64编码,而是在创建为Secret对象时自动进行编码并保存于data字段中stringData字段中的明文不会被API Servers输出。
secret解码
[root@k8s-client-17 secret]# kubectl get secrets db-mysql-secret -o jsonpath='{.data}'
{"password":"MTIzNDU2","username":"cm9vdA=="}[root@k8s-client-17 secret]# echo 'cm9vdA==' | base64 -d
root[root@k8s-client-17 secret]# echo 'MTIzNDU2' | base64 -d
方式二:
编写一个Secret配置文件,如下所示:
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
stringData: #stringData字段提供了明文格式的键值数据,从而免去了事先进行手动编码的麻烦
config.yaml: |
username: 'root'
password: '123456'
type: Opaque #内置类型,用户定义的任意数据
如下图所示:
总结:命令kubectl get 和kubectl describe默认不显示Secret的内容。这是为了防止Secret意外地暴露给旁观者或者保存在终端日志中。
secret解码
[root@k8s-client-17 secret]# kubectl get secrets db-mysql-secret -o jsonpath='{.data}'
{"config.yaml":"dXNlcm5hbWU6ICdyb290JwpwYXNzd29yZDogJzEyMzQ1NicK"}[root@k8s-client-17 secret]# echo 'dXNlcm5hbWU6ICdyb290JwpwYXNzd29yZDogJzEyMzQ1NicK' | base64 -d
username: 'root'
password: '123456'
三、使用Secret
3.1、通过环境变量使用
方法一:使用valueFrom、secretKeyRef、name、key指定要用的key。
---
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
data: #data字段以key/value的方式存储base64编码的任意数据,key必须由字母、数字、-,_ 或 . 组成
username: cm9vdA== #username是key
password: MTIzNDU2 #password是key
type: Opaque #内置类型,用户定义的任意数据
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
env:
- name: USER_NAME #声明环境变量USER_NAME
valueFrom:
secretKeyRef:
name: db-mysql-secret #secretKeyRef中的name与上面创建的secret的name必须保持一致,则secret中的配置才能被pod引用
key: username #key是上线创建Secret中的username
- name: PASS_WORD #声明环境变量PASS_WORD
valueFrom:
secretKeyRef:
name: db-mysql-secret #secretKeyRef中的name与上面创建的secret的name必须保持一致,则secret中的配置才能被pod引用
key: password #key是上线创建Secret中的password
进入nginx容器查看定义的变量,如下图所示:
方法二:通过envFrom、secretRef、name使得configmap中的所有key/value对都自动变成环境变量
---
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
data: #data字段以key/value的方式存储base64编码的任意数据,key必须由字母、数字、-,_ 或 . 组成
username: cm9vdA== #username是key
password: MTIzNDU2 #password是key
type: Opaque #内置类型,用户定义的任意数据
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
envFrom:
- secretRef: #secretKeyRef中的name与上面创建的secret的name必须保持一致,则secret中的配置才能被pod引用
name: db-mysql-secret
进入nginx容器查看定义的变量,如下图所示:
3.2、作为volume挂载使用
---
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
data: #data字段以key/value的方式存储base64编码的任意数据,key必须由字母、数字、-,_ 或 . 组成
username: cm9vdA== #username是key
password: MTIzNDU2 #password是key
type: Opaque #内置类型,用户定义的任意数据
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: foo #需与下面定义的存储卷名称保持一致
mountPath: /etc/foo #容器里挂载目录
readOnly: true
volumes:
- name: foo #基于secret创建存储卷
secret:
secretName: db-mysql-secret #secretName的值与上面创建的secret的name必须保持一致,则secret中的配置才能被pod引用
进入nginx容器查看定义的变量,如下图所示:
四、Secret配置更新
1、使用该Secret挂载的env不会同步更新
[root@k8s-client-17 pod1]# echo -n 'admin' | base64
YWRtaW4=
[root@k8s-client-17 pod1]# echo -n '123789' | base64
MTIzNzg5
[root@k8s-client-17 pod1]# echo -n 'root' | base64
cm9vdA==
[root@k8s-client-17 pod1]# echo -n '123456' | base64
MTIzNDU2
说明:修改Secret中的变量,如下所示
修改前
---
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
data: #data字段以key/value的方式存储base64编码的任意数据,key必须由字母、数字、-,_ 或 . 组成
username: cm9vdA== #username是key
password: MTIzNDU2 #password是key
type: Opaque #内置类型,用户定义的任意数据
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
envFrom:
- secretRef: #secretKeyRef中的name与上面创建的secret的name必须保持一致,则secret中的配置才能被pod引用
name: db-mysql-secret
修改后
---
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
data: #data字段以key/value的方式存储base64编码的任意数据,key必须由字母、数字、-,_ 或 . 组成
username: YWRtaW4= #username是key
password: MTIzNzg5 #password是key
#username: cm9vdA== #username是key
#password: MTIzNDU2 #password是key
type: Opaque #内置类型,用户定义的任意数据
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
envFrom:
- secretRef: #secretKeyRef中的name与上面创建的secret的name必须保持一致,则secret中的配置才能被pod引用
name: db-mysql-secret
进入容器nginx,查看变量没有发生变化,如下图所示
2、使用该secret挂载的Volume 中的数据需要一段时间才能同步更新。
说明:修改Secret中的变量,如下所示
修改前
---
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
data: #data字段以key/value的方式存储base64编码的任意数据,key必须由字母、数字、-,_ 或 . 组成
username: cm9vdA== #username是key
password: MTIzNDU2 #password是key
type: Opaque #内置类型,用户定义的任意数据
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: foo #需与下面定义的存储卷名称保持一致
mountPath: /etc/foo #容器里挂载目录
readOnly: true
volumes:
- name: foo #基于secret创建存储卷
secret:
secretName: db-mysql-secret #secretName的值与上面创建的secret的name必须保持一致,则secret中的配置才能被pod引用
修改后
---
apiVersion: v1
kind: Secret
metadata:
name: db-mysql-secret
data: #data字段以key/value的方式存储base64编码的任意数据,key必须由字母、数字、-,_ 或 . 组成
#username: cm9vdA== #username是key
#password: MTIzNDU2 #password是key
username: YWRtaW4= #username是key
password: MTIzNzg5 #password是key
type: Opaque #内置类型,用户定义的任意数据
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: foo #需与下面定义的存储卷名称保持一致
mountPath: /etc/foo #容器里挂载目录
readOnly: true
volumes:
- name: foo #基于secret创建存储卷
secret:
secretName: db-mysql-secret #secretName的值与上面创建的secret的name必须保持一致,则secret中的配置才能被pod引用
说明:修改secret中的变量后,重新apply资源清单文件
[root@k8s-client-17 pod1]# kubectl apply -f pod2.yaml
secret/db-mysql-secret configured
pod/nginx configured
进入容器nginx,等待一段时间后,查看变量已经发生变化,username的值由之前的root变成了admin,password的值由之前的123456变成了123789,如下图所示:
总结:整理不易,如果对你有帮助,可否点赞关注一下?
更多详细内容请参考:企业级K8s集群运维实战