Kubernetes apiserver 高可用多实例部署如何实现?

来源:站长工具作者:BIT程序员头衔:程序员
导读:本期聚焦于BIT程序员创作的《Kubernetes apiserver 高可用多实例部署如何实现?》,敬请观看详情。kube-apiserver 是 Kubernetes 控制平面的唯一入口,所有 kubectl 请求、控制器监听和组件通信都要经过它。单实例一旦宕机,整个集群的调度、扩缩容和配置下发都会中断。要实现高可用,核心不是简单启动多个进程,而是让多个 apiserver 实例共享同一套 etcd 后端,并在前端挂载负载均衡器统一暴露地址。多实例部署需要解决证书 SAN 配置、节点端口规划、负载均衡健康检查以及 controller-manager 和 scheduler 的选主竞争等问题。本文从架构设计、证书准备、systemd 托管、Nginx 或 HAProxy 负载均衡配置几个层面,给出可落地的部署步骤,并说明多实例模式下 apiserver 自身无状态、etcd 负责一致性的原因。

kube-apiserver 是 Kubernetes 控制面的核心入口,kubectl 命令、kubelet 上报、控制器循环以及 scheduler 的调度决策都依赖它。生产环境中如果只部署一个 apiserver 实例,该进程崩溃或所在节点失联时,整个集群会进入不可管理状态,已有的 Pod 虽然可能继续运行,但无法创建、更新或删除资源。高可用的常见做法是启动多个 apiserver 实例,让它们连接同一个 etcd 集群,并在前端通过负载均衡器提供统一的访问地址。这样任意一个实例故障,负载均衡器会把流量切到其他实例,集群管理能力不中断。多实例部署并不是简单把二进制启动多次,还需要处理证书中的服务地址、客户端访问入口、健康检查路径以及控制面组件之间的选主关系。

Kubernetes apiserver 高可用多实例部署如何实现?

为什么 apiserver 高可用要采用多实例加负载均衡

apiserver 本身是无状态服务,集群的所有持久化数据都保存在 etcd 中。多个 apiserver 实例之间不需要做数据同步,也不存在主从关系,每个实例都可以独立处理读请求和写请求。因此,通过增加实例数量可以线性提升控制面的请求处理能力,尤其是对读操作密集的场景,例如大量 kubectl 查询或控制器频繁 watch 资源变化。不过写入能力仍然受限于 etcd 的提交延迟和磁盘性能,单纯增加 apiserver 实例并不会提高 etcd 的写吞吐。

前端负载均衡器的作用是隐藏后端多个实例的地址,对外只暴露一个稳定的 IP 或域名。如果没有负载均衡,kubectl 必须把 kubeconfig 中的 server 指向某一个具体节点,一旦该节点宕机,客户端就会报连接超时。引入负载均衡后,客户端只需要访问 VIP 或域名,LB 会根据健康检查结果自动把请求转发给可用的 apiserver 实例。四层负载均衡直接转发 TCP 6443 流量,七层负载均衡则可以在 HTTP 层检查 /healthz 或 /readyz 的状态。生产环境通常优先选择四层转发,因为 apiserver 的 TLS 证书仍然由后端实例自己处理,LB 上无需保存私钥,架构更简单。

需要注意的是,apiserver 和 controller-manager、scheduler 的高可用机制并不相同。apiserver 多实例同时工作,只要后端 etcd 一致,任何实例响应请求结果都一致。而 controller-manager 和 scheduler 必须通过租约机制选举出唯一的 leader,避免多个控制器同时执行引发冲突。因此,在规划控制面高可用时,不能把 apiserver 的部署方式直接套用到其他控制面组件上。

多实例部署前的证书与端口规划

证书配置是多实例部署中最容易踩坑的地方。apiserver 的 serving 证书必须包含客户端实际访问的所有地址,否则 TLS 握手会失败。假设三个 apiserver 节点 IP 分别是 10.0.0.1、10.0.0.2、10.0.0.3,负载均衡 VIP 是 10.0.0.100,那么证书的 SAN 列表里至少需要包含这三个节点 IP、VIP、kubernetes 服务 ClusterIP,以及相关域名。如果使用 kubeadm 初始化集群,可以在 ClusterConfiguration 中的 certSANs 字段提前声明这些地址,避免后续重新签证书。

