3、搭建K8s集群:kubeadm部署、二进制部署、高可用方案、集群验证

搭建Kubernetes集群,说白了就是给容器找个家。这个家怎么建?业内主流就两条路:kubeadm二进制部署。我个人习惯是,测试环境用kubeadm,生产环境必须二进制。为什么?往下看你就明白了。

3.1 kubeadm部署:快速上手,适合新手

kubeadm是Kubernetes官方提供的集群部署工具。它的目标就是让你用最少的命令,拉起一个合规的集群。我记得第一次用kubeadm时,只花了15分钟就跑起来了——当然,前提是网络没问题。

3.1.1 环境准备

先说说基础环境。你需要至少两台Linux服务器(我建议CentOS 7.9+或Ubuntu 20.04+)。每台机器都要做这几件事:

  • 关闭swap:swapoff -a,并注释掉/etc/fstab中的swap行
  • 安装Docker或containerd:K8s从1.24开始默认使用containerd
  • 配置内核参数:开启bridge-nf-call-iptables
  • 安装kubeadm、kubelet、kubectl:指定版本,避免意外升级

核心命令示例:

# 安装kubeadm、kubelet、kubectl(以CentOS为例)
cat <

个人经验:我曾经在Ubuntu上踩过坑——默认的iptables规则会导致kube-proxy无法正常工作。解决办法很简单:iptables -P FORWARD ACCEPT。嗯,这个坑我记了好几年。

3.1.2 初始化Master节点

在Master节点上执行初始化命令。这里有个关键点:Pod网络CIDR必须提前规划好。我一般用10.244.0.0/16(Flannel默认)或10.96.0.0/12(Calico常用)。

sudo kubeadm init \
  --apiserver-advertise-address=192.168.1.100 \
  --pod-network-cidr=10.244.0.0/16 \
  --service-cidr=10.96.0.0/12

初始化成功后,你会看到一段提示信息,里面包含kubeadm join命令。记得保存好,那是Worker节点加入集群的凭证。

注意:如果初始化失败,别慌。执行kubeadm reset清理现场,检查日志journalctl -u kubelet。我遇到过最奇葩的问题是——系统时间不同步导致证书验证失败。所以,先配好NTP吧。

3.1.3 安装Pod网络插件

集群初始化后,CoreDNS会一直处于Pending状态。为什么?因为没有网络插件。你需要选择一个CNI插件安装。我个人偏爱Calico,性能好、功能全。

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

等几分钟,检查Pod状态:kubectl get pods -n kube-system。如果所有Pod都Running了,恭喜你,集群通了。

3.1.4 加入Worker节点

在Worker节点上执行刚才保存的join命令:

sudo kubeadm join 192.168.1.100:6443 --token xxxxx --discovery-token-ca-cert-hash sha256:xxxxx

如果token过期了,可以在Master上重新生成:kubeadm token create --print-join-command

3.2 二进制部署:生产环境的首选

说实话,生产环境我从来不用kubeadm。为什么?因为二进制部署让你对集群的每个组件都有完全控制权。你想想看,生产环境出问题时,你能快速定位到是kube-apiserver的问题还是etcd的问题——这种掌控感,kubeadm给不了你。

3.2.1 下载二进制文件

从GitHub Releases页面下载对应版本的二进制包。我建议下载kubernetes-server-linux-amd64.tar.gz,里面包含了所有服务端组件。

wget https://dl.k8s.io/v1.28.0/kubernetes-server-linux-amd64.tar.gz
tar -xzf kubernetes-server-linux-amd64.tar.gz
cd kubernetes/server/bin/
# 这里你会看到kube-apiserver、kube-controller-manager、kube-scheduler等

3.2.2 部署etcd集群

etcd是K8s的大脑,所有数据都存在这里。生产环境必须部署etcd集群(至少3节点)。我习惯把etcd单独部署在三台机器上,不和K8s组件混部。

节点角色 IP地址 etcd成员名
etcd-1 192.168.1.10 etcd1
etcd-2 192.168.1.11 etcd2
etcd-3 192.168.1.12 etcd3

启动etcd时,每个节点都要指定--initial-cluster参数,列出所有成员。我曾经因为写错了一个IP,导致集群无法形成共识——排查了整整两个小时。

3.2.3 部署kube-apiserver

apiserver是K8s的入口,所有请求都经过它。启动参数比较多,我挑几个重点说:

  • --etcd-servers:指向etcd集群地址
  • --service-cluster-ip-range:Service的IP范围
  • --bind-address:监听地址,生产环境建议用内网IP
  • --tls-cert-file--tls-private-key-file:证书文件

