Secret详解

Secret详解

shell 复制代码
secret用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。
 
 用户可以创建自己的secret,系统也会有自己的secret。
 Pod需要先引用才能使用某个secret

Pod使用secret方式:

ABAP 复制代码
作为volume的一个域被一个或多个容器挂载

內建的Secrets:

shell 复制代码
由ServiceAccount创建的API证书附加的秘钥k8s自动生成的用来访问apiserver的Secret,所有Pod会默认使用这个Secret与apiserver通信

创建自己的Secret:

apl 复制代码
方式1:使用kubectl create secret命令(命令行)
方式2:yaml文件创建Secret

实战

命令方式创建secret

假如某个Pod要访问数据库,需要用户名密码,分别存放在2个文件中:username.txt,password.txt

例子:

shell 复制代码
[root@kub-k8s-master ~]# echo -n 'admin' > ./username.txt
[root@kub-k8s-master ~]# echo -n "Cloud@2302" > password.txt

kubectl create secret指令将用户名密码写到secret中,并在apiserver创建Secret

shell 复制代码
[root@kub-k8s-master ~]# kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt

查看创建结果:

shell 复制代码
[root@kub-k8s-master ~]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
db-user-pass          Opaque                                2      54s
default-token-6svwp   kubernetes.io/service-account-token   3      4d11h

注: opaque:英[əʊˈpeɪk] 美[oʊˈpeɪk]  模糊
# Opaque类型的数据是一个map类型,要求value是base64编码格式

查看详细信息:

shell 复制代码
[root@kub-k8s-master ~]# kubectl describe secret db-user-pass
Name:         db-user-pass
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password.txt:  12 bytes
username.txt:  5 bytes

describe指令不会展示secret的实际内容,这是出于对数据的保护的考虑,如果想查看实际内容使用命令:

shell 复制代码
[root@kub-k8s-master ~]# kubectl get secret db-user-pass -o yaml

base64解码:

shell 复制代码
[root@kub-k8s-master ~]# echo Q2xvdWRAMjMwMQ==|base64 --decode
Cloud@2301
yaml方式创建Secret

假如某个Pod要访问数据库,需要用户名密码,现在我们分别设置这个用户名和密码

Secret 对象要求这些数据必须是经过 Base64 转码的,以免出现明文密码显示的安全隐患。

shell 复制代码
创建一个secret.yaml文件,内容用base64编码:明文显示容易被别人发现,这里先转码。

[root@kub-k8s-master ~]# echo -n 'admin' | base64
YWRtaW4=
[root@kub-k8s-master ~]# echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm

创建一个secret.yaml文件,内容用base64编码

shell 复制代码
[root@kub-k8s-master prome]# vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque  #模糊
data:
  username: YWRtaW4=
  password: MTIzNDU2

创建:

shell 复制代码
[root@kub-k8s-master prome]# kubectl apply -f secret.yml 
secret/mysecret created

解析Secret中内容,还是经过编码的---需要解码

shell 复制代码
查看secret
[root@kub-k8s-master ~]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-7vc82   kubernetes.io/service-account-token   3      30h
mysecret              Opaque                                2      6s

查看secret详细信息
[root@kub-k8s-master prome]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2019-10-21T03:07:56Z"
  name: mysecret
  namespace: default
  resourceVersion: "162855"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: 36bcd07d-92eb-4755-ac0a-a5843ed986dd
type: Opaque

手动base64解码方式:

shell 复制代码
[root@kub-k8s-master ~]# echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
使用Secret
shell 复制代码
secret可以作为数据卷挂载或者作为环境变量暴露给Pod中的容器使用,也可以被系统中的其他资源使用。

一个Pod中引用Secret的列子:

shell 复制代码
创建一个Secret,多个Pod可以引用同一个Secret

修改Pod的定义,在spec.volumes[]加一个volume,给这个volume起个名字,spec.volumes[].secret.secretName记录的是要引用的Secret名字
shell 复制代码
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: testredis
    image: daocloud.io/library/redis
    volumeMounts:    #挂载一个卷
    - name: foo     #这个名字需要与定义的卷的名字一致
      mountPath: "/etc/foo"  #挂载到容器里哪个目录下,随便写
      readOnly: true
  volumes:     #数据卷的定义
  - name: foo   #卷的名字这个名字自定义
    secret:    #卷是直接使用的secret。
      secretName: mysecret   #调用刚才定义的secret

或者:
---
apiVersion: v1
kind: Pod
metadata:
 name: mypod
spec:
 volumes:   #相当于是定义数据卷,得先定义数据卷,才能挂载
  - name: yongqi250
    secret:
     secretName: mysecret
 containers:
  - name: liqizhengaisi
    image: daocloud.io/library/nginx
    volumeMounts:
     - name: yongqi250
       mountPath: "/etc/yongqi"
       readOnly: true
      
创建:
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/
root@mypod:/etc/foo# ls
password  username
root@mypod:/etc/foo# cat password 
1f2d1e2e67df
ASN.1 复制代码
结果中看到,保存在 Etcd 里的用户名和密码信息,已经以文件的形式出现在了容器的 Volume 目录里。
而这个文件的名字,就是 kubectl create secret 指定的 Key,或者说是 Secret 对象的 data 字段指定的 Key。 
shell 复制代码
每一个被引用的Secret都要在spec.volumes中定义
 如果Pod中的多个容器都要引用这个Secret那么每一个容器定义中都要指定自己的volumeMounts,但是Pod定义中声明一次spec.volumes就好了。 

