《Kubernetes知识篇:配置管理中心Secret》



一、Secret 概述

1.1、Secret 是什么?

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集群运维实战

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东城绝神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值