第二篇: 部署 Kubernetes 集群(Ubuntu 24.04.3)
前提:app 110机器构建 OCI 镜像的ACR地址:crpi-ua3er91ww0y2dq1i.cn-shenzhen.personal.cr.aliyuncs.com/mirrors-yuan/flask-forum:1.0ctr(全称:containerd CLI)是 containerd 自带的命令行工具,用于拉镜像、跑容器等清理旧容器(如果存在)c 确认容器是否正常2、在 app 机器
python-flask项目开发:
- flask开发完整过程总结:https://blog.csdn.net/qq_38444844/article/details/151928286?spm=1011.2415.3001.5331
- 项目源码:https://gitee.com/loveTianWen/Forum-platform/tree/master
- 第一篇: 使用Docker部署flask项目(Flask + DB 容器化)https://blog.csdn.net/qq_38444844/article/details/155862905?sharetype=blogdetail&sharerId=155862905&sharerefer=PC&sharesource=qq_38444844&spm=1011.2480.3001.8118
目的:部署Kubernetes 集群(Ubuntu 24.04.3)
总体流程:
1 在 app 机器(192.168.56.110)上构建 Flask 项目 OCI 镜像(done)
2 在 db机器(192.168.56.109)用 Containerd 运行 MariaDB (done)
3 在 app 机器用 Containerd 运行Flask 容器,连接远程 DB (done)
4 在 3 台 K8s 机器上搭建集群(kubeadm + Containerd) (done)
5 将Flask 项目部署到 K8s,实现自动化管理 (doing)
| IP 地址 | 主机 | 角色 | 核心职责 | 关键组件 |
|---|---|---|---|---|
| 192.168.56.109 | db | 数据库服务器 | 提供持久化数据存储服务 | Containerd + MariaDB 容器 |
| 192.168.56.110 | app | 应用构建与测试机 | 构建镜像、本地测试、验证跨主机连接 | Containerd + Docker Buildx(兼容模式) + Flask 应用容器 |
| 192.168.56.111 | k8s-master | Kubernetes 控制平面 | 管理集群状态、调度 Pod、提供 API | kubeadm + kube-apiserver + etcd + Containerd |
| 192.168.56.112 | k8s-worker1 | Kubernetes 工作节点 1 | 运行应用 Pod(如 Flask、DB) | kubelet + Containerd |
| 192.168.56.113 | k8s-worker2 | Kubernetes 工作节点2 | 扩展工作负载,实现高可用 | kubelet + Containerd |

前提:app 110机器构建 OCI 镜像的ACR地址:crpi-ua3er91ww0y2dq1i.cn-shenzhen.personal.cr.aliyuncs.com/mirrors-yuan/flask-forum:1.0
1、在 db 机器用 Containerd 运行 MariaDB
- 目标:在 192.168.56.109 (db) 上用 ctr 启动 MariaDB 容器,持久化数据,允许远程连接
a 安装 containerd
containerd 作用: 一个工业级的容器运行时,负责管理容器的整个生命周期: 拉取镜像(pull image) 创建/启动/停止容器管理网络、存储、命名空间等
跟docker比:它是 Kubernetes 默认支持的底层运行时(比 Docker 更轻、更稳定) 不包含 docker build、docker-compose 等高级功能,只专注“运行容器”
ctr(全称:containerd CLI)是 containerd 自带的命令行工具,用于拉镜像、跑容器等
1. 检查是否已安装 containerd(若未安装会报错)
sudo ctr version
2. 更新软件包列表(可选,但推荐)
sudo apt update
3. 安装 containerd(轻量级容器运行时)
sudo apt install -y containerd
4. 启用并立即启动 containerd 服务
sudo systemctl enable --now containerd
systemctl enable:开机自启
--now:立即启动服务(等价于 systemctl start containerd)

