ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Kubernetes二进制部署实战:多主多从高可用集群搭建指南

Kubernetes二进制部署实战:多主多从高可用集群搭建指南 1. 环境规划与部署思路1.1 为什么选择二进制方式部署先聊点实在的。很多人接触Kubernetes第一步用的是kubeadm一条kubeadm init下去集群就拉起来了确实省事。但如果你想把K8S真正吃透或者你所在的场景是内网离线环境、定制化需求极多的政企项目二进制部署是一条绕不开的路。它让你清清楚楚看到每一个组件以什么参数启动、证书是怎么签出来的、kubelet是怎么找到apiserver的——这些底层逻辑搞明白了后面排障会轻松很多。我自己第一次完整看完二进制集群跑起来的时候那种“原来如此”的感觉比用kubeadm跑了十遍都强。再直白一点kubeadm本质上是把二进制部署的过程给封装成了脚手架它做的工作——生成证书、写配置文件、启动静态Pod——每一步都能用二进制方式手工复现。逆着这个思路部署一遍你就等于把kubeadm的底层源码给“拆”了一遍。以后遇到kubeadm诡异的报错你不会慌你能猜到大概是哪一步出了问题。另外版本号和组件一致性在二进制部署里全凭自己把控。你可以自由选择kube-apiserver、kubelet、kube-proxy的具体版本自由度极高。比如这次我们使用的1.35.0版本也是目前社区比较活跃的版本线。如果你看到的版本号和我写的不完全一致很正常K8S的版本迭代速度实在太快我写这篇文章时1.35是个相对较新的版本。所有二进制包务必从官方GitHub Release页面下载且控制面与节点面的组件版本要保持一致这是铁律。1.2 节点规划与网络拓扑多主多从集群关键不只是“多”而是“怎么安排”。我这次规划了6台机器3个控制平面节点3个工作节点。生产环境建议至少这个规模既能保证控制面高可用又不至于把资源开销搞得太大。具体规划如下主机名IP地址角色配置k8s-master01192.168.10.11control-plane4C8Gk8s-master02192.168.10.12control-plane4C8Gk8s-master03192.168.10.13control-plane4C8Gk8s-worker01192.168.10.21worker4C8Gk8s-worker02192.168.10.22worker4C8Gk8s-worker03192.168.10.23worker4C8Gk8s-lb192.168.10.30负载均衡器 VIP独立部署这个拓扑里有一个关键点控制平面节点前面必须加一层负载均衡。如果你的架构里只有三个apiserver却没有VIP或LB那控制面本身就成了单点跟“高可用”三个字完全不沾边。生产环境可以用F5、LVS、KeepalivedHAProxy我们这里用一个单独的节点部署HAProxy再搭配Keepalived提供一个VIP。网络方面也要提前规划清楚三个网段缺一不可节点网络192.168.10.0/24用于节点之间通信Pod网段172.16.0.0/16给CNI插件用的每个Pod会从这个网段拿地址Service网段10.96.0.0/12Kubernetes集群内部的虚拟IP我用的CNI是Calico因为它的BGP模式性能不错网络策略功能也完整。有的团队习惯Flannel但多主多从生产集群我更推荐Calico后面会细说为什么。2. 系统基础环境与工具链2.1 系统初始化与内核参数调优拿到一台全新的Ubuntu 24.04服务器第一件事不是急着装东西而是把系统层面统一调整好。六台机器都要执行这一步漏掉任何一个参数后面都会变成诡异的故障。关闭swap是第一步。Kubernetes对swap的容忍度在1.22之后虽然有所改善但生产环境建议还是关闭因为内存交换会让Pod的QoS保障变得不可预测。sudo swapoff -a sudo sed -i / swap / s/^\(.*\)$/#\1/ /etc/fstab接着加载必要的内核模块。K8S要能跑起来overlay和br_netfilter这两个模块是基础前者负责容器镜像层的存储驱动后者负责把宿主机上的网络桥接流量送到iptables处理。cat EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter内核参数这里有个很容易被忽略的细节net.bridge.bridge-nf-call-iptables。如果不设为1经过网桥的IPv4流量无法被iptables规则处理而K8S的Service转发全靠iptables或IPVS规则——这会导致Service完全不通而节点间ping又是好的特别让人困惑。cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ptables 1 net.bridge.bridge-nf-call-ip6tables 1 net.ipv4.ip_forward 1 vm.swappiness 0 EOF sudo sysctl --system顺手把主机名和hosts都配置好。三台master最好用有明显区分的主机名比如k8s-master01、k8s-master02、k8s-master03因为后面很多证书的CN(Common Name)和节点名是绑定的命名乱套了后面排查会非常痛苦。sudo hostnamectl set-hostname k8s-master01 # /etc/hosts里统一写入 192.168.10.11 k8s-master01 192.168.10.12 k8s-master02 192.168.10.13 k8s-master03 192.168.10.21 k8s-worker01 192.168.10.22 k8s-worker02 192.168.10.23 k8s-worker03 192.168.10.30 k8s-lb注意所有节点的/etc/hosts必须一致尤其是etcd集群之间通信它直接用主机名互相访问。如果你在hosts里漏写某个节点etcd会报警etcdserver: request timed out。这个问题我踩过一次白白浪费了一个下午。2.2 安装containerd并调整关键参数容器运行时我选择containerd这是目前K8S官方推荐的运行时。Docker虽然也能通过cri-dockerd适配器接入K8S但多一层适配就多一层故障面而且在资源占用和镜像拉取速度上containerd都要更轻快一些。Ubuntu 24.04自带的软件源里就有containerd包但版本可能比较旧。为了方便折腾我直接用Docker官方源安装最新版sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release echo \$VERSION_CODENAME\) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt-get update sudo apt-get install -y containerd.io装完先别急着启动生成的默认配置至少有两个地方需要改。第一cgroup驱动必须改成systemd。K8S从1.24开始把节点上的cgroup驱动默认改成了systemd而containerd如果还在用cgroupfs两者就会冲突最典型的症状就是kubelet报failed to run Kubelet\ err\failed to run kubelet\。第二pause镜像地址要改。containerd默认的pause镜像在国外仓库国内环境拉取会超时这一步不改后面初始化集群时会卡在container image pull。sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml然后编辑/etc/containerd/config.toml找到SystemdCgroup改成true同时把sandbox_image改成国内镜像源。[plugins.io.containerd.grpc.v1.cri] sandbox_image registry.aliyuncs.com/google_containers/pause:3.9 [plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options] SystemdCgroup true改完之后重启containerd让它生效。可以顺手验证一下sudo systemctl restart containerd sudo systemctl enable containerd sudo ctr version提醒一个实操细节用ctr命令查看containerd版本时如果报failed to dial\...\说明guard socket路径不对试着加--address /run/containerd/containerd.sock参数。2.3 安装cfssl证书工具证书是整个Kubernetes集群安全的基石我选择用cfssl来签发证书而不是openssl。原因很简单cfssl支持批量签发、JSON配置化管理比openssl一条条命令行敲要高效得多而且配置文件写清楚了后续查看、复用都很方便。三个工具都要装上cfssl、cfssljson、cfssl-certinfo。下载地址可以从GitHub的cloudflare/cfssl仓库找。sudo curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64 -o /usr/local/bin/cfssl sudo curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64 -o /usr/local/bin/cfssljson sudo curl -L https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl-certinfo_1.6.5_linux_amd64 -o /usr/local/bin/cfssl-certinfo sudo chmod x /usr/local/bin/cfssl*我这里为了快速下载用的GitHub直链如果你的网络环境和我不一样可以从国内镜像站下载文件名都一样。后面所有证书相关的操作我都在k8s-master01上执行其他节点只负责接收分发下来的证书文件。3. 证书体系与etcd集群3.1 证书规划与批量签发很多人第一次搞K8S证书都会懵因为需要签的证书太多了etcd集群内部通信要一套etcd和apiserver通信要一套apiserver对外提供服务要一套kubelet跟apiserver通信又要一套。我把它们理成一个清单你就清楚了证书用途CN关键SANca.pem集群根CAkubernetes-etcd-ca.pemetcd根CAetcd-ca-etcd-server.pemetcd对外服务etcd-server所有etcd节点IPhostnameetcd-peer.pemetcd节点间通信etcd-peer所有etcd节点IPhostnameapiserver.pemkube-apiserver对外kube-apiserver集群VIP所有节点IPService网段admin.pemkubectl管理员kubernetes-admin集群VIPkubelet-client.pemapiserver访问kubeletsystem:kubelet-api-admin集群VIPkube-controller-manager.pemcontroller-manager访问apiserversystem:kube-controller-manager集群VIPkube-scheduler.pemscheduler访问apiserversystem:kube-scheduler集群VIPkube-proxy.pemproxy访问apiserversystem:kube-proxy集群VIP这里最容易出错的是apiserver证书的SAN列表。你需要把可能访问apiserver的地址全部写进去三个master节点IP、VIP地址、负载均衡节点的地址还不要忘了Service网段里的kubernetes.default.svc和对应的ClusterIP。缺一个SAN对应的访问方式就会拿到证书校验失败的错误最典型的报错是x509: certificate is valid for ..., not ...。我把证书生成脚本放在/Users/owen/ssl/目录下用一个CA配置文件统一管理基础信息// ca-config.json { signing: { default: { expiry: 876000h }, profiles: { kubernetes: { usages: [signing, key encipherment, server auth, client auth], expiry: 876000h }, etcd: { usages: [signing, key encipherment, server auth, client auth], expiry: 876000h } } } }写CA证书请求文件再生成根CA。注意根CA的CN不能太随意因为后面所有子证书的校验链都要追溯到它。cfssl gencert -initca ca-csr.json | cfssljson -bare ca生成etcd的证书时ca-csr.json里需要注意把三个节点的IP和主机名都写进SAN。这点和单机部署完全不同多主集群一个节点都不能漏。3.2 部署etcd集群etcd是Kubernetes的“神经中枢”所有持久化数据都存在这里。它挂了整个集群的控制面全部瘫痪。多主高可用里etcd通常每个控制平面节点上部署一个实例形成三节点etcd集群。我把etcd二进制放在/usr/local/bin/数据目录放在/var/lib/etcd配置文件放在/etc/etcd。三台master节点上除了IP和hostname不同其余配置基本一致。拿k8s-master01来说配置文件/etc/etcd/etcd.conf大致长这样ETCD_NAMEetcd01 ETCD_DATA_DIR/var/lib/etcd/etcd01 ETCD_LISTEN_PEER_URLShttps://192.168.10.11:2380 ETCD_LISTEN_CLIENT_URLShttps://192.168.10.11:2379,https://127.0.0.1:2379 ETCD_INITIAL_ADVERTISE_PEER_URLShttps://192.168.10.11:2380 ETCD_ADVERTISE_CLIENT_URLShttps://192.168.10.11:2379 ETCD_INITIAL_CLUSTERetcd01https://192.168.10.11:2380,etcd02https://192.168.10.12:2380,etcd03https://192.168.10.13:2380 ETCD_INITIAL_CLUSTER_STATEnew ETCD_INITIAL_CLUSTER_TOKENk8s-etcd-cluster ETCD_CERT_FILE/etc/etcd/ssl/etcd-server.pem ETCD_KEY_FILE/etc/etcd/ssl/etcd-server-key.pem ETCD_CLIENT_CERT_AUTHtrue ETCD_TRUSTED_CA_FILE/etc/etcd/ssl/etcd-ca.pem ETCD_PEER_CERT_FILE/etc/etcd/ssl/etcd-peer.pem ETCD_PEER_KEY_FILE/etc/etcd/ssl/etcd-peer-key.pem ETCD_PEER_CLIENT_CERT_AUTHtrue ETCD_PEER_TRUSTED_CA_FILE/etc/etcd/ssl/etcd-ca.pemETCD_INITIAL_CLUSTER_STATE这里填new只在首次启动时有效。如果三台etcd之前有过数据目录启动会失败并提示cluster ID mismatch这时要清空/var/lib/etcd再重新拉起。我见过有人在测试环境反复初始化集群忘了清数据目录浪费了大量时间排查。三台节点的etcd都启动后检查一下集群状态etcdctl --cacert/etc/etcd/ssl/etcd-ca.pem \ --cert/etc/etcd/ssl/etcd-server.pem \ --key/etc/etcd/ssl/etcd-server-key.pem \ --endpointshttps://192.168.10.11:2379,https://192.168.10.12:2379,https://192.168.10.13:2379 \ endpoint health --cluster正常的输出是三行healthtrue。到这里整个集群的数据底座就稳了。4. 控制平面组件部署4.1 kube-apiserver多实例与负载均衡接入apiserver是整个Kubernetes的入口所有kubectl命令、kubelet心跳、controller-manager和scheduler的请求全都要经过它。它是无状态服务所以多实例部署反而简单——三台master各自跑一个apiserver前面用VIP做负载均衡。我在每台master上创建systemd服务管理apiserver关键启动参数里--advertise-address和--bind-address要改成各自节点的IP--etcd-servers写上三台etcd的地址--service-cluster-ip-range填Service网段10.96.0.0/12--service-node-port-range给NodePort预留端口范围。apiserver的证书路径、客户端CA路径、etcd CA路径都要指向先前生成好的证书一处都不能错。启动前可以先手工执行一下二进制路径看启动参数有没有拼写错误kube-apiserver \ --advertise-address192.168.10.11 \ --bind-address192.168.10.11 \ --secure-port6443 \ --etcd-servershttps://192.168.10.11:2379,https://192.168.10.12:2379,https://192.168.10.13:2379 \ --etcd-cafile/etc/kubernetes/pki/etcd/etcd-ca.pem \ --etcd-certfile/etc/kubernetes/pki/etcd/etcd-server.pem \ --etcd-keyfile/etc/kubernetes/pki/etcd/etcd-server-key.pem \ --client-ca-file/etc/kubernetes/pki/ca.pem \ --tls-cert-file/etc/kubernetes/pki/apiserver.pem \ --tls-private-key-file/etc/kubernetes/pki/apiserver-key.pem \ --service-cluster-ip-range10.96.0.0/12 \ --service-node-port-range30000-32767 \ --authorization-modeNode,RBAC启动后确认6443端口在监听然后测试一下能否正常访问。用curl带证书访问/healthz返回ok就是正常的。多主集群里还要在k8s-lb这台机器上配置HAProxy把三台master的6443端口都代理到一个VIP上。HAProxy的配置不算复杂核心是后半段的backend定义backend k8s-apiserver balance roundrobin option httpchk GET /healthz server master01 192.168.10.11:6443 check server master02 192.168.10.12:6443 check server master03 192.168.10.13:6443 check注意一个细节option httpchk配好HAProxy会通过/healthz接口实时感知apiserver是否存活。如果不配健康检查某个apiserver挂了流量还会继续打过去用户就会偶发连接重置。4.2 kube-controller-manager与kube-scheduler这两个组件通常是成对出现的。controller-manager负责维护集群的期望状态scheduler负责把新Pod调度到合适的节点上它们都是有状态服务但支持选主多实例部署时通过--leader-electtrue参数竞争选主同一时刻只有一个实例真正工作其余处于热备状态。controller-manager的启动参数里要指定--kubeconfig指向哪个配置文件还有--cluster-cidr必须是Pod网段172.16.0.0/16这个参数会直接影响后面网络策略和NodePort的相关行为。三台master都启动后--leader-elect会让它们自动协商这也是为什么我说它们是有状态服务却可以多活部署。scheduler的配置相对简单--kubeconfig指到自己的配置文件--leader-electtrue同样开启选主。这两个组件启动后可以用kubectl get lease看到当前谁是leaderkubectl get leases --all-namespaces看到holderIdentity字段有具体节点名就说明选主机制正常工作了。4.3 kubectl与kubeconfig配置三台master都要能执行kubectl命令实现方式是给每台机器配置好/root/.kube/config。这个kubeconfig文件要引用admin证书server地址填VIP而不是某个单独的master IP这样即使某台apiserver挂了kubectl也能通过VIP正常访问集群。kubectl config set-cluster kubernetes \ --certificate-authority/etc/kubernetes/pki/ca.pem \ --embed-certstrue \ --serverhttps://192.168.10.30:6443 kubectl config set-credentials admin \ --client-certificate/etc/kubernetes/pki/admin.pem \ --embed-certstrue \ --client-key/etc/kubernetes/pki/admin-key.pem kubectl config set-context kubernetes \ --clusterkubernetes --useradmin kubectl config use-context kubernetes配好之后可以验证一下kubectl能不能正常工作。如果报Unable to connect to the server: x509优先检查证书里的SAN是否包含了VIP地址。5. 工作节点与网络打通5.1 部署kubelet与kube-proxy控制面组件全部就绪后终于开始碰工作节点了。这一步就是让每个节点都能运行Pod核心是kubelet和kube-proxy这两个组件。kubelet是运行在每个节点上的“小管家”它负责管理Pod的生命周期和apiserver保持心跳通信。kubelet的启动参数比较多我整理几个容易踩坑的kubelet \ --kubeconfig/etc/kubernetes/kubelet.kubeconfig \ --config/etc/kubernetes/kubelet-config.yaml \ --node-labelsnode-role.kubernetes.io/workertrue \ --container-runtime-endpointunix:///run/containerd/containerd.sock \ --cgroup-driversystemd \ --kube-reservedcpu200m,memory512Mi \ --system-reservedcpu200m,memory512Mi--container-runtime-endpoint这个参数必须指向containerd的socket很多新手容易写成Docker的socket导致kubelet起不来。--cgroup-driver必须和containerd里设置的一致都是systemd否则kubelet会报错。注意kubelet需要的是一个独立的kubeconfig里面用system:node:节点名身份认证。这个证书的CN格式严格敏感必须是system:node:主机名否则apiserver会拒绝它注册节点——这个坑我帮助不止一个人排查过。kube-proxy负责实现Service的网络代理。启动前要检查--proxy-mode默认是iptables生产环境我会改成ipvs。ipvs模式性能更好、规则更清晰适合多主多从中Service数量较多的场景。改ipvs前节点上要确保ipvsadm已安装sudo apt-get install -y ipvsadmkube-proxy启动时会通过kubeconfig连接apiserver从这里读取Service和Endpoint信息然后写入节点的转发规则。5.2 安装Calico CNI插件到这里节点虽然注册到集群了但Pod之间还不能通信。Pod网段的分配和路由转发全靠CNI插件实现。我校生产环境用的Calico它和Flannel最大区别是天然支持NetworkPolicy网络策略且跨节点通信效率更高。在控制面准备好Calico的配置。用kubectl create -f方式安装kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml安装前要把calico.yaml里的CALICO_IPV4POOL_CIDR改成你的Pod网段默认配置通常写的192.168.0.0/16如果你的节点网段正好也是这个就会冲突。我这里的Pod网段是172.16.0.0/16。Calico的安装过程同时也会把calico-node和calico-kube-controllers两个工作负载部署到节点上。安装完成后检查一下kubectl get pods -n calico-system全部Running后测试跨节点Pod网络。在一台节点上创建一个测试Pod去ping另一台节点上的Pod IP通了就说明Calico工作正常。这里分享一个NAT环境下的坑如果你用VMware或VirtualBox搭测试环境节点网段往往是NAT模式Calico默认会启用IPIP隧道流量封装后跨节点通信没问题但如果宿主机防火墙没放行IPIP协议Pod间的互通可能时通时断。建议直接在VNet里把节点互相设为可直连或者改用VXLAN模式踩坑会少很多。5.3 验证集群状态从这一节开始Cluster已经具备完整的控制面和数据面了。先确认节点都变成Ready然后kubectl get nodes看到所有节点的STATUS都是Ready而且要确认VERSION列显示的是1.35.0。如果哪个节点一直NotReady用journalctl -u kubelet -f看kubelet日志大概率是某个参数不对或者证书有问题。控制面Pod的状态也要检查kubectl get pods -n kube-system正常的输出里有coredns、calico-kube-controllers、calico-node等Pod全部Running才算数。最后做个经典的端到端验证创建一个nginx deployment暴露Service从集群外部访问。我习惯用kubectl create deployment nginx --imagenginx:1.27然后kubectl expose deployment nginx --port80 --typeNodePort。访问http://任意节点IP:NodePort端口看到nginx欢迎页就说明整个链路从kubectl到API Server到Controller到Scheduler到Kubelet到Containerd到CNI全链路是通的。6. 高可用验证与故障演练6.1 apiserver单点故障模拟集群跑起来之后一定要做一次高可用验证否则你根本不知道前面搭的HAProxy和VIP是不是真的在干活。我习惯先停掉一台master上的kube-apiserversystemctl stop kube-apiserver然后马上执行kubectl get nodes正常情况下一两秒内能拿到响应因为请求通过VIP转发到了另外两台master。再把HAProxy的状态页打开看一下后端情况你会发现刚才停掉的那台已经被标记为DOWN。这个验证特别重要因为它同时检验了VIP、HAProxy和apiserver本身三层的可用性。如果发现kubectl请求出现间歇性失败多半是HAProxy的balance roundrobin算法劣化了连接或者健康检查配置不对回来改一下HAProxy配置就好。恢复apiserver后再看HAProxy状态页它应该自动重新标记为UP流量重新均匀分配——这个流程就证明了整个控制面的高可用是跑通的。6.2 etcd多节点故障模拟etcd集群的高可用验证同样要做而且比apiserver的验证更谨慎。etcd是持久化存储一旦数据不一致恢复成本很高。我的操作方法是先停掉一台etcd确认集群仍然能正常读写systemctl stop etcd然后创建几个测试资源比如新建namespace、创建configmap观察是否成功。Raft算法要求多数派存活三节点里挂一个完全没问题。随后重启这个etcd观察它是否会自动同步数据。用etcdctl查看成员列表确认它回到集群里。再检查一下这个节点的数据目录大小和另外两个节点对比确认它追上了最新数据。看到数据一致后才算真正完成了一次高可用验证。提醒模拟etcd故障时不要同时停掉两台。三节点etcd只能容忍一台故障同时挂两台意味着写操作会全部失败。如果你非要测试双节点故障的恢复那必须先停一台等集群稳定后再停第二台然后同时重启否则可能面临集群不可用的风险。7. 常见问题与避坑指南走到这一步你的集群已经成功跑起来了。这一节我把部署过程中最常踩的坑汇总一下顺手附上排查思路帮后来的人节省时间。7.1 证书相关的问题如何排查证书问题在K8S集群里出现的频率相当高一堆报错表面上看是网络问题或者权限问题深挖下去全是证书的锅。症状一x509: certificate is valid for A, not B这个是典型的SAN缺失。你用了A地址去访问服务但证书里只签了B地址。解决方式是回到证书生成那一步把你所有会用到的IP、域名、hostname都加进SAN。K8S集群里最容易被遗漏的地址是VIP地址和Service网段的ClusterIP。症状二certificate signed by unknown authority这是CA证书不匹配。要么是客户端没有带正确的CA证书要么是服务端用的证书不是客户端信任的那个CA签出来的。去核对一下相关组件的--client-ca-file、--root-ca-file配置路径和内容。症状三kubelet一直报401 Unauthorizedkubelet用的证书CN不对。必须是system:node:nodeName格式kubelet才会被允许注册节点。手动用改错的证书名生成kubeconfig然后重启kubelet看kubectl get nodes的注册结果。排查证书问题的通用思路是拿到报错里的证书信息用cfssl-certinfo工具看证书内容比对CN和SAN是否符合预期不要凭感觉猜孤证不立。7.2 多主集群专属故障单机集群不会遇到、多主才特有的问题主要有下面这几类。Leader选举异常controller-manager和scheduler的pod一直重启例如报leader-election lost。如果只是偶尔一条那是正常的leader切换心跳如果是频繁报错多半是网络抖动导致选主锁丢失或者多个实例配置了相同的identity导致冲突。确认--leader-electtrue已开启同时检查节点间网络延迟。etcd选主超时apiserver报etcdserver: request timed out说明apiserver访问etcd时连接超时。先确认etcd三个节点之间2380端口是否互通再检查etcd日志里有没有etcdserver: leader changed刷屏。这类问题通常是节点时钟漂移或者磁盘IO瓶颈导致的。VIP漂移后客户端连接重置用户反馈kubectl偶尔会报connection refused。这说明VIP从一台master漂移到了另一台但客户端旧连接没有正确处理。优先确认HAProxy的balance是否为roundrobinHTTP健康检查是否配置正确同时让客户端换用VIP加滚动重连的方式访问。7.3 资源规划与性能心得最后聊点非技术层面的经验。多主多从集群不是“机器越多越好”前期规划资源和预期负载要匹配。控制平面节点建议至少给到4核8Getcd对磁盘IO非常敏感有条件的话用SSD而不是机械盘。kube-apiserver的内存占用会随着集群规模增长变得比较大所以master节点的内存不能吝啬。工作节点根据你业务负载来决定配置但建议都预留至少2核4G给系统组件开销否则一个Pod资源密集型的应用就会把节点打爆。我也建议在生产环境里把组件的日志用journald统一收集并为日志设置合理的轮转策略。K8S组件默认日志量都不小尤其是kubelet和Calico的日志。不限制大小的话半年下来几十G日志文件吓死人。7.4 后续扩展方向集群跑起来了但生产实践才刚刚开始。你可以接着往里加东西给apiserver加审计日志、部署Metrics Server、接入Prometheus监控、配置HPA自动伸缩、做RBAC权限精细化管控。这些玩法每一个都是一大块内容也是Kubernetes真正体现价值的地方。CNI插件、Ingress Controller、存储插件这些生态组件多主集群里也有各自的选型讲究比如存储用Rook-Ceph还是自建NFS动态供给需要根据你的业务场景来判断这个没有标准答案完全取决于你需要什么。我的建议是先把基础集群用稳再一步步叠加而不是一上来就什么都套上去。按照这套流程你应该不难拿到一个完全可用的kubernetes 1.35.0多主多从集群。如果你在部署过程中踩到了这里没有提到的坑多半也是证书SAN、cgroup驱动、版本一致性这三个大方向出了问题先查这三个点大部分迷路的场景都能找回来。
返回列表