映射secret key到指定的路径

可以控制secret key被映射到容器内的路径,利用spec.volumes\[\].secret.items来修改被映射的具体路径

shell 复制代码
[root@kub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml 
pod "mypod" deleted
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
---
apiVersion: v1
kind: Pod
metadata:
 name: mypod
spec:
 containers:
 - name: testredis
   image: daocloud.io/library/redis
   volumeMounts:
   - name: foo
     mountPath: "/etc/foo"
     readOnly: true
 volumes:
 - name: foo
   secret:
     secretName: mysecret
     items:   #定义一个items
      - key: username   #将那个key重新定义到那个目录下
        path: my-group/my-username  #相对路径,相对于/etc/foo的路径
       
2.创建
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
3.从volume中读取secret的值
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash                         
root@mypod:/data# cd /etc/foo/my-group
root@mypod:/etc/foo/my-group# ls
my-username
root@mypod:/etc/foo/my-group# cat my-username 
admin
root@mypod:/etc/foo/my-group#

username被映射到了文件/etc/foo/my-group/my-username而不是/etc/foo/username,而password没有被使用,这种方式每个key的调用需要单独用key像username一样调用

被挂载的secret内容自动更新

也就是如果修改一个Secret的内容,那么挂载了该Secret的容器中也将会取到更新后的值,但是这个时间间隔是由kubelet的同步时间决定的。

shell 复制代码
1.设置base64加密
[root@kub-k8s-master prome]# echo qianfeng | base64
cWlhbmZlbmcK
2.将admin替换成qianfeng
[root@kub-k8s-master prome]# vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: cWlhbmZlbmcK   #修改为qianfeng的base64加密后的
  password: MWYyZDFlMmU2N2Rm
  
1.创建
[root@kub-k8s-master prome]# kubectl apply -f secret.yml 
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
secret/mysecret configured
2.连接pod容器
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/my-group
root@mypod:/etc/foo/my-group# ls
my-username
root@mypod:/etc/foo/my-group# cat my-username 
qianfeng

以环境变量的形式使用Secret(secret更新,pod中不会自动更新)

shell 复制代码
[root@kub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml 
pod "mypod" deleted
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: testredis
    image: daocloud.io/library/redis
    env:  #定义环境变量
     - name: SECRET_USERNAME   #创建新的环境变量名称
       valueFrom:
        secretKeyRef:     #调用的key是什么
         name: mysecret       #变量的值来自于mysecret
         key: username       #username里面的值

2.创建使用secret的pod容器
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
3.连接
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash 
root@mypod:/data# echo $SECRET_USERNAME   #打印一下定义的变量
qianfeng 

实战案例:

ini 复制代码
1.创建数据库用户的密码secret
[root@master test]# echo 'QianFeng@123!' | base64
UWlhbkZlbmdAMTIzIQ==
[root@master test]# cat secret.yml 
apiVersion: v1
kind: Secret
metadata:
 name: mysql-secret
type: Opaque
data:
 password: UWlhbkZlbmdAMTIzIQ==
 
[root@master test]# kubectl apply -f secret.yml

2.创建数据库并使用secret
[root@master test]# cat mysql.yaml 
---
apiVersion: v1
kind: Pod
metadata:
 name: my-mysql
spec:
 containers:
 - name: mysql
   image: daocloud.io/library/mysql:5.7
   ports:
    - containerPort: 3306
   env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
       secretKeyRef:
        name: mysql-secret
        key: password
[root@master test]# kubectl apply -f mysql.yaml
[root@master test]# kubectl get pod -o wide 
NAME       READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
my-mysql   1/1     Running   0          2m47s   10.244.2.13   node2   <none>           <none>

测试:
[root@master test]# mysql -uroot -p'QianFeng@123!' -h 10.244.2.13 -P3306

注意:

shell 复制代码
如果报错:上面这条命令会报错如下
# kubectl exec -it test-projected-volume /bin/sh
error: unable to upgrade connection: Forbidden (user=system:anonymous, verb=create, resource=nodes, subresource=proxy)

解决:绑定一个cluster-admin的权限
# kubectl create clusterrolebinding system:anonymous   --clusterrole=cluster-admin   --user=system:anonymous
clusterrolebinding.rbac.authorization.k8s.io/system:anonymous created
相关推荐
极验1 小时前
智能体时代的自动化对抗:Agent Bot 与隐匿技术共舞
运维·自动化
烈焰晴天1 小时前
Codex 桌面端如何链接Figma MCP 服务器拿到 Figma设计稿精准尺寸等结构化数据 来精准还原UI
服务器·ui·figma
Dlrb12111 小时前
Linux网络编程-网络基础概念(IP, UDP协议)
linux·服务器·网络·网络基础·端口号·ip协议·udp协议
shushangyun_1 小时前
汽车服务行业B2B平台+AI解决方案哪家专业:2026年最新测评
java·运维·网络·数据库·人工智能·汽车
施努卡机器视觉1 小时前
SNK施努卡转子自动化生产线:从铁芯上料到下线,精密装配方案
运维·自动化
小易撩挨踢2 小时前
[特殊字符] Linux 7.1 内核正式发布:距 7.0 仅 9 周,新 CPU/GPU/文件系统全面升级
linux·运维
vortex52 小时前
Linux进程权限继承研究:从setuid()到exec()与system()的行为差异
linux·服务器·系统安全·suid
信也科技布道师3 小时前
从Istio 503 NC 错误深入理解 Mesh 路由全链路原理
java·服务器·网络