python-flask项目开发:

  1. flask开发完整过程总结:https://blog.csdn.net/qq_38444844/article/details/151928286?spm=1011.2415.3001.5331
  2. 项目源码:https://gitee.com/loveTianWen/Forum-platform/tree/master
  3. 第一篇: 使用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/16

Service 网络 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


1192.168.56.112 上执行
sudo kubeadm join 192.168.56.111:6443 \
  --token snp7gh.9or2vxk3appgfn9v \
  --discovery-token-ca-cert-hash sha256:b61e899ebb5f6cb0877ca690d16f5d1b1248791e871f85b55cb26521415d6eda


2192.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
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