端口规划相对简单。生产环境中每个节点都监听同一个安全端口 6443,因为负载均衡器会统一入口,后端节点之间不需要做端口区分。实验环境如果要在同一台机器上启动多个实例,可以使用 6443、6444、6445 等不同端口,但生产不建议这样做。每个 apiserver 还需要通过 --advertise-address 指定本机 IP,该地址会写入端点,供集群内组件发现。同时 --etcd-servers 参数必须指向同一个 etcd 集群,不能指向本地单点 etcd。

下面是一个 kubeadm 配置片段,展示了如何在初始化阶段包含负载均衡地址和多个节点 IP:

apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.28.0
controlPlaneEndpoint: "10.0.0.100:6443"
apiServer:
  certSANs:
  - "10.0.0.100"
  - "kube-api.ippipp.com"
  - "10.0.0.1"
  - "10.0.0.2"
  - "10.0.0.3"
  extraArgs:
    secure-port: "6443"
    etcd-servers: "https://10.0.0.10:2379,https://10.0.0.11:2379,https://10.0.0.12:2379"

使用 systemd 启动多个 kube-apiserver 实例

以二进制方式部署时,需要把 kube-apiserver 可执行文件和证书分发到三个控制面节点。每个节点的配置基本相同,只有 --advertise-address 需要修改为本机 IP。证书文件包括 apiserver 自己的 serving 证书、client CA、etcd 客户端证书、kubelet 客户端证书以及前端代理证书。如果使用 kubeadm 生成的证书,这些文件通常位于 /etc/kubernetes/pki 目录下。

下面是一份典型的 systemd unit 文件,用于在三台节点上分别运行 apiserver。注意 ExecStart 中的反斜杠是 systemd 的续行符,部署时请保留:

[Unit]
Description=Kubernetes API Server
After=network.target etcd.service

[Service]
ExecStart=/usr/local/bin/kube-apiserver \
  --advertise-address=10.0.0.1 \
  --allow-privileged=true \
  --client-ca-file=/etc/kubernetes/pki/ca.crt \
  --enable-admission-plugins=NodeRestriction \
  --enable-bootstrap-token-auth=true \
  --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt \
  --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt \
  --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key \
  --etcd-servers=https://10.0.0.10:2379,https://10.0.0.11:2379,https://10.0.0.12:2379 \
  --kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt \
  --kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key \
  --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \
  --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt \
  --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key \
  --requestheader-allowed-names=front-proxy-client \
  --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt \
  --requestheader-extra-headers-prefix=X-Remote-Extra- \
  --requestheader-group-headers=X-Remote-Group \
  --requestheader-username-headers=X-Remote-User \
  --secure-port=6443 \
  --service-account-key-file=/etc/kubernetes/pki/sa.pub \
  --service-cluster-ip-range=10.96.0.0/12 \
  --tls-cert-file=/etc/kubernetes/pki/apiserver.crt \
  --tls-private-key-file=/etc/kubernetes/pki/apiserver.key
Restart=always
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

在三台节点上分别创建该 unit 文件,并将 --advertise-address 改为 10.0.0.1、10.0.0.2 和 10.0.0.3。保存后执行 systemctl daemon-reloadsystemctl enable --now kube-apiserver。启动后可以通过 ss -lntp | grep 6443 确认端口监听正常,若启动失败则用 journalctl -u kube-apiserver -f 查看详细日志。常见错误包括证书 SAN 不匹配、etcd 地址不可达、service account 公钥路径错误等。

配置 Nginx 或 HAProxy 实现统一访问入口

负载均衡器可以选择 Nginx 或 HAProxy。Nginx 的 stream 模块适合四层 TCP 转发,配置简单,延迟低,不需要在 LB 上部署证书。HAProxy 同样支持四层转发,并且在健康检查方面比 Nginx stream 更灵活。对于控制面流量来说,请求量并不大,因此负载均衡器的性能不是主要瓶颈,关键在于故障摘除速度和配置稳定性。

