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跑通流程,再尝试二进制部署深入理解。毕竟,知其然更要知其所以然。