pod配置管理之configMap和secret
应用部署的一个最佳实践是将应用所需的配置信息与程序进行分离,这样可以使应用程序被更好地复用,通过不同的配置也能实现更灵活的功能。 将应用打包为容器镜像后,可以通过环境变量或者外挂文件的方式在创建容器时进行配置注入, 在大规模容器集群的环境中,对多个容器进行不同的配置将变得非常复杂。 从Kubernetes 1.2开始提供了 一种统一的应用配置管理方案—ConfigMap
注意:ConfigMap是名称空间级别的资源,它必须与引用它的Pod资源在同一空间内
一、configMap:
ConfigMap供容器使用的典型用法如下:
- 生成为容器内的环境变量
- 设置容器启动命令的启动参数(需设置为环境变量)
- 以Volume的形式挂载为容器内部的文件或目录
ConfigMap以一个或多个key:value的形式保存在Kubernetes系统中供应用使用,既可以用于表示一个变量的值(例如apploglevel=info),也 可以用于表示一个完整配置文件的内容(例如server.xml=…) , 可以通过YAML配置文件或者直接使用kubectl create configmap命令行的方式来创建ConfigMap
1、 通过YAML配置文件方式创建:
下图表示定义一个名为nginx-cm的configMap,key为nginxConfig,value的值为文件类型(nginx配置文件),如图:

- nginxConfig:指定configMap中的key,也可以写default.conf或者其余名字
然后执行命令创建configMap,命令为kubectl create -f cm-app.yaml,创建完成后,执行命令kubectl get cm可以查看创建的configMap,如图:

从上图可以看出,configMap已经创建完成,后面的DATA为1表示里面只有一个键值对
1.1、在pod中使用此ConfigMap:
例如:定义Nginx的yaml文件,在文件中通过挂载的形式引入ConfigMap,如图:

- nginx-conf:volumes的名字可自定义
- nginx-cm:指定上面创建的configMap名字
- items–key:指定configMap中的key的值
- path:指定挂载到容器后的名字,也可以自定义,如果不写items字段,将以configMap中的key作为挂载后的key名,例如在configMap中定义test.conf,那么此处就不用items和key和path了
- mountPath:挂载到容器路径conf.d路径下,名字为test.conf
- subPath:指定挂载后的名字,并且不覆盖原有文件
创建pod后,进入到pod中,查看/etc/nginx/conf.d目录下可以看到存在名为test.conf的配置文件,如图:

1.2、修改ConfigMap中value的server_name为test.com,重启pod观察容器内文件test.conf,发现已经变化,如图:
kubectl edit cm nginx-cm -n test
kubectl rollout restart deploy deploy-nginx -n test #重启

1.3、第一步中定义的只是配置文件形式的键值,现在增加一个普通变量形式的键值,如图:

1.4,在pod中引用此configMap,如图:

创建pod,然后进入容器中,可以查看变量已经成功引用进来,如图:

说明:若ConfigMap资源中存在较多的键值数据,而且其大部分甚至是全部键值数据都需要由容器进行引用时,为容器逐一配置相应的环境变量将是一件颇为劳心费神之事,而且极易出错。对此,Pod资源支持在容器中使用envFrom字段直接将ConfigMap资源中的所有键值一次性地导入
2、通过kubectl命令行方式创建
不使用YAML文件,直接通过kubectl create configmap也可以创建ConfigMap,可以使用参数–from-file或–from-literal指定内容,并且可
以在一行命令中指定多个参数,举例说明如下:
2.1、当前目录下含有配置文件server.xml,创建一个包含该内容的configmap,执行命令如下:
#通过文件形式创建
kubectl create configmap cm-server.xml --from-file=server.xml
查看此configmap,内容如下:

2.2、在目录config中包含配置文件aaaa.xml和log.properties两个文件,现在创建一个包含这两个文件的configmap,执行命令如下:
kubectl create configmap config-cm --from-file=config #指定目录名称
查看此configmap,内容如下:

