k8s 挂载 configmap 配置文件到容器

一、部署应用

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pod 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。

ConfigMap 将你的环境配置信息和容器镜像解耦,便于应用配置的修改。

configmap

configmap-demo.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  config.py: |
    key1: value1
    key2: value2
    key3: value3
    key4: value4

deploy部署文件

configmap-pod-demo.yaml

apiVersion: apps/v1                                                                                                                                                            
kind: Deployment                                                                                                                                                               
metadata:                                                                                                                                                                      
  name: my-deployment                                                                                                                                                          
spec:                                                                                                                                                                          
  replicas: 1                                                                                                                                                                  
  selector:                                                                                                                                                                    
    matchLabels:                                                                                                                                                               
      app: my-app                                                                                                                                                              
  template:                                                                                                                                                                    
    metadata:                                                                                                                                                                  
      labels:                                                                                                                                                                  
        app: my-app                                                                                                                                                            
    spec:                                                                                                                                                                      
      containers:                                                                                                                                                              
        - name: my-container                                                                                                                                                   
          image: arm64v8/kibana:7.17.10                                                                                                                                      
          volumeMounts:                                                                                                                                                        
            - name: config-volume                                                                                                                                              
              mountPath: /data/config.py
              subPath: config.py      # 加了 subPath 后,更新configmap不会自动更新pod里边的配置,如果不加则可以自动更新                            
          resources:                                                                                                                                                           
            limits:                                                                                                                                                            
              cpu: "0.5"                                                                                                                                                       
              memory: "512Mi"                                                                                                                                                  
            requests:                                                                                                                                                          
              cpu: "0.2"                                                                                                                                                       
              memory: "256Mi"                                                                                                                                                  
          ports:                                                                                                                                                               
            - containerPort: 5601                                                                                                                                              
      volumes:                                                                                                                                                                 
        - name: config-volume                                                                                                                                                  
          configMap:                                                                                                                                                           
            name: my-configmap     
            items:
              - key: config.py
                path: config.py
            defaultMode: 420   

部署

kubectl apply -f configmap-demo.yaml
kubectl apply -f configmap-pod-demo.yaml

查看部署的容器:

[root@master test]# kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
my-deployment-5bb4866c47-hh979   1/1     Running   0          9m39s

> kubectl exec -it my-deployment-5bb4866c47-hh979 /bin/bash

容器内容:

kibana@my-deployment-5bb4866c47-hh979:/data$ pwd 
/data

kibana@my-deployment-5bb4866c47-hh979:/data$ cat config.py
key1: value1
key2: value2
key3: value3

可以看到pod容器/data/ 目录下,创建了 config.py 文件,应用可以读取该配置文件来做业务操作。

二、自动更新

被挂载的 ConfigMap 内容会被自动更新

卷中使用的 ConfigMap 被更新时,所投射的键最终也会被更新。 kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新。 不过,kubelet 使用的是其本地的高速缓存来获得 ConfigMap 的当前值。 高速缓存的类型可以通过 KubeletConfiguration 结构的 configMapAndSecretChangeDetectionStrategy 字段来配置。

ConfigMap 既可以通过 watch 操作实现内容传播(默认形式),也可实现基于 TTL 的缓存,还可以直接经过所有请求重定向到 API 服务器。 因此,从 ConfigMap 被更新的那一刻算起,到新的主键被投射到 Pod 中去, 这一时间跨度可能与 kubelet 的同步周期加上高速缓存的传播延迟相等。 这里的传播延迟取决于所选的高速缓存类型 (分别对应 watch 操作的传播延迟、高速缓存的 TTL 时长或者 0)。

以环境变量方式使用的 ConfigMap 数据不会被自动更新。 更新这些数据需要重新启动 Pod。

说明: 使用 ConfigMap 作为 subPath 卷挂载的容器将不会收到 ConfigMap 的更新

为什么使用 ConfigMap 作为 subPath 卷挂载的容器将不会收到 ConfigMap 的更新?

当使用 ConfigMap 作为 subPath 卷挂载到容器时,容器将只会在启动时读取 ConfigMap 的内容,并将其复制到该挂载路径中。之后,容器中的文件与 ConfigMap 不再保持关联。

这意味着如果你在 ConfigMap 中更新了配置文件,容器将无法自动检测到更改,并不会自动重新加载或更新挂载的文件。这是因为 Kubernetes 在容器级别处理卷的更改通知,而不是文件级别。因此,对于 ConfigMap 中的更新,容器不会收到通知

subPath是volumes挂载的子目录或单个文件,如果volumes挂载的目录下不存在subPath定义的文件(目录或文件),那么就会在volumes对应的目录下创建一个subPath目录。

在ConfigMap 或 Secret 中使用 subPath,如果不指定subPath,则会把volumeMounts.mountPath对应目录下的文件都清掉,只存放ConfigMap 或 Secret 定义的文件

三、解决方案

在使用 helm upgrade 部署服务的时候, configmap 更新了但是 deployment没有更新,所以,这里就需要再 deployment 文件里边增加版本信息,每次更新时,更改版本信息即可 滚动更新;

在 Kubernetes 的 Deployment 中,以下 spec 字段的更改会触发滚动更新的自动更新机制:

  1. .spec.template.spec.containers[*].image:更改容器镜像时,Kubernetes 会启动新的 Pod 实例,并逐步停止旧的 Pod 实例。
  2. .spec.template.spec.initContainers[*].image:如果有初始化容器(init container),更改其镜像也会触发滚动更新。
  3. .spec.template.metadata.annotations:修改 Pod 模板中的注解也会触发滚动更新。
  4. .spec.template.metadata.labels:修改 Pod 模板中的标签会导致新的 Pod 被创建,并逐步停止旧的 Pod。
  5. .spec.minReadySeconds:增加或减少 minReadySeconds 的值将触发滚动更新,这个字段定义了 Pod 运行后必须等待的最短时间。

需要注意的是,只有在 Deployment 的 .spec.strategy.type 设置为 RollingUpdate 时,这些字段的更改才会触发滚动更新。如果你的滚动更新策略配置正确,但仍然无法自动更新,请检查以上字段是否正确设置,并确保使用 kubectl apply -f Deployment.yaml 或类似的方式应用了新的 Deployment 配置。

  template:
    metadata:
      annotations:
        deployUnit: DEMO
        {{ if .Values.global.deploy_version }}
        deployVersion: {{ .Values.global.deploy_version }}
        {{ end }}
      labels:
        app: {{ .Values.demo.labels }}

相关文章:
kubernetes.io | configmap

为者常成,行者常至