kubelet 配置文件(KubeletConfiguration)与 kubeadm 的 kubelet-config ConfigMap
kubelet-config 讲的是 kubelet 的两层配置:
KubeletConfiguration(apiVersion: kubelet.config.k8s.io/v1beta1),由 kubelet 的 --config 参数指定;kube-system 命名空间的 kubelet-config ConfigMap,再由 kubeadm init / kubeadm join 下发到每个节点的 /var/lib/kubelet/config.yaml。kubelet 的配置项多且杂,官方推荐的做法是把参数写进配置文件而不是命令行:flag 只保留那些"一辈子不会变、或者节点之间不能共享"的东西(如 --hostname-override、--node-ip、--config 本身)。实际上,KubeletConfiguration 对应的大部分命令行 flag 已经被标记为废弃。
| 参数 | 指向什么 | 内容 |
|---|---|---|
--config |
kubelet 的配置文件 | KubeletConfiguration,含 maxPods、evictionHard、cgroupDriver 等 |
--kubeconfig |
访问 apiserver 的凭据文件 | kubeconfig 格式,含 cluster、user、context |
二者完全不同,却在口语里都叫"kubelet 的配置"。并不存在 --kubelet-config-file 这个参数 —— 指向配置文件的就是 --config。
--config=/var/lib/kubelet/config.yaml # KubeletConfiguration
--kubeconfig=/etc/kubernetes/kubelet.conf # 认证凭据
--config-dir=/etc/kubernetes/kubelet.conf.d # drop-in 目录
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: 0.0.0.0
port: 10250
clusterDomain: cluster.local
clusterDNS:
- 10.96.0.10
maxPods: 110
cgroupDriver: systemd
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
apiVersion 与 kind 是必填的。相对路径在配置文件里相对于配置文件所在目录解析,命令行 flag 里的相对路径则相对 kubelet 的工作目录 —— 同一个相对路径在两处含义不同。
官方文档给出的合并顺序(括号里是优先级,越靠后越高):
1. 命令行上的 feature gates # 最低
2. kubelet 配置文件(--config)
3. drop-in 配置文件(--config-dir,按文件名排序)
4. 命令行参数(不含 feature gates) # 最高
要点:
--feature-gates 优先级最低,配置文件里的 featureGates 反而会覆盖它;.conf 后缀的文件(含子目录)。# drop-in 示例:99- 前缀保证排在最后、覆盖前面所有文件
/etc/kubernetes/kubelet.conf.d/99-kubelet-address.conf
# 1. configz:节点上实际生效的完整配置(含默认值)
kubectl proxy --port=8001 &
curl -s http://127.0.0.1:8001/api/v1/nodes/<node-name>/proxy/configz | jq .
# 2. 节点上的文件
sudo cat /var/lib/kubelet/config.yaml
sudo cat /var/lib/kubelet/kubeadm-flags.env # KUBELET_KUBEADM_ARGS="--flag1=value1 ..."
sudo cat /etc/kubernetes/kubelet.conf # 连接 apiserver 的凭据
# 3. 看 kubelet 启动时实际用了哪些参数
sudo systemctl cat kubelet
sudo journalctl -u kubelet -n 100 | head -40
# 4. 打印 kubeadm 的默认配置(含 KubeletConfiguration 的默认值)
kubeadm config print init-defaults --component-configs KubeletConfiguration
# init 时:kubeadm 把 KubeletConfiguration 写到 /var/lib/kubelet/config.yaml,
# 并上传到 kube-system 的 kubelet-config ConfigMap
kubectl -n kube-system get cm kubelet-config -o yaml
# 手工重新上传(改过配置之后)
sudo kubeadm init phase upload-config kubelet
# join 时:kubeadm 用 Bootstrap Token 换取凭据,下载 kubelet-config ConfigMap,
# 写到新节点的 /var/lib/kubelet/config.yaml
kubeadm join <endpoint> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
# 升级时:把 ConfigMap 里的配置重新下发到本节点
sudo kubeadm upgrade node phase kubelet-config
# 升级后重启
sudo systemctl daemon-reload && sudo systemctl restart kubelet
kubeadm 在节点上维护的几个文件:
| 路径 | 内容 |
|---|---|
/var/lib/kubelet/config.yaml |
KubeletConfiguration,来自 kubelet-config ConfigMap |
/var/lib/kubelet/kubeadm-flags.env |
KUBELET_KUBEADM_ARGS,实例相关的 flag(如 cgroup driver) |
/var/lib/kubelet/instance-config.yaml |
kubeadm 探测到的本机信息(如 CRI socket) |
/etc/kubernetes/kubelet.conf |
连接 apiserver 的 kubeconfig |
/etc/kubernetes/kubelet.conf.d/ |
drop-in 配置目录(可选) |
以下取值来自 kubelet.config.k8s.io/v1beta1 的默认化逻辑(即使用 --config 时的默认值):
| 字段 | 默认值 |
|---|---|
| maxPods | 110 |
| cgroupDriver | cgroupfs(kubeadm 会写成 systemd) |
| authentication.anonymous.enabled | false |
| authentication.webhook.enabled | true |
| authorization.mode | Webhook |
| healthzBindAddress / healthzPort | 127.0.0.1:10248 |
| nodeStatusUpdateFrequency | 10s |
| nodeStatusReportFrequency | 5m |
| runtimeRequestTimeout | 2m |
| syncFrequency | 1m |
| imageGCHighThresholdPercent / Low | 85 / 80 |
| imageMinimumGCAge | 2m |
| containerLogMaxSize / MaxFiles | 10Mi / 5 |
| evictionHard | memory.available=100Mi、nodefs.available=10%、nodefs.inodesFree=5%、imagefs.available=15%、imagefs.inodesFree=5% |
| evictionPressureTransitionPeriod | 5m |
| enforceNodeAllocatable | ["pods"] |
| serializeImagePulls | true(设置了 maxParallelImagePulls ≥ 2 时为 false) |
| failSwapOn | true |
| kubeAPIQPS / kubeAPIBurst | 50 / 100 |
| eventRecordQPS / eventBurst | 50 / 100 |
| registryPullQPS / registryBurst | 5 / 10(字段已废弃) |
| containerRuntimeEndpoint | unix:///run/containerd/containerd.sock |
| podLogsDir | /var/log/pods |
| resolvConf | /etc/resolv.conf |
--kubelet-config-file 这个参数。网上不少文章这么写,但 kubelet 的 flag 列表里只有 --config(指向 KubeletConfiguration)、--config-dir(drop-in 目录)和 --kubeconfig(apiserver 凭据)。照抄会导致 kubelet 启动失败。--config 与 --kubeconfig 是两回事。前者是 kubelet 自身的行为配置,后者是访问 apiserver 的身份凭据。把 kubeconfig 的内容塞进 --config,kubelet 会报解码错误。kubelet-config ConfigMap 不会影响已经在运行的节点。ConfigMap 只在 kubeadm init、kubeadm join、kubeadm upgrade node phase kubelet-config 这几个时机被读取并写入节点磁盘。想让改动生效,必须重新下发并重启 kubelet(或直接改节点上的 /var/lib/kubelet/config.yaml)。/var/lib/kubelet/config.yaml 的手工修改。在下一次 kubeadm upgrade 时会用 ConfigMap 的内容重新生成该文件。要长期保留的调整,应该改 ConfigMap(或使用 KubeletConfiguration patches),而不是只改节点上的文件。evictionHard 是整体替换,不是逐项合并。只写一项会让其余阈值归零(等于取消保护)。要么写全五项,要么设置 mergeDefaultEvictionSettings: true。--config 与使用纯命令行 flag,默认值并不相同。为了向后兼容,kubelet 在纯 flag 模式下沿用旧默认(匿名认证开启、授权模式 AlwaysAllow);而用 --config 时,未指定的字段取配置文件版默认值(匿名认证关闭、Webhook 鉴权)。kubeadm 生成的 config.yaml 会显式写出这两个字段,所以 kubeadm 集群不受影响,但手工搭的节点要留意。--v、--vmodule、--log-flush-frequency、--provider-id、--fail-cgroupv1。--config-dir 就没有 drop-in 效果。文件名必须 .conf 结尾,并按文件名字典序合并。--feature-gates 是最低优先级,配置文件里的 featureGates 会覆盖它 —— 与"命令行覆盖配置文件"的通用规则相反。--dynamic-config-dir 已经不存在。历史上的动态 kubelet 配置(DynamicKubeletConfig)机制已被移除,现代 kubelet 的 flag 列表里没有它;不要再按老文档配置。改配置的正规做法是改文件 + 重启 kubelet。cgroupDriver 配错会让节点直接不可用。kubelet 的默认是 cgroupfs,而 containerd 等运行时通常使用 systemd;两者不一致会导致 Pod 无法启动。kubeadm 生成的配置会把它设成 systemd,手工运维时要保证这一项与容器运行时一致。systemctl daemon-reload && systemctl restart kubelet 之后,用 kubectl get nodes -w 观察;配置写错时 kubelet 会启动失败,节点状态停留在旧值,日志在 journalctl -u kubelet。kubeadm-flags.env 里的 flag 覆盖;configz 展示的是 kubelet 进程内实际生效的完整配置(含默认值),这才是排障依据。staticPodPath 与 kubeconfig 里的凭据一样是"高价值配置"。控制面组件以静态 Pod 形式运行,意味着能改 staticPodPath 指向目录的人,就能在节点上以 root 身份运行任意容器。这个字段的权限与审计要按最高等级对待。kubelet — 节点代理kubeadm — Kubernetes集群安装工具feature-gates — 特性门控的启用方式capacity-planning — kubeReserved / systemReserved 预留配置kubeconfig — kubeconfig 文件格式crictl — 容器运行时调试工具