b 生成并启动MariaDB容器
1 创建 MariaDB 数据目录
sudo mkdir -p /data/mariadb
2 从 DaoCloud 镜像源拉取 MariaDB 10.6 镜像
sudo ctr images pull docker.m.daocloud.io/library/mariadb:10.6
3 启动 MariaDB 容器
sudo ctr run -d \
--net-host \ # 使用宿主机网络,直接暴露 3306 端口(无需端口映射)
--mount type=bind,src=/data/mariadb,dst=/var/lib/mysql,options=rbind \ # 挂载数据目录
--env MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=yes \ # 允许 root 空密码(仅测试用)
--env MARIADB_DATABASE=zhiliaooa \ # 自动创建数据库 zhiliaooa
docker.m.daocloud.io/library/mariadb:10.6 mariadb-container \ # 镜像名和容器名
mysqld \ # 显式指定启动命令为 mysqld
--bind-address=0.0.0.0 \ # 监听所有 IP,允许远程连接
--default-authentication-plugin=mysql_native_password # 兼容旧版 MySQL 客户端
4 在另一台机器上使用 MySQL 客户端连接
mysql -h 192.168.56.109 -P 3306 -u root
- 清理旧容器(如果存在)
1 尝试停止容器(如果正在运行)
sudo ctr tasks kill mariadb-container 2>/dev/null || true
2 删除容器(即使不存在也不报错)
sudo ctr containers delete mariadb-container 2>/dev/null || true
3 清理残留快照(containerd 的镜像层快照)
sudo ctr snapshots rm mariadb-container 2>/dev/null || true
4 查看containerd所有正在运行的任务(tasks)
sudo ctr tasks ls
c 确认容器是否正常
1. 检查容器是否在运行
sudo ctr tasks ls | grep mariadb-container
2. 检查 3306 端口是否监听
sudo ss -tuln | grep 3306
3. 尝试连接(空密码)
mysql -h 127.0.0.1 -u root -e "SELECT 1;"
4. 检查数据库是否创建
# 安装 MySQL/MariaDB 客户端(如果未安装)
# sudo apt update && sudo apt install -y mariadb-client
mysql -h 127.0.0.1 -u root -e "SHOW DATABASES;" | grep zhiliaooa
2、在 app 机器用 docker 运行 Flask 容器,并连接远程 DB
环境准备:
主机:app 机器(192168.56.110)
运行方式:Docker容器
容器名称:forum-app
镜像:flask-forum:1.0 (阿里云acr私有应用镜像)
访问地址:http://192.168.56.110:5000
数据库:连接192.168.56.109的MariaDB
环境变量配置:
- DB_HOST: 192.168.56.109 (db机)
- DB_PORT: 3306
- DB_USER: root
- DB_PASSWORD: [密码] (方便测试未设置passwrod)
- DB_NAME: forum
前提:在 app 机器上先登录 ACR:
- 登录时一定记得username值加上双引号! sudo docker login --username=“xxx”
crpi-ua3er91ww0y2dq1i.cn-shenzhen.personal.cr.aliyuncs.com

a 检查主机状态
- 查看docker容器状态(可选)
1 查看所有正在运行的Docker容器
sudo docker ps
2 查看所有Docker容器(包括已停止的)
sudo docker ps -a
3 查看容器详细信息
sudo docker inspect forum-app
4 查看容器日志
sudo docker logs forum-app
sudo docker logs --tail 50 --follow forum-app # 实时查看最后50行日志
5 查看容器资源使用情况
sudo docker stats forum-app
- 确认docker配置,服务,镜像是否正常
1 Docker已登录ACR(认证存储在~/.docker/config.json)
cat ~/.docker/config.json
2 Docker服务运行
sudo systemctl status docker
3 Docker镜像已拉取
sudo docker images | grep flask-forum

b 用 docker运行 Flask 容器,连接远程 DB
操作步骤:
在 app 机器 (192.168.56.110) 上执行
用 docker运行 Flask 容器,连接远程 MariaDB (192.168.56.109)
1 、确认镜像地址(自己的 阿里云ACR仓库镜像地址)
FULL_IMAGE="crpi-ua3er91ww0y2dq1i.cn-shenzhen.personal.cr.aliyuncs.com/mirrors-yuan/flask-forum:1.0"
2 检查 Docker 镜像是否存在
sudo docker images | grep flask-forum || echo "镜像不存在,需要拉取"
3 Docker 拉取 Flask 应用镜像
sudo docker pull "$FULL_IMAGE"
4 清理旧flask-app容器,避免冲突(可选)
if sudo docker ps -a | grep -q "flask-app"; then
sudo docker stop flask-app 2>/dev/null || true
sudo docker rm flask-app
fi
5 启动 Flask 容器,关键:传入远程 DB 192.168.56.109的连接参数
sudo docker run -d \
--name flask-app \
--network host \
-e DB_HOST=192.168.56.109 \
-e DB_PORT=3306 \
-e DB_USER=root \
-e DB_PASSWORD="" \
-e DB_NAME=forum \
"$FULL_IMAGE"
6 等待应用启动,本地测试访问
sleep 3
curl -s http://localhost:5000 | head -n 5
如果看到 HTML 内容(如 <html>, <title> 等),说明跨主机 DB 连接成功
外部可通过 http://192.168.56.110:5000 访问应用

