K8存储之ConfigMap、Secret
ConfigMap
ConfigMap是一种API对象,用来将非加密数据保存到键值对中。可以用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap供容器使用的典型用法如下:
- 生成为容器内的环境变量
- 设置容器启动命令的启动参数(需设置为环境变量)
- 以volume的形式挂载为容器内部的文件或者目录
configmap创建:
基于字面值用命令行创建:
# 命令格式 kubectl create configmap <映射名称> <数据源> # <映射名称> 是为指定的ConfigMap 名称,<数据源> 是要从中提取数据的目录、 文件或者字面值。
比如我们创建一个configmap,里面有两个变量值,一个是nginx_port=80,一个是nginx_server_ip=192.168.248.130
[root@master ~]# kubectl create configmap nginx-env --from-literal=nginx_port=80 --from-literal=nginx_server=192.168.248.130 configmap/nginx-env created
查看configmap
[root@master ~]# kubectl get configmap NAME DATA AGE kube-root-ca.crt 1 81d nginx-env 2 82s [root@master ~]# kubectl describe configmap nginx-env Name: nginx-env Namespace: default Labels: <none> Annotations: <none> Data ==== nginx_port: ---- 80 nginx_server: ---- 192.168.248.130 Events: <none>
此时名为nginx-env的configmap已经被创建,查看详细信息发现定义的变量值已经被写入。
同时也可以通过yaml文件被创建
#vim configmap_nginx.yaml
piVersion: v1 kind: ConfigMap metadata: name: nginx-env2 namespace: default data: nginx_port: "80" nginx_server: 192.168.248.130
[root@master ~]# kubectl apply -f configmap_nginx.yaml configmap/nginx-env2 created [root@master ~]# kubectl get configmap NAME DATA AGE kube-root-ca.crt 1 81d nginx-env 2 16m nginx-env2 2 16s [root@master ~]# kubectl describe configmap nginx-env2 Name: nginx-env2 Namespace: default Labels: <none> Annotations: <none> Data ==== nginx_port: ---- 80 nginx_server: ---- 192.168.248.130 Events: <none>
基于文件创建ConfigMap
当configmap中需要被定义多个变量时,我们可以将变量写入到文件中,然后基于文件来创建configmap。用--from-file=<文件路径> 来指定,可以使用多次来指定不同的配置文件。文件在configmap中以键值对的形式被创建,键的名字就是文件名,值就是文件内容。
[root@master env]# cat /root/env/nginx-env #查看变量文件
nginx_port=80
nginx_server=192.168.248.130
[root@master env]# kubectl create configmap nginx-config --from-file=/root/env/nginx-env configmap/nginx-config created
[root@master env]# kubectl get configmap nginx-config NAME DATA AGE nginx-config 1 58s [root@master env]# kubectl describe configmap nginx-config Name: nginx-config Namespace: default Labels: <none> Annotations: <none> Data ==== nginx-env: #文件名 ---- nginx_port=80 #文件中内容 nginx_server=192.168.248.130 #文件内容 Events: <none>
基于目录创建ConfigMap
跟基于文件创建ConfigMap一样,只是把文件路径换为目录路径
[root@master env]# ll /root/env/ 总用量 12 -rw-r--r--. 1 root root 158 7月 30 14:48 game.properties -rw-r--r--. 1 root root 46 7月 30 14:50 nginx-env -rw-r--r--. 1 root root 317 7月 30 14:44 ui.properties [root@master env]# kubectl create configmap config-env --from-file=/root/env/ configmap/config-env created [root@master env]# kubectl describe configmap config-env Name: config-env Namespace: default Labels: <none> Annotations: <none> Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 nginx-env: ---- nginx_port=80 nginx_server=192.168.248.130 ui.properties: ---- color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice Events: <none>
使用ConfigMap
环境变量方式
ConfigMap一定要先于pod创建,再创建一个pod,并挂载ConfigMap。
我们就用上面创建的名为nginx-env的ConfigMap来实验。先创建一个pod
[root@master ~]# cat test.yaml apiVersion: v1 kind: Service metadata: name: service-nginx namespace: default spec: type: NodePort selector: app: nginx ports: - name: nginx port: 80 targetPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: mydeploy namespace: default spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: name: web labels: app: nginx spec: containers: - name: nginx image: nginx:1.21.4 ports: - name: nginx containerPort: 80 volumeMounts: - name: html mountPath: /user/share/nginx/html/ env: - name: TEST_PORT valueFrom: configMapKeyRef: name: nginx-env key: nginx_port - name: TEST_HOST valueFrom: configMapKeyRef: name: nginx-env key: nginx_server volumes: - name: html emptyDir: {}
创建pod并查看
[root@master ~]# kubectl apply -f test.yaml service/service-nginx created deployment.apps/mydeploy created [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE mydeploy-7bfd9b98c7-jwlcs 1/1 Running 0 5s [root@master ~]# kubectl exec mydeploy-7bfd9b98c7-jwlcs -it -- /bin/bash root@mydeploy-7bfd9b98c7-jwlcs:/# printenv KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_SERVICE_PORT=443 HOSTNAME=mydeploy-7bfd9b98c7-jwlcs SERVICE_NGINX_SERVICE_PORT_NGINX=80 PWD=/ SERVICE_NGINX_SERVICE_HOST=10.110.104.68 SERVICE_NGINX_PORT=tcp://10.110.104.68:80 SERVICE_NGINX_PORT_80_TCP_PORT=80 SERVICE_NGINX_PORT_80_TCP_PROTO=tcp TEST_PORT=80 PKG_RELEASE=1~bullseye HOME=/root KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 TEST_HOST=192.168.248.130 SERVICE_NGINX_PORT_80_TCP=tcp://10.110.104.68:80 NJS_VERSION=0.7.0 TERM=xterm SHLVL=1 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 KUBERNETES_SERVICE_HOST=10.96.0.1 KUBERNETES_PORT=tcp://10.96.0.1:443 KUBERNETES_PORT_443_TCP_PORT=443 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin NGINX_VERSION=1.21.4 SERVICE_NGINX_SERVICE_PORT=80 SERVICE_NGINX_PORT_80_TCP_ADDR=10.110.104.68 _=/usr/bin/printenv root@mydeploy-7bfd9b98c7-jwlcs:/#
可以发现configMap当中的环境变量已经注入到了pod容器当中
注意:用这种环境变量的注入方式,pod启动后,如果在去修改configMap当中的变量,对于pod是无效的,如果是以卷的方式挂载,是可的实时更新的。
以存储卷的形式挂载到pod中
[root@master ~]# cat test1.yaml apiVersion: v1 kind: Service metadata: name: service-nginx namespace: default spec: type: NodePort selector: app: nginx ports: - name: nginx port: 80 targetPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: mydeploy namespace: default spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: name: web labels: app: nginx spec: containers: - name: nginx image: nginx:1.21.4 ports: - name: nginx containerPort: 80 volumeMounts: - name: nginx-config mountPath: /nginx/vars/ readOnly: true volumes: - name: nginx-config configMap: name: nginx-env
创建pod并进入查看/nginx/vars/下的变量文件
[root@master ~]# kubectl apply -f test1.yaml service/service-nginx created deployment.apps/mydeploy created [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE mydeploy-6dc957dc5-9lj4j 1/1 Running 0 2s [root@master ~]# kubectl exec mydeploy-6dc957dc5-9lj4j -it -- /bin/bash root@mydeploy-6dc957dc5-9lj4j:/# ls bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt nginx opt proc root run sbin srv sys tmp usr var root@mydeploy-6dc957dc5-9lj4j:/# cd nginx/vars/ root@mydeploy-6dc957dc5-9lj4j:/nginx/vars# ls nginx_port nginx_server root@mydeploy-6dc957dc5-9lj4j:/nginx/vars# cat nginx_port 80 root@mydeploy-6dc957dc5-9lj4j:/nginx/vars#
我们查看到 nginx/vars/nginx_port中内容为80 ,修改nginx-env中的nginx_port值为8080
[root@master ~]# kubectl edit configmap nginx-env "/tmp/kubectl-edit-vz3zm.yaml" 15L, 463C written deployment.apps/mydeploy configured [root@master ~]# kubectl get pod # Please edit the object below. Lines beginning with a '#' will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # apiVersion: v1 data: nginx_port: "8080" nginx_server: 192.168.248.130 kind: ConfigMap metadata: creationTimestamp: "2022-07-30T08:20:11Z" name: nginx-env namespace: default resourceVersion: "411597" uid: 0b42384e-03d5-499d-9527-e546e3477d2e
我们再进入容器查看nginx/vars/nginx_port的值,此时已经变成8080
[root@master ~]# kubectl exec mydeploy-6dc957dc5-9lj4j -it -- /bin/bash root@mydeploy-6dc957dc5-9lj4j:/# cat nginx/vars/nginx_port 8080 root@mydeploy-6dc957dc5-9lj4j:/#
Secret
Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 Secret 可以独立于使用它们的 Pod, 因此在创建、查看和编辑 Pod 的工作流程中暴露 Secret(及其数据)的风险较小。
- Service Account:用来访问Kubernetes API,有Kubernetes自动创建并且会自动挂载到Pod的 /run/secrets/kubernetes.io/serviceaccount 目录中。
- Opaque:base64 编码格式的 Secret,用来存储密码、密钥等;但数据也可以通过base64 –decode解码得到原始数据,所有加密性很弱。
- kubernetes.io/dockerconfigjson : 用来存储私有docker registry的认证信息。
Secret的创建方式跟ConfigMap相似,只不过时把变量通过base64进行了转码
手动创建base64加密
[root@master ~]# echo -n 'admin' | base64 YWRtaW4= [root@master ~]# echo -n 'qwe123QAZ' | base64 cXdlMTIzUUFa
手动解密
[root@master ~]# echo -n 'YWRtaW4=' | base64 -d admin [root@master ~]# echo -n 'cXdlMTIzUUFa' | base64 -d qwe123QAZ
创建Secret
一、通过命令行创建
[root@master ~]# kubectl create secret test-secret --help Create a secret using specified subcommand. Available Commands: docker-registry 创建一个给 Docker registry 使用的 secret generic 从本地 file, directory 或者 literal value 创建一个 secret tls 创建一个 TLS secret Usage: kubectl create secret [flags] [options] Use "kubectl <command> --help" for more information about a given command. Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@master ~]# kubectl create secret generic test-user --from-literal=user=admin secret/test-user created [root@master ~]# kubectl create secret generic test-passwd --from-literal=passwd=qwe123QAZ secret/test-passwd created [root@master ~]# kubectl get secret NAME TYPE DATA AGE default-token-mkcn2 kubernetes.io/service-account-token 3 82d test-passwd Opaque 1 21s test-user Opaque 1 46s [root@master ~]#
我们通过查看secret发现刚刚创建的类型为Opaque
二、通过yaml创建
[root@master ~]# cat secret.yaml apiVersion: v1 kind: Secret metadata: name: test-secret type: Opaque #注意类型为Opaque data: test-user: YWRtaW4= #值为base64编码后的 test-passwd: cXdlMTIzUUFa #值为编码后的
secret使用
一、通过变量注入
[root@master ~]# cat secret-pod.yaml apiVersion: v1 kind: Pod metadata: name: mypod namespace: default spec: containers: - name: nginx image: nginx:1.21.4 imagePullPolicy: IfNotPresent env: - name: nginx-user valueFrom: secretKeyRef: name: test-secret key: test-user - name: nginx-passwd valueFrom: secretKeyRef: name: test-secret key: test-passwd
创建pod并查看
[root@master ~]# kubectl apply -f secret-pod.yaml pod/mypod created [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE mydeploy-6dc957dc5-9lj4j 1/1 Running 0 4h42m mypod 1/1 Running 0 18s
进入pod查看
[root@master ~]# kubectl exec mypod -it -- /bin/bash root@mypod:/# printenv nginx-user=admin nginx-passwd=qwe123QAZ KUBERNETES_SERVICE_PORT_HTTPS=443 KUBERNETES_SERVICE_PORT=443 HOSTNAME=mypod SERVICE_NGINX_SERVICE_PORT_NGINX=80 PWD=/ SERVICE_NGINX_SERVICE_HOST=10.111.70.83 SERVICE_NGINX_PORT=tcp://10.111.70.83:80 SERVICE_NGINX_PORT_80_TCP_PORT=80 SERVICE_NGINX_PORT_80_TCP_PROTO=tcp PKG_RELEASE=1~bullseye HOME=/root KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443 SERVICE_NGINX_PORT_80_TCP=tcp://10.111.70.83:80 NJS_VERSION=0.7.0 TERM=xterm SHLVL=1 KUBERNETES_PORT_443_TCP_PROTO=tcp KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1 KUBERNETES_SERVICE_HOST=10.96.0.1 KUBERNETES_PORT=tcp://10.96.0.1:443 KUBERNETES_PORT_443_TCP_PORT=443 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin NGINX_VERSION=1.21.4 SERVICE_NGINX_SERVICE_PORT=80 SERVICE_NGINX_PORT_80_TCP_ADDR=10.111.70.83 _=/usr/bin/printenv root@mypod:/#
二、通过Volume挂载的方式
[root@master ~]# cat secret-pod2.yaml apiVersion: v1 kind: Pod metadata: name: nginx namespace: default spec: containers: - name: nginx image: nginx:1.21.4 imagePullPolicy: IfNotPresent volumeMounts: - name: test-secret mountPath: /nginx/ readOnly: true volumes: - name: test-secret projected: sources: - secret: name: test-secret
创建pod,并进入容器查看
[root@master ~]# kubectl exec nginx -it -- /bin/bash root@nginx:/# ls bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt nginx opt proc root run sbin srv sys tmp usr var root@nginx:/# cd nginx root@nginx:/nginx# ls test-passwd test-user root@nginx:/nginx# cat test-passwd qwe123QAZ root@nginx:/nginx# cat test-user admin root@nginx:/nginx#
最后我们来对比下Secret和ConfigMap这两种资源对象的异同点:
相同点:
key/value的形式
属于某个特定的namespace
可以导入到环境变量
可以通过目录/文件形式挂载
通过 volume 挂载的配置信息均可热更新
不同点:
Secret 可以被 ServerAccount 关联
Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret 参数中,用于拉取私有仓库的镜像
Secret 支持 Base64 加密
Secret 分为 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque 三种类型,而 Configmap 不区分类型