一、环境准备:
三台Ubuntu 26.04 虚拟机,使用Containerd方式部署
Containerd版本:V2.2.2
Kubernetes版本:V1.36.0
k8s-master 12C4G 192.168.25.148
k8s-node1 12C2G 192.168.25.138
k8s-node2 12C2G 192.168.25.142
二、准备DNS解析(所有主机)
cat >> /etc/hosts <<EOF
192.168.25.148 k8s-master
192.168.25.138 k8s-node1
192.168.25.142 k8s-node2
EOF
三、修改YUM源(可选,所有主机)
Ubuntu 默认连接国外仓库,可能速度不太好,可以尝试换成国内的仓库加快速度,如果要做,建议在所有机器上都做一下
换源脚本
#!/bin/bash
# 通用换源脚本:CentOS 固定阿里源,Debian/Ubuntu 自动测速选择最快国内源
# 不依赖 bc、lsb_release 等额外包,仅需 curl 或 wget
set -e
RED='\033[31m'
GREEN='\033[32m'
YELLOW='\033[33m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
# 检查 root
if [[ $EUID -ne 0 ]]; then
error "请使用 root 用户或 sudo 执行此脚本"
fi
# 1. 外网连通性检测(仅测试 baidu.com)
info "正在检测外网连通性..."
if curl -s --connect-timeout 5 http://www.baidu.com > /dev/null; then
info "外网连通性正常"
elif wget -q --timeout=5 --spider http://www.baidu.com; then
info "外网连通性正常"
else
warn "无法访问 baidu.com,外网连接失败"
echo -e "\n=== 网卡信息 ==="
if command -v ip &> /dev/null; then
ip addr show
elif command -v ifconfig &> /dev/null; then
ifconfig -a
else
echo "未找到 ip 或 ifconfig 命令,无法显示网卡信息"
fi
error "脚本已退出,请检查网络配置"
fi
# 2. 检查下载工具
info "检查下载工具..."
if command -v wget &> /dev/null; then
DOWNLOADER="wget"
info "使用 wget 下载"
elif command -v curl &> /dev/null; then
DOWNLOADER="curl"
info "使用 curl 下载"
else
error "未找到 wget 或 curl,请安装其中之一后重试"
fi
# 3. 识别操作系统及版本(完全基于 /etc/os-release,不依赖 lsb_release)
get_os() {
if [ ! -f /etc/os-release ]; then
error "无法找到 /etc/os-release,不支持该系统"
fi
. /etc/os-release
case "$ID" in
centos|rhel)
OS="centos"
VERSION=$(echo "$VERSION_ID" | cut -d. -f1)
;;
ubuntu)
OS="ubuntu"
VERSION=$(echo "$VERSION_ID" | cut -d. -f1)
# 优先使用 UBUNTU_CODENAME,其次 VERSION_CODENAME
CODENAME="${UBUNTU_CODENAME:-$VERSION_CODENAME}"
if [ -z "$CODENAME" ]; then
error "无法获取 Ubuntu 版本代号"
fi
;;
debian)
OS="debian"
VERSION=$(echo "$VERSION_ID" | cut -d. -f1)
CODENAME="$VERSION_CODENAME"
# 处理 sid / testing
if [ -z "$CODENAME" ] && [ -f /etc/debian_version ]; then
if grep -qi "sid" /etc/debian_version; then
CODENAME="sid"
elif grep -qi "testing" /etc/debian_version; then
CODENAME="testing"
fi
fi
;;
*)
error "不支持的系统: $ID"
;;
esac
}
get_os
info "检测到系统: $OS ${VERSION:-$CODENAME}"
if [ "$OS" = "ubuntu" ] || [ "$OS" = "debian" ]; then
info "发行版代号: $CODENAME"
fi
# ------------------------------------------------------------
# CentOS 部分(固定阿里源)
# ------------------------------------------------------------
if [ "$OS" = "centos" ]; then
case "$VERSION" in
6) REPO_URL="https://mirrors.aliyun.com/repo/Centos-vault-6.10.repo" ;;
7) REPO_URL="https://mirrors.aliyun.com/repo/Centos-7.repo" ;;
8) REPO_URL="https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo" ;;
*) error "CentOS $VERSION 不受支持(仅支持 6/7/8)" ;;
esac
BACKUP_DIR="/etc/yum.repos.d/backup_$(date +%Y%m%d_%H%M%S)"
info "备份原有 repo 文件到 $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
cp -a /etc/yum.repos.d/*.repo "$BACKUP_DIR/" 2>/dev/null || true
rm -rf /etc/yum.repos.d/*.repo
TARGET="/etc/yum.repos.d/CentOS-Base.repo"
info "下载阿里云镜像源..."
if [ "$DOWNLOADER" = "wget" ]; then
wget -O "$TARGET" "$REPO_URL" || error "下载失败"
else
curl -o "$TARGET" "$REPO_URL" || error "下载失败"
fi
# 修复非阿里云 ECS 用户可能出现的域名解析问题
info "清理无效域名(mirrors.cloud.aliyuncs.com / mirrors.aliyuncs.com)..."
sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' "$TARGET"
info "生成 yum 缓存..."
yum clean all || error "换源失败:yum clean all 失败"
yum makecache || error "换源失败:yum makecache 失败"
info "CentOS 换源完成!"
exit 0
fi
# ------------------------------------------------------------
# Debian / Ubuntu 部分:多镜像源延迟测速(纯 Shell,无 bc)
# ------------------------------------------------------------
declare -A MIRRORS
MIRRORS=(
["阿里源"]="http://mirrors.aliyun.com"
["腾讯源"]="http://mirrors.cloud.tencent.com"
["华为源"]="https://mirrors.huaweicloud.com"
["清华源"]="https://mirrors.tuna.tsinghua.edu.cn"
)
# 根据发行版确定路径和组件
if [ "$OS" = "debian" ]; then
REPO_PATH="debian"
COMPONENTS="main contrib non-free non-free-firmware"
# Debian 特殊处理:如果代号是 sid 或 testing,使用对应的 Release 文件
if [ "$CODENAME" = "sid" ] || [ "$CODENAME" = "testing" ]; then
TEST_CODENAME="$CODENAME"
else
TEST_CODENAME="$CODENAME"
fi
elif [ "$OS" = "ubuntu" ]; then
REPO_PATH="ubuntu"
COMPONENTS="main restricted universe multiverse"
TEST_CODENAME="$CODENAME"
else
error "不支持的系统"
fi
# 测速函数:返回连接时间(毫秒整数),失败返回 999999
test_speed() {
local base_url=$1
local test_url="${base_url}/${REPO_PATH}/dists/${TEST_CODENAME}/Release"
local timeout=3
if command -v curl &> /dev/null; then
# curl 输出 time_total 单位为秒(浮点),转换为毫秒整数
local time_sec=$(curl -o /dev/null -s -w '%{time_total}' --connect-timeout $timeout --max-time $timeout "$test_url" 2>/dev/null)
if [[ -n "$time_sec" && "$time_sec" != "0" && "$time_sec" != "0.000" ]]; then
# 去掉小数点,取整毫秒:例如 0.123 -> 123
local ms=$(echo "$time_sec" | awk '{printf "%.0f", $1 * 1000}')
echo "${ms:-999999}"
else
echo "999999"
fi
elif command -v wget &> /dev/null; then
# wget 使用 --spider 和 --server-response,记录耗时(需要 date 计算差值)
local start=$(date +%s%3N)
if wget --spider --timeout=$timeout --tries=1 "$test_url" 2>/dev/null; then
local end=$(date +%s%3N)
local elapsed=$((end - start))
echo "${elapsed:-999999}"
else
echo "999999"
fi
else
echo "999999"
fi
}
info "正在检测各镜像源延迟(请稍候)..."
BEST_MIRROR=""
BEST_TIME=999999
for name in "${!MIRRORS[@]}"; do
url=${MIRRORS[$name]}
printf "测试 %-8s (%s) ... " "$name" "$url"
time_ms=$(test_speed "$url")
echo "${time_ms}ms"
if [ "$time_ms" -lt "$BEST_TIME" ]; then
BEST_TIME=$time_ms
BEST_MIRROR="$name"
BEST_URL="$url"
fi
done
if [ -z "$BEST_MIRROR" ]; then
error "所有镜像源均不可达,请检查网络或手动配置源"
fi
info "最优镜像源: $BEST_MIRROR ($BEST_URL), 延迟 ${BEST_TIME}ms"
# 备份现有源配置
BACKUP_DIR="/etc/apt/backup_$(date +%Y%m%d_%H%M%S)"
info "备份现有 APT 源配置到 $BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
[ -f /etc/apt/sources.list ] && cp -a /etc/apt/sources.list "$BACKUP_DIR/"
# 备份并移除所有 sources.list.d 下的 .list 和 .sources 文件,避免冲突
if ls /etc/apt/sources.list.d/*.{list,sources} &>/dev/null 2>&1; then
mkdir -p "$BACKUP_DIR/sources.list.d"
cp -a /etc/apt/sources.list.d/*.{list,sources} "$BACKUP_DIR/sources.list.d/" 2>/dev/null || true
rm -f /etc/apt/sources.list.d/*.{list,sources}
warn "已清空 /etc/apt/sources.list.d/ 下的所有源文件,改用传统 sources.list"
fi
# 生成新的 sources.list
info "生成新的源列表..."
cat > /etc/apt/sources.list <<EOF
deb ${BEST_URL}/${REPO_PATH} ${TEST_CODENAME} ${COMPONENTS}
deb ${BEST_URL}/${REPO_PATH} ${TEST_CODENAME}-updates ${COMPONENTS}
deb ${BEST_URL}/${REPO_PATH} ${TEST_CODENAME}-backports ${COMPONENTS}
EOF
# Ubuntu 额外添加安全源
if [ "$OS" = "ubuntu" ]; then
cat >> /etc/apt/sources.list <<EOF
deb ${BEST_URL}/${REPO_PATH} ${TEST_CODENAME}-security ${COMPONENTS}
EOF
fi
# 清空 APT 缓存
info "清空 APT 软件包索引..."
apt clean || error "换源失败:apt clean 失败"
# 更新 APT 缓存
info "更新 APT 软件包索引..."
apt update || error "换源失败:apt update 失败"
info "换源完成!当前使用镜像源: $BEST_MIRROR ($BEST_URL)"
在线版
curl -sSL https://www.sunzishaokao.com/Linux换源脚本.sh | bash
四、Containerd 部署(所有主机)
安装Containerd
wget https://gh-proxy.com/github.com/containerd/nerdctl/releases/download/v2.2.2/nerdctl-full-2.2.2-linux-amd64.tar.gz
tar Cxzvvf /usr/local nerdctl-full-2.2.2-linux-amd64.tar.gz
生成配置文件
mkdir -p /etc/containerd/certs.d/
containerd config default > /etc/containerd/config.toml
配置镜像源
# 方案1(快速、但付费,最低10元50GB流量)
# 先去https://1ms.run/?aff=1726注册账户并购买资源包,然后使用下方命令一键配置付费镜像源
sudo bash -c "$(curl -sSL https://n3.ink/helper)"
# 方案2
#沙盒镜像改为国内
sed -i '/^\s*\[plugins.'"'"'io.containerd.cri.v1.images'"'"'.pinned_images\]/{n;s|^\(\s*\)sandbox = .*$|\1sandbox = '"'"'registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.10'"'"'|}' /etc/containerd/config.toml
#添加加速器地址
sed -i '/^\s*\[plugins.'"'"'io.containerd.cri.v1.images'"'"'.registry\]/{n;s|^\(\s*\)config_path = .*$|\1config_path = '"'"'/etc/containerd/certs.d'"'"'|}' /etc/containerd/config.toml
#添加docker.io加速
mkdir /etc/containerd/certs.d/docker.io/ -p
cat > /etc/containerd/certs.d/docker.io/hosts.toml <<-'EOF'
server = "https://registry-1.docker.io"
[host."https://docker.1ms.run"]
capabilities = ["pull", "resolve", "push"]
EOF
#添加registry.k8s.io加速
mkdir /etc/containerd/certs.d/registry.k8s.io/ -p
cat > /etc/containerd/certs.d/registry.k8s.io/hosts.toml <<-'EOF'
server = "https://registry.k8s.io"
[host."https://registry.aliyuncs.com/google_containers"]
capabilities = ["pull", "resolve"]
EOF
启动Containerd服务
systemctl daemon-reload
systemctl enable --now containerd
systemctl enable --now buildkit
添加nerdctl命令自动补齐功能(可选)
nerdctl completion bash > /etc/bash_completion.d/nerdctl
source /etc/bash_completion.d/nerdctl
五、Kubernetes 组件安装(所有主机)
关闭虚拟内存
swapoff -a
sed -i 's/.*swap.*/#&/' /etc/fstab
允许 iptables 检查桥接流量
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
安装 kubeadm
# 安装依赖
apt-get update && apt-get install -y apt-transport-https curl
# 创建密钥存储目录
mkdir -p /etc/apt/keyrings
# 下载并安装阿里云 Kubernetes GPG 密钥
curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.36/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes.gpg
# 配置 Kubernetes 阿里云 APT 软件源
echo "deb [signed-by=/etc/apt/keyrings/kubernetes.gpg] https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.36/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
# 更新软件源索引并安装k8s组件
apt-get update && apt-get install -y kubelet kubeadm kubectl
# 固定版本
apt-mark hold kubelet kubeadm kubectl
添加命令自动补齐功能
kubectl completion bash > /etc/bash_completion.d/kubectl
kubeadm completion bash > /etc/bash_completion.d/kubeadm
source /etc/bash_completion.d/kubectl
source /etc/bash_completion.d/kubeadm
集成containerd
crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl images
六、Kubernetes Master部署
集群部署
下方kubeadm.yaml中name字段必须在网络中可被解析,也可以将解析记录添加到集群中所有机器的/etc/hosts中
生成默认配置
kubeadm config print init-defaults > kubeadm.yaml
修改配置
# 1. 设置master节点IP
sed -i 's/.*advert.*/ advertiseAddress: 192.168.25.148/g' kubeadm.yaml
# 2.设置master主机名
sed -i 's/.*name.*/ name: k8s-master/g' kubeadm.yaml
# 3.修改k8s镜像源
# 如果你购买了1ms.run镜像源
sed -i 's/imageRepo.*/imageRepository: k8s.1ms.run/g' kubeadm.yaml
# 如果你没有购买1ms.run镜像源
sed -i 's@imageRepo.*@imageRepository: registry.aliyuncs.com/google_containers@g' kubeadm.yaml
如果遇到coredns拉取问题(not found),建议在imageRepository下方通过dns.imageRepository方式指定一下coredns仓库名(如图,根据情况修改镜像源)

