首页 > 教程攻略 > ai教程 >高可用 kubernetes 集群部署实践

高可用 kubernetes 集群部署实践

来源:互联网 时间:2026-07-02 07:21:36

Kubernetes(k8s)凭借其优秀的架构设计、灵活的扩展能力以及丰富的应用编排模型,已经稳稳坐上了容器编排领域事实标准的宝座。越来越多的企业开始拥抱这一趋势,将k8s作为容器化应用的基础设施,并逐步把核心业务迁移上来。

对于基础设施来说,可用性从来都是重中之重。各大云计算厂商自然也纷纷推出了高可用、可扩展的k8s托管服务,其中比较有代表性的包括Amazon EKS、Azure Kubernetes Service(AKS)、Google Kubernetes Engine,以及阿里云容器服务Kubernetes版等。

不过话说回来,虽然公有云托管的k8s服务百花齐放,但很多企业出于各种原因,仍然有自建集群的需求。也正因如此,市场上涌现出了一大批出色的k8s集群部署方案,它们的特点可以归纳如下:

部署方案特点
Kubeadm1. 官方出品的部署工具,提供了k8s集群生命周期管理的领域知识。
2. 旨在成为更高级别工具的可组合构建块。
Kubespray1. 支持在裸机以及AWS、GCE、Azure等众多云平台上部署k8s。
2. 基于Ansible Playbook定义k8s集群部署任务。
3. 支持大部分流行的Linux发行版。
Kops1. 仅支持在AWS、GCE等少数云平台上部署k8s。
2. 建立在状态同步模型上,支持dry-run和自动幂等性。
3. 能够自动生成Terraform配置。
Rancher Kubernetes Engine(RKE)1. 来自著名的开源企业级容器管理平台Rancher,是一款轻量级的k8s安装工具。
2. 支持在裸机、虚拟机、公有云上部署和管理k8s集群。

在上述方案中,RKE在易用性和灵活性上确实有着独到的优势。接下来,我们就把目光聚焦到RKE身上,具体聊聊如何利用它来部署一套高可用的k8s集群。本文使用的RKE版本为v0.2.2

高可用k8s集群架构

在动手之前,先得把高可用k8s集群的架构特点摸清楚。下面是官方推荐的高可用集群架构图。

k8s_arch

其核心思路很清晰:让k8s master节点中的各类组件都具备高可用性,从而彻底消除单点故障。

先看看各个核心组件是如何实现高可用的:

kube-apiserver

——它对外暴露了k8s API,是访问集群的唯一入口。幸运的是,apiserver本身是无状态的,所以思路很简单:启动多个实例,前面再挂一个负载均衡器,高可用就到位了。

etcd

——这是整个集群的数据中心,存储着网络配置和所有对象的状态信息,重要性不言而喻。通过部署奇数个etcd实例,就能构建一个既冗余又可靠的数据存储层。

kube-scheduler

——它负责为新创建的pod挑选一个合适的节点来运行。需要注意的是,一个集群中只能有一个活跃的kube-scheduler实例。不过没关系,我们可以同时启动多个,借助领导者选举功能来实现高可用。

kube-controller-manager

——集群内部的管理控制中心,类似一个大脑。和scheduler一样,它也只有一个活跃实例在干活,但也可以启动多个副本并通过领导者选举来保障高可用。

除此之外,在构建集群时还有两个细节值得特别关注:一是节点上k8s进程的可靠性,要让kubelet、kube-scheduler、kube-controller-manager这些关键进程在出故障后能够自动重启;二是要为worker节点上的非pod进程预留足够的资源,防止它们和pod争抢资源,最终导致节点资源短缺。

使用RKE构建高可用k8s集群

节点规划

构建集群的第一步,就是把手里的服务器按照节点功能划分清楚。下表展示了笔者环境下的节点规划情况。

IP角色
192.168.0.10部署节点
192.168.0.11k8s master - apiserver, etcd, scheduler, controller-manager
192.168.0.12k8s master - apiserver, etcd, scheduler, controller-manager
192.168.0.13k8s master - apiserver, etcd, scheduler, controller-manager
192.168.0.14k8s worker - kubelet, kube-proxy
192.168.0.15k8s worker - kubelet, kube-proxy
192.168.0.16k8s worker - kubelet, kube-proxy
192.168.0.17k8s worker - kubelet, kube-proxy

简单说明一下规划思路:这里单独拿出一台机器(192.168.0.10)作为部署节点。如果机器数紧张,也可以把这个部署节点直接加进k8s集群里。为保证可用性,用了三台机器来承载k8s master组件。条件允许的话,更推荐把etcd和master中的其他组件分开部署,这样可以根据实际需求灵活调整实例数量。比如,在访问压力不大但对数据可靠性要求极高的情况下,可以专门挑5台机器部署etcd,另外再挑3台机器部署master里的其他组件。剩下的四台机器就是worker节点了,它们的数量需要根据实际情况动态调整。如果发现pod因为资源不足一直处于pending状态,就该给worker扩容了;反过来,如果node的资源利用率长期偏低,而且上面的pod都能被重新调度到其他节点,那就可以考虑缩容。

环境准备

规划完节点之后,就该着手准备环境了。主要包含以下几项工作:

首先是

安装RKE

——在部署节点(192.168.0.10)上下载RKE二进制包,具体安装方法可以参考官方文档中的“download-the-rke-binary”。

其次是

配置SSH免密登录

——RKE是通过SSH tunnel来安装部署k8s集群的,所以需要配置RKE所在节点到所有k8s节点的免密登录。如果RKE所在节点也要加入集群,还要记得配置本机到自身的SSH免密登录。

然后是

安装docker