c 把docker命令存为一键执行脚本(可选)
- 可把上面docker执行的命令,保存为start-flask.sh一键式执行脚本
sudo tee start-flask.sh > /dev/null << 'EOF'
# 注意:脚本执行失败后会退出自动xshell,可注释掉
set -e
# 1 、确认镜像地址(自己的 阿里云ACR仓库镜像地址)
FULL_IMAGE="crpi-ua3er91ww0y2dq1i.cn-shenzhen.personal.cr.aliyuncs.com/mirrors-yuan/flask-forum:1.0"
# 2 检查 Docker 镜像是否存在
sudo docker images | grep flask-forum || echo "镜像不存在,需要拉取"
# 3 Docker 拉取 Flask 应用镜像
sudo docker pull "$FULL_IMAGE"
# 4 清理旧flask-app容器,避免冲突(可选)
if sudo docker ps -a | grep -q "flask-app"; then
sudo docker stop flask-app 2>/dev/null || true
sudo docker rm flask-app
fi
# 5 启动 Flask 容器,关键:传入远程 DB 192.168.56.109的连接参数
sudo docker run -d \
--name flask-app \
--network host \
-e DB_HOST=192.168.56.109 \
-e DB_PORT=3306 \
-e DB_USER=root \
-e DB_PASSWORD="" \ # 注意是无密码登录
-e DB_NAME=forum \
"$FULL_IMAGE"
# 6 等待应用启动,本地测试访问
sleep 3
curl -s http://localhost:5000 | head -n 5
EOF
d 一键式执行操作步骤(可选)
1. 赋予执行权限
chmod +x start-flask.sh
2. 运行
./start-flask.sh
3、验证
http://192.168.56.110:5000/
4、db机器是否联通
telnet 192.168.56.109 3306
拓展:
a. 用Containerd执行命令
下面脚本中sudo ctr images pull “$FULL_IMAGE”:会失败,
因为app机器之前用的是docker拉取镜像,而docker与Containerd并不兼容,如果想要使用Containerd,需要添加配置认证( /etc/containerd/certs.d/crpi-ua3er91ww0y2dq1i.cn-shenzhen.personal.cr.aliyuncs.com/certs.d)
因为flask应用在110 app机器已经使用docker启动了,所以就不用Containerd了
操作步骤:
在 app 机器 (192.168.56.110) 上执行
用 containerd 运行 Flask 容器,连接远程 MariaDB (192.168.56.109)
sudo tee start-flask.sh > /dev/null << 'EOF'
set -e
1 检查数据库连接 (192.168.56.109:3306)是否可达
if ! timeout 5 bash -c "cat < /dev/null > /dev/tcp/192.168.56.109/3306" 2>/dev/null; then
echo "无法连接数据库 (192.168.56.109:3306),请先确保 MariaDB 正常运行并监听端口!"
exit 1
fi
echo "数据库连接正常!"
2 配置镜像
ACR_REGISTRY="crpi-ua3er91ww0y2dq1i.cn-shenzhen.personal.cr.aliyuncs.com"
NAMESPACE="mirrors-yuan"
IMAGE_NAME="flask-forum"
TAG="1.0"
FULL_IMAGE="$ACR_REGISTRY/$NAMESPACE/$IMAGE_NAME:$TAG"
3 拉取Flask 应用镜像
sudo ctr images pull "$FULL_IMAGE"
4 清理旧flask-app 容器
if sudo ctr containers list | grep -q "flask-app"; then
sudo ctr tasks kill flask-app 2>/dev/null || true
sudo ctr containers delete flask-app
fi
5 启动 Flask 容器(连接远程 DB: 192.168.56.109)
sudo ctr run -d \
--net-host \
--env DB_HOST=192.168.56.109 \
--env DB_PORT=3306 \
--env DB_USER=root \
--env DB_PASSWORD="" \
--env DB_NAME=zhiliaooa \
"$FULL_IMAGE" flask-app
6 等待Flask 容器启动,应用初始化
sleep 3
curl -s http://localhost:5000 | head -n 5
如果看到 HTML 内容,说明跨主机 DB 连接成功
外部可通过浏览器 http://192.168.56.110:5000 访问应用
EOF
b. 一键式执行操作步骤
1. 赋予执行权限
chmod +x run-flask.sh
2. 运行
./run-flask.sh
3、验证
http://192.168.56.110:5000/
4、db机器是否联通
telnet 192.168.56.109 3306
3、搭建 K8s 集群并部署 Flask 应用
前提:一定要在k8s所有节点永久禁用 swap
- Kubernetes 默认禁止在启用 swap 的系统上运行 kubelet。
a 在所有 K8s 节点安装 containerd + kubeadm(master + workers)
在所有 K8s 节点上执行
1、禁用 swap
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
2、加载内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
3、 配置 sysctl 参数
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、 安装 containerd
sudo apt update
sudo apt install -y containerd
5、 配置 containerd
sudo mkdir -p /etc/containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml
6、修改 containerd 配置使用 systemd cgroup
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
7、重启 containerd
sudo systemctl restart containerd
sudo systemctl enable containerd
8、 添加 Kubernetes APT 源
# a. 安装必要的工具
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg
# b. 添加 Kubernetes 官方 GPG 密钥
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# c. 添加正确的 Kubernetes APT 源
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# d. 或者使用阿里云镜像源(如果官方源慢)
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
# e. 添加阿里云镜像源的 GPG 密钥
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
9、 安装 kubeadm kubelet kubectl
sudo apt update
sudo apt install -y kubelet kubeadm kubectl
10、 锁定版本,防止自动升级
sudo apt-mark hold kubelet kubeadm kubectl
11、 配置 kubelet 使用 systemd cgroup 驱动
cat <<EOF | sudo tee /etc/default/kubelet
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
EOF
12、 重启并启用 kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet
sudo systemctl enable kubelet
- 安装验证
验证各组件安装是否成功
- containerd:
sudo systemctl status containerd | head -5
- kubelet:
sudo systemctl status kubelet | head -5
- 版本信息:
kubeadm version
kubectl version --client 2>/dev/null || echo "安装 kubectl"
containerd --version
- 必要服务状态:
sudo systemctl is-active containerd
sudo systemctl is-active kubelet
sudo systemctl is-enabled containerd
sudo systemctl is-enabled kubelet
- Kubernetes 节点基础组件运行良好

