Kubernetes 集群搭建笔记(Ubuntu 24.04 + kubeadm + Docker + cri-dockerd + Flannel)
本文记录了在 windows 虚拟机VMware中安装 Ubuntu 24.04 ,从零开始搭建一个 Kubernetes 集群的过程,版本为 v1.28.15,使用 Docker 作为容器运行时,通过 cri-dockerd 适配,网络插件选用 Flannel。
1. 主机规划
kubernetes-master
:控制平面节点(master)kubernetes-node1
、kubernetes-node2
:工作节点(node)kubernetes-registry
:私有镜像仓库
2. 安装 Docker
使用阿里云源安装 Docker CE:
阿里云 Docker 安装文档
验证安装:
docker version
systemctl enable docker --now
3. 安装 cri-dockerd
Kubernetes 从 1.24 起不再直接支持 Docker,需要 cri-dockerd
作为适配层。
参考文档:cri-dockerd 安装
安装完成后,确认 socket 文件路径:
- Docker:
/var/run/cri-dockerd.sock
- containerd:
/var/run/containerd/containerd.sock
4. 安装 Kubernetes 组件
需要安装以下三个组件:
kubelet
:节点代理,负责启动和管理 Podkubeadm
:集群初始化工具kubectl
:命令行客户端
参考阿里云镜像源: 阿里云 Kubernetes 镜像
5. 初始化前环境清理脚本
文件:prepare_env.sh
#!/bin/bash
set -e
echo "[1/5] 停止 kubelet..."
sudo systemctl stop kubelet
# 检测 CRI
if [ -S /var/run/cri-dockerd.sock ]; then
CRI_SOCKET="unix:///var/run/cri-dockerd.sock"
echo "[+] Docker CRI detected, using $CRI_SOCKET"
elif [ -S /var/run/containerd/containerd.sock ]; then
CRI_SOCKET="unix:///var/run/containerd/containerd.sock"
echo "[+] containerd detected, using $CRI_SOCKET"
else
echo "[-] No CRI detected! Exiting."
exit 1
fi
echo "[2/5] 重置 kubeadm..."
sudo kubeadm reset -f --cri-socket=$CRI_SOCKET --ignore-preflight-errors=Swap
echo "[3/5] 清理旧证书和配置..."
sudo rm -rf /etc/kubernetes/pki
sudo rm -rf /etc/kubernetes/*.conf
sudo rm -rf ~/.kube
echo "[4/5] 删除旧的 etcd 数据和 kubelet 状态..."
sudo rm -rf /var/lib/etcd
sudo rm -rf /var/lib/kubelet/*
echo "[5/5] 检查端口 6443 占用..."
if lsof -i :6443 >/dev/null; then
echo "[-] Port 6443 is still in use! Please kill the process occupying it before proceeding."
lsof -i :6443
exit 1
fi
echo "环境清理完成,CRI socket: $CRI_SOCKET"
执行脚本:
bash prepare_env.sh
6. 初始化 Master 节点
为避免镜像拉取是出现问题,使用kubeadm初始化之前先要准备好docker镜像,本次记录中通过
kubeadm config images list
获取镜像列表,然后从阿里云获取镜像存入本地harbor的方法,见如下的命令
#!/bin/bash
#
# 同步 Kubernetes 核心镜像到私有 Harbor 仓库
# 版本:1.28.15
# 说明:
# 1. 从阿里云 registry 拉取镜像(解决国外 registry 拉取慢的问题)
# 2. 重新打 tag 到内部 Harbor
# 3. 推送到内网 Harbor
# 4. 删除中转镜像,避免混乱
#
#-----------------------------
# 基本变量配置
#-----------------------------
K8S_VERSION="1.28.15" # 指定 Kubernetes 版本
SRC_REGISTRY="registry.aliyuncs.com/google_containers" # 源镜像仓库(阿里云镜像)
DST_REGISTRY="kubernetes-registry.moon.com/google_containers" # 目标私有仓库(Harbor)
#-----------------------------
# Step 1: 获取该版本所需镜像列表
#-----------------------------
# kubeadm 会列出部署该版本 Kubernetes 所需的所有镜像
# 例如:registry.k8s.io/kube-apiserver:v1.28.15
# awk 提取最后一段,只保留 "kube-apiserver:v1.28.15"
#-----------------------------
echo "[INFO] 获取 Kubernetes $K8S_VERSION 镜像列表..."
images=$(kubeadm config images list --kubernetes-version="${K8S_VERSION}" | awk -F'/' '{print $NF}')
#-----------------------------
# Step 2: 循环同步每个镜像
#-----------------------------
for image in ${images}; do
echo
echo "==============================="
echo "[INFO] 正在处理镜像: ${image}"
echo "==============================="
# 拉取镜像(从阿里云源)
echo "[STEP] 拉取 ${SRC_REGISTRY}/${image}"
docker pull ${SRC_REGISTRY}/${image}
# 打上私有仓库标签
echo "[STEP] 重新打标签为 ${DST_REGISTRY}/${image}"
docker tag ${SRC_REGISTRY}/${image} ${DST_REGISTRY}/${image}
# 推送到私有 Harbor 仓库
echo "[STEP] 推送到 Harbor:${DST_REGISTRY}/${image}"
docker push ${DST_REGISTRY}/${image}
# 删除中转镜像,只保留目标镜像
echo "[STEP] 删除本地中转镜像 ${SRC_REGISTRY}/${image}"
docker rmi ${SRC_REGISTRY}/${image}
echo "[DONE] 镜像 ${image} 已同步至 Harbor。"
done
#-----------------------------
# Step 3: 完成提示
#-----------------------------
echo
echo "=========================================="
echo "[SUCCESS] 所有 Kubernetes ${K8S_VERSION} 镜像已同步完成。"
echo "可在 Harbor 上查看:${DST_REGISTRY}"
echo "=========================================="
之后就可以初始化了,见如下bash文件
文件:init_k8s.sh
#!/bin/bash
set -e
# 请根据 prepare_env.sh 输出填入 CRI socket
CRI_SOCKET="unix:///var/run/cri-dockerd.sock"
echo "[1/1] 初始化 Kubernetes master..."
sudo kubeadm init \
--kubernetes-version=1.28.15 \
--apiserver-advertise-address=10.0.0.5 \
--image-repository=kubernetes-registry.moon.com/google_containers \
--pod-network-cidr="10.244.0.0/16" \
--service-cidr="10.96.0.0/12" \
--ignore-preflight-errors=Swap \
--cri-socket=$CRI_SOCKET
echo "------------------------------------------------"
echo "初始化完成!"
执行初始化脚本:
bash init_k8s.sh
初始化成功后,根据 kubeadm init
的输出,复制 kubeadm join
命令到各个 node
节点运行。
7. 配置 kubectl
在 master 节点执行:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
验证:
kubectl get nodes
8. 安装网络插件 Flannel
安装 Flannel 网络插件,保证 Pod 之间可以互通:
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
9. 验证集群状态
kubectl get nodes
示例输出:
NAME STATUS ROLES AGE VERSION
kubernetes-master Ready control-plane 47h v1.28.15
kubernetes-node1 Ready <none> 26h v1.28.15
kubernetes-node2 Ready <none> 26h v1.28.15
至此,Kubernetes 集群安装完成 🎉
10. 常见问题排查
swap 未关闭
Kubernetes 要求禁用 swap:
sudo swapoff -a sed -i '/ swap / s/^/#/' /etc/fstab
镜像拉取失败
- 配置国内镜像仓库(如阿里云、七牛、腾讯云),或使用自建
kubernetes-registry
。
- 配置国内镜像仓库(如阿里云、七牛、腾讯云),或使用自建
6443 端口被占用
检查并释放端口:
lsof -i :6443 kill -9 <PID>
flannel 网络不通
- 确认
--pod-network-cidr
与 flannel 配置一致(默认10.244.0.0/16
)。 - 检查 CNI 插件目录
/etc/cni/net.d/
是否存在配置文件。
- 确认
文档信息
- 本文作者:Chaojie Men
- 本文链接:https://menchaojie.github.io/2025/10/03/k8s/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)