1. ConfigMap
日常开发过程中,我们一般使用的都是本地或测试环境,连接的数据库等中间件肯定和生产环境是不一样的,这时我们一般会使用多套配置文件来制作多个容器镜像,更好一点的办法是将配置文件单独挂载到容器中。而[ConfigMap](https://kubernetes.io/zh/docs/concepts/configuration/configmap/)就是Kubernetes提供的一种用于保存一些非机密性的数据的资源对象,例如配置文件,环境变量。使用时,可以将其用作环境变量或存储卷注入到Pod中,这样可以将环境配置信息和容器镜像解耦,便于应用配置的修改。
2. Secret
官方文档
Secret 是 Kubernetes 中用来存储敏感认证信息的一种重要资源,大致可以分为三种类型:docker-registry,generic和tls,从名称上就可以看出来,分别用于存储镜像仓库认证信息,一般信息和证书信息。
2.1 创建 Secret
2.1.1 kubectl create 命令创建
使用 kubectl 管理 Secret
查看命令帮助:
[root@center-188 pod]# kubectl create secret --helpCreate a secret using specified subcommand.Available Commands:docker-registry Create a secret for use with a Docker registrygeneric Create a secret from a local file, directory or literal valuetls Create a TLS secretUsage: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 allcommands).
可以看到子命令,及使用方式说明。另外,还可以继续跟上子命令,查看更详细的帮助信息,例如:kubectl create secret tls --help。
帮助说明的非常详细,建议仔细看一下,这里再举几个例子说明一下。
在命令行中直接指定键值对信息:
使用--from-literal参数,可以直接在命令行中指定键值对信息。
[root@center-188 pod]# kubectl create secret generic ssh-user --from-literal=user=root -n wuvikrsecret/ssh-user created# 可以看到在wuvikr名称空间下创建了一个名为ssh-user的secret[root@center-188 pod]# kubectl get secret -n wuvikrNAME TYPE DATA AGEssh-user Opaque 1 28s# 查看详细信息# 其中data字段中,保存的就是我们指定的信息# 需要注意的是这里的cm9vdA==并不是加密信息,仅仅是root的base64转码后的信息# 生产中如果安全要求很高,可以使用secret加密插件[root@center-188 pod]# kubectl get secret ssh-user -n wuvikr -o yamlapiVersion: v1data:user: cm9vdA==kind: Secretmetadata:creationTimestamp: "2021-02-26T01:38:27Z"name: ssh-usernamespace: wuvikrresourceVersion: "46489313"selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-useruid: 5d16c41f-1b70-4d3c-934e-ecfa7b29ab5etype: Opaque
从文件中读取键值对信息:
--from-literal参数,还可以从文件中读取键值对信息。
[root@center-188 pod]# cat passwd.txt123456# 这里--from-file后也可以跟上键名,如果不指定,默认键名为文件名[root@center-188 pod]# kubectl create secret generic ssh-pass --from-file=./passwd.txt -n wuvikrsecret/ssh-pass created[root@center-188 pod]# kubectl get secret -n wuvikrNAME TYPE DATA AGEssh-pass Opaque 1 8sssh-user Opaque 1 9m21s# 查看详细信息[root@center-188 pod]# kubectl get secret ssh-pass -n wuvikr -o yamlapiVersion: v1data:passwd.txt: MTIzNDU2Cg== # 由于没有指定键名,键名默认为文件名了kind: Secretmetadata:creationTimestamp: "2021-02-26T01:47:40Z"name: ssh-passnamespace: wuvikrresourceVersion: "46491627"selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-passuid: 1bd4650a-b58c-4e4a-9f15-cf0234bb10b6type: Opaque# 这一次我们指定一下键名为pass[root@center-188 pod]# kubectl create secret generic ssh-pass1 --from-file=pass=./passwd.txt -n wuvikr[root@center-188 pod]# kubectl get secret ssh-pass1 -n wuvikr -o yamlapiVersion: v1data:pass: MTIzNDU2Cg== # 指定了键名为passkind: Secretmetadata:creationTimestamp: "2021-02-26T01:54:26Z"name: ssh-pass1namespace: wuvikrresourceVersion: "46493370"selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-pass1uid: dddb33d7-af66-44c0-b2f4-15d96ec64ef2type: Opaque# 当然也可以将多个文件加入到一个secret中[root@center-188 pod]# kubectl create secret generic ssh-account -n wuvikr --from-file=username=./username.txt --from-file=password=./passwd.txt[root@center-188 pod]# kubectl get secret ssh-account -n wuvikr -o yamlapiVersion: v1data:password: MTIzNDU2Cg==username: YWRtaW4Kkind: Secretmetadata:creationTimestamp: "2021-02-26T05:09:37Z"name: ssh-accountnamespace: wuvikrresourceVersion: "46541985"selfLink: /api/v1/namespaces/wuvikr/secrets/ssh-accountuid: 13a19839-ae6b-4b6b-bfe1-b2026dfeb668type: Opaque# 如果需要用到的secret值很多,一个个添加的话实在太麻烦了# 因此,--from-file参数还支持直接指定目录# 其目录中所有的文件都会被加载到secret中去# 但是这种情况下,就不能在命令行中指定键名了,默认键名均为文件名。[root@center-188 pod]# ll filestotal 8-rw-r--r-- 1 root root 4 Feb 26 09:49 01.txt-rw-r--r-- 1 root root 4 Feb 26 09:49 02.txt[root@center-188 pod]# cat files/01.txt files/02.txtaaabbb[root@center-188 pod]# kubectl create secret generic test01 --from-file=./files/ -n wuvikr[root@center-188 pod]# kubectl get secret test01 -n wuvikr -o yamlapiVersion: v1data:01.txt: YWFhCg==02.txt: YmJiCg==kind: Secretmetadata:creationTimestamp: "2021-02-26T01:50:59Z"name: test01namespace: wuvikrresourceVersion: "46492414"selfLink: /api/v1/namespaces/wuvikr/secrets/test01uid: 65a61fa1-c9f0-4a9c-bf84-a1bf7e97fdcb
环境变量键值对文件:
使用--from-env-file参数可以直接加载文件中的键值对到 secret 中。
有时候在写 yaml 文件的时候,可能要为某个 Pod 指定多个 ENV,这时我们可以直接将这些 ENV 都写入一个文件中,然后创建一个含有文件中所有 ENV 的 secret,再直接挂载到容器中使用。
[root@center-188 pod]# cat env-mysql.txtMYSQL_ROOT_PASSWORD=744123MYSQL_DATABASE=testdbMYSQL_USER=testMYSQL_PASSWORD=123456[root@center-188 pod]# kubectl create secret generic env-mysql --from-env-file=./env-mysql.txt -n wuvikrsecret/env-mysql created[root@center-188 pod]# kubectl get secret env-mysql -n wuvikr -o yamlapiVersion: v1data:MYSQL_DATABASE: dGVzdGRiMYSQL_PASSWORD: MTIzNDU2MYSQL_ROOT_PASSWORD: NzQ0MTIzMYSQL_USER: dGVzdA==kind: Secretmetadata:creationTimestamp: "2021-02-26T02:09:58Z"name: env-mysqlnamespace: wuvikrresourceVersion: "46497156"selfLink: /api/v1/namespaces/wuvikr/secrets/env-mysqluid: 3e706ce9-c260-495f-ba98-9cca55de8f12type: Opaque
2.1.2 直接写 yaml 文件创建
使用配置文件管理 Secret
如果很熟悉 secret 的格式的话,完全可以自己写一份 yaml 文件来创建新的 secret。可以从已有的 secret 导出一个当做模板,再按需修改就行了。
# 导出已有模板[root@center-188 secret]# kubectl get secret ssh-user -n wuvikr -o yaml > my-secret.yaml# 按需修改,保留以下基础部分即可[root@center-188 secret]# cat my-secret.yamlapiVersion: v1data:user: cm9vdA==kind: Secretmetadata:name: ssh-usernamespace: wuvikr# 创建Secret[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
......
