资讯动态

kubeadm多master高可用集群部署实战:HAProxy+Keepalived+etcd架构全解析

发布时间:2026/10/22 10:58:48 来源:尧图企业网站定制
kubeadm部署多master高可用集群这件事我相信很多朋友跟我一样最早都是从单master起步的。单master在测试环境完全够用可真到了准备上生产、或者需要对外提供稳定服务的时候单控制面就成了所有人心里最不踏实的那根刺apiserver一挂整个集群的调度、心跳、控制面全部瘫痪kubectl都不好使运维只能干瞪眼。更别提如果只是etcd单点存储真到宕机恢复的时候数据安全也是大问题。这篇文章我用kubeadm完整走一遍1.2x版本的多master高可用部署覆盖整体架构设计、基础环境准备、haproxykeepalived外部负载均衡层、控制面节点初始化与扩容、worker接入、以及最后的高可用故障演练。整篇适合两类人一类是已经在单master上跑过一段时间、想补齐高可用能力的运维开发另一类是刚接触k8s、希望直接按生产标准搭一套集群的新手。过程中我会把我实际踩过的坑和官方文档不会写清楚的地方都标出来尽量让你照着做就能复现。1. 高可用的本质单控制面为什么不够整体架构怎么搭1.1 单master集群的三个致命场景先说说为什么单master撑不住生产。Kubernetes控制面核心组件包括kube-apiserver、kube-controller-manager、kube-scheduler以及存储状态的etcd。kube-apiserver是整个集群的唯一入口所有kubectl请求、worker节点kubelet的心跳、控制器和调度器的读写全都走它。一旦这台机器宕机或者apiserver进程异常整个集群就进入了“有node但没人管”的状态kubectl完全连不上无法做任何变更、排查、发布worker节点上的kubelet发不出心跳控制器也没法正常调度Pod如果etcd也在同一台机器上并且磁盘损坏那集群数据恢复起来就更头疼了不只是“短暂不可用”而是“数据可能没了一半”。在生产环境里这种控制面不可用的时间窗口越长业务影响就越大。所以我们要做的并不是“多复制几台机器”而是要保证控制面任何一台节点失效时集群仍然能对外提供完整的读写能力同时数据层面有可靠的一致性保证。1.2 多master架构里的两个关键机制第一个关键机制是etcd的Raft多数派协议。kubeadm在1.2x版本里默认采用的是堆叠式stackedetcd也就是每一台master节点上都会跑一个etcd实例三个master就是三个etcd副本。Raft协议要求写入必须得到多数派也就是3节点中的至少2台确认所以只要不是同时挂掉两台masteretcd都能继续正常工作不会出现数据脑裂或者写入冲突。第二个关键机制是外部负载均衡层。虽然三台master都各自运行了kube-apiserver但kubectl、kubelet、scheduler、controller-manager这些客户端不能“各连各的”否则每个客户端视角中的master列表不一致就会出现某些组件只跟某一台master通信的情况。所以必须引入一个统一的入口也就是通过一个虚拟IPVIP或者内部域名把请求分发到三台apiserver上。这个入口自身也要高可用不然它挂了所有流量还是进不去。我这里用的是自建方式两台haproxy做四层负载均衡配合keepalived提供VIP漂移能力。如果你们环境里本身有云负载均衡产品也可以把这一层完全托管掉架构思路是一样的。小规模环境如果不要求LB本身高可用只搭一台haproxy也能用但这篇文章按生产标准写成两台。1.3 节点规划与版本选型我建议的最小高可用规模是3台master加2台worker再加2台LB机器。master数量选择3而不是2原因很直接etcd需要多数派2台master中挂掉1台就只剩1台无法形成多数派3台master即使挂1台剩2台仍然可以正常工作。这也是生产环境最常见、性价比最高的配比。节点角色主机名IP地址建议配置master-01k8s-master-01192.168.10.114C / 8G / 80Gmaster-02k8s-master-02192.168.10.124C / 8G / 80Gmaster-03k8s-master-03192.168.10.134C / 8G / 80Gworker-01k8s-worker-01192.168.10.214C / 8G / 100Gworker-02k8s-worker-02192.168.10.224C / 8G / 100Glb-01k8s-lb-01192.168.10.302C / 4G / 40Glb-02k8s-lb-02192.168.10.312C / 4G / 40G虚拟IPVIP我规划为192.168.10.100后续所有kubectl、kubelet都通过这个地址访问apiserver。版本选型方面文章以Kubernetes v1.27.3为例整个1.24到1.29系列都适用。需要注意几个配套组件的版本保持一致kubeadm、kubelet、kubectl必须是同一个版本不能混着用containerd使用1.7.x系列网络插件选calico它在多master场景下最省心。操作系统我以Ubuntu 22.04为例CentOS上的思路完全一样只有包管理命令和部分配置文件路径不同。2. 基础环境准备网络、内核、容器运行时每一样都别想跳过2.1 hosts、内核模块和系统参数这一步看起来基础但实际部署中大量问题都出在这里。首先在所有节点上把每个节点的IP和主机名写进/etc/hosts确保任何节点之间都能通过主机名互相访问后面kubeadm初始化、join节点的时候会频繁使用主机名通信。192.168.10.11 k8s-master-01 192.168.10.12 k8s-master-02 192.168.10.13 k8s-master-03 192.168.10.21 k8s-worker-01 192.168.10.22 k8s-worker-02 192.168.10.30 k8s-lb-01 192.168.10.31 k8s-lb-02然后开启Kubernetes需要的内核模块和系统参数。cat EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 EOF sudo sysctl --system这里的net.bridge.bridge-nf-call-iptables如果不开Kubernetes里ClusterIP类型的Service在跨节点访问时会出现网络不通的诡异问题而且很难排查。net.ipv4.ip_forward则是Pod流量转发、NodePort访问的必备前提。如果你发现modprobe之后/proc/sys/net/bridge下看不到相关文件可以先modprobe br_netfilter再看。关闭swap也是必须的。kubelet对swap的依赖是它无法正确计算Node资源、QoS分类也会出问题所以从1.2x开始kubelet默认不允许swap开启。执行下面命令并把/etc/fstab里的swap行注释掉确保重启之后也不会自动挂载。sudo swapoff -a sudo sed -i / swap / s/^/#/ /etc/fstab2.2 容器运行时containerd的安装与配置Kubernetes从1.24版本开始彻底不再支持docker作为运行时而是通过CRI接口对接containerd。我们直接使用containerd就对了。这里我以Ubuntu上通过apt安装containerd.io为例如果系统仓库里没有或版本太旧也可以直接从容器运行时官方仓库下载对应版本的二进制包解压到/usr/local。装好之后需要生成一份默认配置文件sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml然后要改两个关键位置。第一个是cgroup驱动Kubernetes节点默认的cgroup驱动是systemdcontainerd默认配置是cgroupfs如果不改之后kubelet启动会不断报错Pod也起不来。找到SystemdCgroup那一行改成true。[plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc] [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options] SystemdCgroup true第二个是沙箱镜像pause。containerd创建每一个Pod之前都会先启动一个pause容器默认使用的是registry.k8s.io/pause:3.9这类地址如果你的服务器拉不了这个镜像后面所有Pod都会卡在ContainerCreating。建议直接改成你自己环境能访问的镜像仓库里的pause镜像版本。[plugins.io.containerd.grpc.v1.cri] sandbox_image registry.example.com/pause:3.9改完执行sudo systemctl restart containerd然后sudo systemctl status containerd确认状态是active。这一步很多人跳过结果后面Pod全部起不来排查半天才定位到是sandbox_image的问题。2.3 安装kubeadm、kubelet、kubectlkubeadm、kubelet、kubectl三个包在Debian系通过apt安装CentOS系通过yum安装。国内服务器通常会把官方源替换成镜像站地址这里要注意三个包必须指定同一个版本号防止apt自动升级时把kubelet和kubeadm升到不同版本。我以Ubuntu 22.04为例先安装apt源需要的工具然后添加Kubernetes的apt仓库。仓库地址你按自己实际能访问到的镜像站替换。sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl gpg curl -fsSL https://mirrors.example.com/kubernetes/apt/doc/apt-key.gpg \ | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo deb [signed-by/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.example.com/kubernetes/apt/ kubernetes-xenial main \ | sudo tee /etc/apt/sources.list.d/kubernetes.list sudo apt-get update sudo apt-get install -y kubelet1.27.3-00 kubeadm1.27.3-00 kubectl1.27.3-00 sudo apt-mark hold kubelet kubeadm kubectl最后一行apt-mark hold很关键防止后续系统升级时把集群组件版本搞乱。安装完成后把kubelet设置成开机自启比如sudo systemctl enable --now kubelet但此时先不用启动它kubelet会等kubeadm初始化完成之后拿到配置再正常工作。2.4 提前拉取必要镜像kubeadm init的时候会拉取一堆组件镜像包括kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、etcd、pause等。如果你的服务器网络环境访问registry.k8s.io不顺畅强烈建议先在第一个master节点上把镜像列表打出来然后通过kubeadm配置文件里的imageRepository字段指向国内镜像站。kubeadm config images list --kubernetes-version v1.27.3比如你用某个镜像站的google_containers项目那在之后的kubeadm配置里就写imageRepository: registry.example.com/google_containers。为了验证仓库地址是否可用可以先手动拉一遍kubeadm config images pull --image-repository registry.example.com/google_containers如果这条命令没有报错说明镜像站和版本是可用的。这一步值得花时间做后面init会顺畅很多。3. 前置控制面入口haproxy和keepalived的落地细节3.1 为什么这一层不能直接省掉有人可能会问三台master上都装了apiserver为什么我不直接在kubectl里配置三个地址而要额外搭一套负载均衡这里有个关键原因Kubernetes的kubelet、controller-manager、scheduler以及各种客户端都需要通过一个稳定的地址访问apiserver如果这个地址一会指向这个master、一会指向那个master集群内的证书和连接都容易混乱。而且一旦某个master故障客户端并不会自动切换必须有负载均衡器来做健康检查和流量分发。外部LB层的作用就是对外暴露一个稳定的VIP内部把流量转发到三台master的6443端口。keepalived负责VIP的高可用haproxy负责后端节点的健康检查和负载均衡。当某台master挂了haproxy会自动把它摘掉当某台haproxy所在的LB节点挂了keepalived会把VIP漂移到另一台LB节点。这样一个两层高可用机制保证了控制面入口不会成为新的单点。3.2 haproxy配置要点两台LB节点上都需要安装haproxy安装命令Ubuntu用apt install haproxyCentOS用yum install haproxy。然后写配置文件/etc/haproxy/haproxy.cfg。这是一个最小可用的四层TCP负载均衡配置global log /dev/log local0 maxconn 4096 user haproxy group haproxy daemon defaults log global mode tcp option tcplog retries 3 timeout connect 5s timeout client 30s timeout server 30s frontend k8s_api bind *:6443 default_backend k8s_masters backend k8s_masters balance roundrobin option tcp-check server master-01 192.168.10.11:6443 check fall 3 rise 2 server master-02 192.168.10.12:6443 check fall 3 rise 2 server master-03 192.168.10.13:6443 check fall 3 rise 2这里有几个细节。mode tcp而不是mode http因为apiserver的流量是HTTPS加密的四层流量不需要也不应该在haproxy这一层做七层解析。option tcp-check表示用TCP层面的连通性来检测后端健康状态比单纯依赖check更可靠。fall 3 rise 2表示连续3次失败才判定后端不可用连续2次成功才重新启用避免apiserver短暂重启时被频繁摘掉和加回。配置好之后用haproxy -c -f /etc/haproxy/haproxy.cfg检查语法然后systemctl restart haproxy确认服务正常监听6443端口。3.3 keepalived VIP配置安装keepalived之后在两台LB节点上分别配置keepalived。第一台LB节点设置为MASTER状态第二台设置为BACKUP。注意两台机器的配置文件必须高度一致否则VRRP协议会出问题。LB-01节点的/etc/keepalived/keepalived.confvrrp_script chk_haproxy { script /usr/bin/killall -0 haproxy interval 2 weight 2 } vrrp_instance k8s_vip { state MASTER interface eth0 virtual_router_id 51 priority 101 advert_int 1 authentication { auth_type PASS auth_pass K8S8char } virtual_ipaddress { 192.168.10.100/24 dev eth0 label eth0:vip } track_script { chk_haproxy } }LB-02节点把state改成BACKUPpriority改成100其他内容保持一致。这里最需要关注的是track_script。keepalived如果只绑定网卡状态那么haproxy进程挂掉、但机器本身还活着的时候VIP不会漂移用户请求就会全部打到这台haproxy已经宕机的LB上。所以必须通过脚本检测haproxy进程一旦进程消失立即降低本机优先级触发VIP切换到备用节点。auth_pass长度不能超过8个字符这是keepalived的硬性限制。另外如果两台LB之间的网络有交换机或者防火墙管控要确保VRRP协议报文能正常通过云主机上还经常碰到安全组必须显式放行VRRP协议的情况。3.4 验证VIP与负载均衡状态两台LB配置完成后重启keepalived服务然后从master或任意一台机器上验证。首先检查VIP是否已经在一台LB节点上出现ip addr show eth0正常情况下第一台LB节点上会多出一个eth0:vip的虚拟接口。然后验证通过VIP访问apiserver健康检查接口curl -k https://192.168.10.100:6443/healthz能看到ok就是正常的。这一步验证通过之后再做一个简单的故障切换测试在LB-01上停掉haproxy服务观察VIP是否在几秒内漂移到LB-02上。4. 第一个控制面节点kubeadm配置与初始化的每一步4.1 kubeadm配置文件详解在所有准备工作完成之后进入关键步骤在master-01上初始化第一个控制面节点。我不推荐直接敲一串长长的kubeadm init命令行而是建议把所有配置写进一个YAML文件这样以后集群重建、二次部署都可以复用别人review你的配置也一目了然。在master-01上创建kubeadm-config.yamlapiVersion: kubeadm.k8s.io/v1beta3 kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.10.11 bindPort: 6443 nodeRegistration: criSocket: unix:///var/run/containerd/containerd.sock name: k8s-master-01 --- apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.27.3 imageRepository: registry.example.com/google_containers controlPlaneEndpoint: 192.168.10.100:6443 networking: podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12 apiServer: certSANs: - 192.168.10.11 - 192.168.10.12 - 192.168.10.13 - 192.168.10.100 - k8s-master-01 - k8s-master-02 - k8s-master-03几个字段必须认真对待。controlPlaneEndpoint必须写成VIP地址加端口也就是192.168.10.100:6443而不是master-01自己的IP。后续所有节点、所有客户端拿到这个配置后都会通过VIP访问控制面。certSANs是很多人会踩坑的地方。apiserver作为服务端它签发的TLS证书里必须包含客户端可能访问到的所有地址否则客户端用VIP访问apiserver时会直接报certificate验证失败。所以这里除了三个master的IP和主机名之外一定要把VIP也加进去。如果你后面还想用域名访问集群再把域名加进这个列表。podSubnet我用的是calico默认支持的10.244.0.0/16后面装calico时记得保持一致。如果你环境里这个网段和现有网络冲突换个网段后要同时改这里和calico的配置。4.2 执行init并理解关键输出配置文件准备好之后在master-01上执行初始化sudo kubeadm init --config kubeadm-config.yaml --upload-certs--upload-certs这个参数不是可选项对多master集群至关重要。它会把控制面节点之间通信所需的证书和密钥上传到集群的Secret中并在输出里生成一个certificate key。后面第二、第三个master加入时必须带上这个key才能从集群里获取这些证书从而无缝加入控制面。初始化过程一般会持续几分钟期间主要在拉取镜像、生成证书、启动apiserver/controller-manager/scheduler的静态Pod。命令执行成功之后末尾会输出三块内容配置kubectl所需的几条cp命令让worker节点加入集群的kubeadm join命令包含token让其他master节点加入控制面的kubeadm join命令包含token和certificate key。这三块内容最好都保存下来特别是kubeadm join命令。如果当时忘记保存后面仍可以通过命令重新生成token获取join命令。4.3 kubectl配置与单机验证初始化完成后在master-01上执行mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config然后kubectl get nodes应该能看到master-01状态是NotReady页面显示为NotReady是正常的因为网络插件还没装。此时还要检查一下核心组件Pod是否正常运行kubectl get pods -n kube-system如果一切正常你会看到kube-apiserver、etcd、kube-controller-manager、kube-scheduler以静态Pod方式运行在master-01上状态为Running或ContainerCreating。4.4 安装calico网络插件没有网络插件之前控制面虽然起来了但集群内Pod之间、Pod与Service之间是彻底不通的所以NotReady状态会一直存在。这里使用calico网络插件。先获取calico的manifest文件curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.26/manifests/calico.yaml我一般会在这个文件里做两处调整。第一处是把Pod网段改成和kubeadm配置里的podSubnet一致找到CALICO_IPV4POOL_CIDR环境变量确认值是10.244.0.0/16。第二处是设置网卡自动探测方法。如果服务器只有一张内网网卡可能不需要改但如果有多个网卡就得显式指定用哪块网卡否则calico可能选错网卡导致跨节点通信失败。在calico.yaml的env配置里加入- name: IP_AUTODETECTION_METHOD value: interfaceeth0修改之后执行kubectl apply -f calico.yaml等待几分钟kubectl get pods -n kube-system里所有calico相关的Pod应该会慢慢变成Running然后kubectl get nodes应该会看到master-01的状态变成Ready。到这里第一个控制面节点已经就绪但它还是孤单的。集群的高可用能力要靠下一节把master-02、master-03拉进来才能真正建立起来。5. 控制面扩容与worker接入从join到全部Ready5.1 重新生成join命令如果刚才初始化时保存了join命令可以直接用。如果像我一样经常忘记保存也没关系在master-01上重新生成即可。给worker节点生成join命令kubeadm token create --print-join-command给其他master节点生成包含证书key的join命令kubeadm init phase upload-certs --upload-certs这条命令会输出一个新的certificate key然后把它和token拼到一起就是完整的master join命令。需要注意如果已经有一堆master节点加入过了再重新upload-certs会重新生成一套证书密钥。这个操作在控制面扩容前做是没有问题的。5.2 第二个、第三个master加入控制面在master-02上提前完成基础环境配置同第2节的hosts、内核参数、containerd、kubeadm安装然后执行master join命令。典型的命令长这样sudo kubeadm join 192.168.10.100:6443 --token token \ --discovery-token-ca-cert-hash sha256:hash \ --control-plane --certificate-key key注意到我已经把join地址写成了VIP地址192.168.10.100:6443而不是master-01的IP这样新master才能通过统一的控制面入口完成接入。--control-plane参数告诉kubeadm这是控制面节点它会在本机拉起来etcd和apiserver的静态Pod并从集群Secret中拉取证书。master-02和master-03都执行同样的命令执行顺序没有要求但不建议同时在两台机器上join前面先等完成了再处理下一台方便观察日志定位问题。master-02加入完成之后回到master-01上执行kubectl get nodes正常情况下会看到三个master节点并且都处于Ready状态。再看一下etcd集群状态由于三台master上都在跑etcd它们会自动通过Raft组成一个三节点的etcd集群。你可以随时kubectl get pods -n kube-system | grep etcd确认三个etcd Pod都是Running。这里有一个很常见的坑master-02的join命令执行完之后如果长时间卡在等待control-plane不要急着CtrlC。第一件事是kubectl get pods -A看看master-02上的apiserver和etcd状态第二件事是journalctl -u kubelet -f看kubelet日志。多数情况下问题出在镜像拉取、证书key不对、或者防火墙没放行端口。5.3 worker节点加入worker节点的加入比master简单得多只需要token不需要--control-plane和--certificate-key。在worker-01和worker-02上执行sudo kubeadm join 192.168.10.100:6443 --token token \ --discovery-token-ca-cert-hash sha256:hashworker节点join成功后会作为普通计算节点注册到集群中。回到master-01执行kubectl get nodes所有节点都应变成Ready。此时可以用一个调度测试验证集群的完整性kubectl run test-nginx --imagenginx --replicas2 kubectl get pods -o wide看到两个Pod分别调度到不同node上并且Running说明整个集群已经从“多点控制面”到“Pod调度”全链路打通了。5.4 节点角色与标签确认多master集群起来之后可以用kubectl get nodes -o custom-columnsNAME:.metadata.name,ROLES:.metadata.labels,STATUS:.status.conditions查看节点角色。master节点上默认带着node-role.kubernetes.io/control-plane污点普通业务Pod不会调度到master上。如果你希望某些管理类组件或少量测试Pod也能跑在master节点上需要给这些Pod单独加容忍但生产环境不建议这样做。另外我建议尽早给worker节点打上用途标签比如zone、disk类型、GPU等为后续工作负载的亲和性调度做准备。这些标签在部署有状态服务时价值很大。6. 高可用验证与故障演练模拟真实宕机后的表现6.1 演练一master节点宕机部署完成不等于高可用只有真正故障演练验证过之后你才能对这套集群放心。我最推荐做的第一个演练就是把其中一台master直接关停观察集群是否仍然可用。先选择一台master比如master-01在它上面执行sudo systemctl stop kubelet停掉kubelet之后这台master上的apiserver、etcd静态Pod也会被停止或进入短暂异常状态。此时你从另一台机器上执行kubectl get nodes只要apiserver仍然正常响应并且node列表里其余节点显示Ready就说明控制面已经由另外两台master接管了。继续kubectl run test-nginx --imagenginxPod应该能正常创建和调度这说明调度器和控制器也在正常工作。需要注意的一点是三台master中挂掉一台时etcd仍然满足多数派2/3所以集群完全可用。但如果同时挂掉两台masteretcd就无法满足多数派整个控制面会进入只读或不可用状态。因此生产环境里至少保持3台master是有硬道理的。恢复方式很简单sudo systemctl start kubeletkubelet会自动重新拉起master-01上的静态Pod等Pod恢复后kubectl get nodes会看到master-01回到Readyetcd也会重新加入集群。整个过程不需要手动干预这也是kubeadm堆叠架构比较省心的地方。6.2 演练二负载均衡节点故障第二部分故障发生在LB层。在LB-01上停掉haproxysudo systemctl stop haproxy注意此时LB-01机器本身还活着但haproxy进程没了。keepalived的track_script脚本大约两秒后会探测到进程异常从而降低本机优先级VIP会漂移到LB-02。你可以先在LB-02上执行ip addr show eth0确认VIP已挂上来然后再次通过VIP访问apiserver健康检查curl -k https://192.168.10.100:6443/healthz如果返回ok说明控制面的外部入口切换是成功的。这个演练对客户端完全无感因为客户端访问的始终是同一个VIP。恢复haproxy之后如果你用的是上面示例中的抢占模式配置VIP可能会自动漂回LB-01如果你在生产环境里希望漂移后尽量不抖动可以考虑使用nopreempt非抢占模式具体取舍取决于你们的网络场景。这里我想特别提醒VIP漂移后如果业务侧有长连接可能会短暂中断但在Kubernetes场景下kubectl和组件重试机制比较完善影响通常可控。6.3 常见问题对照表下面这个对照表是我在多次部署过程中整理出来的供你在排错时快速定位。能提前看一遍很多问题就能在前面规避掉。症状可能原因排查方向kubeadm init卡在等待apiserver镜像拉取失败、cgroup驱动不对看kubectl get pods -n kube-systemjournalctl -u kubelet -f通过VIP访问apiserver报证书错误apiServer.certSANs里漏掉了VIP检查kubeadm配置文件certSANs重新初始化或更新证书join时报sha256校验不一致token过期或哈希拼写错误在master上重新执行kubeadm token create --print-join-command节点一直NotReady网络插件未安装或选错网卡检查calico相关Pod日志确认IP_AUTODETECTION_METHODPod一直ContainerCreatingsandbox_image里的pause镜像拉不到修改containerd配置里的sandbox_image并重启containerdcontainerd报cgroup错误SystemdCgroup未设为true改/etc/containerd/config.toml重启containerdVIP ping不通keepalived配置不匹配、VRRP被安全组拦截systemctl status keepalived检查日志和防火墙两台master同时宕机后集群不可用etcd失去多数派生产环境尽量保持3台master不要少于3台另外一个值得关注的点是证书续期。从1.2x版本开始kubeadm默认对kubelet、admin.conf等证书做自动续期正常轮转不需要人为干预。但如果你部署完后把集群放到一边不管超过一年又突然发现kubectl证书过期可以用kubeadm certs renew all手工续期然后在kubectl需要重新更新~/.kube/config。6.4 日常运维中的几个经验习惯多master集群跑起来之后日常运维和单master有些区别。我自己的习惯是第一所有面向集群的操作都通过VIP或域名进行不要直接连某台master的IP这样既能利用负载均衡的故障转移能力也能让kubeconfig里的服务器地址始终保持稳定。第二监控维度要比单master集群多一层。除了看kube-apiserver、etcd本身的状态还要关注haproxy后端健康检查和keepalived的角色状态这两个指标直接决定了控制面外部入口是否可靠。etcd的磁盘IOPS和延迟也要盯紧etcd对磁盘延时的容忍度比你想象中低得多。第三在做任何控制面节点的维护操作前先确认至少还有两台master在线避免无意中把集群降级到“只剩一台控制面”的危险状态。尤其在做etcd备份、节点重启、内核升级这类操作前记得先确认集群健康状况。最后再分享一个我自己踩过不少次的细节如果你在云主机上部署VIP之外一定要检查安全组对VRRP协议的放行情况。keepalived的配置看起来完全没问题但VIP就是起不来多半是VRRP报文被安全策略拦掉了。这类问题排查成本很高建议在规划阶段就把网络策略列表写清楚。多master高可用集群搭完之后后面要做的就是把生产环境里的Ingress、监控、日志、证书管理这些组件逐步铺上去。但地基打得稳不稳就看控制面这一层的高可用是否经得起故障考验。希望这篇文章能帮你把这一步走扎实。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