1. ConfigMap

日常开发过程中,我们一般使用的都是本地或测试环境,连接的数据库等中间件肯定和生产环境是不一样的,这时我们一般会使用多套配置文件来制作多个容器镜像,更好一点的办法是将配置文件单独挂载到容器中。而[ConfigMap](https://kubernetes.io/zh/docs/concepts/configuration/configmap/)就是Kubernetes提供的一种用于保存一些非机密性的数据的资源对象,例如配置文件,环境变量。使用时,可以将其用作环境变量或存储卷注入到Pod中,这样可以将环境配置信息和容器镜像解耦,便于应用配置的修改。

2. Secret

官方文档
Secret 是 Kubernetes 中用来存储敏感认证信息的一种重要资源,大致可以分为三种类型:docker-registrygenerictls,从名称上就可以看出来,分别用于存储镜像仓库认证信息,一般信息和证书信息。

2.1 创建 Secret

2.1.1 kubectl create 命令创建

使用 kubectl 管理 Secret
查看命令帮助:

  1. [root@center-188 pod]# kubectl create secret --help
  2. Create a secret using specified subcommand.
  3. Available Commands:
  4. docker-registry Create a secret for use with a Docker registry
  5. generic Create a secret from a local file, directory or literal value
  6. tls Create a TLS secret
  7. Usage:
  8. kubectl create secret [flags] [options]
  9. Use "kubectl <command> --help" for more information about a given command.
  10. Use "kubectl options" for a list of global command-line options (applies to all
  11. commands).

可以看到子命令,及使用方式说明。另外,还可以继续跟上子命令,查看更详细的帮助信息,例如:kubectl create secret tls --help
帮助说明的非常详细,建议仔细看一下,这里再举几个例子说明一下。

在命令行中直接指定键值对信息:

使用--from-literal参数,可以直接在命令行中指定键值对信息。

  1. [root@center-188 pod]# kubectl create secret generic ssh-user --from-literal=user=root -n wuvikr
  2. secret/ssh-user created
  3. # 可以看到在wuvikr名称空间下创建了一个名为ssh-user的secret
  4. [root@center-188 pod]# kubectl get secret -n wuvikr
  5. NAME TYPE DATA AGE
  6. ssh-user Opaque 1 28s
  7. # 查看详细信息
  8. # 其中data字段中,保存的就是我们指定的信息
  9. # 需要注意的是这里的cm9vdA==并不是加密信息,仅仅是root的base64转码后的信息
  10. # 生产中如果安全要求很高,可以使用secret加密插件
  11. [root@center-188 pod]# kubectl get secret ssh-user -n wuvikr -o yaml
  12. apiVersion: v1
  13. data:
  14. user: cm9vdA==
  15. kind: Secret
  16. metadata:
  17. creationTimestamp: "2021-02-26T01:38:27Z"
  18. name: ssh-user
  19. namespace: wuvikr
  20. resourceVersion: "46489313"
  21. selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-user
  22. uid: 5d16c41f-1b70-4d3c-934e-ecfa7b29ab5e
  23. type: Opaque

从文件中读取键值对信息:

--from-literal参数,还可以从文件中读取键值对信息。

  1. [root@center-188 pod]# cat passwd.txt
  2. 123456
  3. # 这里--from-file后也可以跟上键名,如果不指定,默认键名为文件名
  4. [root@center-188 pod]# kubectl create secret generic ssh-pass --from-file=./passwd.txt -n wuvikr
  5. secret/ssh-pass created
  6. [root@center-188 pod]# kubectl get secret -n wuvikr
  7. NAME TYPE DATA AGE
  8. ssh-pass Opaque 1 8s
  9. ssh-user Opaque 1 9m21s
  10. # 查看详细信息
  11. [root@center-188 pod]# kubectl get secret ssh-pass -n wuvikr -o yaml
  12. apiVersion: v1
  13. data:
  14. passwd.txt: MTIzNDU2Cg== # 由于没有指定键名,键名默认为文件名了
  15. kind: Secret
  16. metadata:
  17. creationTimestamp: "2021-02-26T01:47:40Z"
  18. name: ssh-pass
  19. namespace: wuvikr
  20. resourceVersion: "46491627"
  21. selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-pass
  22. uid: 1bd4650a-b58c-4e4a-9f15-cf0234bb10b6
  23. type: Opaque
  24. # 这一次我们指定一下键名为pass
  25. [root@center-188 pod]# kubectl create secret generic ssh-pass1 --from-file=pass=./passwd.txt -n wuvikr
  26. [root@center-188 pod]# kubectl get secret ssh-pass1 -n wuvikr -o yaml
  27. apiVersion: v1
  28. data:
  29. pass: MTIzNDU2Cg== # 指定了键名为pass
  30. kind: Secret
  31. metadata:
  32. creationTimestamp: "2021-02-26T01:54:26Z"
  33. name: ssh-pass1
  34. namespace: wuvikr
  35. resourceVersion: "46493370"
  36. selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-pass1
  37. uid: dddb33d7-af66-44c0-b2f4-15d96ec64ef2
  38. type: Opaque
  39. # 当然也可以将多个文件加入到一个secret中
  40. [root@center-188 pod]# kubectl create secret generic ssh-account -n wuvikr --from-file=username=./username.txt --from-file=password=./passwd.txt
  41. [root@center-188 pod]# kubectl get secret ssh-account -n wuvikr -o yaml
  42. apiVersion: v1
  43. data:
  44. password: MTIzNDU2Cg==
  45. username: YWRtaW4K
  46. kind: Secret
  47. metadata:
  48. creationTimestamp: "2021-02-26T05:09:37Z"
  49. name: ssh-account
  50. namespace: wuvikr
  51. resourceVersion: "46541985"
  52. selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-account
  53. uid: 13a19839-ae6b-4b6b-bfe1-b2026dfeb668
  54. type: Opaque
  55. # 如果需要用到的secret值很多,一个个添加的话实在太麻烦了
  56. # 因此,--from-file参数还支持直接指定目录
  57. # 其目录中所有的文件都会被加载到secret中去
  58. # 但是这种情况下,就不能在命令行中指定键名了,默认键名均为文件名。
  59. [root@center-188 pod]# ll files
  60. total 8
  61. -rw-r--r-- 1 root root 4 Feb 26 09:49 01.txt
  62. -rw-r--r-- 1 root root 4 Feb 26 09:49 02.txt
  63. [root@center-188 pod]# cat files/01.txt files/02.txt
  64. aaa
  65. bbb
  66. [root@center-188 pod]# kubectl create secret generic test01 --from-file=./files/ -n wuvikr
  67. [root@center-188 pod]# kubectl get secret test01 -n wuvikr -o yaml
  68. apiVersion: v1
  69. data:
  70. 01.txt: YWFhCg==
  71. 02.txt: YmJiCg==
  72. kind: Secret
  73. metadata:
  74. creationTimestamp: "2021-02-26T01:50:59Z"
  75. name: test01
  76. namespace: wuvikr
  77. resourceVersion: "46492414"
  78. selfLink: /api/v1/namespaces/wuvikr/secrets/test01
  79. uid: 65a61fa1-c9f0-4a9c-bf84-a1bf7e97fdcb

环境变量键值对文件:

使用--from-env-file参数可以直接加载文件中的键值对到 secret 中。
有时候在写 yaml 文件的时候,可能要为某个 Pod 指定多个 ENV,这时我们可以直接将这些 ENV 都写入一个文件中,然后创建一个含有文件中所有 ENV 的 secret,再直接挂载到容器中使用。

  1. [root@center-188 pod]# cat env-mysql.txt
  2. MYSQL_ROOT_PASSWORD=744123
  3. MYSQL_DATABASE=testdb
  4. MYSQL_USER=test
  5. MYSQL_PASSWORD=123456
  6. [root@center-188 pod]# kubectl create secret generic env-mysql --from-env-file=./env-mysql.txt -n wuvikr
  7. secret/env-mysql created
  8. [root@center-188 pod]# kubectl get secret env-mysql -n wuvikr -o yaml
  9. apiVersion: v1
  10. data:
  11. MYSQL_DATABASE: dGVzdGRi
  12. MYSQL_PASSWORD: MTIzNDU2
  13. MYSQL_ROOT_PASSWORD: NzQ0MTIz
  14. MYSQL_USER: dGVzdA==
  15. kind: Secret
  16. metadata:
  17. creationTimestamp: "2021-02-26T02:09:58Z"
  18. name: env-mysql
  19. namespace: wuvikr
  20. resourceVersion: "46497156"
  21. selfLink: /api/v1/namespaces/wuvikr/secrets/env-mysql
  22. uid: 3e706ce9-c260-495f-ba98-9cca55de8f12
  23. type: Opaque

2.1.2 直接写 yaml 文件创建

使用配置文件管理 Secret
如果很熟悉 secret 的格式的话,完全可以自己写一份 yaml 文件来创建新的 secret。可以从已有的 secret 导出一个当做模板,再按需修改就行了。

  1. # 导出已有模板
  2. [root@center-188 secret]# kubectl get secret ssh-user -n wuvikr -o yaml > my-secret.yaml
  3. # 按需修改,保留以下基础部分即可
  4. [root@center-188 secret]# cat my-secret.yaml
  5. apiVersion: v1
  6. data:
  7. user: cm9vdA==
  8. kind: Secret
  9. metadata:
  10. name: ssh-user
  11. namespace: wuvikr
  12. # 创建Secret
  13. [root@center-188 secret]# kubectl apply -f ./my-secret.yaml

注意:data 字段中保存的是 base64 编码的值。

# 先将要编辑的内容转换为base64编码,再编辑修改secret文件。
[root@center-188 secret]# echo 'passwd' | base64
cGFzc3dkCg==

2.2 编辑 secret

可以使用 kubectl edit 命令来编辑修改已有的 secret:

[root@center-188 secret]# kubectl edit secrets ssh-user -n wuvikr

# 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:
  user: cm9vdA==
kind: Secret
metadata:
  creationTimestamp: "2021-02-26T01:38:27Z"
  name: ssh-user
  namespace: wuvikr
  resourceVersion: "46489313"
  selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-user
  uid: 5d16c41f-1b70-4d3c-934e-ecfa7b29ab5e
type: Opaque

2.3. secret 的使用

2.3.1 volume 挂载的方式

apiVersion: v1
kind: Pod
metadata:
  name: secret-volume-test
  namespace: wuvikr
spec:
  containers:
  - name: secret-volume-test
    image: busybox
    args:
    - sleep
    - "86400"
    volumeMounts:
    - name: ssh-cred
      mountPath: "/tmp"
      readOnly: true
  volumes:
  - name: ssh-cred
    secret:
      secretName: ssh-account

执行上面的 yaml,并进入到容器中:

[root@center-188 pod]# kubectl apply -f secret-volume-test.yaml
pod/secret-volume-test created

[root@center-188 pod]# kubectl exec -it secret-volume-test -n wuvikr -- sh
/ # cd /tmp
/tmp # ls -al
total 0
drwxrwxrwt    3 root     root           120 Feb 26 05:29 .
drwxr-xr-x    1 root     root            29 Feb 26 05:29 ..
drwxr-xr-x    2 root     root            80 Feb 26 05:29 ..2021_02_26_05_29_13.312279811
lrwxrwxrwx    1 root     root            31 Feb 26 05:29 ..data -> ..2021_02_26_05_29_13.312279811
lrwxrwxrwx    1 root     root            15 Feb 26 05:29 password -> ..data/password
lrwxrwxrwx    1 root     root            15 Feb 26 05:29 username -> ..data/username
/tmp # cat username password
admin
123456

可以看到上面有两个软连接文件 password 和 username,这是 Kubernetes 为了保持安全更新的一个机制,kubelet 会周期性同步检查被挂载的 secret 是不是最新的,当etcd中的 secret 被更新后,Pod 中挂载的 secret 也会得到更新,但是这并不是实时更新,中间会有一个延迟。
上面的挂载方式默认会将 secret 中的所有键全部挂载进容器中去,有时候或许只想挂载 secret 中的某几个键,这种情况下可以使用spec.volumes[].secret.items字段来实现:

apiVersion: v1
kind: Pod
metadata:
  name: secret-volume-item-test
  namespace: wuvikr
spec:
  containers:
  - name: secret-volume-item-test
    image: busybox
    args:
    - sleep
    - "86400"
    volumeMounts:
    - name: ssh-cred
      mountPath: "/tmp"
      readOnly: true
  volumes:
  - name: ssh-cred
    secret:
      secretName: ssh-account
      items:
      - key: username
        path: my-path/username

和之前的 yaml 文件几乎一样,唯一不同的就是在spec.volumes[].secret下使用了items 字段,只有在 items 中指定的键会加载到 Pod 中。
运行一下上面的yaml,并进入到容器中:

[root@center-188 pod]# kubectl apply -f secret-volume-item-test.yaml
pod/secret-volume-test created

[root@center-188 pod]# kubectl exec -it secret-volume-item-test -n wuvikr -- sh
/ # cd /tmp
/tmp # ls -al
total 0
drwxrwxrwt    3 root     root           100 Feb 26 05:46 .
drwxr-xr-x    1 root     root            29 Feb 26 05:46 ..
drwxr-xr-x    3 root     root            60 Feb 26 05:46 ..2021_02_26_05_46_42.795865831
lrwxrwxrwx    1 root     root            31 Feb 26 05:46 ..data -> ..2021_02_26_05_46_42.795865831
lrwxrwxrwx    1 root     root            14 Feb 26 05:46 my-path -> ..data/my-path
/tmp # cd my-path/
/tmp/..2021_02_26_05_46_42.795865831/my-path # ls
username

除了只加载了 username 之外,还可以发现username Secret 这次存储在了 /tmp/my-path/username 文件中而不是 /tmp/username 中了,这是spec.volumes[].secret.items[].path字段所实现的,而且这还是一个必须字段

2.3.2 环境变量的形式使用

环境变量的形式使用 secret 有两种方式,下面第一种写法是从 secret 中引用某个环境变量,而第二种写法直接加载 secret 中全部的环境变量。

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
  namespace: wuvikr
spec:
  containers:
  - name: mycontainer
    image: mysql:latest
    env:
      - name: MYSQL_ROOT_PASSWORD
        valueFrom:
          secretKeyRef:
            name: env-mysql
            key: MYSQL_ROOT_PASSWORD
---
apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
  namespace: wuvikr
spec:
  containers:
  - name: mycontainer
    image: mysql:latest
    envFrom:
    - secretRef:
        name: env-mysql

执行上面的第二个 yaml,并进入到容器中:

[root@center-188 secret]# kubectl apply -f secret-env-pod.yaml
pod/secret-env-pod created

# 查看环境变量
[root@center-188 secret]# kubectl exec -it secret-env-pod -n wuvikr -- bash
root@secret-env-pod:/# printenv
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
MYSQL_MAJOR=8.0
HOSTNAME=secret-env-pod
PWD=/
MYSQL_ROOT_PASSWORD=744123
MYSQL_PASSWORD=123456
MYSQL_USER=test
HOME=/root
KUBERNETES_PORT_443_TCP=tcp://10.68.0.1:443
MYSQL_VERSION=8.0.23-1debian10
GOSU_VERSION=1.12
TERM=xterm
SHLVL=1
KUBERNETES_PORT_443_TCP_PROTO=tcp
MYSQL_DATABASE=testdb
KUBERNETES_PORT_443_TCP_ADDR=10.68.0.1
KUBERNETES_SERVICE_HOST=10.68.0.1
KUBERNETES_PORT=tcp://10.68.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
_=/usr/bin/printenv

注意:Secret 更新之后对应的环境变量并不会被更新,如果某个secret已经被更新,对于已经引用过该 secret 的容器来说,并不会主动更新 ENV,除非重启该 Pod。
对于这种情况有第三方解决方案,可以在secret更新的时候同步更新容器中的环境变量。

2.3.3 docker-registry 类型的使用

创建 docker-registry 凭据:

kubectl create secret docker-registry registry-auth \
--docker-username=admin \
--docker-password=Harbor12345 \
--docker-server=172.16.17.100
在 yaml 中使用这个凭据:
......
spec:
    imagePullSecrets:
    - name: registry-auth
  containers:
  - name: tomcat
      image: registry.cn-shanghai.aliyuncs.com/wuvikr-test/tomcat8.5:v1
    imagePullPolicy: Always
  restartPolicy: Always
......