简介
生产环境中很多应用程序的配置可能需要通过配置文件,命令行参数和环境变量的组合配置来完成。这些配置应该从image中解耦,以此来保持容器化应用程序的可移植性。在K8S1.2后引入ConfigMap来处理这种类型的配置数据。
- Configmap用于保存服务的配置数据,以键值对形式存储。
- configMap 资源提供了向 Pod 注入配置数据的方法。
- 旨在让镜像和配置文件
解耦
,以便实现镜像的可移植性
和可复用性
。 - 典型的使用场景:
- 填充环境变量的值
- 设置容器内的命令行参数
- 填充卷的配置文件
创建ConfigMap
创建ConfigMap的方式有4种:
• 使用字面值创建
• 使用文件创建
• 使用目录创建
• 编写configmap的yaml文件创建
使用字面值创建
[root@server2 manifest]# kubectl create configmap mycm --from-literal=wo=caoaoyuan --from-literal=ni=liuyan
configmap/mycm created /cm名,任意 /输入健值对
[root@server2 manifest]# kubectl get cm
NAME DATA AGE
mycm 2 115s
[root@server2 manifest]# kubectl describe cm mycm
Name: mycm
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
ni:
----
liuyan
wo:
----
caoaoyuan
Events: <none>
文件的形式
[root@server2 manifest]# kubectl create configmap my-config-2 --from-file=/etc/resolv.conf
configmap/my-config-2 created
[root@server2 manifest]# kubectl get cm
NAME DATA AGE
my-config-2 1 7s
mycm 2 4m4s
[root@server2 manifest]# kubectl describe cm my-config-2
Name: my-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
resolv.conf: //key的名称是文件名称
----
3
nameserver 114.114.114.114 //value的值是这个文件的内容
Events: <none>
[root@server2 manifest]# cat /etc/resolv.conf
nameserver 114.114.114.114
通过目录创建
[root@server2 ~]# mkdir test
[root@server2 ~]# cp /etc/resolv.conf test/
[root@server2 ~]# cp /etc/fstab test/
[root@server2 ~]# ls test/
fstab resolv.conf
[root@server2 ~]# kubectl create configmap my-config-3 --from-file=test
configmap/my-config-3 created
[root@server2 ~]# kubectl describe cm my-config-3
Name: my-config-3
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
fstab:
----
#
# /etc/fstab
# Created by anaconda on Tue Apr 28 02:35:30 2020
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/rhel-root / xfs defaults 0 0
UUID=004d1dd6-221a-4763-a5eb-c75e18655041 /boot xfs defaults 0 0
#/dev/mapper/rhel-swap swap swap defaults 0 0
resolv.conf:
----
nameserver 114.114.114.114
Events: <none>
可以发现通过目录进行创建的时候,是把目录内的文件作为,key, 其内容作为 value。
编写configmap的yaml文件
[root@server2 ~]# mkdir cm
[root@server2 ~]# cd cm/
[root@server2 cm]# vim cm1.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1-config
data:
db_host: "172.25.0.250" //还是健值对的形式
db_port: "3306"
[root@server2 cm]# kubectl create -f cm1.yaml
[root@server2 cm]# kubectl describe cm cm1
Name: cm1-config
Namespace: default
Labels: <none>
Annotations:
Data
====
db_host:
----
172.25.0.250
db_port:
----
3306
Events: <none>
如何使用configmap
- 通过环境变量的方式直接传递给pod
- 通过在pod的命令行下运行的方式
- 作为volume的方式挂载到pod内
通过环境变量
方式一:重新定义
[root@server2 cm]# vim cm1.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1-config
data:
db_host: "172.25.0.250"
db_port: "3306"
---
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
command: ["/bin/sh", "-c", "env"] //启用这个pod执行这个命令
env:
- name: key1 //环境变量名称
valueFrom: //数据来源
configMapKeyRef:
name: cm1-config //把configmap的数据应用到pod中
key: db_host //健是上面定义的key1,值是db_host的值
- name: key2
valueFrom:
configMapKeyRef:
name: cm1-config
key: db_port
restartPolicy: Never
[root@server2 cm]# kubectl apply -f cm1.yml
configmap/cm1-config unchanged
pod/pod1 created
[root@server2 cm]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod1 0/1 Completed 0 6s //执行命令后就完成了
[root@server2 cm]# kubectl logs pod1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=pod1
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
key1=172.25.0.250 //key1对应db_host值
KUBERNETES_PORT_443_TCP_PROTO=tcp
key2=3306 //key2对应db_port的值
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
[root@se
方式二:直接导入cm
[root@server2 cm]# vim cm1.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1-config
data:
db_host: "172.25.0.250"
db_port: "3306"
---
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
command: ["/bin/sh", "-c", "env"]
envFrom:
- configMapRef:
name: cm1-config ///直接从cm中导入数据
restartPolicy: Never
[root@server2 cm]# kubectl apply -f cm1.yml
configmap/cm1-config unchanged
pod/pod1 created
[root@server2 cm]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod1 0/1 Completed 0 6s
[root@server2 cm]# kubectl logs pod1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=pod1
SHLVL=1
db_port=3306
...
db_host=172.25.0.250 //导入了cm中的值
使用conigmap设置命令行参数
[root@server2 cm]# vim cm1.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1-config
data:
db_host: "172.25.0.250"
db_port: "3306"
---
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
[root@server2 cm]# kubectl apply -f cm1.yml
configmap/cm1-config unchanged
pod/pod1 created
[root@server2 cm]# kubectl logs pod1
172.25.0.250 3306 //调用出来了
通过数据卷使用configmap
[root@server2 cm]# vim cm1.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1-config
data:
db_host: "172.25.0.250"
db_port: "3306"
---
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: pod1
image: busybox
command: ["/bin/sh", "-c", "cat /config/db_host"] /查看改目录下内容,没有会自动创建
volumeMounts: /卷挂载
- name: config-volume /使用的卷的名称
mountPath: /config /挂载点
volumes: /指定卷
- name: config-volume //指定卷名称
configMap:
name: cm1-config //映射到cm上,
[root@server2 cm]# kubectl apply -f cm1.yml
configmap/cm1-config unchanged
pod/pod1 created
[root@server2 cm]# kubectl logs pod1
172.25.0.250 db_host的值
更改一下:
command: ["/bin/sh", "-c", "cat /config/db_port"] /改为查看端口
[root@server2 cm]# kubectl apply -f cm1.yml
configmap/cm1-config unchanged
pod/pod1 created
[root@server2 cm]# kubectl logs pod1
3306
这样就明白了吧。
我们还可以登陆进去看一下。
[root@server2 cm]# cat cm1.yml
...(省略)
spec:
containers:
- name: pod1
image: nginx /换为nginx镜像
volumeMounts:
- name: config-volume
mountPath: /config
volumes:
- name: config-volume
configMap:
name: cm1-config
[root@server2 cm]# kubectl apply -f cm1.yml
configmap/cm1-config unchanged
pod/pod1 created
[root@server2 cm]# kubectl exec -it pod1 -- bash
root@pod1:/# cd /config/
root@pod1:/config# ls
db_host db_port
root@pod1:/config# cat db_host
172.25.0.250
root@pod1:/config# cat db_port
3306root@pod1:/config#
configmap热更新
configmap管理的是配置数据,是和服务挂钩的,当服务配置发生改变时,cm 也应该进行热更新。
就比如我们上面的 cm 中有两个数据, db_host 、db_port,当他们的数据发生改变时,会不会进行热更新哪。
[root@server2 cm]# kubectl edit cm cm1-config //直接编辑这个 cm
# 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:
db_host: 172.25.0.100
db_port: "3300" //改变地址和端口
kind: ConfigMap
[root@server2 cm]# kubectl describe cm cm1-config
Name: cm1-config
Namespace: default
Labels: <none>
Annotations:
Data
====
db_host:
----
172.25.0.100
db_port:
----
3300 //可见cm已经改变
Events: <none>
那末pod中会不会自动进行更新哪?
[root@server2 cm]# kubectl exec -it pod1 -- cat /config/db_host
172.25.0.100
[root@server2 cm]# kubectl exec -it pod1 -- cat /config/db_port
3300
我们再外部更新完卷之后,pod内也发生了变化。但是pod的服务并没有发生变化。
我们现在把 pod 内 nginx 的配置文件放到数据卷中,将 cm 和pod内的容器结合起来,当我们更改时,让他自动热更新到 pod 中 的 nginx 服务 中去。
这是我们就需要用到deployment的控制器来进行滚动更新。
[root@server2 cm]# vim server.conf //编写一个nginx的配置文件
server {
listen 8000; / 修改一下端口
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
[root@server2 cm]# kubectl create configmap nginx-config --from-file=server.conf //创建cm
configmap/nginx-config created
[root@server2 cm]# kubectl describe cm nginx-config
Name: nginx-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
server.conf:
----
server {
listen 8000;
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
Events: <none>
创建控制器:
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 //挂载到include目录下
volumes:
- name: config-volume
configMap:
name: nginx-config //映射nginx-config 这个cm的数据
[root@server2 cm]# kubectl apply -f cm1.yml
deployment.apps/my-nginx created
[root@server2 cm]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx-575fd5b9c4-nmm4b 1/1 Running 0 34s 10.244.141.216 server3 <none> <none>
[root@server2 cm]# curl 10.244.141.216
curl: (7) Failed connect to 10.244.141.216:80; Connection refused
[root@server2 cm]# curl 10.244.141.216:8000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title> //80端口访问不到,8000端口生效了
登陆进pod中查看:
[root@server2 cm]# kubectl exec -it my-nginx-7db4c4f989-scdc4 -- cat /etc/nginx/conf.d/server.conf
server {
listen 8000; /是8000端口
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
热更新:
[root@server2 cm]# kubectl edit cm nginx-config //编辑cm
data:
server.conf: "server {\n listen\t8080 端口换为8080端口
[root@server2 cm]# kubectl exec my-nginx-7db4c4f989-scdc4 -- cat /etc/nginx/conf.d/server.conf
server {
listen 8080; /变成了8080端口
server_name _;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
但是pod仍然没有改变,只是配置文件变了,还没有触发。
[root@server2 cm]# curl 10.244.22.11:8080
curl: (7) Failed connect to 10.244.22.11:8080; Connection refused
[root@server2 cm]# curl 10.244.22.11:8000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title> 8000端口依然访问,更新后的8080端口访问不到
需要手动触发Pod滚动更新, 这样才能再次加载nginx.conf配置文件:
[root@server2 cm]# kubectl patch deployments.apps my-nginx --patch \
'{"spec": {"template":{"metadata": {"annotations": {"version/config": "2020062701"}}}}}'
my-nginx
指定控制器,因为控制器下可能有多个pod
version/config": "20200219
指定版本
这是之前的pod:
[root@server2 cm]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx-7db4c4f989-scdc4 1/1 Running 0 16m 10.244.22.11 server4 <none> <none>
[root@server2 cm]# kubectl patch deployments.apps my-nginx --patch '{"spec": {"template":{"metadata": {"annotations": {"version/config": "2020062701"}}}}}'
deployment.apps/my-nginx patched
[root@server2 cm]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx-7db4c4f989-scdc4 1/1 Running 0 20m 10.244.22.11 server4 <none> <none>
my-nginx-7f45d597d5-n7jft 0/1 ContainerCreating 0 4s <none> server3 <none> <none>
[root@server2 cm]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx-7db4c4f989-scdc4 0/1 Terminating 0 20m <none> server4 <none> <none>
my-nginx-7f45d597d5-n7jft 1/1 Running 0 7s 10.244.141.217 server3 <none> <none>
可以看出新建了一个pod,之前的pod已经删除了
[root@server2 cm]# curl 10.244.141.217:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title> /已经切换到8080端口了