在生产环境中经常会遇到需要修改配置文件的情况,传统的修改方式不仅会影响到服务的正常运行,而且操作步骤也很繁琐。
为了解决这个问题,kubernetes项目从1.2版本引入了ConfigMap功能,用于将应用的配置信息与程序的分离。
这种方式不仅可以实现应用程序的复用,而且还可以通过不同的配置实现更灵活的功能。
在创建容器时,用户可以将应用程序打包为容器镜像后,通过环境变量或者外接挂载文件的方式进行配置注入。
格式:
ConfigMap是以key:value的形式保存配置项,既可以用于表示一个变量的值(例如config=info),也可以用于表示一个完整配置文件的内容(例如server.xml=…)。ConfigMap在容器使用的典型用法如下。
填充环境变量的值
设置容器内的命令行参数
填充卷的配置文件
更通俗的理解
将配置项设置为容器内的环境变量。
将启动参数设置为环境变量。
以Volume的形式挂载到容器内部的文件或目录。
作用:
Configmap用于保存配置数据,以键值对形式存储。
configMap 资源提供了向 Pod 注入配置数据的方法。
旨在让镜像和配置文件解耦,以便实现镜像的可移植性和可复用性。
创建ConfigMap的方式有4种:
使用字面值创建
使用文件创建
使用目录创建
编写configmap的yaml文件创建
kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
实验环境:
和之前k8s系列文章的环境一样。这里不再赘述。
kubectl create configmap my-config-2 --from-file=/etc/resolv.conf
key的名称是文件名称,value的值是这个文件的内容
kubectl create configmap my-config-3 --from-file=test
目录中的文件名为key,文件内容是value
$ vim cm1.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1-config
data:
db_host: "172.25.0.250"
db_port: "3306"
$ kubectl create -f cm1.yaml
通过环境变量的方式直接传递给pod
通过在pod的命令行下运行的方式
作为volume的方式挂载到pod内(通过Volume挂载的方式将ConfigMap中的内容
挂载为容器内部的文件或目录。)
$ vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
command: ["/bin/sh", "-c", "env"]
env:
- name: key1
valueFrom:
configMapKeyRef:
name: cm1-config
key: db_host
- name: key2
valueFrom:
configMapKeyRef:
name: cm1-config
key: db_port
restartPolicy: Never
注意:该Pod在执行完启动命令后将会退出,并且不会被系统自动重启(restartPolicy=Never)。
2.
3.查看pod的详细信息时
Kubernetes在1.6版本引入新字段envFrom,可以实现在Pod环境中将ConfigMap中所有定义的key=value自动生成为环境变量,代码格式如下所示。
$ vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
command: ["/bin/sh", "-c", "env"]
envFrom:
- configMapRef:
name: cm1-config
restartPolicy: Never
$ vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
command: ["/bin/sh", "-c", "echo $(db_host) $(db_port)"]
envFrom:
- configMapRef:
name: cm1-config
restartPolicy: Never
$ kubectl create -f pod1.yaml
pod/pod1 created
$ kubectl logs pod1
172.25.0.250 3306
$ vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod2
spec:
containers:
- name: pod2
image: busybox
command: ["/bin/sh", "-c", "cat /config/db_host"]
volumeMounts:
- name: config-volume
mountPath: /config
volumes:
- name: config-volume
configMap:
name: cm1-config
restartPolicy: Never
$ kubectl create -f pod2.yaml
pod/pod2 created
$ kubectl logs pod2
172.25.0.250
$vim pod3.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /config
volumes:
- name: config-volume
configMap:
name: cm1-config
$ kubectl apply -f pod3.yaml
deployment.apps/my-nginx created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx-7cb8dd86c9-77dqm 1/1 Running 0 11s
$ kubectl exec my-nginx-7cb8dd86c9-77dqm cat /config/db_host
172.25.0.250
$ kubectl exec my-nginx-7cb8dd86c9-77dqm cat /config/db_port
3306
$ kubectl edit cm cm1-config
configmap/cm1-config edited
Pod数据并不会实时更新,需要等待几秒:
$ kubectl exec my-nginx-7cb8dd86c9-77dqm cat /config/db_port
8080
1.
2.
3.
4.发现在容器内实现了更新,但是真实使用时还是没有更新
5.
configmap热更新后,并不会触发相关Pod的滚动更新,需要手动触发:
$ kubectl patch deployments.apps my-nginx --patch '{"spec":
{"template": {"metadata": {"annotations": {"version/config":
"20200219"}}}}}'
每次通过修改“version/config”来触发Pod滚动更新。
使用configmap挂载的env环境变量是不会更新的。
实例:
$ vim nginx.conf
server {
listen 8000;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
$ kubectl create configmap nginxconf --from-file=nginx.conf
二、
vim nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: config-volume
mountPath: /etc/nginx/conf.d
volumes:
- name: config-volume
configMap:
name: nginxconf
$ kubectl apply -f nginx.yaml
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-58c4868d54-gwr5t 1/1 Running 0 5m59s 10.244.1.95 server2
$ curl 10.244.1.95:8000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
$ kubectl edit cm nginxconf
configmap/nginxconf edited
$ kubectl exec my-nginx-58c4868d54-gwr5t cat /etc/nginx/conf.d/nginx.conf
server {
listen 8080;
...
可以看出configmap热更新以生效,但访问Pod的8080端口是无效的:
$ curl 10.244.1.95:8080
curl: (7) Failed connect to 10.244.1.95:8080; Connection refused
需要手动触发Pod滚动更新, 这样才能再次加载nginx.conf配置文件:
$ kubectl patch deployments.apps my-nginx --patch '{"spec": ": {"template": {"metadata": {"annotations": {"version/config": "20200219"}}}}}'
使用ConfigMap的限制条件如下。
◎ ConfigMap必须在Pod之前创建。
◎ ConfigMap受Namespace限制,只有处于相同Namespace中的Pod才可以引用它。
◎ ConfigMap中的配额管理还未能实现。
◎ kubelet只支持可以被API Server管理的Pod使用ConfigMap。
kubelet在本Node上通过 --manifest-url或–config自动创建的静态Pod将无法引用ConfigMap。
◎ 在Pod对ConfigMap进行挂载(volumeMount)操作时,在容器内部只能挂载
为“目录”,无法挂载为“文件”。
在挂载到容器内部后,在目录下将包含ConfigMap定义的每个item,如果在该目录下原来还有其他文件,则容器内的该目录将被挂载的ConfigMap覆盖。
如果应用程序需要保留原来的其他文件,则需要进行额外的处理。
可以将ConfigMap挂载到容器内部的临时目录,再通过启动脚本将配置文件复制或
者链接到(cp或link命令)应用所用的实际配置目录下。