二进制部署kubernetes是生产环境高可控性刚需,etcd证书必须独立签发、不可复用k8s ca,csr中hosts需包含所有节点ip和dns,且systemd配置中--peer-trusted-ca-file须指向etcd专属ca。

二进制安装 Kubernetes 不是“备选方案”,而是生产环境高可控性的刚需路径——尤其当集群需对接内网审计、定制化证书策略、或规避容器运行时抽象层干扰时,它几乎是唯一选择。
etcd 证书必须独立签发,不能复用 k8s CA
常见错误是直接用 kubernetes-ca.pem 去签 etcd 服务端证书,这会导致 etcdctl 连接失败或 apiserver 启动报 tls: bad certificate。etcd 是独立的分布式键值存储,其 TLS 链路与 k8s 控制面完全隔离,必须用专属 CA 或至少明确指定 --peer-cert-file 和 --trusted-ca-file 参数指向正确的证书对。
- 生成 etcd 证书时,
cfssl的 CSR 中hosts字段必须包含所有 etcd 节点 IP 和 DNS 名(如192.168.31.211,k8s-master-01),缺一不可 - etcd systemd service 中的
--peer-trusted-ca-file必须指向 etcd 自己的 CA,不是/etc/k8s/pki/ca.pem - 验证方式:在任一 master 执行
etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/etcd/ssl/ca.pem --cert=/etc/etcd/ssl/member.pem --key=/etc/etcd/ssl/member-key.pem endpoint health
kubelet 启动失败常因 bootstrap 流程卡在 CSR 等待批准
node 节点执行 systemctl start kubelet 后,kubectl get csr 显示 Pending 状态却迟迟不变成 Approved,本质是 RBAC 授权未生效或 controller-manager 未正确加载 bootstrap 相关参数。
- 确认
kube-controller-manager启动参数含--bootstrap-kubeconfig和--experimental-cluster-signing-duration,且指向的是 controller-manager 自身能读取的 kubeconfig - 检查
system:kubelet-bootstrapClusterRoleBinding 是否存在:kubectl get clusterrolebinding system:kubelet-bootstrap - 若 CSR 长期 Pending,手动批准:
kubectl certificate approve <csr-name></csr-name>;但上线前务必补全自动批准逻辑,否则扩容 node 会阻塞 -
bootstrap.kubeconfig中的 server 地址必须是 LB VIP 或 DNS,不能写死某台 master 的 IP,否则 LB 切换后 kubelet 无法续签
apiserver 的 --advertise-address 不等于 --bind-address
很多部署脚本把两者设成同一个 IP,导致多 master 场景下节点访问 apiserver 时证书校验失败,报错 x509: certificate is valid for 192.168.31.211, not 192.168.31.210(VIP)。
-
--bind-address是监听地址,通常为0.0.0.0或本机内网 IP,仅控制监听范围 -
--advertise-address是对外广播地址,必须和 apiserver 证书中 SAN(Subject Alternative Name)列表完全一致,且应设为 VIP(如192.168.31.210) - 生成 apiserver 证书时,CSR 的
hosts至少包含:127.0.0.1, 所有 master IP, VIP,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local - 若已部署完才发现证书不匹配,只能重签证书 + 重启所有 master 组件,无法热更新
containerd 配置里 disable_cgroup = false 是硬性要求
在 CentOS 7 / RHEL 7 系统上,若 containerd config.toml 中 disable_cgroup = true(默认值),kubelet 会持续报错 failed to run Kubelet: failed to create kubelet: misconfiguration: cgroup driver: "systemd" does not match with docker cgroup driver: "cgroupfs",即使你没装 Docker。
- kubelet 默认期望 runtime 使用 systemd cgroup driver,而 containerd 默认用 cgroupfs —— 这个不匹配不会在启动时报错,而是在 pod 创建阶段静默失败
- 必须显式设置:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]下添加SystemdCgroup = true - 同时确认
kubelet启动参数含--cgroup-driver=systemd,且与 containerd 配置严格一致 - 修改后需执行
systemctl restart containerd && systemctl restart kubelet,并检查crictl info | grep cgroup输出是否为systemd
最易被忽略的是证书有效期与集群生命周期的错配:etcd 和 apiserver 证书默认 1 年,但生产集群往往运行 3 年以上。一旦过期,整个控制面将不可用,且无法通过 kubectl 修复——必须用 etcdctl 直接操作底层数据,风险极高。建议签发时统一用 --ca-config 指定 10 年有效期,并记录所有证书的 not_after 时间戳到 CMDB。