开始部署
modprobe br_netfilter
kubeadm init --config kubeadm.yaml
出现下面的提示就是成功了,保存好join的命令
Your Kubernetes control-plane has initialized successfully!
...
kubeadm join 192.168.8.3:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:d0edd579cbefc3baee6c2253561e24261300ede214ae172bf9687404e09104bf
授权管理权限
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
部署Calico网络插件
下载配置
curl -O https://gh-proxy.com/raw.githubusercontent.com/projectcalico/calico/v3.31.4/manifests/calico.yaml
修改镜像源
# 如已购买1ms.run镜像源
sed -i 's/quay.io/quay.1ms.run/g' calico.yaml
应用部署
kubectl apply -f calico.yaml
六、Kubernetes Node部署
通过之前生成的jojn命令到node节点部署,如果时间长忘记了join参数,可以在master节点上用以下方法重新生成
kubeadm token create --print-join-command
七、重置集群(针对于部署失败)
kubeadm reset -f
rm -rf /etc/kubernetes /var/lib/etcd /var/lib/kubelet
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
systemctl stop containerd
systemctl stop kubelet
crictl rm -f $(crictl ps -aq) 2>/dev/null
crictl rmi --prune 2>/dev/null
systemctl daemon-reload
systemctl restart containerd
systemctl restart kubelet
rm -rf /etc/cni/net.d
rm -rf $HOME/.kube/config
八、交流答疑
如果你也深耕或想入门云计算,不妨扫码进软栈交流群!圈内头部大佬常驻,有问题随时提问,即时答疑交流。

广告:
© 版权声明
THE END













暂无评论内容