1 ConfigMap基本概念
1.1 什么是ConfigMap
ConfigMap是一种API对象,用来将非机密性的数据保存到键值对中。使用时,Pod可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap将你的环境配置信息和容器镜像解耦,便于应用配置的修改。
1.2 ConfigMap应用场景
- 使用 k8s 部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,configmap可以将配置信息和docker镜像解耦,以便实现镜像的可移植性和可复用性,因为一个configMap其实就是一系列配置信息的集合,可直接注入到Pod中给容器使用。configmap注入方式有两种,一种将configMap做为存储卷,一种是将configMap通过env中configMapKeyRef 注入到容器中。
- 使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦,使用configmap可以友好的进行配置共享。
1.3 局限性
ConfigMap并不提供保密或者加密功能。 如果你想存储的数据是机密的,请使用Secret, 或者使用其他第三方工具来保证你的数据的私密性,而不是用ConfigMap。
ConfigMap在设计上不是用来保存大量数据的。在ConfigMap中保存的数据不可超过1 MiB。如果你需要保存超出此尺寸限制的数据,你可能希望考虑挂载存储卷 或者使用独立的数据库或者文件服务。
2 创建ConfigMap
2.1 基于命令创建CM
1、查看帮助命令
kubectl create configmap --help
2、使用kubectl create configmap命令使用--from-literal选项给出键值对来创建configmap
kubectl create cm nginx-config --from-literal=nginx.host='0.0.0.0' --from-literal=nginx.port='9999'
3、查看ConfigMap资源
2.2 基于文件创建CM
通过指定文件创建一个configmap,--from-file=<文件>,默认文件名为key,文件内容为value。
1、创建配置文件
vim nginx.conf
server {
server_name www.nginx.com;
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
}
include /etc/nginx/conf.d/*.cfg;
}
#用于开启Nginx状态模块配置
vim nginx_status.cfg
location /nginx_status {
stub_status;
access_log off;
}
2、创建ConfigMap
kubectl create cm nginx-cm-file \
--from-file=nginx.conf \
--from-file=nginx_status=nginx_status.cfg
3、查看ConfigMap资源
2.3 基于目录创建CM
对于配置文件较多且无需自定义键名的场景,直接使用--from-file选项附加一个目录路径就能将该目录下的所有文件创建于同一个ConfigMap资源中,各文件名就是键名称。
1、创建ConfigMap
kubectl create cm nginx-cm-folder --from-file=/root/ConfigMap
2、查看ConfigMap资源
2.4 配置清单创建CM
apiVersion: v1
kind: ConfigMap
metadata:
name:
namespace:
data:
# 类属性键;每一个键都映射到一个简单的值
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
# 类文件键
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
nginx.conf: |
server {
server_name www.nginx.com;
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
}
include /etc/nginx/conf.d/*.cfg;
}
3 Pod引用ConfigMap
3.1 通过环境变量引用CM键值
3.1.1 env引用变量示例
Pod清单中除了使用value字段直接给定变量之外,还支持valueFrom字段嵌套configMapKeyRef来引用ConfigMap对象的键值。
env:
- name: #要赋值的环境变量名称
valueFrom: #定义变量的引用
configMapKeyRef: #变量来自于ConfigMap对象
name: #ConfigMap对象的名称(因为有很多configmap,需要指定具体的名称)
key: #configmap的键名称
这种方式赋值环境变量与直接赋值环境变量方式并无区别,它们都可以用于容器的启动脚本或直接传递给容器应用等。
3.1.2 env引用变量实践
1、创建ConfigMap资源
vim nginx-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-cm
namespace: default
data:
nginx.host: "0.0.0.0"
nginx.port: "8848"
2、创建Pod资源清单,通过env方式引用变量
vim nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
spec:
containers:
- name: nginx
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- "/bin/sh"
- "-c"
- "printenv"
env:
- name: NGINX_HOST
valueFrom:
configMapKeyRef:
name: nginx-cm
key: nginx.host
- name: NGINX_PORT
valueFrom:
configMapKeyRef:
name: nginx-cm
key: nginx.port
被引用的ConfigMap资源必须事先存在,否则无法再Pod对象中引用ConfigMap资源,另外ConfigMap属于名称空间级别的资源,它必须与引用它的Pod资源在同一名称空间。
3、查看输出
3.2 通过卷挂载方式引用CM
使用环境变量方式导入ConfigMap对象中来源较长的文件内容,会导致占据过多的内存空间。而且以环境变量方式使用的ConfigMap数据不会被自动更新。更新这些数据需要重新启动Pod。
对于给容器提供配置文件类数据,直接通过挂载的方式进行引用,会是一种更好的选择。
要在一个Pod的存储卷中使用ConfigMap:
- 创建一个ConfigMap对象或者使用现有的ConfigMap对象。多个Pod可以引用同一个ConfigMap。
- 修改Pod定义,在spec.volumes[]下添加一个卷。 为该卷设置任意名称,之后将spec.volumes[].configMap.name字段设置为对你的ConfigMap对象的引用。
- 为每个需要该ConfigMap的容器添加一个.spec.containers[].volumeMounts[]。设置.spec.containers[].volumeMounts[].readOnly=true并将.spec.containers[].volumeMounts[].mountPath设置为一个未使用的目录名,ConfigMap内容将出现在该目录中。
- 更改你的镜像或者命令行,以便程序能够从该目录中查找文件。ConfigMap 中的每个data键会变成mountPath下面的一个文件名。
3.2.1 引用整个存储卷
1、配置pod资源清单
vim nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
spec:
containers:
- name: nginx
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- "/bin/sh"
- "-c"
- "ls -la /tmp/nginx"
volumeMounts:
- name: nginx-cm
mountPath: /tmp/nginx
readOnly: true
volumes:
- name: nginx-cm
configMap:
name: nginx-cm
2、查看输出
3.2.2 引用存储卷部分键值
有些应用场景,仅期望向容器中挂载指定的键,而不是所有的键。
1、配置pod资源清单
vim nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
spec:
containers:
- name: nginx
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- "/bin/sh"
- "-c"
- "ls -la /tmp/nginx"
volumeMounts:
- name: nginx-cm
mountPath: /tmp/nginx
readOnly: true
volumes:
- name: nginx-cm
configMap:
name: nginx-cm
items:
- key: nginx.host
path: nginx.host.txt
mode: 0600
2、查看输出
3.2.3 引用存储卷单个键值
前两种方式,无论是装在ConfigMap对象中的所有文件还是部分文件,挂载点目录下原有的文件都会被隐藏。
对于期望将ConfigMap对象提供的配置文件补充在挂载点目录下的需求来说,这种方法难以实现,可以通过容器的volumeMounts字段subpath来解决。
1、配置Pod资源清单
vim nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: nginx-cm
mountPath: /etc/nginx/conf.d/nginx.host.txt #挂载地址必须是具体的文件名,不能是目录
subPath: nginx.host #ConfigMap的key
volumes:
- name: nginx-cm
configMap:
name: nginx-cm
2、查看结果
使用ConfigMap作为subPath卷挂载的容器将不会收到 ConfigMap 的更新。
3.2.4 ConfigMap热更新
当卷中使用的ConfigMap被更新时,所投射的键最终也会被更新。kubelet 组件会在每次周期性同步时检查所挂载的ConfigMap是否为最新。
Kubelet在每次定期同步时都会检查所挂载的ConfigMap是否是最新的。 然而,它使用其基于TTL机制的本地缓存来获取ConfigMap的当前值。因此,从ConfigMap更新到新键映射到Pod的总延迟可能与kubelet同步周期(默认为1分钟)+kubelet中ConfigMap缓存的TTL(默认为1分钟)一样长。 你可以通过更新Pod的一个注解来触发立即刷新。
1、编写Pod资源清单
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: NGINX_HOST
valueFrom:
configMapKeyRef:
name: nginx-cm
key: nginx.host
volumeMounts:
- name: nginx-cm-v
mountPath: /etc/nginx/conf.d/
volumes:
- name: nginx-cm-v
configMap:
name: nginx-cm
2、查看数据
3、更改ConfigMap
kubectl edit cm nginx-cm
将nginx.host值更改
nginx.host: 1.1.1.1
4、查看数据
使用该ConfigMap挂载的Env不会同步更新
使用该ConfigMap挂载的Volume中的数据需要一段时间才能同步更新
4 Redis结合ConfigMap实践
4.1创建ConfigMap
1、资源清单
vim redis-cm.yaml
apiVersion:v1
kind:ConfigMap
metadata:
name:redis-cm
namespace:default
data:
redis-config:|
bind 0.0.0.0
port 6666
4.2创建Redis-Pod
创建资源清单
apiVersion:v1
kind:Pod
metadata:
name:redis
namespace:default
spec:
containers:
- name:redis
image:redis:latest
imagePullPolicy:IfNotPresent
command:
- "redis-server"
- "/redis/redis.conf"
volumeMounts:
- name:redis-cm-v
mountPath:/redis/redis.conf
subPath:redis-config
volumes:
- name:redis-cm-v
configMap:
name:redis-cm