最近在维护一套基于Docker和cri-dockerd的Kubernetes生产集群时,遇到了一个棘手的问题:每当服务器意外重启或计划性关机后,kube-apiserver、kube-controller-manager和kube-scheduler这三个核心控制平面组件总是无法自动恢复。这直接导致集群控制面瘫痪,需要手动干预才能恢复正常。
这种情况在传统systemd管理的Kubernetes集群中并不常见,因为systemd会默认自动重启这些关键服务。但在使用Docker容器运行时配合cri-dockerd的场景下,这些核心组件的生命周期管理出现了特殊的行为模式。
在标准的Kubernetes部署中,控制平面组件通常以三种方式运行:
我们的环境属于第三种情况,且使用了Docker作为容器运行时。这里的关键在于:当Docker服务重启时,默认不会自动恢复之前运行的容器,这与systemd的服务恢复机制有本质区别。
cri-dockerd作为Docker和Kubernetes CRI接口之间的适配层,其行为会影响容器的生命周期管理。当节点重启时:
Kubelet理论上应该负责重新创建这些组件容器,但在我们的场景中观察到:
最直接的解决方法是配置Docker的restart policy:
bash复制# 修改现有容器配置
docker update --restart=unless-stopped <container_id>
# 或者创建新容器时指定
docker run --restart=unless-stopped ...
对于已经部署的Kubernetes组件,可以通过修改它们的容器定义:
bash复制# 以kube-apiserver为例
docker inspect k8s_kube-apiserver | grep -A 10 RestartPolicy
更符合Kubernetes设计理念的方式是将这些组件转为静态Pod:
bash复制--pod-manifest-path=/etc/kubernetes/manifests
yaml复制apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
spec:
containers:
- name: kube-apiserver
image: k8s.gcr.io/kube-apiserver:v1.24.0
...
restartPolicy: Always
对于仍想保持Docker容器运行方式的场景,可以优化systemd单元配置:
ini复制[Unit]
After=docker.service cri-dockerd.service
Requires=docker.service cri-dockerd.service
bash复制ExecStartPost=/usr/local/bin/check-kube-components.sh
bash复制systemctl stop kubelet
systemctl stop docker
systemctl start docker
systemctl start kubelet
bash复制kubectl get pods -n kube-system
docker ps | grep -E 'apiserver|controller|scheduler'
建议监控以下指标判断恢复是否成功:
| 指标名称 | 检查方法 | 预期值 |
|---|---|---|
| API Server响应状态 | curl -k https://localhost:6443 | HTTP 200 |
| Controller Manager活跃状态 | kubectl get cs | Healthy |
| Scheduler活跃状态 | kubectl get cs | Healthy |
| 容器运行状态 | docker inspect |
Running |
在长时间停机后可能遇到证书过期问题:
bash复制# 检查证书有效期
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates
# 提前续期证书
kubeadm alpha certs renew all
多个组件同时启动可能导致:
建议在systemd单元中添加延迟启动:
ini复制[Service]
ExecStartPre=/bin/sleep 30
配置完善的日志收集以便故障诊断:
bash复制# Docker日志驱动配置
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
对于生产环境,我强烈建议采用静态Pod部署方案配合适当的监控告警。这种方案在我维护的多个集群中表现出最稳定的恢复特性,特别是在意外断电等极端场景下仍能保持较高的可用性。