Kubernetes运行Sidecar时CrashLoopBackOff及ConfigMap卷挂载超时
在Kubernetes集群Deployment中新增Sidecar容器后,Pod启动失败,核心报错如下:
MountVolume.SetUp failed for volume "initdb" : failed to sync configmap cache: timed out waiting for the condition
执行kubectl describe pod mypod可见业务容器处于CrashLoopBackOff状态,重启次数持续上涨,事件列表持续抛出FailedMount警告,提示initdb卷的ConfigMap缓存同步超时。未添加Sidecar时Deployment可正常运行,添加Sidecar后立刻触发该故障。
1. 故障根本原因
该问题和挂载超时阈值没有关系,核心原因是新增Sidecar后,Pod的Spec中引入了名为initdb的ConfigMap类型卷引用,但存在配置错误,导致kubelet始终无法从apiserver同步到对应ConfigMap的缓存,常见错误场景:
initdb对应的ConfigMap资源不存在于Pod所在的命名空间- Pod Spec的顶层
volumes段没有正确定义initdb卷与对应ConfigMap的映射关系,或卷名、ConfigMap名存在拼写错误 - 未加Sidecar时Pod运行正常,是因为之前的Pod Spec根本没有引用
initdb卷,不存在同步需求;添加Sidecar后要么是Sidecar本身配置了挂载initdb卷但没补全卷定义,要么是修改Sidecar配置时误操作引入了无效的ConfigMap卷引用。
从提供的Deployment配置片段可直接看到异常:当前配置里volumes段只定义了volume-db这一个ConfigMap卷,但实际运行的Pod信息里出现了未在配置中声明的initdb卷,属于典型的配置不匹配问题。
2. 是否需要调大挂载超时阈值?
不需要。
Kubelet默认的ConfigMap缓存同步超时阈值完全覆盖正常集群的通信场景,调大参数只会掩盖配置错误,只要ConfigMap不存在、卷引用关系错误的问题不解决,等待再久也会触发超时,无法从根上解决问题。
3. 正确配置示例
先执行前置检查,确认ConfigMap是否存在:
# 替换为你的Pod所在命名空间 kubectl get configmap initdb -n <your-namespace>
- 如果返回NotFound,先创建对应的initdb ConfigMap
- 如果ConfigMap存在,按照以下规则修正Deployment配置:
场景1:Sidecar/业务容器/Init容器需要挂载initdb ConfigMap
需要在Pod Spec的顶层volumes段补全initdb卷的定义,再在需要挂载该卷的容器volumeMounts段声明挂载路径,参考配置片段如下:
apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/name: mydeployment name: mydeployment spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: mydeployment template: metadata: labels: app.kubernetes.io/name: mydeployment spec: volumes: - name: volume-db configMap: name: volume-db # 补全initdb卷的定义,和引用的ConfigMap名称对应 - name: initdb configMap: name: initdb optional: false initContainers: - name: database # 注意修正原配置里的datbase拼写错误 image: "myrepo/postgres:xxx" volumeMounts: - mountPath: /etc/postgresql name: volume-db readOnly: true # init容器需要挂载initdb就保留该段,不需要就删除 # - mountPath: /docker-entrypoint-initdb.d # name: initdb # readOnly: true containers: - name: maincontainer image: "myrepo/maincontainer:xxx" imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 protocol: TCP livenessProbe: httpGet: path: /maincontainer/health # 原配置写的localhost前缀为错误配置,httpGet默认访问Pod IP,不需要加localhost port: http initialDelaySeconds: 20 timeoutSeconds: 250 readinessProbe: httpGet: path: /maincontainer/health port: http initialDelaySeconds: 20 timeoutSeconds: 250 successThreshold: 5 periodSeconds: 10 # 主容器需要挂载initdb就保留该段,不需要就删除 # volumeMounts: # - name: initdb # mountPath: /path/you/need - name: sidecarcontainer image: "myrepo/sidecarcontainer:xxx" imagePullPolicy: IfNotPresent # Sidecar需要挂载initdb就补全下面的volumeMounts配置,不需要的话不要引入initdb的卷引用 volumeMounts: - name: initdb mountPath: /path/for/sidecar readOnly: true
场景2:不需要initdb卷
直接检查Sidecar、Init容器、主容器的volumeMounts配置,删掉所有对initdb卷的引用,同时删掉顶层volumes段里多余的initdb卷定义即可。
内容的提问来源于stack exchange,提问作者X T

