一、shell脚本一键部署
#!/bin/bash
set -e
# 节点配置
MASTER1="192.168.177.125"
MASTER2="192.168.177.126"
MASTER3="192.168.177.127"
WORKER1="192.168.177.128"
KEEPALIVED_VIP="192.168.177.129"
# 当前主机IP
CURRENT_IP=$(hostname -I | awk '{print $1}')
# 判断当前节点角色
if [ "$CURRENT_IP" = "$MASTER1" ] || [ "$CURRENT_IP" = "$MASTER2" ] || [ "$CURRENT_IP" = "$MASTER3" ]; then
NODE_ROLE="master"
elif [ "$CURRENT_IP" = "$WORKER1" ]; then
NODE_ROLE="worker"
else
echo "Error: Current IP $CURRENT_IP is not in the cluster plan."
exit 1
fi
sudo apt update && sudo apt upgrade -y
sudo modprobe br_netfilter
echo "=== 内核模块检查 ==="
if ! lsmod | grep br_netfilter; then
echo "错误:br_netfilter 模块未加载,即将重启系统..."
logger -t k8s-install "br_netfilter 模块缺失,触发重启"
sudo reboot
exit 1 # 确保如果reboot失败会退出脚本
fi
# 1. 基础环境配置
function setup_basic_env() {
echo ">>> Setting up basic environment..."
# 禁用Swap
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
# 关闭防火墙
systemctl stop ufw && systemctl disable ufw
# 设置hosts解析
cat >> /etc/hosts <<EOF
$MASTER1 master1
$MASTER2 master2
$MASTER3 master3
$WORKER1 worker1
EOF
# 加载内核模块
cat > /etc/modules-load.d/k8s.conf <<EOF
br_netfilter
EOF
# 内核参数
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
}
echo "=== 内核模块检查 ==="
if ! lsmod | grep br_netfilter; then
echo "错误:br_netfilter 模块未加载,即将重启系统..."
logger -t k8s-install "br_netfilter 模块缺失,触发重启"
sudo reboot
exit 1 # 确保如果reboot失败会退出脚本
fi
# 2. 安装容器运行时 (Containerd) - 使用阿里云镜像源
function install_containerd() {
echo ">>> Installing Containerd..."
apt-get update
apt-get install -y ca-certificates curl gnupg lsb-release
# 添加阿里云Docker GPG密钥
mkdir -p /etc/apt/keyrings
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker-aliyun.gpg
# 添加阿里云Docker仓库
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker-aliyun.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker-aliyun.list > /dev/null
# 安装Containerd
apt-get update
apt-get install -y containerd.io
# 配置Containerd
mkdir -p /etc/containerd
# 确保containerd配置正确
sudo tee /etc/containerd/config.toml >/dev/null <<EOF
version = 2
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
endpoint = ["https://registry.aliyuncs.com/google_containers"]
EOF
systemctl restart containerd
}
# 3. 安装kubeadm/kubelet/kubectl - 使用阿里云镜像源
function install_k8s_tools() {
echo ">>> Installing Kubernetes tools..."
apt-get update && apt-get install -y apt-transport-https curl
# 添加阿里云Kubernetes源
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat > /etc/apt/sources.list.d/kubernetes-aliyun.list <<EOF
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
}
# 4. 配置Keepalived (仅Master节点)
function setup_keepalived() {
if [ "$NODE_ROLE" != "master" ]; then
return
fi
echo ">>> Configuring Keepalived on $CURRENT_IP..."
apt-get install -y keepalived
# 生成Keepalived配置
PRIORITY=100
if [ "$CURRENT_IP" = "$MASTER1" ]; then
PRIORITY=150
elif [ "$CURRENT_IP" = "$MASTER2" ]; then
PRIORITY=120
fi
cat > /etc/keepalived/keepalived.conf <<EOF
vrrp_script chk_kubeapi {
script "nc -zv localhost 6443"
interval 2
weight -5
fall 3
rise 2
}
vrrp_instance VI_1 {
state BACKUP
interface ens33
virtual_router_id 51
priority $PRIORITY
advert_int 1
authentication {
auth_type PASS
auth_pass 42
}
virtual_ipaddress {
$KEEPALIVED_VIP
}
track_script {
chk_kubeapi
}
}
EOF
systemctl enable keepalived && systemctl start keepalived
}
# 5. 初始化Master节点 (仅第一个Master)
function init_master() {
if [ "$CURRENT_IP" != "$MASTER1" ]; then
return
fi
echo ">>> Initializing first master node..."
kubeadm init \
--control-plane-endpoint="$KEEPALIVED_VIP:6443" \
--upload-certs \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=$CURRENT_IP \
--image-repository registry.aliyuncs.com/google_containers # 使用阿里云镜像仓库
# 配置kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# 保存join命令
JOIN_CMD=$(kubeadm token create --print-join-command)
echo "Worker join command: $JOIN_CMD" > /root/join-command.txt
CERT_KEY=$(kubeadm init phase upload-certs --upload-certs | tail -1)
echo "Master join command: kubeadm join $KEEPALIVED_VIP:6443 --token $(echo $JOIN_CMD | awk '{print $5}') --discovery-token-ca-cert-hash $(echo $JOIN_CMD | awk '{print $7}') --control-plane --certificate-key $CERT_KEY" >> /root/join-command.txt
}
# 6. 加入其他Master节点
function join_masters() {
if [ "$CURRENT_IP" = "$MASTER1" ] || [ "$NODE_ROLE" != "master" ]; then
return
fi
echo ">>> Joining as additional master node..."
if [ -f "/tmp/join-command.txt" ]; then
bash /tmp/join-command.txt
else
echo "Error: Join command not found. Please copy /root/join-command.txt from master1 to /tmp/join-command.txt"
exit 1
fi
}
# 7. 加入Worker节点
function join_workers() {
if [ "$NODE_ROLE" != "worker" ]; then
return
fi
echo ">>> Joining as worker node..."
if [ -f "/tmp/join-command.txt" ]; then
bash /tmp/join-command.txt
else
echo "Error: Join command not found. Please copy /root/join-command.txt from master1 to /tmp/join-command.txt"
exit 1
fi
}
# 8. 安装网络插件 (仅第一个Master) - 使用国内镜像
function install_network_plugin() {
if [ "$CURRENT_IP" != "$MASTER1" ]; then
return
fi
echo ">>> Installing Flannel network plugin..."
# 使用国内镜像源下载flannel配置
curl -o kube-flannel.yml https://ghproxy.com/https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
sed -i 's/quay.io/quay.mirrors.ustc.edu.cn/g' kube-flannel.yml # 替换镜像源
kubectl apply -f kube-flannel.yml
}
# 9. 验证集群状态 (仅第一个Master)
function verify_cluster() {
if [ "$CURRENT_IP" != "$MASTER1" ]; then
return
fi
echo ">>> Verifying cluster status..."
sleep 30 # 等待组件启动
kubectl get nodes
kubectl get pods -n kube-system
}
# 主执行流程
setup_basic_env
install_containerd
install_k8s_tools
setup_keepalived
if [ "$NODE_ROLE" = "master" ]; then
if [ "$CURRENT_IP" = "$MASTER1" ]; then
init_master
install_network_plugin
verify_cluster
else
join_masters
fi
else
join_workers
fi
echo ">>> Kubernetes cluster setup completed on $CURRENT_IP!"
使用说明:
脚本适配:
替换脚本中的 , 和 为 kubeadm init 输出的实际值
确保所有节点可以互相SSH访问(用于复制join命令)
执行顺序:
先在 master1 (192.168.177.125) 上运行脚本
从 master1 获取 /root/join-command.txt 中的命令
在其他节点上运行脚本前,先修改 join_masters() 和 join_workers() 函数中的join命令
网络接口:
脚本默认使用 ens33 作为Keepalived网络接口,请根据实际网卡名修改
VIP验证:
部署完成后,在任一Master节点执行 ip a 查看VIP是否绑定
测试VIP漂移:停止当前持有VIP的Master节点的keepalived服务,观察VIP是否迁移
完整流程:
bash
在master1上执行
chmod +x deploy_k8s_ha.sh
bash -xe ./deploy_k8s_ha.sh
获取join命令
cat /root/join-command.txt
在其他节点上执行前,修改脚本中的join命令部分
然后分别在其他节点执行
./deploy_k8s_ha.sh
此脚本实现了完整的自动化部署,包括:
基础环境配置
Containerd安装
Kubernetes组件安装
Keepalived高可用配置
多Master节点加入
Worker节点加入
网络插件部署
二、部署其他节点
从master1节点复制join命令到其他节点
scp root@192.168.177.125:/root/join-command.txt /tmp/
在其他节点上执行脚本
./k8s-ha-setup.sh