4. Kubernetes集群部署:kubeadm部署生产级集群、高可用架构设计、集群升级与备份策略
聊到Kubernetes集群部署,我见过不少团队在这个环节栽跟头。有人图省事直接用minikube上生产,有人照着官方文档一步步来结果网络插件死活起不来。说实话,部署一个能用的集群不难,难的是部署一个能扛住生产压力的集群。今天我就把这几年的实战经验掰开揉碎,跟你聊聊怎么用kubeadm搭一套靠谱的生产级集群。
4.1 为什么选kubeadm?
市面上部署K8s的工具不少,kops、kubespray、Rancher各有千秋。但我个人习惯用kubeadm。为什么?因为它够轻量、够标准。kubeadm是Kubernetes官方出品的部署工具,说白了就是把集群初始化的流程封装成了几个命令。你不需要理解背后所有的证书签发、组件启动细节,但又能保留对集群的完全控制权。
我在项目中遇到过用一键部署工具翻车的情况——版本依赖锁死、自定义配置困难、出了问题都不知道日志在哪。kubeadm就没这毛病,它生成的集群跟手动搭建的几乎一样,后续运维起来特别顺手。
4.2 环境准备:别在起跑线上摔倒
部署之前,先把环境收拾利索。我见过太多人上来就装,结果卡在某个依赖上半天找不出原因。
节点规划建议:
- Master节点: 至少3台,奇数台。etcd需要多数派才能工作,3台能容忍1台故障,5台能容忍2台
- Worker节点: 根据业务量来,建议从3台起步
- 操作系统: Ubuntu 22.04 LTS 或 CentOS 7.9+,内核版本不低于5.4
- 容器运行时: containerd 1.6+,别用Docker了,K8s 1.24以后已经弃用Docker作为运行时
基础配置清单:
# 关闭swap
sudo swapoff -a
# 永久关闭(编辑/etc/fstab注释掉swap行)
# 加载内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置内核参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
4.3 使用kubeadm部署生产级集群
环境准备好了,咱们开始动手。我会把步骤拆开讲,每一步都告诉你为什么这么做。
4.3.1 安装kubeadm、kubelet、kubectl
这三个组件版本必须一致。我习惯用阿里云的镜像源,国内下载速度快很多。
# 添加Kubernetes源
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet=1.28.0-00 kubeadm=1.28.0-00 kubectl=1.28.0-00
sudo apt-mark hold kubelet kubeadm kubectl
4.3.2 初始化第一个Master节点
初始化之前,先准备好配置文件。我个人习惯用配置文件而不是命令行参数,这样后续升级、重建都能复用。
cat <<EOF | sudo tee kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: "192.168.1.10" # 改成你的Master IP
bindPort: 6443
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: "v1.28.0"
controlPlaneEndpoint: "192.168.1.100:6443" # 负载均衡器地址
apiServer:
extraArgs:
authorization-mode: "Node,RBAC"
controllerManager: {}
scheduler: {}
etcd:
local:
dataDir: "/var/lib/etcd"
networking:
serviceSubnet: "10.96.0.0/12"
podSubnet: "10.244.0.0/16"
dnsDomain: "cluster.local"
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs" # 使用IPVS模式,性能更好
EOF
sudo kubeadm init --config=kubeadm-config.yaml --upload-certs
这里有个关键点——controlPlaneEndpoint。生产环境一定要配负载均衡器,别直接把Master IP写死。你想想看,如果Master挂了,kubelet连不上API Server,整个集群就瘫痪了。用负载均衡器,至少能保证API Server的高可用。
4.3.3 加入其他Master节点
初始化完成后,会输出一条join命令,类似这样:
kubeadm join 192.168.1.100:6443 --token xxxxx --discovery-token-ca-cert-hash sha256:xxxxx --control-plane --certificate-key xxxxx
在另外两台Master上执行这条命令就行。注意--control-plane参数,不加的话会当成Worker节点加入。
kubeadm token create --print-join-command重新生成。我曾经因为准备环境花了太久,结果token过期了,排查了半天才发现。
4.3.4 安装网络插件
集群初始化后,CoreDNS会一直处于Pending状态,因为还没装网络插件。我推荐Calico,功能全面、性能稳定。
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26/manifests/custom-resources.yaml
等几分钟,确认所有Pod都Running了:
kubectl get pods -n calico-system
kubectl get nodes # 所有节点都应该是Ready状态
4.4 高可用架构设计
单Master集群玩玩还行,上生产必须高可用。高可用说白了就是:任何一个组件挂了,集群还能正常工作。
4.4.1 控制平面高可用
控制平面的核心是API Server、Controller Manager、Scheduler和etcd。API Server是无状态的,前面挂负载均衡器就行。Controller Manager和Scheduler通过选主机制实现高可用——同一时间只有一个实例在工作,主挂了备自动顶上。
etcd是状态存储,它的高可用最复杂。我建议用独立的etcd集群,别跟K8s控制平面混部。原因很简单:etcd对磁盘IO敏感,跟其他组件抢资源容易出问题。
| 组件 | 高可用方式 | 推荐数量 |
|---|---|---|
| API Server | 负载均衡器 + 多实例 | 3台 |
| Controller Manager | 选主(Leader Election) | 3台 |
| Scheduler | 选主(Leader Election) | 3台 |
| etcd | Raft共识算法 | 3台或5台 |
4.4.2 负载均衡器配置
负载均衡器可以用硬件F5,也可以用软件方案。我个人推荐HAProxy + Keepalived,简单可靠。
# HAProxy配置示例
frontend kubernetes-frontend
bind *:6443
mode tcp
option tcplog
default_backend kubernetes-backend
backend kubernetes-backend
mode tcp
option tcp-check
balance roundrobin
server master1 192.168.1.10:6443 check fall 3 rise 2
server master2 192.168.1.11:6443 check fall 3 rise 2
server master3 192.168.1.12:6443 check fall 3 rise 2
4.5 集群升级策略
升级K8s集群,说白了就是版本迭代。但K8s的升级有个铁律:只能逐版本升级,不能跨大版本。比如1.27升1.28可以,1.27直接升1.29不行。
4.5.1 升级前的准备工作
我每次升级前都会做这几件事:
- 备份etcd: 这是最重要的,etcd里存着集群的所有状态
- 检查API兼容性: 用
kubectl convert检查旧API是否被废弃 - 查看变更日志: 重点关注不兼容的变更
- 先在测试环境验证: 千万别直接上生产,我吃过这个亏
4.5.2 升级步骤
升级顺序是:先升级Master节点,再升级Worker节点。每个节点都要先升级kubeadm,再升级kubelet和kubectl。
# 1. 在Master节点上升级kubeadm
sudo apt-get update
sudo apt-get install -y kubeadm=1.28.1-00 --allow-change-held-packages
# 2. 检查升级计划
sudo kubeadm upgrade plan
# 3. 执行升级
sudo kubeadm upgrade apply v1.28.1
# 4. 升级kubelet和kubectl
sudo apt-get install -y kubelet=1.28.1-00 kubectl=1.28.1-00 --allow-change-held-packages
sudo systemctl restart kubelet
# 5. 确认节点状态
kubectl get nodes
kubectl drain驱逐Pod,升级完再执行kubectl uncordon。这样能保证业务不中断。我习惯一次升级一个Worker节点,观察10分钟没问题再升级下一个。
4.6 备份策略:别等出事了才后悔
备份这事,说起来简单做起来难。我见过太多团队备份脚本写好了但从来没验证过恢复流程,真到出事了才发现备份文件是坏的。
4.6.1 备份什么
K8s集群需要备份的核心数据:
- etcd数据: 集群的所有资源对象、配置信息
- 证书文件: /etc/kubernetes/pki/ 目录下的所有文件
- kubeadm配置: 初始化时用的配置文件
- 存储类配置: 如果有自定义的StorageClass
4.6.2 备份etcd
etcd备份推荐用etcdctl的snapshot命令:
# 创建快照
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db
# 恢复快照(在etcd数据目录清空后执行)
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot-20240101.db \
--data-dir=/var/lib/etcd-restore
4.6.3 自动化备份脚本
手动备份不靠谱,写个定时任务吧:
#!/bin/bash
# /usr/local/bin/etcd-backup.sh
BACKUP_DIR="/backup/etcd"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
mkdir -p $BACKUP_DIR
ETCDCTL_API=3 etcdctl snapshot save $BACKUP_DIR/snapshot_$DATE.db \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# 压缩并上传到远程存储
gzip $BACKUP_DIR/snapshot_$DATE.db
rsync -avz $BACKUP_DIR/ user@backup-server:/remote-backup/
# 清理过期备份
find $BACKUP_DIR -type f -mtime +$RETENTION_DAYS -delete
然后加到crontab里:
0 2 * * * /usr/local/bin/etcd-backup.sh
嗯,到这里,K8s集群部署的核心内容就讲完了。从环境准备到高可用设计,从升级策略到备份恢复,每一步都有坑,但只要你按规范来,生产集群稳稳的。下一章咱们聊聊集群的日常运维和监控告警,到时候见。