启动示例:

./kube-apiserver \
  --etcd-servers=https://192.168.1.10:2379,https://192.168.1.11:2379,https://192.168.1.12:2379 \
  --service-cluster-ip-range=10.96.0.0/12 \
  --bind-address=192.168.1.100 \
  --secure-port=6443 \
  --tls-cert-file=/etc/kubernetes/pki/apiserver.crt \
  --tls-private-key-file=/etc/kubernetes/pki/apiserver.key

3.2.4 部署kube-controller-manager和kube-scheduler

这两个组件相对简单。controller-manager负责维护集群状态,scheduler负责把Pod调度到合适的节点上。它们都通过--kubeconfig连接apiserver。

# controller-manager
./kube-controller-manager \
  --kubeconfig=/etc/kubernetes/controller-manager.conf \
  --leader-elect=true

# scheduler
./kube-scheduler \
  --kubeconfig=/etc/kubernetes/scheduler.conf \
  --leader-elect=true

避坑指南:我曾经在生产环境遇到过controller-manager频繁leader切换的问题。后来发现是--leader-elect-lease-duration设置太短。建议设置为15秒以上,避免网络抖动导致频繁选举。

3.2.5 部署kubelet和kube-proxy

kubelet是每个节点上都有的代理,负责管理Pod的生命周期。kube-proxy负责Service的网络代理。这两个组件通过--kubeconfig连接apiserver,注册自身节点信息。

3.3 高可用方案:让集群永不宕机

单Master节点?那是测试环境干的事。生产环境必须高可用。说白了,就是让apiserver、controller-manager、scheduler这些关键组件都有备份。

3.3.1 高可用架构

标准的K8s高可用架构是这样的:

  • 多Master节点:至少3个,通过负载均衡器(如HAProxy、Nginx)分发请求
  • etcd集群:至少3节点,保证数据一致性
  • Worker节点:根据业务需求扩展

你想想看,如果只有一个Master,它挂了整个集群就瘫痪了。三个Master,挂一个还能正常工作——这就是高可用的意义。

3.3.2 负载均衡配置

我用HAProxy做负载均衡,配置很简单:

frontend k8s-api
    bind *:6443
    default_backend k8s-masters

backend k8s-masters
    balance roundrobin
    server master1 192.168.1.100:6443 check
    server master2 192.168.1.101:6443 check
    server master3 192.168.1.102:6443 check

然后所有kubelet和kubectl都指向这个负载均衡器的地址。这样,任何一个Master挂了,流量自动切换到其他Master。

3.3.3 组件高可用

controller-manager和scheduler本身就支持leader选举。只要启动时加上--leader-elect=true,它们会自动选出一个leader。leader挂了,其他节点会重新选举。

注意:etcd的高可用需要特别注意网络延迟。三个etcd节点之间的延迟最好控制在10ms以内。我曾经在跨地域部署时,因为网络延迟过高导致etcd频繁超时——最后不得不改为单地域部署。

3.4 集群验证:确认一切正常

集群搭好了,怎么确认它真的能用?我有一套标准的验证流程:

3.4.1 节点状态检查

kubectl get nodes
# 输出示例:
# NAME           STATUS   ROLES    AGE   VERSION
# master1        Ready    master   1d    v1.28.0
# master2        Ready    master   1d    v1.28.0
# worker1        Ready    <none>   1d    v1.28.0

所有节点都应该是Ready状态。如果有NotReady的节点,检查kubelet日志:journalctl -u kubelet -f

3.4.2 系统Pod检查

kubectl get pods -n kube-system
# 确保CoreDNS、kube-proxy等都在Running状态

3.4.3 部署测试应用

我习惯部署一个nginx来验证:

kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get svc nginx
# 访问 http://任意节点IP:NodePort

如果浏览器能打开nginx的欢迎页,说明集群正常工作。

3.4.4 高可用验证

这是我最喜欢的一步——故意搞破坏。停掉一个Master节点上的kube-apiserver服务,然后执行kubectl get nodes。如果还能正常返回,说明高可用生效了。

验证命令:

# 在master1上停止apiserver
systemctl stop kube-apiserver

# 在另一台机器上执行
kubectl get nodes
# 应该还能正常返回结果

嗯,到这里,你的K8s集群就搭建完成了。从kubeadm的快速部署,到二进制的手动搭建,再到高可用的架构设计——每一步都有它的意义。我个人建议,初学者先用kubeadm跑通流程,再尝试二进制部署深入理解。毕竟,知其然更要知其所以然。

专注资料整理