本文为X86/amd64架构部署文档
本文使用脚本的方式安装kubernetes集群。脚本中涵盖Kubernete官方安装步骤的所有内容。
安装前必读
本文分别提供两个脚本,请仔细阅读以下内容
- 第一个是安装Master节点脚本在整个集群搭建过程中只在第一台机器上执行,用以构建集群并安装集群组件,其余master节点请使用第二个加入节点脚本加入进集群。
- 第二个是加入集群脚本执行时请根据提示选择加入的是master节点还是work节点,master为管理节点,一般为3个,worker为工作节点,一般在工管分离架构时选择。
- 在脚本执行过程中如有错误,或意外中断,脚本可重复执行
- 脚本在下载软件包时如超时或其他错误,请等待重试,直至完成下载.
- 特殊配置,允许在Master上运行pod,如果你只有3个节点,请在机器都加入集群以后执行以下3条命令
kubectl get node|grep -v NAME|awk '{print $1}' | xargs -I {} kubectl taint node {} node-role.kubernetes.io/master- kubectl get node|grep -v NAME|awk '{print $1}' | xargs -I {} kubectl taint node {} node-role.kubernetes.io/control-plane- kubectl get node|grep -v NAME|awk '{print $1}' | xargs -I {} kubectl patch node {} -p '{"spec":{"unschedulable":false}}'
请注意: 在执行脚本时除一开始的人机交互外脚本还会输出需要人为决策性的命令! 并有完整的提示! 请仔细阅读!
如系统为ubuntu时执行脚本不能使用 sh 需要使用 bash 来执行改脚本! 例如: bash xxx.sh
安装Master节点脚本
请根据情况修改脚本中以下变量内容
- 服务器网卡名称
export INTERFACE=enp4s0
- 服务器IP
export IP=172.16.10.79
- 集群负载IP,必须与服务器同网段
export VIP=172.16.10.5
- 集群内部通讯SVC IP段
export SERVICE_CIDR="10.254.0.0/16"
- 实例IP段
export POD_NETWORK_CIDR="172.30.0.0/16"
将以下脚本保存在Master机器上
#!/bin/bash
set -e
# 检查是否以 root 用户执行
if [ "$(id -u)" -ne 0 ]; then
echo -e "\033[0;31m请使用 root 用户运行此脚本。\033[0m"
exit 1
fi
# 设置环境变量
export INTERFACE=enp4s0
export IP=172.16.10.79
export VIP=172.16.10.5
export SERVICE_CIDR="10.254.0.0/16"
export POD_NETWORK_CIDR="172.30.0.0/16"
export KUBERNETES_VERSION="1.25.14"
export HOSTNAME="node01"
export PORT=6443
echo "当前设置的网卡名称为:$INTERFACE"
echo "当前设置的K8s集群负载均衡地址为:$VIP"
echo "当前设置的主机名为:$HOSTNAME"
echo "当前设置的主机IP为:$IP"
echo "当前设置的K8s集群API端口为:$PORT"
echo "当前设置的Service CIDR为:$SERVICE_CIDR"
echo "当前设置的Pod Network CIDR为:$POD_NETWORK_CIDR"
echo "当前设置的Kubernetes版本为:$KUBERNETES_VERSION"
echo "${RED}如系统为ubuntu请使用bash执行该脚本.${NC}"
read -p "请确认以上变量内容是否已修改正确 (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "请修改脚本中的变量内容后再运行脚本。"
exit 1
fi
export K8S_WORK_DIR=/install/k8s/kubernetes
export CALICO_WORK_DIR=/install/k8s/calico
export IMAGE_REPOSITORY=registry.aliyuncs.com/google_containers
export CONTROLLER_PLAN_ENDPOINT="$VIP:$PORT"
# 设置 PATH 环境变量
export PATH=$PATH:/usr/local/bin:/usr/local/sbin
if ! grep -q "/usr/local/bin" /etc/profile; then
echo 'export PATH=$PATH:/usr/local/bin' >> /etc/profile
echo -e "${GREEN}已将 /usr/local/bin 添加到 PATH 并写入 /etc/profile${NC}"
fi
if ! grep -q "/usr/local/sbin" /etc/profile; then
echo 'export PATH=$PATH:/usr/local/sbin' >> /etc/profile
echo -e "${GREEN}已将 /usr/local/sbin 添加到 PATH 并写入 /etc/profile${NC}"
fi
# 颜色定义
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo -e "${GREEN}开始安装配置...${NC}"
# 设置主机名并更新 /etc/hosts
hostnamectl set-hostname $HOSTNAME
# 检查 /etc/hosts 文件中是否存在主机名与 IP 地址的 hosts
if ! grep -q "$HOSTNAME" /etc/hosts; then
ip_address=$(hostname -I | awk '{print $1}')
echo "$ip_address $HOSTNAME" | tee -a /etc/hosts
echo "$VIP core.harbor.domain" | tee -a /etc/hosts
echo -e "${GREEN}/etc/hosts 文件中已添加主机名与 IP 地址${NC}"
else
echo -e "${GREEN}/etc/hosts 文件中已存在主机名与 IP 地址${NC}"
fi
# 使 PATH 变量生效
source /etc/profile
configure_centos() {
# 修改 CentOS 仓库源为阿里云镜像源
if ! grep -q "mirrors.aliyun.com" /etc/yum.repos.d/CentOS-Base.repo; then
if grep -q "release 7" /etc/centos-release; then
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://mirror.centos.org|baseurl=https://mirrors.aliyun.com|g' /etc/yum.repos.d/CentOS-Base.repo
echo -e "${GREEN}已修改 CentOS 7 仓库源为阿里云镜像源${NC}"
elif grep -q "release 8" /etc/centos-release; then
if ! grep -q "vault.centos.org" /etc/yum.repos.d/CentOS-Base.repo; then
sed -i -e "s|mirrorlist=|#mirrorlist=|g" /etc/yum.repos.d/CentOS-*
sed -i -e "s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g" /etc/yum.repos.d/CentOS-*
echo -e "${GREEN}已修改 CentOS 8.x 仓库源${NC}"
else
echo -e "${GREEN}CentOS 8.x 仓库源已设置${NC}"
fi
else
echo -e "${GREEN}系统不是 CentOS 7 或 8,无需修改仓库源${NC}"
fi
else
echo -e "${GREEN}CentOS 仓库源已是阿里云镜像源${NC}"
fi
# 安装依赖包
echo -e "${GREEN}安装依赖包中···${NC}"
yum install -y epel-release >/dev/null
DEPENDENCIES="conntrack ipvsadm ipset jq sysstat curl iptables wget lrzsz nc tar ntpdate nfs-utils vim netcat gcc make gperf yum-plugin-versionlock"
for package in $DEPENDENCIES; do
if ! rpm -q $package &>/dev/null; then
if yum install -y $package >/dev/null; then
echo -e "${GREEN}$package 已成功安装${NC}"
else
echo -e "${RED}$package 安装失败,请检查网络连接或软件源配置。${NC}"
exit 1
fi
else
echo -e "${GREEN}$package 已经安装${NC}"
fi
done
}
# 配置Ubuntu
configure_ubuntu() {
echo -e "${GREEN}正在配置 Ubuntu...${NC}"
#强制免交互自动重启服务
export DEBIAN_FRONTEND=noninteractive
export UCF_FORCE_CONFFOLD=YES
# 修改APT源为阿里云源
if ! grep -q "mirrors.aliyun.com" /etc/apt/sources.list; then
cp /etc/apt/sources.list /etc/apt/sources.list.bak
cat > /etc/apt/sources.list << EOF
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc) main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc)-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc)-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc)-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc)-backports main restricted universe multiverse
EOF
echo -e "${GREEN}APT源已修改为阿里云源${NC}"
else
echo -e "${GREEN}APT源已是阿里云源${NC}"
fi
# 更新系统
apt-get update
# 安装依赖包
echo -e "${GREEN}安装依赖包中···${NC}"
apt-get install -y apt-utils >/dev/null
DEPENDENCIES="conntrack ipvsadm ipset jq sysstat curl iptables wget lrzsz tar ntpdate nfs-common vim build-essential"
for package in $DEPENDENCIES; do
if ! dpkg -l | grep -q "^ii $package "; then
if apt-get install -y $package >/dev/null; then
echo -e "${GREEN}$package 已成功安装${NC}"
else
echo -e "${RED}$package 安装失败,请检查网络连接或软件源配置。${NC}"
exit 1
fi
else
echo -e "${GREEN}$package 已经安装${NC}"
fi
done
# 逐个检查每个依赖包是否已安装成功
for package in $DEPENDENCIES; do
if ! dpkg -l | grep -q "^ii $package "; then
echo -e "${RED}$package 安装失败,请手动检查并安装。${NC}"
exit 1
else
echo -e "${GREEN}$package 已成功安装并可用${NC}"
fi
done
}
# 检查 /etc/profile 中是否有 ulimit 设置,如果没有就添加进去
configure_ulimit() {
if ! grep -q "ulimit -SHn 1048576" /etc/profile; then
echo "ulimit -SHn 1048576" >> /etc/profile
echo -e "${GREEN}已将 ulimit -SHn 1048576 添加到 /etc/profile${NC}"
else
echo -e "${GREEN}/etc/profile 中已存在 ulimit -SHn 1048576${NC}"
fi
# 使 ulimit 设置生效
source /etc/profile
}
# 调整时区
adjust_timezone() {
if [ "$(timedatectl show --property=Timezone --value)" != "Asia/Shanghai" ];then
timedatectl set-timezone Asia/Shanghai
echo -e "${GREEN}时区已设置为 Asia/Shanghai${NC}"
else
echo -e "${GREEN}时区已是 Asia/Shanghai${NC}"
fi
# 将当前的 UTC 时间写入硬件时钟
if [ "$(timedatectl show --property=LocalRTC --value)" != "0" ];then
timedatectl set-local-rtc 0
echo -e "${GREEN}已将 UTC 时间写入硬件时钟${NC}"
else
echo -e "${GREEN}硬件时钟已是 UTC 时间${NC}"
fi
# 重启时间的服务和任务调度服务
#systemctl restart rsyslog
#systemctl restart crond
#echo -e "${GREEN}时间服务和任务调度服务已重启${NC}"
# 同步时间
/usr/sbin/ntpdate pool.ntp.org
if [ $? -eq 0 ]; then
echo -e "${GREEN}时间已同步${NC}"
else
echo -e "${RED}时间同步失败,请检查网络连接或时间服务器配置。${NC}"
fi
}
# 安装 libseccomp 的函数
install_libseccomp() {
local LIBSECCOMP_VERSION="2.5.2"
# 检查系统版本
if { [ -f /etc/centos-release ] && grep -q -E "7\.([0-8]|9[^\.])|8\.[0-9]+" /etc/centos-release; } || { [ -f /etc/os-release ] && grep -q "22\.[0-9]\|24\.[0-9]" /etc/os-release; }; then
echo -e "${GREEN}系统版本高于 Ubuntu 22 或 CentOS 7.9,不需要安装 libseccomp${NC}"
return
fi
# 检查已安装的 libseccomp 版本
if [ -f "/usr/local/lib/pkgconfig/libseccomp.pc" ]; then
local INSTALLED_VERSION=$(grep "Version:" /usr/local/lib/pkgconfig/libseccomp.pc | awk '{print $2}')
if [ "$INSTALLED_VERSION" = "$LIBSECCOMP_VERSION" ]; then
echo -e "${GREEN}libseccomp $LIBSECCOMP_VERSION 已经安装${NC}"
return
else
echo -e "${YELLOW}已安装 libseccomp 版本为 $INSTALLED_VERSION, 需要升级到 $LIBSECCOMP_VERSION${NC}"
fi
else
echo -e "${YELLOW}未检测到已安装的 libseccomp,准备安装 $LIBSECCOMP_VERSION${NC}"
fi
cd /tmp
if [ ! -f libseccomp-${LIBSECCOMP_VERSION}.tar.gz ]; then
attempts=0
success=false
url="https://cloud-help.mandao.com/uploads/cloud/install/runtime/libseccomp-${LIBSECCOMP_VERSION}.tar.gz"
while [ $attempts -lt 6 ]; do
wget $url -O libseccomp-${LIBSECCOMP_VERSION}.tar.gz && success=true && break
attempts=$((attempts + 1))
echo -e "${GREEN}下载失败,重试第 $attempts 次...${NC}"
sleep 5
done
if ! $success; then
echo -e "${RED}下载 libseccomp 失败,请检查网络连接或下载地址。${NC}"
exit 1
fi
else
echo -e "${GREEN}libseccomp-${LIBSECCOMP_VERSION}.tar.gz 已存在,跳过下载。${NC}"
fi
tar -xzf libseccomp-${LIBSECCOMP_VERSION}.tar.gz
cd libseccomp-${LIBSECCOMP_VERSION}
echo -e "${GREEN}正在配置,请等待!${NC}"
# 配置并隐藏输出,失败时提示查看日志
./configure > /tmp/libseccomp_configure.log 2>&1 || {
echo -e "${RED}配置失败,请查看 /tmp/libseccomp_configure.log 了解详情。${NC}"
exit 1
}
echo -e "${GREEN}正在编译,请等待!${NC}"
# 编译并隐藏输出,失败时提示查看日志
make -j2 > /tmp/libseccomp_make.log 2>&1 || {
echo -e "${RED}编译失败,请查看 /tmp/libseccomp_make.log 了解详情。${NC}"
exit 1
}
# 安装并隐藏输出,失败时提示查看日志
make install > /tmp/libseccomp_install.log 2>&1 || {
echo -e "${RED}安装失败,请查看 /tmp/libseccomp_install.log 了解详情。${NC}"
exit 1
}
ldconfig
echo -e "${GREEN}libseccomp $LIBSECCOMP_VERSION 已成功安装${NC}"
# 检查并更新 ldconfig 缓存
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf
ldconfig
}
# 停止并禁用防火墙和 dnsmasq
disable_services() {
# 停止并禁用防火墙
if systemctl is-active --quiet firewalld; then
systemctl stop firewalld
echo -e "${GREEN}防火墙已停止${NC}"
fi
if systemctl is-enabled --quiet firewalld; then
systemctl disable firewalld
echo -e "${GREEN}防火墙已禁用${NC}"
fi
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
iptables -P FORWARD ACCEPT
echo -e "${GREEN}iptables 规则已清除${NC}"
# 停止并禁用 dnsmasq
if systemctl is-active --quiet dnsmasq; then
systemctl stop dnsmasq
echo -e "${GREEN}dnsmasq 已停止${NC}"
fi
if systemctl is-enabled --quiet dnsmasq; then
systemctl disable dnsmasq
echo -e "${GREEN}dnsmasq 已禁用${NC}"
fi
}
# 关闭 SELinux 和 Swap
disable_swap_selinux() {
# 关闭 Swap
if swapon --summary | grep -q 'partition\|file'; then
swapoff -a
echo -e "${GREEN}Swap 已关闭${NC}"
fi
if grep -q 'swap' /etc/fstab; then
sed -i '/swap/d' /etc/fstab
echo -e "${GREEN}/etc/fstab 中的 Swap 条目已删除${NC}"
fi
# 关闭 SELinux(如果安装了工具)
if command -v getenforce &> /dev/null; then
if [ "$(getenforce)" != "Disabled" ];then
setenforce 0
echo -e "${GREEN}SELinux 已设置为 Permissive${NC}"
fi
else
echo -e "${YELLOW}getenforce 命令未找到,跳过 SELinux 设置步骤。${NC}"
fi
if command -v setenforce &> /dev/null; then
if grep -q 'SELINUX=enforcing' /etc/selinux/config;then
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
echo -e "${GREEN}SELinux 配置文件已修改为 Disabled${NC}"
fi
else
echo -e "${YELLOW}setenforce 命令未找到,跳过 SELinux 设置步骤。${NC}"
fi
}
# 配置 Kubernetes 优化参数和加载内核模块
configure_kubernetes() {
# 配置 Kubernetes 优化参数
if [ ! -f /etc/sysctl.d/kubernetes.conf ]; then
cat > /tmp/kubernetes.conf << EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
EOF
cp /tmp/kubernetes.conf /etc/sysctl.d/kubernetes.conf
sysctl -p /etc/sysctl.d/kubernetes.conf &
rm -rf /tmp/kubernetes.conf
echo -e "${GREEN}Kubernetes 优化参数已配置${NC}"
else
echo -e "${GREEN}Kubernetes 优化参数已存在${NC}"
fi
# 加载内核模块
for module in br_netfilter ip_vs; do
if ! lsmod | grep -q "$module"; then
modprobe $module
echo -e "${GREEN}内核模块 $module 已加载${NC}"
else
echo -e "${GREEN}内核模块 $module 已存在${NC}"
fi
done
}
# 设置文件句柄
configure_file_handles() {
updateSysCtl() {
key=$1
value=$2
filePath=/etc/sysctl.conf
if grep -q $key $filePath; then
sed -i "/$key/d" $filePath
fi
echo "$key = $value" | tee -a $filePath
echo -e "${GREEN}已设置 $key = $value${NC}"
}
updateSysCtl "fs.file-max" "1000000"
updateSysCtl "net.ipv4.ip_conntrack_max" "1000000"
updateSysCtl "net.ipv4.netfilter.ip_conntrack_max" "1000000"
sysctl -p &
echo -e "${GREEN}文件句柄已设置${NC}"
}
# 安装容器运行时 Containerd
install_containerd() {
export PATH=$PATH:/usr/local/bin
if [ ! -f /usr/local/bin/containerd ]; then
#local url="https://github.com/containerd/containerd/releases/download/v1.7.7/cri-containerd-cni-1.7.7-linux-amd64.tar.gz"
local url="https://cloud-help.mandao.com/uploads/cloud/install/runtime/cri-containerd-cni-1.7.20-linux-amd64.tar.gz"
local file="/tmp/cri-containerd-cni-1.7.20-linux-amd64.tar.gz"
local attempts=0
local success=false
# 检测 /tmp 目录下是否有该文件
if [ -f "$file" ]; then
echo -e "${GREEN}检测到 /tmp 目录下已存在 cri-containerd-cni-1.7.20-linux-amd64.tar.gz 文件,尝试解压...${NC}"
tar -zxvf "$file" -C / || {
echo -e "${RED}解压失败,删除文件并重新下载...${NC}"
rm -f "$file"
}
fi
# 如果文件不存在或解压失败后被删除,则重新下载
if [ ! -f "$file" ]; then
while [ $attempts -lt 6 ]; do
wget "$url" -O "$file" && success=true && break
attempts=$((attempts + 1))
echo -e "${GREEN}下载失败,重试第 $attempts 次...${NC}"
sleep 5
done
if ! $success; then
echo -e "${RED}下载 containerd 失败,请检查网络连接或下载地址。${NC}"
exit 1
fi
tar -zxvf "$file" -C / || {
echo -e "${RED}解压失败,请手动检查问题。${NC}"
exit 1
}
else
echo -e "${GREEN}文件已存在且解压成功。${NC}"
fi
source /etc/profile
echo -e "${GREEN}Containerd 已安装${NC}"
else
echo -e "${GREEN}Containerd 已存在${NC}"
fi
# 配置 Containerd 服务
if [ ! -f /usr/local/lib/systemd/system/containerd.service ]; then
mkdir -p /usr/local/lib/systemd/system/
cp /etc/systemd/system/containerd.service /usr/local/lib/systemd/system/containerd.service
systemctl daemon-reload
systemctl enable --now containerd
sleep 2
echo -e "${GREEN}Containerd 服务已启动${NC}"
else
echo -e "${GREEN}Containerd 服务已存在${NC}"
fi
# 生成 Containerd 配置
if [ ! -f /etc/containerd/config.toml ]; then
mkdir -p /etc/containerd
containerd config default | tee /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's/registry.k8s.io\/pause:3.8/registry.aliyuncs.com\/google_containers\/pause:3.8/' /etc/containerd/config.toml
systemctl restart containerd
echo -e "${GREEN}Containerd 配置已生成并应用${NC}"
else
echo -e "${GREEN}Containerd 配置已存在${NC}"
fi
# 检查默认 CNI 配置文件是否存在
DEFAULT_CNI_CONFIG="/etc/cni/net.d/10-containerd-net.conflist"
if [ -f "$DEFAULT_CNI_CONFIG" ]; then
echo -e "${GREEN}检测到默认 CNI 配置文件 $DEFAULT_CNI_CONFIG,开始清理。${NC}"
# 清理默认 CNI 配置文件
rm -rf /etc/cni/net.d/*
echo -e "${GREEN}默认 CNI 配置文件已清理。${NC}"
# 重启 containerd 服务
systemctl restart containerd
echo -e "${GREEN}containerd 服务已重启。${NC}"
else
echo -e "${GREEN}未检测到默认 CNI 配置文件,无需清理。${NC}"
fi
}
# 安装 Kubernetes 工具的函数
install_kubernetes_tools() {
if ! kubectl version --client &>/dev/null; then
if [ -f /etc/centos-release ]; then
cat << EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubelet-$KUBERNETES_VERSION kubeadm-$KUBERNETES_VERSION kubectl-$KUBERNETES_VERSION --disableexcludes=kubernetes
systemctl enable kubelet && systemctl start kubelet
yum versionlock kubelet-$KUBERNETES_VERSION-0 kubeadm-$KUBERNETES_VERSION-0 kubectl-$KUBERNETES_VERSION-0
echo -e "${GREEN}kubelet-$KUBERNETES_VERSION、kubeadm-$KUBERNETES_VERSION 和 kubectl-$KUBERNETES_VERSION 已安装并锁定版本${NC}"
elif [ -f /etc/lsb-release ]; then
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat << EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet=$KUBERNETES_VERSION-00 kubeadm=$KUBERNETES_VERSION-00 kubectl=$KUBERNETES_VERSION-00
systemctl enable kubelet && systemctl start kubelet
apt-mark hold kubeadm kubelet kubectl
echo -e "${GREEN}kubelet-$KUBERNETES_VERSION、kubeadm-$KUBERNETES_VERSION 和 kubectl-$KUBERNETES_VERSION 已安装并锁定版本${NC}"
fi
else
echo -e "${GREEN}kubelet-$KUBERNETES_VERSION、kubeadm-$KUBERNETES_VERSION 和 kubectl-$KUBERNETES_VERSION 已安装并锁定版本${NC}"
fi
}
# 安装负载均衡器 kube-vip 的函数
install_kube_vip() {
#export KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | jq -r ".[0].name")
if [ -z "$KVVERSION" ]; then
export KVVERSION="v0.8.0" # 使用一个已知存在的版本
fi
#while ! ctr images ls | grep -q "ghcr.io/kube-vip/kube-vip:$KVVERSION"; do
while ! ctr images ls | grep -q "dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION"; do
#ctr image pull ghcr.io/kube-vip/kube-vip:$KVVERSION
ctr image pull dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION
if [ $? -eq 0 ]; then
echo -e "${GREEN}kube-vip 镜像已下载${NC}"
else
echo -e "${RED}kube-vip 镜像下载失败,正在重试...${NC}"
sleep 5
fi
done
echo -e "${GREEN}kube-vip 镜像已存在${NC}"
export kube_vip_file="/etc/kubernetes/manifests/kube-vip.yaml"
# 检查是否已存在有效的 kube-vip 配置文件
if [ -f $kube_vip_file ] && grep -q "$INTERFACE" $kube_vip_file && grep -q "$VIP" $kube_vip_file; then
echo -e "${GREEN}kube-vip 配置文件已存在且有效,跳过生成。${NC}"
else
# 如果文件不存在或内容无效,则删除并生成新的配置文件
echo "生成新的 kube-vip 配置文件..."
rm -f /etc/kubernetes/manifests/kube-vip.yaml
#ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:$KVVERSION vip /kube-vip manifest pod \
ctr run --rm --net-host dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION vip /kube-vip manifest pod \
--interface $INTERFACE \
--vip $VIP \
--controlplane \
--arp \
--leaderElection | tee $kube_vip_file >/dev/null &
# 等待配置文件生成
echo -e "${GREEN}等待3秒${NC}"
sleep 3
if [ ! -f $kube_vip_file ] || ! (grep -q "$INTERFACE" $kube_vip_file && grep -q "$VIP" $kube_vip_file); then
echo -e "${RED}kube-vip 文件生成出错,请检查。${NC}"
echo -e "${RED}若文件生成出错请尝试修改 KVVERSION 变量,降低 kube-vip 版本。${NC}"
exit 1
fi
grep -q "image: ghcr.io/kube-vip/kube-vip:$KVVERSION" /etc/kubernetes/manifests/kube-vip.yaml
if [ $? -eq 0 ]; then
echo -e "${GREEN}正在将镜像地址替换为 dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION ${NC}"
sed -i "s|image: ghcr.io/kube-vip/kube-vip:$KVVERSION|image: dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION|" /etc/kubernetes/manifests/kube-vip.yaml
echo -e "${GREEN}替换完成。${NC}"
else
echo -e "${GREEN}未找到原始镜像地址 ghcr.io/kube-vip/kube-vip:$KVVERSION,无需替换。${NC}"
fi
fi
}
# 初始化 Kubernetes 集群
initialize_kubernetes_cluster() {
# 初始化 Kubernetes 集群
if [ -f /etc/kubernetes/admin.conf ]; then
echo -e "${RED}检测到 /etc/kubernetes/admin.conf 文件,Kubernetes 集群已初始化。跳过初始化步骤。${NC}"
else
kubeadm init \
--control-plane-endpoint "$CONTROLLER_PLAN_ENDPOINT" \
--upload-certs \
--kubernetes-version $KUBERNETES_VERSION \
--image-repository $IMAGE_REPOSITORY \
--pod-network-cidr $POD_NETWORK_CIDR \
--service-cidr=$SERVICE_CIDR 2>&1 | tee -a /tmp/kubernetes_install_token.txt
fi
# 配置 kubeconfig
if [ ! -f $HOME/.kube/config ]; then
rm -rf $HOME/.kube
mkdir -p $HOME/.kube
ln -s /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
echo -e "${GREEN}kubeconfig 已配置${NC}"
else
echo -e "${GREEN}kubeconfig 已存在${NC}"
fi
export KUBECONFIG=/etc/kubernetes/admin.conf
# 检查 kubelet 服务状态并输出
if systemctl is-active --quiet kubelet; then
echo -e "${GREEN}kubelet 服务正在运行${NC}"
else
echo -e "${RED}kubelet 服务未运行${NC}"
fi
if systemctl is-enabled --quiet kubelet; then
echo -e "${GREEN}kubelet 服务已启用开机启动${NC}"
else
echo -e "${RED}kubelet 服务未启用开机启动${NC}"
fi
# 查看组件状态
echo -e "${GREEN}等待5秒查看组件状态...${NC}"
sleep 5
kubectl get pod -n kube-system
}
install_calico() {
# 安装网络组件
# 初始化环境变量
echo -e "\e[1;32m POD_NETWORK_CIDR=$POD_NETWORK_CIDR \e[0m"
# 下载calico模版
mkdir -p $CALICO_WORK_DIR
if [ ! -f $CALICO_WORK_DIR/tigera-operator.yaml ]; then
attempts=0
success=false
url="https://cloud-help.mandao.com/uploads/cloud/install/calico/v3.26.3/tigera-operator.yaml"
while [ $attempts -lt 6 ]; do
wget $url -O tigera-operator.yaml && success=true && break
attempts=$((attempts + 1))
echo -e "${GREEN}下载失败,重试第 $attempts 次...${NC}"
sleep 5
done
if ! $success; then
echo -e "${RED}下载 tigera-operator.yaml 失败,请检查网络连接或下载地址。${NC}"
exit 1
fi
mv tigera-operator.yaml $CALICO_WORK_DIR/tigera-operator.yaml
echo -e "${GREEN}tigera-operator.yaml 已下载并移动到 $CALICO_WORK_DIR${NC}"
else
echo -e "${GREEN}tigera-operator.yaml 已存在${NC}"
fi
if [ ! -f $CALICO_WORK_DIR/custom-resources.yaml ]; then
attempts=0
success=false
url="https://cloud-help.mandao.com/uploads/cloud/install/calico/v3.26.3/custom-resources.yaml"
while [ $attempts -lt 6 ]; do
wget -O custom-resources.yaml $url && success=true && break
attempts=$((attempts + 1))
echo -e "${GREEN}下载失败,重试第 $attempts 次...${NC}"
sleep 5
done
if ! $success; then
echo -e "${RED}下载 custom-resources.yaml 失败,请检查网络连接或下载地址。${NC}"
exit 1
fi
mv custom-resources.yaml $CALICO_WORK_DIR/custom-resources.yaml
echo -e "${GREEN}custom-resources.yaml 已下载并移动到 $CALICO_WORK_DIR${NC}"
else
echo -e "${GREEN}custom-resources.yaml 已存在${NC}"
fi
# 修改配置
if ! grep -q "blockSize: 24" $CALICO_WORK_DIR/custom-resources.yaml; then
sed -i s/"blockSize: 26"/"blockSize: 24"/g $CALICO_WORK_DIR/custom-resources.yaml
echo -e "${GREEN}blockSize 已修改为 24${NC}"
else
echo -e "${GREEN}blockSize 已经是 24${NC}"
fi
if ! grep -q "$POD_NETWORK_CIDR" $CALICO_WORK_DIR/custom-resources.yaml; then
sed -i "s#cidr: 192.168.0.0/16#cidr: $POD_NETWORK_CIDR#g" $CALICO_WORK_DIR/custom-resources.yaml
echo -e "${GREEN}cidr 已修改为 $POD_NETWORK_CIDR${NC}"
else
echo -e "${GREEN}cidr 已经是 $POD_NETWORK_CIDR${NC}"
fi
if ! grep -q " registry: dockerhub.mandao.com" $CALICO_WORK_DIR/custom-resources.yaml; then
sed -i 's/ # Configures Calico networking./&\n registry: dockerhub.mandao.com/' $CALICO_WORK_DIR/custom-resources.yaml
echo -e "${GREEN}registry 已添加为 dockerhub.mandao.com${NC}"
else
echo -e "${GREEN}registry 已经存在${NC}"
fi
echo -e "${GREEN}睡眠5秒${NC}"
sleep 5
# 创建
kubectl create -f $CALICO_WORK_DIR/tigera-operator.yaml
echo -e "${GREEN}睡眠10秒${NC}"
sleep 10
kubectl create -f $CALICO_WORK_DIR/custom-resources.yaml
echo -e "${GREEN}睡眠30秒${NC}"
sleep 30
# 验证
kubectl get pod -n calico-system
# 查看集群状态
kubectl get node
echo -e "${GREEN}STATUS都变为Ready则网络组件安装正常${NC}"
echo -e "${GREEN}网络组件不正常时可暂时跳过,先加入两个机器进入集群后再来修复网络组件,一般该组件需要去下载calico镜像${NC}"
# 特殊配置:允许给 Master 节点分配实例(仅用于测试环境)
echo -e "${RED}特殊配置:允许给 Master 节点分配实例(仅用于测试环境)
kubectl get node|grep -v NAME|awk '{print \$1}' | xargs -I {} kubectl taint node {} node-role.kubernetes.io/master-
kubectl get node|grep -v NAME|awk '{print \$1}' | xargs -I {} kubectl taint node {} node-role.kubernetes.io/control-plane-
kubectl get node|grep -v NAME|awk '{print \$1}' | xargs -I {} kubectl patch node {} -p '{\"spec\":{\"unschedulable\":false}}'
${NC}"
}
ulimit -SHn 1048576
echo "=========================================================="
echo -e "${GREEN} 开始安装基础环境 ${NC}"
echo "=========================================================="
# 检查系统类型并调用相应的函数
if [ -f /etc/centos-release ]; then
configure_centos
elif [ -f /etc/lsb-release ]; then
configure_ubuntu
else
echo -e "${RED}不支持的操作系统。${NC}"
exit 1
fi
configure_ulimit
adjust_timezone
disable_services
disable_swap_selinux
echo "=========================================================="
echo -e "${GREEN} 配置系统参数 ${NC}"
echo "=========================================================="
configure_kubernetes
configure_file_handles
echo "=========================================================="
echo -e "${GREEN} 开始安装 runc 依赖包 ${NC}"
echo "=========================================================="
sleep 2
install_libseccomp
echo "=========================================================="
echo -e "${GREEN} 开始安装 Containerd 容器运行时 ${NC}"
echo "=========================================================="
install_containerd
echo "=========================================================="
echo -e "${GREEN} 开始安装 Kubernetes 软件包 ${NC}"
echo "=========================================================="
install_kubernetes_tools
echo "=========================================================="
echo -e "${GREEN} 开始生成 kube-vip 配置文件 ${NC}"
echo "=========================================================="
install_kube_vip
echo "=========================================================="
echo -e "${GREEN} 开始初始化 Kubernetes 集群 ${NC}"
echo "=========================================================="
initialize_kubernetes_cluster
echo "=========================================================="
echo -e "${GREEN} 开始安装 Calico ${NC}"
echo "=========================================================="
install_calico
加入集群脚本
请根据情况修改脚本中以下变量内容
- 服务器网卡名称
export INTERFACE=ens192 - 集群负载IP
export VIP=172.16.10.5
请注意: 如果你的机器是使用虚拟机模版克隆的也就是说不是刚装好操作系统的机器,为避免某些错误,请手动修改机器的hostname
将以下脚本保存在需要加入集群的机器上
#!/bin/bash
# 其它节点加入集群脚本
# 在需要加入的节点上运行
set -e
# 检查是否以 root 用户执行
if [ "$(id -u)" -ne 0 ]; then
echo -e "\033[0;31m请使用 root 用户运行此脚本。\033[0m"
exit 1
fi
# 设置环境变量
export INTERFACE=ens192
export VIP=172.16.10.5
export KUBERNETES_VERSION="1.25.14"
echo "当前设置的网卡名称为:$INTERFACE"
echo "当前设置的K8s集群负载均衡地址为:$VIP"
echo "当前设置的Kubernetes版本为:$KUBERNETES_VERSION"
read -p "请确认以上变量内容是否已修改正确 (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
echo "请修改脚本中的变量内容后再运行脚本。"
exit 1
fi
# 颜色定义
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo -e "${GREEN}开始安装配置...${NC}"
# 选择节点类型
echo -e "${RED}不加master就选worker master为主节点,worker为工作节点!${NC}"
read -p "请选择节点类型 (master/worker): " node_type
if [ "$node_type" != "master" ] && [ "$node_type" != "worker" ]; then
echo -e "${RED}无效的节点类型。请选择 'master' 或 'worker'。${NC}"
exit 1
fi
# 检查主机名是否为 localhost
hostname=$(hostname)
if [[ "$hostname" == *"localhost"* ]]; then
echo -e "${RED}为区分节点机器,请修改主机名,建议主机名中包含明显的IP标识${NC}"
exit 1
fi
# 检查 /etc/hosts 文件中是否存在主机名与 IP 地址的 hosts
if ! grep -q "$hostname" /etc/hosts; then
ip_address=$(hostname -I | awk '{print $1}')
echo "$ip_address $hostname" | tee -a /etc/hosts
echo "$VIP core.harbor.domain" | tee -a /etc/hosts
echo -e "${GREEN}/etc/hosts 文件中已添加主机名与 IP 地址${NC}"
else
echo -e "${GREEN}/etc/hosts 文件中已存在主机名与 IP 地址${NC}"
fi
# 配置CentOS
configure_centos() {
# 修改 CentOS 仓库源为阿里云镜像源
if grep -q "release 7" /etc/centos-release; then
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://mirror.centos.org|baseurl=https://mirrors.aliyun.com|g' /etc/yum.repos.d/CentOS-Base.repo
echo -e "${GREEN}已修改 CentOS 7 仓库源为阿里云镜像源${NC}"
elif grep -q "release 8" /etc/centos-release; then
if ! grep -q "vault.centos.org" /etc/yum.repos.d/CentOS-Base.repo; then
sed -i -e "s|mirrorlist=|#mirrorlist=|g" /etc/yum.repos.d/CentOS-*
sed -i -e "s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g" /etc/yum.repos.d/CentOS-*
echo -e "${GREEN}已修改 CentOS 8.x 仓库源${NC}"
else
echo -e "${GREEN}CentOS 8.x 仓库源已设置${NC}"
fi
else
echo -e "${GREEN}系统不是 CentOS 7 或 8,无需修改仓库源${NC}"
fi
# 安装依赖包
echo -e "${GREEN}安装依赖包中···${NC}"
yum install -y epel-release >/dev/null
DEPENDENCIES="conntrack ipvsadm ipset jq sysstat curl iptables wget lrzsz nc tar ntpdate nfs-utils vim netcat gcc make gperf yum-plugin-versionlock"
for package in $DEPENDENCIES; do
if ! rpm -q $package &>/dev/null; then
if yum install -y $package >/dev/null; then
echo -e "${GREEN}$package 已成功安装${NC}"
else
echo -e "${RED}$package 安装失败,请检查网络连接或软件源配置。${NC}"
exit 1
fi
else
echo -e "${GREEN}$package 已经安装${NC}"
fi
done
}
# 配置Ubuntu
configure_ubuntu() {
echo -e "${GREEN}正在配置 Ubuntu...${NC}"
#强制免交互自动重启服务
export DEBIAN_FRONTEND=noninteractive
export UCF_FORCE_CONFFOLD=YES
# 修改APT源为阿里云源
if ! grep -q "mirrors.aliyun.com" /etc/apt/sources.list; then
cp /etc/apt/sources.list /etc/apt/sources.list.bak
cat > /etc/apt/sources.list << EOF
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc) main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc)-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc)-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc)-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ $(lsb_release -sc)-backports main restricted universe multiverse
EOF
echo -e "${GREEN}APT源已修改为阿里云源${NC}"
else
echo -e "${GREEN}APT源已是阿里云源${NC}"
fi
# 更新系统
apt-get update
# 安装依赖包
echo -e "${GREEN}安装依赖包中···${NC}"
apt-get install -y apt-utils >/dev/null
DEPENDENCIES="conntrack ipvsadm ipset jq sysstat curl iptables wget lrzsz tar ntpdate nfs-common vim build-essential"
for package in $DEPENDENCIES; do
if ! dpkg -l | grep -q "^ii $package "; then
if apt-get install -y $package >/dev/null; then
echo -e "${GREEN}$package 已成功安装${NC}"
else
echo -e "${RED}$package 安装失败,请检查网络连接或软件源配置。${NC}"
exit 1
fi
else
echo -e "${GREEN}$package 已经安装${NC}"
fi
done
# 逐个检查每个依赖包是否已安装成功
for package in $DEPENDENCIES; do
if ! dpkg -l | grep -q "^ii $package "; then
echo -e "${RED}$package 安装失败,请手动检查并安装。${NC}"
exit 1
else
echo -e "${GREEN}$package 已成功安装并可用${NC}"
fi
done
}
# 检查 /etc/profile 中是否有 ulimit 设置,如果没有就添加进去
configure_ulimit() {
if ! grep -q "ulimit -SHn 1048576" /etc/profile; then
echo "ulimit -SHn 1048576" >> /etc/profile
echo -e "${GREEN}已将 ulimit -SHn 1048576 添加到 /etc/profile${NC}"
else
echo -e "${GREEN}/etc/profile 中已存在 ulimit -SHn 1048576${NC}"
fi
# 使 ulimit 设置生效
source /etc/profile
}
# 调整时区
adjust_timezone() {
if [ "$(timedatectl show --property=Timezone --value)" != "Asia/Shanghai" ]; then
timedatectl set-timezone Asia/Shanghai
echo -e "${GREEN}时区已设置为 Asia/Shanghai${NC}"
else
echo -e "${GREEN}时区已是 Asia/Shanghai${NC}"
fi
# 将当前的 UTC 时间写入硬件时钟
if [ "$(timedatectl show --property=LocalRTC --value)" != "0" ]; then
timedatectl set-local-rtc 0
echo -e "${GREEN}已将 UTC 时间写入硬件时钟${NC}"
else
echo -e "${GREEN}硬件时钟已是 UTC 时间${NC}"
fi
# 重启时间的服务和任务调度服务
#systemctl restart rsyslog
#systemctl restart crond
#echo -e "${GREEN}时间服务和任务调度服务已重启${NC}"
# 同步时间
/usr/sbin/ntpdate pool.ntp.org
if [ $? -eq 0 ]; then
echo -e "${GREEN}时间已同步${NC}"
else
echo -e "${RED}时间同步失败,请检查网络连接或时间服务器配置。${NC}"
fi
}
# 安装 libseccomp 的函数
install_libseccomp() {
local LIBSECCOMP_VERSION="2.5.2"
# 检查系统版本
if { [ -f /etc/centos-release ] && grep -q -E "7\.([0-8]|9[^\.])|8\.[0-9]+" /etc/centos-release; } || { [ -f /etc/os-release ] && grep -q "22\.[0-9]\|24\.[0-9]" /etc/os-release; }; then
echo -e "${GREEN}系统版本高于 Ubuntu 22 或 CentOS 7.9,不需要安装 libseccomp${NC}"
return
fi
# 检查已安装的 libseccomp 版本
if [ -f "/usr/local/lib/pkgconfig/libseccomp.pc" ]; then
local INSTALLED_VERSION=$(grep "Version:" /usr/local/lib/pkgconfig/libseccomp.pc | awk '{print $2}')
if [ "$INSTALLED_VERSION" = "$LIBSECCOMP_VERSION" ]; then
echo -e "${GREEN}libseccomp $LIBSECCOMP_VERSION 已经安装${NC}"
return
else
echo -e "${YELLOW}已安装 libseccomp 版本为 $INSTALLED_VERSION, 需要升级到 $LIBSECCOMP_VERSION${NC}"
fi
else
echo -e "${YELLOW}未检测到已安装的 libseccomp,准备安装 $LIBSECCOMP_VERSION${NC}"
fi
cd /tmp
if [ ! -f libseccomp-${LIBSECCOMP_VERSION}.tar.gz ]; then
attempts=0
success=false
url="https://cloud-help.mandao.com/uploads/cloud/install/runtime/libseccomp-${LIBSECCOMP_VERSION}.tar.gz"
while [ $attempts -lt 6 ]; do
wget $url -O libseccomp-${LIBSECCOMP_VERSION}.tar.gz && success=true && break
attempts=$((attempts + 1))
echo -e "${GREEN}下载失败,重试第 $attempts 次...${NC}"
sleep 5
done
if ! $success; then
echo -e "${RED}下载 libseccomp 失败,请检查网络连接或下载地址。${NC}"
exit 1
fi
else
echo -e "${GREEN}libseccomp-${LIBSECCOMP_VERSION}.tar.gz 已存在,跳过下载。${NC}"
fi
tar -xzf libseccomp-${LIBSECCOMP_VERSION}.tar.gz
cd libseccomp-${LIBSECCOMP_VERSION}
echo -e "${GREEN}正在配置,请等待!${NC}"
# 配置并隐藏输出,失败时提示查看日志
./configure > /tmp/libseccomp_configure.log 2>&1 || {
echo -e "${RED}配置失败,请查看 /tmp/libseccomp_configure.log 了解详情。${NC}"
exit 1
}
echo -e "${GREEN}正在编译,请等待!${NC}"
# 编译并隐藏输出,失败时提示查看日志
make -j2 > /tmp/libseccomp_make.log 2>&1 || {
echo -e "${RED}编译失败,请查看 /tmp/libseccomp_make.log 了解详情。${NC}"
exit 1
}
# 安装并隐藏输出,失败时提示查看日志
make install > /tmp/libseccomp_install.log 2>&1 || {
echo -e "${RED}安装失败,请查看 /tmp/libseccomp_install.log 了解详情。${NC}"
exit 1
}
ldconfig
echo -e "${GREEN}libseccomp $LIBSECCOMP_VERSION 已成功安装${NC}"
# 检查并更新 ldconfig 缓存
echo "/usr/local/lib" > /etc/ld.so.conf.d/local-lib.conf
ldconfig
}
# 停止并禁用防火墙和 dnsmasq
disable_services() {
# 停止并禁用防火墙
if systemctl is-active --quiet firewalld; then
systemctl stop firewalld
echo -e "${GREEN}防火墙已停止${NC}"
fi
if systemctl is-enabled --quiet firewalld; then
systemctl disable firewalld
echo -e "${GREEN}防火墙已禁用${NC}"
fi
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
iptables -P FORWARD ACCEPT
echo -e "${GREEN}iptables 规则已清除${NC}"
# 停止并禁用 dnsmasq
if systemctl is-active --quiet dnsmasq; then
systemctl stop dnsmasq
echo -e "${GREEN}dnsmasq 已停止${NC}"
fi
if systemctl is-enabled --quiet dnsmasq; then
systemctl disable dnsmasq
echo -e "${GREEN}dnsmasq 已禁用${NC}"
fi
}
# 关闭 SELinux 和 Swap
disable_swap_selinux() {
# 关闭 Swap
if swapon --summary | grep -q 'partition\|file'; then
swapoff -a
echo -e "${GREEN}Swap 已关闭${NC}"
fi
if grep -q 'swap' /etc/fstab; then
sed -i '/swap/d' /etc/fstab
echo -e "${GREEN}/etc/fstab 中的 Swap 条目已删除${NC}"
fi
# 关闭 SELinux(如果安装了工具)
if command -v getenforce &> /dev/null; then
if [ "$(getenforce)" != "Disabled" ];then
setenforce 0
echo -e "${GREEN}SELinux 已设置为 Permissive${NC}"
fi
else
echo -e "${YELLOW}getenforce 命令未找到,跳过 SELinux 设置步骤。${NC}"
fi
if command -v setenforce &> /dev/null; then
if grep -q 'SELINUX=enforcing' /etc/selinux/config;then
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
echo -e "${GREEN}SELinux 配置文件已修改为 Disabled${NC}"
fi
else
echo -e "${YELLOW}setenforce 命令未找到,跳过 SELinux 设置步骤。${NC}"
fi
}
# 配置 Kubernetes 优化参数和加载内核模块
configure_kubernetes() {
# 配置 Kubernetes 优化参数
if [ ! -f /etc/sysctl.d/kubernetes.conf ]; then
cat > /tmp/kubernetes.conf << EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
EOF
cp /tmp/kubernetes.conf /etc/sysctl.d/kubernetes.conf
sysctl -p /etc/sysctl.d/kubernetes.conf &
rm -rf /tmp/kubernetes.conf
echo -e "${GREEN}Kubernetes 优化参数已配置${NC}"
else
echo -e "${GREEN}Kubernetes 优化参数已存在${NC}"
fi
# 加载内核模块
for module in br_netfilter ip_vs; do
if ! lsmod | grep -q "$module"; then
modprobe $module
echo -e "${GREEN}内核模块 $module 已加载${NC}"
else
echo -e "${GREEN}内核模块 $module 已存在${NC}"
fi
done
}
# 设置文件句柄
configure_file_handles() {
updateSysCtl() {
key=$1
value=$2
filePath=/etc/sysctl.conf
if grep -q $key $filePath; then
sed -i "/$key/d" $filePath
fi
echo "$key = $value" | tee -a $filePath
echo -e "${GREEN}已设置 $key = $value${NC}"
}
updateSysCtl "fs.file-max" "1000000"
updateSysCtl "net.ipv4.ip_conntrack_max" "1000000"
updateSysCtl "net.ipv4.netfilter.ip_conntrack_max" "1000000"
sysctl -p &
echo -e "${GREEN}文件句柄已设置${NC}"
}
# 安装容器运行时 Containerd
install_containerd() {
export PATH=$PATH:/usr/local/bin
if [ ! -f /usr/local/bin/containerd ]; then
#local url="https://github.com/containerd/containerd/releases/download/v1.7.7/cri-containerd-cni-1.7.7-linux-amd64.tar.gz"
local url="https://cloud-help.mandao.com/uploads/cloud/install/runtime/cri-containerd-cni-1.7.20-linux-amd64.tar.gz"
local file="/tmp/cri-containerd-cni-1.7.20-linux-amd64.tar.gz"
local attempts=0
local success=false
# 检测 /tmp 目录下是否有该文件
if [ -f "$file" ]; then
echo -e "${GREEN}检测到 /tmp 目录下已存在 cri-containerd-cni-1.7.20-linux-amd64.tar.gz 文件,尝试解压...${NC}"
tar -zxvf "$file" -C / || {
echo -e "${RED}解压失败,删除文件并重新下载...${NC}"
rm -f "$file"
}
fi
# 如果文件不存在或解压失败后被删除,则重新下载
if [ ! -f "$file" ]; then
while [ $attempts -lt 6 ]; do
wget "$url" -O "$file" && success=true && break
attempts=$((attempts + 1))
echo -e "${GREEN}下载失败,重试第 $attempts 次...${NC}"
sleep 5
done
if ! $success; then
echo -e "${RED}下载 containerd 失败,请检查网络连接或下载地址。${NC}"
exit 1
fi
tar -zxvf "$file" -C / || {
echo -e "${RED}解压失败,请手动检查问题。${NC}"
exit 1
}
else
echo -e "${GREEN}文件已存在且解压成功。${NC}"
fi
source /etc/profile
echo -e "${GREEN}Containerd 已安装${NC}"
else
echo -e "${GREEN}Containerd 已存在${NC}"
fi
# 配置 Containerd 服务
if [ ! -f /usr/local/lib/systemd/system/containerd.service ]; then
mkdir -p /usr/local/lib/systemd/system/
cp /etc/systemd/system/containerd.service /usr/local/lib/systemd/system/containerd.service
systemctl daemon-reload
systemctl enable --now containerd
sleep 2
echo -e "${GREEN}Containerd 服务已启动${NC}"
else
echo -e "${GREEN}Containerd 服务已存在${NC}"
fi
# 生成 Containerd 配置
if [ ! -f /etc/containerd/config.toml ]; then
mkdir -p /etc/containerd
containerd config default | tee /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's/registry.k8s.io\/pause:3.8/registry.aliyuncs.com\/google_containers\/pause:3.8/' /etc/containerd/config.toml
systemctl restart containerd
echo -e "${GREEN}Containerd 配置已生成并应用${NC}"
else
echo -e "${GREEN}Containerd 配置已存在${NC}"
fi
# 检查默认 CNI 配置文件是否存在
DEFAULT_CNI_CONFIG="/etc/cni/net.d/10-containerd-net.conflist"
if [ -f "$DEFAULT_CNI_CONFIG" ]; then
echo -e "${GREEN}检测到默认 CNI 配置文件 $DEFAULT_CNI_CONFIG,开始清理。${NC}"
# 清理默认 CNI 配置文件
rm -rf /etc/cni/net.d/*
echo -e "${GREEN}默认 CNI 配置文件已清理。${NC}"
# 重启 containerd 服务
systemctl restart containerd
echo -e "${GREEN}containerd 服务已重启。${NC}"
else
echo -e "${GREEN}未检测到默认 CNI 配置文件,无需清理。${NC}"
fi
}
# 安装 Kubernetes 工具的函数
install_kubernetes_tools() {
if ! kubectl version --client &>/dev/null; then
if [ -f /etc/centos-release ]; then
cat << EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubelet-$KUBERNETES_VERSION kubeadm-$KUBERNETES_VERSION kubectl-$KUBERNETES_VERSION --disableexcludes=kubernetes
systemctl enable kubelet && systemctl start kubelet
yum versionlock kubelet-$KUBERNETES_VERSION-0 kubeadm-$KUBERNETES_VERSION-0 kubectl-$KUBERNETES_VERSION-0
echo -e "${GREEN}kubelet-$KUBERNETES_VERSION、kubeadm-$KUBERNETES_VERSION 和 kubectl-$KUBERNETES_VERSION 已安装并锁定版本${NC}"
elif [ -f /etc/lsb-release ]; then
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat << EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet=$KUBERNETES_VERSION-00 kubeadm=$KUBERNETES_VERSION-00 kubectl=$KUBERNETES_VERSION-00
systemctl enable kubelet && systemctl start kubelet
apt-mark hold kubeadm kubelet kubectl
echo -e "${GREEN}kubelet-$KUBERNETES_VERSION、kubeadm-$KUBERNETES_VERSION 和 kubectl-$KUBERNETES_VERSION 已安装并锁定版本${NC}"
fi
else
echo -e "${GREEN}kubelet-$KUBERNETES_VERSION、kubeadm-$KUBERNETES_VERSION 和 kubectl-$KUBERNETES_VERSION 已安装并锁定版本${NC}"
fi
}
# 安装负载均衡器 kube-vip 的函数
install_kube_vip() {
#export KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | jq -r ".[0].name")
if [ -z "$KVVERSION" ]; then
export KVVERSION="v0.8.0" # 使用一个已知存在的版本
fi
#while ! ctr images ls | grep -q "ghcr.io/kube-vip/kube-vip:$KVVERSION"; do
while ! ctr images ls | grep -q "dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION"; do
#ctr image pull ghcr.io/kube-vip/kube-vip:$KVVERSION
ctr image pull dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION
if [ $? -eq 0 ]; then
echo -e "${GREEN}kube-vip 镜像已下载${NC}"
else
echo -e "${RED}kube-vip 镜像下载失败,正在重试...${NC}"
sleep 5
fi
done
echo -e "${GREEN}kube-vip 镜像已存在${NC}"
export kube_vip_file="/etc/kubernetes/manifests/kube-vip.yaml"
# 检查是否已存在有效的 kube-vip 配置文件
if [ -f $kube_vip_file ] && grep -q "$INTERFACE" $kube_vip_file && grep -q "$VIP" $kube_vip_file; then
echo -e "${GREEN}kube-vip 配置文件已存在且有效,跳过生成。${NC}"
else
# 如果文件不存在或内容无效,则删除并生成新的配置文件
echo "生成新的 kube-vip 配置文件..."
rm -f /etc/kubernetes/manifests/kube-vip.yaml
#ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:$KVVERSION vip /kube-vip manifest pod \
ctr run --rm --net-host dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION vip /kube-vip manifest pod \
--interface $INTERFACE \
--vip $VIP \
--controlplane \
--arp \
--leaderElection | tee $kube_vip_file >/dev/null &
# 等待配置文件生成
echo -e "${GREEN}等待3秒${NC}"
sleep 3
if [ ! -f $kube_vip_file ] || ! (grep -q "$INTERFACE" $kube_vip_file && grep -q "$VIP" $kube_vip_file); then
echo -e "${RED}kube-vip 文件生成出错,请检查。${NC}"
echo -e "${RED}若文件生成出错请尝试修改 KVVERSION 变量,降低 kube-vip 版本。${NC}"
exit 1
fi
grep -q "image: ghcr.io/kube-vip/kube-vip:$KVVERSION" /etc/kubernetes/manifests/kube-vip.yaml
if [ $? -eq 0 ]; then
echo -e "${GREEN}正在将镜像地址替换为 dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION ${NC}"
sed -i "s|image: ghcr.io/kube-vip/kube-vip:$KVVERSION|image: dockerhub.mandao.com/kube-vip/kube-vip:$KVVERSION|" /etc/kubernetes/manifests/kube-vip.yaml
echo -e "${GREEN}替换完成。${NC}"
else
echo -e "${GREEN}未找到原始镜像地址 ghcr.io/kube-vip/kube-vip:$KVVERSION,无需替换。${NC}"
fi
fi
}
# 检查系统类型并调用相应的函数
if [ -f /etc/centos-release ]; then
configure_centos
elif [ -f /etc/lsb-release ]; then
configure_ubuntu
else
echo -e "${RED}不支持的操作系统。${NC}"
exit 1
fi
configure_ulimit
adjust_timezone
install_libseccomp
disable_services
disable_swap_selinux
configure_kubernetes
configure_file_handles
install_containerd
install_kubernetes_tools
if [ "$node_type" == "master" ]; then
install_kube_vip
fi
# 在第一台Master节点执行以下语句
echo "================================================================================"
echo -e "${RED}请注意,以下为加入集群的方式,请仔细阅读!!!!${NC}"
echo -e "${RED}请在已加入集群的Master节点上执行以下命令,并根据下方的说明进行操作${NC}"
echo -e "
================================================================================
#设置环境变量
cat << EOF > kubeadm-init-config
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
nodeRegistration:
criSocket: /var/run/cri-dockerd.sock
EOF
#此命令生成的结果粘贴至需要加入Master节点的机器
echo \$(kubeadm token create --print-join-command) --control-plane --certificate-key \$(kubeadm init phase upload-certs --upload-certs --config kubeadm-init-config | tail -n 1)
#此命令生成的结果粘贴至需要加入worker节点的机器
kubeadm token create --print-join-command
===============================================================================
"
# 最终检查 /etc/hosts 文件内容
echo -e "${RED}请检查 /etc/hosts 文件中包含 IP 和主机名的条目,如果没有,请手动添加hostname的解析:${NC}"
grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' /etc/hosts
作者:范云龙 创建时间:2024-09-04 11:03
最后编辑:范云龙 更新时间:2025-04-29 18:46
最后编辑:范云龙 更新时间:2025-04-29 18:46