如果使用 Nginx stream 模块,可以在 nginx.conf 中增加如下配置。该配置会监听 VIP 10.0.0.100 的 6443 端口,并把流量按最少连接数分发到三个 apiserver 实例:

stream {
    upstream kube_apiserver {
        least_conn;
        server 10.0.0.1:6443 max_fails=3 fail_timeout=30s;
        server 10.0.0.2:6443 max_fails=3 fail_timeout=30s;
        server 10.0.0.3:6443 max_fails=3 fail_timeout=30s;
    }

    server {
        listen 10.0.0.100:6443;
        proxy_pass kube_apiserver;
        proxy_connect_timeout 1s;
        proxy_timeout 10s;
    }
}

HAProxy 的配置同样直观。下面的示例使用 TCP 模式监听 6443 端口,并启用 tcp-check 检查后端端口连通性:

global
    log /dev/log local0
    maxconn 20000

defaults
    mode tcp
    timeout connect 5s
    timeout client 30s
    timeout server 30s

frontend kube_apiserver_front
    bind 10.0.0.100:6443
    default_backend kube_apiserver_back

backend kube_apiserver_back
    balance roundrobin
    option tcp-check
    server apiserver1 10.0.0.1:6443 check
    server apiserver2 10.0.0.2:6443 check
    server apiserver3 10.0.0.3:6443 check

四层 TCP 健康检查只能确认端口是否打开,无法判断 apiserver 是否真正处于 Ready 状态。例如 apiserver 进程还在但 etcd 连接已断,TCP 检查仍然会通过,但请求会返回 500。因此生产环境建议在 LB 上配置七层健康检查,向 /healthz 或 /readyz 发起 HTTP 请求。Nginx 社区版 stream 模块不支持 HTTP 健康检查,HAProxy 可以通过 option httpchk GET /healthz 实现,但需要把 mode 切换为 http。如果坚持使用四层,也可以在每台控制面节点本地部署一个轻量健康检查脚本,由 LB 定期执行探测,但维护成本较高。

验证高可用与故障转移

完成负载均衡配置后,应该把 kubeconfig 文件中的 server 地址修改为 https://10.0.0.100:6443,然后执行 kubectl get nodes 验证集群可访问。如果证书 SAN 中没有包含 VIP 地址,此时会直接报 x509 证书错误。出现这种情况时,需要重新生成包含 VIP 的证书并滚动更新所有 apiserver 实例。

故障转移测试可以这样进行:在节点 10.0.0.1 上执行 systemctl stop kube-apiserver,模拟一个实例宕机。随后从客户端继续执行 kubectl get pods -A,正常情况下请求会自动转到 10.0.0.2 或 10.0.0.3,只会有极短时间的连接重试。恢复该实例后,LB 会根据健康检查结果将其重新加入后端池。这个过程对客户端完全透明,是实现控制面高可用的核心验证步骤。

还需要检查 controller-manager 和 scheduler 连接 apiserver 的方式。kubeadm 默认将这两个组件的 kubeconfig 中 server 配置为 127.0.0.1:6443,也就是只连接本机的 apiserver。如果希望这两个组件也具备高可用访问能力,需要把 server 改为负载均衡地址。下面是一个简化后的 controller-manager kubeconfig 片段,重点在于 clusters 下的 server 字段:

apiVersion: v1
kind: Config
clusters:
- cluster:
    certificate-authority-data: ...
    server: https://10.0.0.100:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: controller-manager
  name: system:kube-controller-manager
current-context: system:kube-controller-manager
users:
- name: controller-manager
  user:
    client-certificate-data: ...
    client-key-data: ...

整体来看,apiserver 高可用多实例部署的关键点可以归纳为:共享同一套 etcd 后端、证书 SAN 覆盖所有访问地址、每个实例只修改本机 advertise 地址、前端负载均衡统一入口、健康检查尽量覆盖应用层状态。只要这些环节配置正确,任意一个 apiserver 节点故障都不会影响集群的管理面可用性。

Kubernetes apiserver高可用多实例部署修改时间:2026-08-21 23:36:06

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。