2.3、直接通过–from-literal参数加上文本内容进行创建configmap,如下:
kubectl create configmap cm-literal --from-literal=loglevel=info --from-literal=datadir=/var/data
查看configmap内容如下:

3、指定挂载的文件权限
如果不指定挂载后的文件权限,默认权限为644,如果要指定权限,有两种方式:
第一种,通过defaultMode参数,设置文件test.conf权限为666,如下:

defaultMode参数对configMap的items下的所有文件都生效,再次进入pod中查看权限,如图:

第二种:直接在当前item下通过mode来设置test.conf文件权限为0664,mode只对当前文件生效,如图:

进入pod中查看文件test.conf的权限,如图:

如果同时配置了defaultMode和mode,那么mode会覆盖defaultMode,因为mode的优先级更高一些
总结:
- ConfigMap必须在Pod之前创建
- ConfigMap受Namespace限制,只有处于相同Namespace中的 Pod才可以引用它
- Pod引用的键必须存在于ConfigMap中,否则Pod无法启动,一直处于ContainerCreating状态,可以通过describe命令查看
- 使用envFrom配置容器环境变量时,默认会跳过被视为无效的键,但是不影响Pod启动,无效的变量会记录在事件日志中
二、secret
ConfigMap主要用于非安全的数据,与其对应的是Secret对象类型,用来保存敏感信息,例如密码、令牌和SSH Key,将这些信息放在Secret中比较安全和灵活。用户可以创建Secret并且引用到Pod中,比如使用Secret初始化Redis、MySQL密码等
创建secret
可以使用命令行工具Kubectl或者通过YAML/JSON文件创建
1、下面例子通过命令行以文件形式在test命名空间中创建secret,保存数据库的账号和密码,如下:
echo -n "admin" > username.txt
echo -n "123456" > password.txt
kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt -n test #generic表示创建通用型的secret

2、通过yaml文件来创建secret
通过yaml创建secret时,每一项内容必须是base64编码的,因此需要对明文进行编码,如下:
echo -n "admin" | base64
echo -n "123456" | base64

定义yaml文件,将上述编码后的username和password写入,如图:

被加密后的内容无法直接查看,如果要查看需要解码,命令如下:
echo "YWRtaW4=" |base64 --decode
secret实践
Secret和ConfigMap的用法类似,也可以作为数据卷被挂载,或作为环境变量以供Pod的容器使用
1、下面将上图中创建的db-user-pass的secret挂载到nginx容器的/etc/test下,如图:

进入容器的/etc/test目录,可以看到文件username和password,如图:

由于没有指定挂载文件的名称,因此会用Secret数据中的Key名作为文件,和ConfigMap一致
2、指定挂载后的文件名,通过items字段,可写多个,如图:

进入容器中,查看挂载后的文件名称,已经变为了指定的,如图:

3、将secret作为环境变量方式注入,如图:

进入容器中,打印环境变量信息,如图:

envFrom的用法和ConfigMap一致,将configMapRef改为secretRef即可,文件权限和ConfigMap用法一样
4、secret类型
在实际使用时,用得最多的是通用型Opaque、镜像仓库Secret和HTTPS证书的Secret
(1)、下面命令创建一个用于docker仓库认证的secret,如下:
#mydockerregistry表示自定义的secret名
kubectl create secret docker-registry mydockerregistry --docker-server=https://192.168.1.5 --docker-username=admin --docker-password=12345

创建后在pod中就可以通过imagePullSecrets来引用此secret,如图:

(2)、下面表示创建一个https证书类型的secret,如下:
kubectl create secret tls test-tls --key=tls.key --cert=tls.crt
创建完成后将证书绑定到ingress上即可,如图:

一个Ingress可以绑定多个TLS类型的Secret,同一个Secret也可以被多个Ingress使用
注意:如果程序没有自动加载配置的功能,那么修改了configMap和secret后需要重启应用的


