关键词:Kubernetes排障、CreateContainerConfigError、Secret not found、K8s Secret、命名空间 namespace、kubectl describe pod、环境变量 envFrom secretRef、secretKeyRef、Helm Secret管理、Kustomize disableNameSuffixHash、生产事故复盘、K8s故障SOP
结论先行:这不是“Pod/镜像/资源”的问题,是配置引用的 Secret 在目标命名空间里不存在(或名字不一致),Kubernetes 校验失败直接拒绝启动容器。
1. 典型现象与定位入口
1.1 现象(Pod 卡住、容器不启动)
常见状态/报错组合:
-
Pod 已创建、Deployment 看起来也“对”
-
但容器始终不启动
-
kubectl describe 的 Events 里出现:
-
CreateContainerConfigError
-
Secret "<name>" not found
-
1.2 直接看 Pod Events
kubectl describe pod <pod-name> -n <namespace>
你通常会在 Events 里看到类似:
- Error: secret "db-credentials" not found
2. 为什么会“直接拒绝启动”
2.1 Secret 是命名空间级别资源(namespace-scoped)
-
Secret 只能被同一命名空间内的 Pod 引用
-
dev/db-credentials 和 prod/db-credentials 是两份完全不同的对象,即便名字相同也不互通
2.2 Kubernetes 机制
当 Pod spec 里写了:
envFrom:
– secretRef:
name: db–credentials
Kubernetes 的判断非常硬:在该命名空间里是否存在同名 Secret;不存在就失败。
3. 复盘
一个微服务上线,Deployment 引用数据库凭据:
- envFrom.secretRef.name: db-credentials
- Pod 结果卡在 CreateContainerConfigError,报 Secret "db-credentials" not found
- 集群没问题、镜像没问题、代码也没问题——配置错/缺才是根因
4. 标准化排障 SOP(按这个顺序,最快解决)
Step 0:确认你操作的是“哪个集群”
很多“明明创建了 Secret 还是找不到”,本质是建在 A 集群,Pod 跑在 B 集群。
kubectl config current-context
kubectl cluster-info
Step 1:确认命名空间
kubectl config view –minify | grep namespace || true
kubectl get pod <pod-name> -A | head
Step 2:确认 Secret 是否存在
kubectl get secret <secret-name> -n <namespace>
kubectl get secrets -n <namespace> | grep -n "<secret-name>" || true
绝大多数情况下:它就是不在这个 namespace 里。
Step 3:对照工作负载 YAML,检查引用点(名字、路径、类型)
常见引用点:
-
envFrom.secretRef.name
-
env[].valueFrom.secretKeyRef.name
-
volumes[].secret.secretName
-
imagePullSecrets[].name
快速拉取当前生效配置(以 Deployment 为例):
kubectl get deploy <deploy-name> -n <namespace> -o yaml | sed -n '1,200p'
Step 4:修复(3 选 1)
-
创建缺失 Secret
-
把 Secret 部署到正确命名空间
-
修正 YAML 引用名(与真实 Secret 名完全一致)
Step 5:验证(必须做复核)
kubectl rollout restart deploy <deploy-name> -n <namespace>
kubectl rollout status deploy <deploy-name> -n <namespace>
kubectl get pod -n <namespace> -owide
5. 常见根因清单(实战高频)
5.1 Secret 创建在错误的命名空间
-
应用在 payments
-
Secret 却建在 default
-
结果:Not found
5.2 Secret 名字拼写错误(肉眼最难发现)
secretRef:
name: db–credetials # 拼写错
5.3 Secret 还没部署(发布顺序/依赖问题)
-
CI/CD 执行顺序问题
-
Helm Chart 依赖/钩子顺序问题
-
手工创建漏了
5.4 Kustomize 生成 Secret 被自动加后缀,导致“引用名对不上”
真实场景常见:kustomize 生成的 Secret 名变成 mysql-pass-<hash>,但你的 YAML 还在引用 mysql-pass,最终报 not found。可通过 generatorOptions.disableNameSuffixHash: true 等方式处理。
6. 修复示例
6.1 直接创建 Secret(通用做法)
kubectl create secret generic db-credentials -n payments \\
–from-literal=DB_USER='user1' \\
–from-literal=DB_PASS='StrongPassw0rd!'
6.2 用清单方式管理(推荐:纳入 IaC/Helm/GitOps)
cat > db-credentials.secret.yaml <<'EOF'
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: payments
type: Opaque
stringData:
DB_USER: "user1"
DB_PASS: "StrongPassw0rd!"
EOF
kubectl apply -f db-credentials.secret.yaml
Secret 属于敏感数据对象,推荐用“受控流程 + 权限隔离 + GitOps/密钥系统”管理,不要长期依赖手工创建。
6.3 把“缺 Secret”变成发布前置校验(避免上线才炸)
# 发布前校验:引用的 Secret 必须存在
kubectl get secret db-credentials -n payments >/dev/null
8. 一页纸 Checklist(排障/上线通用)
-
kubectl config current-context 是否正确
-
Pod 所在 namespace 是否正确
-
kubectl get secret <name> -n <namespace> 是否存在
-
Workload YAML 引用名是否完全一致(含大小写/连字符)
-
是否存在 kustomize/helm 重命名导致不一致
-
修复后 rollout status + describe pod 复核无 Events 报错


