前言:
kubernetes集群内的两种资源secret和configMap是比较类似的两种资源,但使用范围以及使用方法上又有所不同,因此,本文将两者合并到一起来讲。下面是关于两者的一些简单介绍。
Secret介绍
k8s secrets用于存储和管理一些敏感数据,比如密码,token,密钥等敏感信息。它把 Pod 想要访问的加密数据存放到 Etcd 中。然后用户就可以通过在 Pod 的容器里挂载 Volume 的方式或者环境变量的方式访问到这些 Secret 里保存的信息了,从名字上看,我们应该也能想到,有一些不太方便向外人展示的信息加密是secret的主要功能。
configMap介绍
ConfigMap是一种API对象,用来将非加密数据保存到键值对中。可以用作环境变量、命令行参数或者存储卷中的配置文件,从名字上看,我们也应该能想到,此类资源主要是做配置映射的,当然了,配置的一般内容是包括环境变量,命令行参数以及配置文件的形式这些的。
ConfigMap可以将环境变量配置信息和容器镜像解耦,便于应用配置的修改。如果需要存储加密信息时可以使用Secret对象。主要作用就是为了让镜像和配置文件解耦,以便实现镜像的可移植性和可复用性。
OK,以上所述讲的就一个意思,secret和configMap都是实现和pod交互作用。
secret的表现形式:
A,Secret有三种类型
- generic(通用的):保存密码数据等用它就可以Opaque:base64 编码格式的 Secret,用来存储密码、密钥等;但数据也可以通过base64 –decode解码得到原始数据,所有加密性很弱。在真正的生产环境中,你需要在 Kubernetes 中开启 Secret 的加密插件,增强数据的安全性。
命令行快速创建secret:
此secret有三个键值对,password1到3
kubectl create secret generic mysql-root-password --from-literal=password1=MyP@ss123 --from-literal=password2=123456 --from-literal=password3=456789--dry-run=client -o yaml>test-secret.yaml
文件清单形式:
apiVersion: v1 data: #1. data 字段用来存储 base64 编码的任意数据 password1: TXlQQHNzMTIz #base64编码之后的字符串 password2: MTIzNDU2 #base64编码之后的字符串 password3: NDU2Nzg5 #base64编码之后的字符串 stringData: #2. stringData 字段是为了方便,它允许 Secret 使用未编码的字符串 password4: qwerty kind: Secret metadata: name: mysql-root-password
通常此类secret是自定义的。
- tls:保存私钥和证书Service Account:用来访问Kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的 /run/secrets/kubernetes.io/serviceaccount 目录中。
例如,我的集群只是一个初始的集群,secret和sa集群认为是一样的,都是一样的,describe查看也是一样的(当然,这里的作用是传递token,与apiserver和etcd交互):
[root@k8s-master ~]# k get sa -A NAMESPACE NAME SECRETS AGE default default 1 3d kube-node-lease default 1 3d kube-public default 1 3d kube-system calico-kube-controllers 1 2d12h kube-system calico-node 1 2d12h kube-system coredns 1 2d20h kube-system default 1 3d kube-system metrics-server 1 2d13h [root@k8s-master ~]# k get secret -A NAMESPACE NAME TYPE DATA AGE default default-token-w5n59 kubernetes.io/service-account-token 3 3d kube-node-lease default-token-tnvkp kubernetes.io/service-account-token 3 3d kube-public default-token-gprb8 kubernetes.io/service-account-token 3 3d kube-system calico-kube-controllers-token-sstpp kubernetes.io/service-account-token 3 2d12h kube-system calico-node-token-6mx29 kubernetes.io/service-account-token 3 2d12h kube-system coredns-token-ff62s kubernetes.io/service-account-token 3 2d20h kube-system default-token-wrcjr kubernetes.io/service-account-token 3 3d kube-system metrics-server-token-k6szn kubernetes.io/service-account-token 3 2d13h
只是查看secret会有详细的值而已
[root@k8s-master ~]# k describe secret metrics-server-token-k6szn -n kube-system Name: metrics-server-token-k6szn Namespace: kube-system Labels: <none> Annotations: kubernetes.io/service-account.name: metrics-server kubernetes.io/service-account.uid: 689995bb-1f70-4a19-a02b-e491d8ffe8e4 Type: kubernetes.io/service-account-token Data ==== ca.crt: 1359 bytes namespace: 11 bytes token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjQtS3N6djBxZmotSFJtTUdFTzhQWFVlQmE3TnBzeTlKLVJjY05fYWxqRkkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJtZXRyaWNzLXNlcnZlci10b2tlbi1rNnN6biIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJtZXRyaWNzLXNlcnZlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjY4OTk5NWJiLTFmNzAtNGExOS1hMDJiLWU0OTFkOGZmZThlNCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTptZXRyaWNzLXNlcnZlciJ9.M-NA1Pab26QkAbsjWxCxB7aIgRkAbcVjmJSjEIOY-gpkvNKkJET4NsDVKm2cZ7y4AMlZtn6l3lP-7OdS_IEP359vyCX3WeBWZbdwkva39GCt4ErD-Mmhonhxt4vE9oC17yRg3GvGI-o3TSsJ61QKEJE76bz4tpqKJNQh__AxdvsqWd1s0c6oNLZrycYjzBVW1cRVNWQqfbByYPN23KOWxc4Od452RYn1tS07exIO2JOdgoq4Dw7mG0rqeaeL99Gae4XJ3EnM0C3OPkeLN40dCE75XKGeL5dS3aFJrlDQTPmZ9962-YORzQU2Xu4rVZzzkh67ed9CAg61IIaPJm7NOQ [root@k8s-master ~]# [root@k8s-master ~]# k describe sa metrics-server -n kube-system Name: metrics-server Namespace: kube-system Labels: k8s-app=metrics-server Annotations: Image pull secrets: <none> Mountable secrets: metrics-server-token-k6szn Tokens: metrics-server-token-k6szn Events: <none>
- docker-registry: 用来存储私有docker registry的认证信息,我们每一个node运行pod之前会把pod依赖的镜像要先检查本地有没有,如果没有就回去仓库服务器上拖,如果我们用的是私有仓库的话,必须要输入账号和密码才能访问,账号密码放哪儿呢?也就意味着当前node要自动去通过认证然后去拖镜像否则pod就会运行失败,也就意味着拉取的时候要现在节点上使用docker login然后docker pull。因此很多时候我们k8s节点要运行pod获取镜像,而若镜像若托管在在必须要认证才能获取到的私有镜像仓库中时,kubelet要能自动完成,因此拖镜像和认证是通过kubelet指挥着docker去做的,那我们怎么去提供这个私有数据呢。第一种方式是我们使用secret,使用我们pods.spec.imagePullSecrets字段,表示pod创建时,它如果要连到私有镜像仓库服务器,需要认证那么这里我们应该放个secret,这个secret包含了让我们kubelet或我们docker去链接私有仓库服务器时的账号和密码,这个账号密码就是由secret提供的,这个对象必须是专用的对象,就是我们这个docker-registry
定义的时候通常tpye是type: kubernetes.io/dockerconfigjson
B,
pod引用secret的三种形式:
- 作为挂载到一个或多个容器上的卷 中的文件。
- 映射为容器内的环境变量。
- 由 kubelet 在为 Pod 拉取镜像时使用
1)作为文件挂载到pod内
创建一个pod,此pod使用上面创建的secret,挂载到opt目录下:
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx:1.20 name: nginx volumeMounts: #在容器中使用pod定义的volumes - name: secretconfig mountPath: /opt/ readOnly: true volumes: #在pod中定义volumes - name: secretconfig secret: secretName: mysql-root-password
进入pod查看是否挂载,并查看stringDate的值是否和上面的secret一致:
[root@k8s-master wd]# k exec -it nginx-85cf9f64ff-tljmd -- /bin/bash root@nginx-85cf9f64ff-tljmd:/# ls -al /opt/ total 0 drwxrwxrwt 3 root root 160 Oct 7 12:00 . drwxr-xr-x 1 root root 51 Oct 7 10:16 .. drwxr-xr-x 2 root root 120 Oct 7 12:00 ..2022_10_07_12_00_52.102045942 lrwxrwxrwx 1 root root 31 Oct 7 12:00 ..data -> ..2022_10_07_12_00_52.102045942 lrwxrwxrwx 1 root root 16 Oct 7 10:16 password1 -> ..data/password1 lrwxrwxrwx 1 root root 16 Oct 7 10:16 password2 -> ..data/password2 lrwxrwxrwx 1 root root 16 Oct 7 10:16 password3 -> ..data/password3 lrwxrwxrwx 1 root root 16 Oct 7 12:00 password4 -> ..data/password4 root@nginx-85cf9f64ff-tljmd:/# cat /opt/password4 qwertyr
热更新secret:
更改上面的secret清单文件,增加一个password5,然后apply secret文件,此时nginx这个pod不需要更新就可以看到多出一个password5文件
[root@k8s-master wd]# cat test-secret.yaml apiVersion: v1 data: password1: TXlQQHNzMTIz password2: MTIzNDU2 password3: NDU2Nzg5 stringData: password4: qwerty password5: 324dfe3432423 kind: Secret metadata: name: mysql-root-password #更改secret文件 [root@k8s-master wd]# k apply -f test-secret.yaml secret/mysql-root-password configured
root@nginx-85cf9f64ff-tljmd:/# ls -al /opt/ total 0 drwxrwxrwt 3 root root 180 Oct 7 12:36 . drwxr-xr-x 1 root root 51 Oct 7 10:16 .. drwxr-xr-x 2 root root 140 Oct 7 12:36 ..2022_10_07_12_36_50.416957405 lrwxrwxrwx 1 root root 31 Oct 7 12:36 ..data -> ..2022_10_07_12_36_50.416957405 lrwxrwxrwx 1 root root 16 Oct 7 10:16 password1 -> ..data/password1 lrwxrwxrwx 1 root root 16 Oct 7 10:16 password2 -> ..data/password2 lrwxrwxrwx 1 root root 16 Oct 7 10:16 password3 -> ..data/password3 lrwxrwxrwx 1 root root 16 Oct 7 12:00 password4 -> ..data/password4 lrwxrwxrwx 1 root root 16 Oct 7 12:36 password5 -> ..data/password5
2)
env环境变量形式挂载
修改上面的那个nginx部署清单文件:
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx name: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx:1.20 name: nginx env: - name: PASSWORD1 valueFrom: secretKeyRef: name: mysql-root-password key: password1 - name: PASSWORD5 valueFrom: secretKeyRef: name: mysql-root-password key: password5
此时,重新应用这个部署文件后,pod的名称会发生改变,因此,重新查询出此pod的名字,并进入pod打印变量password1的值:
[root@k8s-master wd]# k get po NAME READY STATUS RESTARTS AGE nginx-5cd897998-rm4kv 1/1 Running 0 87s [root@k8s-master wd]# k exec -it nginx-5cd897998-rm4kv -- /bin/bash root@nginx-5cd897998-rm4kv:/# echo $PASSWORD1 MyP@ss123
OK,可以看到环境变量在pod内生效了,打印出了正确的值,那么,stringDate能否正确打印呢,答案是肯定的,但,此时secret不能热更新了,也就是说环境变量形式的引用secret,secret改变不会自动将它的值作为变量映射到pod内。
[root@k8s-master wd]# k exec -it nginx-cb84ddc9-lvz4k -- /bin/bash root@nginx-cb84ddc9-lvz4k:/# echo $PASSWORD5 324dfe3432423
3)
docker私有仓库的专有secret引用
第一种方式:
假设本地的docker仓库已经安装完毕并调试好了,不管是habore还是官方镜像搭建的私人仓库都有配置文件,此文件假定名字是config.json
[root@ip-172-31-10-110 ~]# base64 -w 0 ~/.docker/config.json ewoJImF1dGhjNWdlpHVnVaenB5Wld4aFFFeFdUa2xCVGtBeU1ERTMiCgkJfSwKCQkidXJlZy5rOHMueXVud2VpLnJlbGEubWUiOiB7CgkJCSJhdXRoIjogIloyRnZaM1Z2WkdWdVp6cHlaV3hoUUV4V1RrbEJUa0F5TURFMyIKCQl9Cgl9LAoJIkh0dHBIZWFkZXJzIjogewoJCSJVc2VyLUFnZW50IjogIkRvY2tlci1DbGllbnQvMTguMDYuMS1jZSAobGludXgpIgoJfQp9
创建secret:
### vim secret.yaml apiVersion: v1 kind: Secret metadata: name: regsecret namespace: default data: .dockerconfigjson: ewoJImF1dGhjNWdlpHVnVaenB5Wld4aFFFeFdUa2xCVGtBeU1ERTMiCgkJfSwKCQkidXJlZy5rOHMueXVud2VpLnJlbGEubWUiOiB7CgkJCSJhdXRoIjogIloyRnZaM1Z2WkdWdVp6cHlaV3hoUUV4V1RrbEJUa0F5TURFMyIKCQl9Cgl9LAoJIkh0dHBIZWFkZXJzIjogewoJCSJVc2VyLUFnZW50IjogIkRvY2tlci1DbGllbnQvMTguMDYuMS1jZSAobGludXgpIgoJfQp9 type: kubernetes.io/dockerconfigjson
pod 拉取镜像的时候引用此secret:
[root@ip-172-31-10-110 ~]# vim test.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: dentestreplce spec: replicas: 1 template: metadata: labels: name: dentestreplace spec: containers: - name: dentestreplace imagePullPolicy: Always image: ureg.k8s.test.com/rela_dev/logreport:latest imagePullSecrets: - name: regsecret
第二种方式:
使用命令创建Secret
kubectl create secret docker-registry regsecret --docker-server=ureg.k8s.test.com --docker-username=lvnian --docker-password=LVNIAN@2017 --docker-email=lvnian@rela.me
regsecret: 指定密钥的键名称, 可自行定义 --docker-server: 指定docker仓库地址 --docker-username: 指定docker仓库账号 --docker-password: 指定docker仓库密码 --docker-email: 指定邮件地址 -n : 命名空间,在那个命名空间创建,就只能在那个命名空间使用这个secret
命令行生成的secret和上面文件生成的secret引用都是一样的,没什么可说的了。