AIGC标识 kubelet 会拉起 /etc/kubernetes/manifests 下的所有 Pod 吗?

结论

不会。 kubelet 只处理 .yaml、.yml、.json 三种扩展名的文件,其他文件(.txt、.md、.bak、二进制文件、无扩展名文件等)会被直接忽略,不记录错误,也不会创建 Pod。子目录不会递归扫描。即使是 yaml 文件,内容解析失败或校验不通过也不会拉起 Pod。

分析版本

  • 软件:Kubernetes kubelet
  • 版本:v1.29(源码逻辑自 v1.6 引入后长期稳定,v1.20+ 无变化)
  • 源码路径:pkg/kubelet/config/file.go
  • 核心函数:extractFromPath()、isPodManifestFile()

详细分析

1. 静态 Pod 目录监控机制

kubelet 通过启动参数 --pod-manifest-path 指定静态 Pod 清单目录,默认值为 /etc/kubernetes/manifests。

kubelet 启动时会创建一个文件源(sourceFile),定期扫描该目录,并通过 fsnotify 监听文件变化。当目录中有文件新增、修改或删除时,kubelet 会触发重新扫描。

2. 文件过滤逻辑(核心)

扫描目录时,extractFromPath() 函数对每个文件依次做以下判断:

2.1 跳过子目录

if file.IsDir() {
    continue  // 子目录直接跳过,不递归扫描
}

manifests 目录下的子目录不会被递归处理,子目录里的 yaml 文件也不会被读取。

2.2 只识别三种扩展名

func isPodManifestFile(filename string) bool {
    ext := filepath.Ext(filename)
    return ext == ".yaml" || ext == ".yml" || ext == ".json"
}

只有扩展名是 .yaml、.yml、.json 的文件才会进入下一步解析。其他文件直接跳过,不记录任何日志。

这意味着:

  • test.txt → 忽略
  • README.md → 忽略
  • pod.yaml.bak → 忽略(扩展名是 .bak)
  • pod(无扩展名)→ 忽略
  • pod.yaml → 处理
  • pod.yml → 处理
  • pod.json → 处理

2.3 读取并解析文件内容

通过扩展名过滤后,kubelet 读取文件内容,尝试解析为 Pod 对象:

pod, err := kubetypes.DecodePod(data)
if err != nil {
    klog.ErrorS(err, "Failed to decode pod manifest file", "path", path)
    continue
}
  • 解析失败 → 记录错误日志(Failed to decode pod manifest file),不创建 Pod
  • 解析成功 → 进入字段校验

2.4 字段校验

解析成功后,kubelet 还会对 Pod 字段做基本校验:

  • metadata.name 必填
  • spec 不能为空
  • 容器列表不能为空
  • 等等

校验不通过的 Pod 同样会被拒绝,不会创建。

3. 完整处理流程

扫描 /etc/kubernetes/manifests 目录
        │
        ▼
  是子目录吗? ──是──→ 跳过
        │否
        ▼
  扩展名是 .yaml/.yml/.json 吗? ──否──→ 直接跳过(无日志)
        │是
        ▼
  读取文件内容
        │
        ▼
  解析为 Pod 对象 ──失败──→ 记录错误日志,跳过
        │成功
        ▼
  字段校验 ──不通过──→ 记录错误,跳过
        │通过
        ▼
  创建/更新静态 Pod ✅

4. 验证方法

4.1 放入非 yaml 文件测试

# 放一个 txt 文件
echo "test content" > /etc/kubernetes/manifests/test.txt

# 查看 kubelet 日志,不会有任何关于 test.txt 的记录
journalctl -u kubelet -f --since "1 min ago" | grep -i "test.txt"
# 无输出 → 说明被直接忽略

# 查看 pod,不会有 test 相关的 pod
kubectl get pods -A | grep test

4.2 放入无效 yaml 文件测试

# 放一个格式错误的 yaml
cat > /etc/kubernetes/manifests/bad.yaml <<EOF
apiVersion: v1
kind: Pod
metadata
  name: bad-pod
EOF
# 注意:上面 metadata 后面少了冒号,yaml 语法错误

# 查看 kubelet 日志,会有解析错误
journalctl -u kubelet -f --since "1 min ago" | grep -i "bad.yaml"
# 输出类似:Failed to decode pod manifest file ... bad.yaml

4.3 查看当前静态 Pod

# 静态 Pod 的命名格式是 <pod-name>-<node-name>
kubectl get pods -A | grep -E "etcd|kube-apiserver|kube-controller|kube-scheduler"
# 这些控制平面组件通常都是以静态 Pod 方式运行的

5. 注意事项

  1. 文件扩展名严格匹配:pod.yaml.bak 的扩展名是 .bak,不会被处理。如果想临时禁用某个静态 Pod,把文件重命名为 pod.yaml.disabled 即可。

  2. 大小写敏感:Linux 上 pod.YAML 不会被识别(扩展名是大写的 .YAML),必须是小写。

  3. 符号链接:kubelet 会跟随符号链接,如果 manifests 目录下有指向外部 yaml 文件的软链接,也会被处理。

  4. 文件权限:kubelet 需要有读取文件的权限,通常以 root 运行所以没问题,但如果以非 root 用户运行需要注意权限。

  5. 删除文件即删除 Pod:从 manifests 目录删除 yaml 文件,kubelet 检测到后会自动删除对应的静态 Pod。

6. 源码位置参考

kubernetes/
└── pkg/
    └── kubelet/
        └── config/
            ├── file.go          # sourceFile 实现,extractFromPath、isPodManifestFile
            ├── file_linux.go    # Linux 平台特定的文件监听
            └── types.go         # Pod 配置类型定义

核心函数 isPodManifestFile 在 pkg/kubelet/config/file.go 中,自 Kubernetes v1.6 引入静态 Pod 目录扫描机制以来,该过滤逻辑一直保持稳定,截至 v1.29 无变化。

posted on 2026-09-10 23:58  王景迁  阅读(14)  评论(0)    收藏  举报

导航