kubernetes存储 -- Configmap应用配置管理

    技术2022-07-10  146

    简介

    生产环境中很多应用程序的配置可能需要通过配置文件,命令行参数和环境变量的组合配置来完成。这些配置应该从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端口了
    Processed: 0.014, SQL: 9