b 初始化 Master 节点
在 k8s-master (192.168.56.111) 执行:
1. 清理现有配置
sudo kubeadm reset -f > /dev/null 2>&1 || true
sudo rm -rf /etc/kubernetes/ /var/lib/etcd/ /var/lib/kubelet/ ~/.kube/
sudo systemctl stop kubelet docker 2>/dev/null || true
2. 初始化 Kubernetes 控制平面
sudo kubeadm init \
--apiserver-advertise-address=192.168.56.111 \
--pod-network-cidr=10.244.0.0/16 \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.28.15 \
--ignore-preflight-errors=Port-10250
3. 配置 kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
4. 配置网络和调度
# 允许在 master 上调度 pod(可选)
kubectl taint nodes --all node-role.kubernetes.io/control-plane- node-role.kubernetes.io/master-
5. 安装 Flannel 网络插件
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
6. 等待集群就绪
sleep 10
kubectl wait --for=condition=Ready nodes --all --timeout=120s
7. join 命令用于 worker 节点
kubeadm token create --print-join-command
c 配置 kubelet 使用 containerd
1 创建 kubelet 配置文件
sudo mkdir -p /etc/systemd/system/kubelet.service.d
cat << 'EOF' | sudo tee /etc/systemd/system/kubelet.service.d/0-containerd.conf
[Service]
Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
EOF
2 重新加载 systemd
sudo systemctl daemon-reload
d 启用并启动 kubelet
sudo systemctl enable kubelet
sudo systemctl start kubelet
sudo systemctl status kubelet --no-pager
e 拉取 Kubernetes 镜像
# 使用阿里云镜像仓库拉取所有镜像
sudo kubeadm config images pull \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.28.15 \
--cri-socket=unix:///run/containerd/containerd.sock
f 初始化集群
# 使用最简化的参数初始化
sudo kubeadm init \
--apiserver-advertise-address=192.168.56.111 \ # 指定 master 的 IP
--pod-network-cidr=10.244.0.0/16 \ # Pod 网段(Flannel 默认用这个)
--image-repository=registry.aliyuncs.com/google_containers \ # 使用阿里云镜像源
--kubernetes-version=v1.28.15 \ # 指定 K8s 版本
--cri-socket=unix:///run/containerd/containerd.sock \ # 使用 containerd 作为 CRI
--ignore-preflight-errors=all \ # 忽略所有预检错误(谨慎使用)
--v=5 # 输出详细日志
执行成功后,kubeadm 会:
- 启动 control-plane 组件(api-server、etcd、scheduler 等)
- 自动生成一个 临时 token(如 snp7gh.9or2vxk3appgfn9v)
- 自动计算 CA 证书的 SHA256 哈希值:f23bcae48ea799df4354df57028e8687c08a87901b9a22aa03920c5dd1a4d436
- 自动生成完整的 kubeadm join 命令,供 worker 节点使用
之后worker节点加入集群时,可直接在worker机器执行下面命令
kubeadm join 192.168.56.111:6443 --token gchxy6.ojcsg3btn3ejtgbz \
--discovery-token-ca-cert-hash sha256:f23bcae48ea799df4354df57028e8687c08a87901b9a22aa03920c5dd1a4d436
g 在 master 节点安装Flannel 网络插件
kube-flannel:第三方插件(包括 CNI、CSI、Device Plugins)使用独立命名空间
kube-system:是Kubernetes 核心控制平面组件(kube-apiserver, coredns, kube-proxy)的默认位置
在 k8s-master (192.168.56.111) 上执行
1 安装 Flannel 网络插件,通过官方 YAML 安装
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
2 等待网络插件就绪
sleep 30
3 检查网络插件状态
kubectl get pods -A | grep flannel
4 如果 Flannel 有问题,尝试安装 Calico
if kubectl get pods -n kube-system -l app=flannel 2>/dev/null | grep -q "Error"; then
echo "Flannel 有问题,尝试安装 Calico"
kubectl delete -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/calico.yaml
# 等待 Calico 启动
sleep 30
fi
- ls -l /etc/cni/net.d/:查看是否有CNI 配置文件
10-flannel.conflist
- cat /etc/cni/net.d/* :批量查看目录下所有文件内容
- cat /etc/cni/net.d/10-flannel.conflist:查看flannel配置内容
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
- kubectl get pods -A | grep -i -E ‘flannel|calico|weave|cilium|cni’:查看所有 Pod,包括 Completed/Errored 的
kube-flannel kube-flannel-ds-gbd4k 1/1 Running 0 5d18h
kube-flannel kube-flannel-ds-gxn8d 1/1 Running 0 5d18h
kube-flannel kube-flannel-ds-rlq68 1/1 Running 0 5d18h

h 安装 Calico(可选)
在 k8s-master (192.168.56.111) 上执行
1 安装 Calico 网络插件
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/calico.yaml
2 等待 Calico 启动1-2分钟
sleep 60
3 检查 Calico 状态
kubectl get pods -n kube-system -l k8s-app=calico-node
kubectl get daemonsets -n kube-system
CNI不同网络插件适用场景
| 特性 | Flannel | Calico | Weave Net |
|---|---|---|---|
| 默认模式 | VXLAN overlay | IPIP(跨子网) / BGP(高性能路由) | VXLAN + Fast Datapath(eBPF 优化) |
| NetworkPolicy | 不支持 | 原生完整支持 / BGP(高性能路由) | 支持(功能较基础) |
| 配置复杂度 | 简单 | IPIP(跨子网) / 中等(需理解网络模型) | 中等(开箱即用但选项多 |
| 性能 | 中等(VXLAN 封装开销) | 高(BGP 模式无封装,接近物理网络) | 中等偏高(Fast Datapath 优化) |
| 典型使用场景 | 学习/实验环境小型简单生产集群(无安全隔离需求) | 中大型生产集群 ,需要网络安全策略(如多租户、合规),高性能要求场景 | 小规模混合云/跨公网集群,需要简单部署 + 基础策略 + 可选流量加密 |
4、Kubernetes 集群部署成功
部署时间: 2025-12-31
部署环境: Ubuntu 24.04.3 LTS
内核版本: 6.8.0-71-generic
Kubernetes 集群部署成功:部署状态 完全正常,可投入生产使用
- 集群状态汇总表

网络地址规划
Pod 网络 CIDR: 10.244.0.0/16Service 网络 CIDR: 10.96.0.0/12
DNS 服务 IP: 10.96.0.10
API Server 端点: 192.168.56.111:6443
5、将Worker 节点加入集群
- 把112 和 113 加入集群,在 k8s-worker1 和 k8s-worker2 上执行(替换为你的实际 join 命令):
查看当前有效的 token
kubeadm token list
1 在 192.168.56.112 上执行
sudo kubeadm join 192.168.56.111:6443 \
--token snp7gh.9or2vxk3appgfn9v \
--discovery-token-ca-cert-hash sha256:b61e899ebb5f6cb0877ca690d16f5d1b1248791e871f85b55cb26521415d6eda
2 在 192.168.56.113 上执行
sudo kubeadm join 192.168.56.111:6443 \
--token snp7gh.9or2vxk3appgfn9v \
--discovery-token-ca-cert-hash sha256:b61e899ebb5f6cb0877ca690d16f5d1b1248791e871f85b55cb26521415d6eda
3 在 master上验证worker节点是否加入成功(等待几分钟,查看节点状态)
kubectl get nodes -w
kubectl get pods -n kube-system
# 输出应该类似:
# NAME STATUS ROLES AGE VERSION
# k8s-master Ready control-plane 45m v1.28.2
# k8s-worker1 NotReady <none> 1m v1.28.2
# k8s-worker2 NotReady <none> 1m v1.28.2
problem set
问题1:app 110机器无法连接telnet 192.168.56.109 3306
问题:
ubuntu@app:~$ telnet 192.168.56.109 3306
Trying 192.168.56.109...
telnet: Unable to connect to remote host: Connection refused
ubuntu@app:~$
1. 删除名为 mariadb-container 的容器定义(如果存在)
注意:若容器正在运行,此命令会失败;需先 kill
sudo ctr containers delete mariadb-container
2. 定义镜像地址(使用 DaoCloud 加速源)
IMAGE="docker.m.daocloud.io/library/mariadb:10.6"
3. 后台启动 MariaDB 容器
sudo ctr run -d \
--net-host \ # 使用宿主机网络,直接暴露 3306 端口
--mount type=bind,src=/data/mariadb,dst=/var/lib/mysql,options=rbind \ # 挂载数据目录(读写)
--env MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=yes \ # 允许 root 密码为空(仅测试!)
--env MARIADB_DATABASE=forum \ # 自动创建名为 'forum' 的数据库
"$IMAGE" \ # 镜像
mariadb-container # 容器名称
问题2:/run/mysqld 目录缺失,权限或挂载配置不当
问题描述
在使用 containerd(通过 ctr)启动 MariaDB 容器时,容器启动后立即退出,日志中出现以下错误:
find: '/run/mysqld': No such file or directory
根本原因:
MariaDB 容器启动过程中需要在 /run/mysqld 目录下创建 Unix socket 和 PID 文件。
然而,containerd 默认不会自动创建该运行时目录,且官方 MariaDB
镜像的入口脚本依赖此目录存在。若未显式提供,会导致初始化失败并退出。
该问题本质:
是运行时目录缺失,常伴随权限或挂载配置不当,属于典型的容器运行环境适配问题。 解决目标 在 db 节点(192.168.56.109)上,通过
ctr 正确启动 MariaDB 容器, 确保:
宿主机提供持久、权限正确的 /run/mysqld 对应目录;
以 bind mount方式挂载至容器内 /run/mysqld;
容器能正常初始化并持续运行。
步骤 1:彻底清理旧容器和数据
# 停止并删除所有相关容器
sudo ctr tasks kill mariadb-server 2>/dev/null || true
sudo ctr containers delete mariadb-server 2>/dev/null || true
sudo ctr snapshots rm mariadb-server 2>/dev/null || true
# 清理旧数据(谨慎操作!)
sudo rm -rf /data/mariadb /opt/mariadb-data /tmp/mariadb-temp
步骤 2:创建统一的数据与运行目录(推荐结构)
# 创建持久化目录
sudo mkdir -p /data/mariadb/{data,run,log}
# 设置 MariaDB 容器用户 UID=999(官方镜像默认用户)
sudo chown -R 999:999 /data/mariadb
sudo chmod 755 /data/mariadb
data/ → 存放数据库文件
run/ → 挂载为 /run/mysqld,解决 socket 目录缺失问题
log/ → 存放错误日志
步骤 3:创建自定义配置文件
sudo tee /data/mariadb/my.cnf <<'EOF'
[mysqld]
bind-address = 0.0.0.0
port = 3306
socket = /run/mysqld/mysqld.sock # 必须与挂载目录一致
datadir = /var/lib/mysql
pid-file = /run/mysqld/mysqld.pid
log-error = /var/log/mysql/error.log
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
max_connections = 1000
innodb_buffer_pool_size = 256M
[client]
default-character-set = utf8mb4
EOF
步骤 4:创建启动脚本
cat > start_mariadb.sh <<'EOF'
#!/bin/bash
set -e
IMAGE="docker.m.daocloud.io/library/mariadb:10.6"
CONTAINER_NAME="mariadb-server"
# 拉取 MariaDB 镜像
sudo ctr images pull "$IMAGE"
# 清理旧容器(如果存在)
sudo ctr tasks kill "$CONTAINER_NAME" 2>/dev/null || true
sudo ctr containers delete "$CONTAINER_NAME" 2>/dev/null || true
# 启动 MariaDB 容器
sudo ctr run -d \
--net-host \
--mount type=bind,src=/data/mariadb/data,dst=/var/lib/mysql,options=rbind:rw \
--mount type=bind,src=/data/mariadb/run,dst=/run/mysqld,options=rbind:rw \ # 关键:提供 /run/mysqld
--mount type=bind,src=/data/mariadb/log,dst=/var/log/mysql,options=rbind:rw \
--mount type=bind,src=/data/mariadb/my.cnf,dst=/etc/mysql/conf.d/custom.cnf,options=rbind:rw \
--env MARIADB_ROOT_PASSWORD=RootPass123! \ # 密码应该是空
--env MARIADB_DATABASE=forum_db \
--env MARIADB_USER=forum_admin \
--env MARIADB_PASSWORD=AdminPass123! \
"$IMAGE" \
"$CONTAINER_NAME"
# 等待容器启动 (15秒)
sleep 15
# 检查容器任务状态
sudo ctr tasks ls | grep "$CONTAINER_NAME"
# 检查 3306 端口是否监听
sudo ss -tuln | grep ':3306'
# 测试本地连接
if ! command -v mysql &> /dev/null; then
sudo apt update && sudo apt install -y mariadb-client
fi
if mysql -h 127.0.0.1 -u forum_admin -pAdminPass123! -e "SHOW DATABASES;" &>/dev/null; then
echo "MariaDB 连接成功!"
else
echo "连接失败,请检查日志:/data/mariadb/log/error.log"
fi
EOF
# 添加执行权限
chmod +x start_mariadb.sh
# 执行脚本
./start_mariadb.sh
验证要点
容器是否运行 sudo ctr tasks list
端口是否监听 sudo ss -tuln | grep 3306
日志是否有错 cat /data/mariadb/log/error.log
能否连接 mysql -h127.0.0.1 -u forum_admin -pAdminPass123! -e “SELECT 1”
问题3: telnet 192.168.56.109 3306 时报错
!#08S01Got packets out of orderConnection closed by foreign host.
错误信息:08S01:MySQL 错误代码,表示协议错误
Got packets out of order:收到乱序的数据包
Connection closed by foreign host.:服务器关闭了连接
原因:
MySQL/MariaDB使用二进制协议,而不是文本协议。当你用 telnet 连接时:
服务器发送二进制握手包
客户端(你的 telnet)应该回应一个结构化的认证包
自动输入了随机文本 a
服务器无法解析,认为协议错误,所以关闭连接
ubuntu@app:~$ telnet 192.168.56.109 3306
Trying 192.168.56.109...
Connected to 192.168.56.109.
Escape character is '^]'.
a
5.5.5-10.6.24-MariaDB-ubu2204SISD;<[4þ4E>H-G`+VNf6mysql_native_password123456
!#08S01Got packets out of orderConnection closed by foreign host.
方法:
前提:在 app 机器 (192.168.56.110) 上安装 MySQL 客户端
1 使用正确的 MySQL 客户端测试
sudo apt update
sudo apt install -y mysql-client
2 测试连接(mysql我设置了空密码)
mysql -h 192.168.56.109 -u root -e "SHOW DATABASES;"
问题4:master中CNI 配置丢失或初始化失败
- 修复 CNI 网络配置
在 k8s-master (192.168.56.111) 上执行
1 检查 CNI 目录
ls -la /etc/cni/net.d/ 2>/dev/null || echo "目录不存在"
2 如果目录不存在,创建它
sudo mkdir -p /etc/cni/net.d/
sudo mkdir -p /opt/cni/bin/
3 重启 kubelet 以重新初始化 CNI
sudo systemctl restart kubelet
sleep 15
4 检查 kubelet 状态
sudo systemctl status kubelet --no-pager | head -10
问题5:无法拉取 pause 镜像
官方名称:Pause Container(沙箱容器 / Infra Container)
核心作用:为 Pod 提供共享的网络和 IPC命名空间基础
- 核心问题:pause 镜像失败,registry.k8s.io/pause:3.8 无法访问
- 容器运行时配置错误:containerd 还在尝试使用国外的镜像仓库
- Kubernetes 中的 Pod 是一组共享资源的容器,而这个“共享”的基础,就是由 pause 容器提供的。
步骤 1: 停止所有服务并重置
1 停止 kubelet
sudo systemctl stop kubelet
2 重置 kubeadm
sudo kubeadm reset -f
3 清理文件
sudo rm -rf /etc/kubernetes/ /var/lib/etcd/ /var/lib/kubelet/ /var/lib/cni/
sudo rm -rf ~/.kube/
4 清理 iptables
sudo iptables -F && sudo iptables -t nat -F && sudo iptables -t mangle -F && sudo iptables -X
步骤 2: 修复 containerd 配置
1 备份原有配置
sudo cp /etc/containerd/config.toml /etc/containerd/config.toml.backup
2 重新配置 containerd 使用阿里云镜像
sudo tee /etc/containerd/config.toml << 'EOF'
version = 2
root = "/var/lib/containerd"
state = "/run/containerd"
[grpc]
address = "/run/containerd/containerd.sock"
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://docker.mirrors.ustc.edu.cn", "https://registry-1.docker.io"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
endpoint = ["https://registry.aliyuncs.com/google_containers"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
endpoint = ["https://registry.aliyuncs.com/google_containers"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
endpoint = ["https://registry.aliyuncs.com/google_containers"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]
endpoint = ["https://quay.mirrors.ustc.edu.cn"]
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
EOF
3 重启 containerd
sudo systemctl restart containerd
步骤 3: 手动拉取 pause 镜像
1 使用 ctr 手动拉取阿里云的 pause 镜像
sudo ctr -n k8s.io images pull registry.aliyuncs.com/google_containers/pause:3.9
2 查看是否拉取成功
sudo ctr -n k8s.io images list | grep pause
问题6:Kubernetes 集群网络与镜像源修复记录
适用于 Ubuntu 22.04 + containerd + kubeadm 部署的集群
工作节点有两个主要问题:
1、journalctl -u kubelet 报错: failed to get sandbox image"registry.k8s.io/pause:3.8": failed to pull image
2、初始状态下 :CNI配置缺失:/etc/cni/net.d/ 目录是空的(权限问题,无法远程创建worker节点目录)
3、Pod 无法分配 IP,处于 ContainerCreating 或ErrImagePull 状态
4、pause 镜像拉取失败:网络无法访问 registry.k8s.io/pause:3.8
步骤 1:在所有节点配置 containerd 使用阿里云 pause 镜像
1 使用 sudo 权限创建 CNI 配置 (可选,正常情况下会被 Flannel 自动创建)
sudo mkdir -p /etc/cni/net.d
2 创建CNI flannel网络配置
sudo tee /etc/containerd/config.toml << 'EOF'
version = 2
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
# 注意:新版 containerd 推荐将 registry mirrors 放在 certs.d 目录下
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
EOF
3 重启 containerd 生效
sudo systemctl restart containerd
4 手动拉取 pause 镜像(确保本地存在)
sudo ctr -n k8s.io images pull registry.aliyuncs.com/google_containers/pause:3.9
步骤 2:在 master 节点 部署 Flannel 网络插件
验证命令(每台机器执行):
grep sandbox_image /etc/containerd/config.toml
sudo ctr -n k8s.io images list | grep pause
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
registry.aliyuncs.com/google_containers/pause:3.9
- Flannel 会自动完成以下工作:
1 在 每个节点 创建 /etc/cni/net.d/10-flannel.conflist
2 将 CNI 二进制(如 flannel,portmap)复制到 /opt/cni/bin/
3 启动 kube-flannel-ds-* Pod,负责子网分配和 vxlan 封装
步骤 3:验证 Flannel 是否生效:
# 检查 DaemonSet 状态(应在所有节点 Running)
kubectl get pods -n kube-flannel -o wide
# 检查 CNI 配置文件(所有节点应一致)
ls /etc/cni/net.d/
# 输出:10-flannel.conflist
# 查看内容(应包含 flannel + portmap 插件)
cat /etc/cni/net.d/10-flannel.conflist
步骤 4:验证集群整体修复结果
1. 所有节点变为 Ready
kubectl get nodes
2. 创建测试 Pod 验证网络和镜像
kubectl run test-nginx --image=nginx
sleep 10
kubectl get pod test-nginx -o wide # 应显示 Running + 分配 IP
3. 清理测试 Pod
kubectl delete pod test-nginx
更多推荐



所有评论(0)