——RKE是通过docker镜像rancher/hyperkube来启动各个k8s组件的,所以k8s集群中所有节点(从192.168.0.11到192.168.0.17这7台机器)都必须安装docker。

最后是

关闭swap

——从k8s 1.8版本开始,官方要求关闭系统的swap,否则在默认配置下kubelet根本启动不了。这里需要把所有的k8s worker节点的swap都关掉。

配置cluster.yml

环境准备完成后,就需要通过cluster.yml文件来描述集群的组成和k8s的部署方式了。

配置集群组成

配置文件中的nodes配置项用来描述集群的构成。按照之前的节点规划,对于k8s master节点,要将它们的角色设置为controlplaneetcd;对于worker节点,则将角色设置为worker

nodes: - address: 192.168.0.11 user: admin role: - controlplane - etcd ... - address: 192.168.0.14 user: admin role: - worker

设置资源预留

K8s的worker节点上并非只运行pod进程,还有很多其他重要的进程,比如k8s管理进程(如kubelet、dockerd)和系统守护进程(如systemd)。这些进程对于集群的稳定性至关重要,所以必须为它们预留足够的资源。

在笔者的环境中,每个worker节点的配置是:32核CPU,64Gi内存,100Gi存储。具体预留策略为:为k8s管理进程预留1核CPU、2Gi内存和1Gi存储;为系统进程预留1核CPU、1Gi内存和1Gi存储。同时,还设置了500Mi的内存驱逐阈值和10%的磁盘驱逐阈值。

在这个场景下,节点实际可分配的CPU资源是29核,可分配的内存资源是60.5Gi,可分配的磁盘资源是88Gi。对于内存、磁盘这类不可压缩资源,一旦pod的使用总量超过上述阈值,QoS较低的pod就会率先被驱逐。对于CPU这种可压缩资源,即使节点上的所有进程都全力占用CPU,pod类进程加起来也不会超过29核。

上述资源预留设置在cluster.yml中的具体表现形式如下:

services: kubelet: extra_args: cgroups-per-qos: True cgroup-driver: cgroupfs kube-reserved: cpu=1,memory=2Gi,ephemeral-storage=1Gi kube-reserved-cgroup: /runtime.service system-reserved: cpu=1,memory=1Gi,ephemeral-storage=1Gi system-reserved-cgroup: /system.slice enforce-node-allocatable: pods,kube-reserved,system-reserved eviction-hard: memory.a vailable<500Mi,nodefs.a vailable<10%

关于资源预留更详细的内容,可以参考官方文章《Reserve Compute Resources for System Daemons》。

部署k8s集群

cluster.yml配置妥当之后,一个命令rke up就能完成整个集群的部署。下图展示了通过RKE部署的k8s集群架构图。

rke_arch

这个架构有几个鲜明的特点:集群中的每一个组件都通过容器的方式启动,并且重启策略都设置为always。这样一来,即使它们意外退出,也能被自动重新拉起。Master节点上的kube-scheduler和kube-controller-manager直接与本机的API server通信。Worker节点上的nginx-proxy维护了一份API server的地址列表,负责袋里kubelet和kube-proxy发往API server的请求。此外,为了提升集群的灾备能力,master节点上的etcd-rolling-snapshots会定期将etcd的快照保存到本地目录/opt/rke/etcd-snapshots中。

配置负载均衡器

集群部署完成之后,就可以通过API server来访问k8s了。由于环境中启动了多个kube-apiserver实例以实现高可用,因此需要为这些实例架设一个负载均衡器。这里我们在192.168.0.10上部署了一台nginx来完成这个任务,nginx.conf的具体配置如下:

... stream { upstream apiserver { server 192.168.0.11:6443 weight=5 max_fails=3 fail_timeout=60s; server 192.168.0.12:6443 weight=5 max_fails=3 fail_timeout=60s; server 192.168.0.13:6443 weight=5 max_fails=3 fail_timeout=60s; } server { listen 6443; proxy_connect_timeout 1s; proxy_timeout 10s; proxy_pass apiserver; } } ...

不过要注意一个常见的坑:配置完负载均衡器之后,如果直接通过它提供的端口访问API server,很可能会遇到这样的异常:Unable to connect to the server: x509: certificate is valid for xxx, not 192.168.0.10。这是因为API server的PKI证书中并不包含负载均衡器的IP地址或域名。解决方案很简单:通过cluster.yml中的authentication配置项,把负载均衡器的IP或域名加到证书的SANS中。

authentication: strategy: x509 sans: - "192.168.0.10"

修改完cluster.yml之后,再执行rke cert-rotate命令来更新证书。

验证

当所有步骤都走完之后,可以用kubectl get nodes命令来看看所有节点的状态。如果所有节点的状态都变成了Ready,那就说明集群部署成功了。

NAME STATUS ROLES AGE VERSION 192.168.0.11 Ready controlplane,etcd 1d v1.13.5 192.168.0.12 Ready controlplane,etcd 1d v1.13.5 192.168.0.13 Ready controlplane,etcd 1d v1.13.5 192.168.0.14 Ready worker 1d v1.13.5 192.168.0.15 Ready worker 1d v1.13.5 192.168.0.16 Ready worker 1d v1.13.5 192.168.0.17 Ready worker 1d v1.13.5

总结

Rancher Kubernetes Engine(RKE)确实为用户屏蔽了创建k8s集群的众多复杂细节,极大地简化了部署步骤,降低了构建门槛。对于有自建k8s集群需求的企业来说,这无疑是一个非常不错的选择。

参考资料

  • Announcing RKE, a Lightweight Kubernetes Installer
  • An Introduction to Rancher Kubernetes Engine (RKE)