从零搭建 Kubernetes 集群并部署 Kuboard v3 管理面板 —— 国内环境完整实战教程

从零搭建 Kubernetes 集群并部署 Kuboard v3 管理面板 ------ 国内环境完整实战教程

作者 :实战运维团队 | 环境 :ecs-2c98 四节点集群 | 软件版本 :K8s v1.32.13 + Kuboard v3 + containerd 2.2.1 + Flannel v0.28.5

更新日期 :2025年

阅读时长 :约 60 分钟 | 实战时长:约 90 分钟


📋 目录 (Table of Contents)

章节 标题 内容概览
第一篇 Kuboard 与 Kubernetes 入门 概念、对比、架构设计
第1章 Kuboard 概述 产品定位、与 K8s Dashboard 对比、功能特点
第2章 环境准备与架构设计 集群规划、端口规划、ASCII 架构图
第二篇 Kubernetes 集群搭建 从裸机到 Ready 集群
第3章 系统环境初始化 hosts、swap、内核模块、sysctl
第4章 容器运行时 containerd 安装配置 安装、配置、SystemdCgroup
第5章 kubeadm/kubelet/kubectl 安装 版本锁定、组件说明
第6章 Master 节点初始化与 kubeadm init 阿里云镜像加速、初始化输出解读
第7章 CNI 网络插件 Flannel 部署 国内镜像拉取踩坑、Flannel 原理
第8章 Worker 节点加入集群 token 管理、join 命令复用
第三篇 Kuboard 部署与使用 管理面板实战
第9章 Kuboard v3 部署 华为云 SWR 镜像、K8s Deployment + NodePort
第10章 Kuboard 界面实战 集群导入、工作负载管理、监控
第四篇 踩坑与最佳实践 血泪经验总结
第11章 国内镜像加速方案汇总 registry.aliyuncs.com、hub.rat.dev、中科大镜像
第12章 常见问题排查指南 Pod 排错、网络排错、kubeadm 排错
附录 速查表与配置详解 命令速查、containerd 配置、YAML 模板

第一篇:Kuboard 与 Kubernetes 入门


第1章:Kuboard 概述

1.1 什么是 Kuboard?(What is Kuboard?)

Kuboard 是一款国产的 Kubernetes 多集群管理面板,提供了比官方 Kubernetes Dashboard 更贴近国内用户使用习惯的图形化界面。它基于 Kubernetes 的 kubectl proxy 模式工作,通过读取 K8s API Server 的数据进行可视化展示和管理。

核心定位

  • 🎯 多集群管理:一个 Kuboard 实例可管理多个 K8s 集群
  • 🎯 审计与权限:内置 RBAC 可视化管理,支持 LDAP/AD 集成
  • 🎯 国产化适配:中文界面、华为云 SWR 镜像加速、国内网络友好

小知识 :Kuboard 的作者是中国开发者,官网 kuboard.cn 在国内访问速度极快,文档也是全中文的,对国内运维工程师非常友好。


1.2 Kuboard v3 核心功能

功能模块 功能描述 对应 K8s 对象
集群概览 节点状态、Pod 运行数、资源使用率仪表盘 Node, Pod, Metrics
工作负载 Deployment / StatefulSet / DaemonSet / Job / CronJob 管理 Workload API
服务与路由 Service / Ingress 可视化配置 Service, Ingress
配置管理 ConfigMap / Secret 创建与编辑 ConfigMap, Secret
存储管理 PV / PVC / StorageClass 管理 Storage API
命名空间 Namespace 资源配额 (ResourceQuota) 管理 Namespace, ResourceQuota
集群导入 通过 kubeconfig 或 Token 导入外部集群 --
审计日志 操作记录与变更追踪 Event + Audit Log

1.3 Kuboard vs Kubernetes Dashboard 对比

对比维度 Kubernetes Dashboard Kuboard v3
界面语言 英文为主,中文非官方翻译 ✅ 全中文原生支持
多集群管理 ❌ 每个集群需独立部署 ✅ 一个实例管理多集群
权限管理 (RBAC) 基础支持,配置复杂 ✅ 图形化 RBAC 管理
审计日志 ❌ 无内置审计 ✅ 内置操作审计
LDAP/AD 集成 需额外配置 ✅ 原生支持
微服务视图 ❌ 无 ✅ 支持以应用为中心视图
部署方式 YAML 手动部署 ✅ 支持 K8s YAML / Docker Compose
镜像来源 registry.k8s.io (国外) ✅ SWR 华为云镜像 (国内加速)
文档 英文官方文档 ✅ 中文详细文档 + 视频教程
活跃度 CNCF 官方维护 社区活跃,更新频繁
适合人群 K8s 资深用户 国内运维、DevOps 团队

结论 :如果你在国内生产环境使用 K8s,Kuboard 的中文界面 + 国内镜像加速 + 多集群管理是显著优势;如果你在国际环境或需要 CNCF 官方认证工具,Dashboard 更合适。


1.4 Kuboard 架构原理

复制代码
┌─────────────────────────────────────────────────────────────┐
│                      Browser (浏览器)                        │
│                   http://<NodeIP>:30080                     │
└──────────────────────────┬──────────────────────────────────┘
                           │ HTTP
                           ▼
┌─────────────────────────────────────────────────────────────┐
│              Kuboard Pod (Deployment)                        │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  kuboard (Go Backend + Vue Frontend)               │    │
│  │  - 读取 kubeconfig 访问 API Server                  │    │
│  │  - 提供 Web UI 服务 (端口 80)                       │    │
│  │  - 管理多个集群的连接信息                            │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  Service: kuboard (NodePort 30080)                         │
└──────────────────────────┬──────────────────────────────────┘
                           │ kubeconfig / Token
                           ▼
┌─────────────────────────────────────────────────────────────┐
│              Kubernetes API Server                           │
│                   (https://:6443)                          │
└─────────────────────────────────────────────────────────────┘

关键点

  1. Kuboard 本身以 Pod 形式运行在 K8s 集群内(也可以跑在集群外)
  2. 通过 kubeconfig 文件ServiceAccount Token 连接目标集群的 API Server
  3. Kuboard 的 Go 后端 代理所有 kubectl 操作,Vue 前端 提供 UI
  4. NodePort 30080 是访问入口,默认账号 admin,密码 Kuboard123

第2章:环境准备与架构设计

2.1 集群规划 (Cluster Planning)

本次实战使用 4 台华为云 ECS 弹性云服务器 (实例类型 ecs-2c98),具体规划如下:

节点主机名 节点别名 角色 (Role) 公网 IP (Public IP) 私网 IP (Private IP) 配置
kuboard-01 ecs-2c98-0001 Master + Kuboard 120.46.195.39 192.168.0.85 2vCPU / 4GiB (ac9.large.2)
kuboard-02 ecs-2c98-0002 Worker-1 120.46.32.153 192.168.0.28 同上
kuboard-03 ecs-2c98-0003 Worker-2 1.94.204.169 192.168.0.153 同上
kuboard-04 ecs-2c98-0004 Worker-3 120.46.129.80 192.168.0.51 同上

为什么只有 1 个 Master? 生产环境推荐 3 Master 节点做高可用(etcd 奇数节点),但本次为实战教程,单 Master 足以演示完整流程。后续可扩展为多 Master。


2.2 整体架构 ASCII 图

复制代码
                                    ┌──────────────────────────────────┐
                                    │      Internet (公网访问)          │
                                    │                                  │
                                    │  访问 Kuboard:                    │
                                    │  http://120.46.195.39:30080      │
                                    └──────────────┬───────────────────┘
                                                   │
                                                   │ NodePort 30080
                                                   ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│                         Kubernetes Cluster (ecs-2c98)                      │
│                                                                              │
│  ┌─────────────────────┐    ┌─────────────────────┐    ┌─────────────────┐  │
│  │   Master Node       │    │   Worker Node 1     │    │  Worker Node 2  │  │
│  │   kuboard-01        │    │   kuboard-02        │    │  kuboard-03     │  │
│  │                     │    │                     │    │                 │  │
│  │  ┌───────────────┐  │    │  ┌───────────────┐  │    │  ┌───────────┐  │  │
│  │  │ Control Plane │  │    │  │   kubelet     │  │    │  │ kubelet   │  │  │
│  │  │               │  │    │  │   kube-proxy  │  │    │  │ kube-proxy│  │  │
│  │  │ - API Server  │◄─┼────┼──┤   (Pod Net)  │  │    │  │ (Pod Net) │  │  │
│  │  │ - etcd        │  │    │  │               │  │    │  │           │  │  │
│  │  │ - Scheduler   │  │    │  │   [User Pods] │  │    │  │ [User Pods]│  │  │
│  │  │ - Controller  │  │    │  └───────────────┘  │    │  └───────────┘  │  │
│  │  └───────────────┘  │    └─────────────────────┘    └─────────────────┘  │
│  │  ┌───────────────┐  │                                                     │
│  │  │   Kuboard     │  │    ┌─────────────────────┐                          │
│  │  │   (Pod)       │  │    │   Worker Node 3     │                          │
│  │  │   Port: 80    │  │    │   kuboard-04        │                          │
│  │  └───────────────┘  │    │                     │                          │
│  └─────────────────────┘    │  ┌───────────────┐  │                          │
│        ▲                     │  │   kubelet     │  │                          │
│        │ kubeconfig          │  │   kube-proxy  │  │                          │
│        │                     │  │   (Pod Net)   │  │                          │
│        │                     │  └───────────────┘  │                          │
│        │                     └─────────────────────┘                          │
│  ┌─────┴─────────────┐                                                   │
│  │   Admin Laptop    │                                                   │
│  │  (运维工程师电脑)  │                                                   │
│  │  kubectl + SSH    │                                                   │
│  └───────────────────┘                                                   │
│                                                                              │
│  Flannel CNI: Pod CIDR 10.244.0.0/16 (每个 Node 分配一个 /24 子网)          │
│  Service CIDR: 10.96.0.0/12 (kubeadm 默认)                                 │
└──────────────────────────────────────────────────────────────────────────────┘

 Legend (图例):
   █  Control Plane 组件 (Master 专属)
   ░  Worker 组件 (工作节点)
   ↔  Pod 网络 (Flannel Overlay Network)

2.3 网络规划 (Network Planning)

Kubernetes 网络模型有三层:

网络层 CIDR 说明
Node Network (节点网络) 192.168.0.0/24 华为云 VPC 私网,节点间通信
Pod Network (容器网络) 10.244.0.0/16 Flannel CNI 分配,每个 Node 一个 /24 子网
Service Network (服务网络) 10.96.0.0/12 kubeadm 默认,ClusterIP 分配范围

Flannel 子网分配示例(实际分配取决于 Flannel 的 hostgw/VXLAN 模式):

复制代码
kuboard-01 (Master):  Pod CIDR = 10.244.0.0/24
kuboard-02 (Worker):  Pod CIDR = 10.244.1.0/24
kuboard-03 (Worker):  Pod CIDR = 10.244.2.0/24
kuboard-04 (Worker):  Pod CIDR = 10.244.3.0/24

2.4 端口规划与防火墙规则 (Port Planning & Firewall)

2.4.1 Master 节点必需端口
协议 端口 服务 说明
TCP 6443 Kubernetes API Server 所有节点kubectl 访问
TCP 2379-2380 etcd server/client 仅 Master 节点间通信(多 Master 时需要)
TCP 10250 kubelet API 所有节点 kubelet 与 API Server 通信
TCP 10259 kube-scheduler 健康检查(可选外部访问)
TCP 10257 kube-controller-manager 健康检查(可选外部访问)
TCP 30080 Kuboard NodePort 浏览器访问 Kuboard
UDP 8472 Flannel VXLAN Pod 跨节点通信(Overlay 网络)
2.4.2 Worker 节点必需端口
协议 端口 服务 说明
TCP 10250 kubelet API API Server → kubelet
TCP 30000-32767 NodePort Services 外部访问 Service
UDP 8472 Flannel VXLAN Pod 跨节点通信
TCP 30080 Kuboard (NodePort) 所有节点开放,便于高可用访问
2.4.3 华为云安全组配置

在华为云控制台,为 ecs-2c98 安全组添加以下入方向规则:

复制代码
# Master 节点 (kuboard-01)
TCP  6443  0.0.0.0/0    # API Server (建议限制为管理IP)
TCP  30080 0.0.0.0/0    # Kuboard Web UI
TCP  10250 192.168.0.0/24  # kubelet API (仅内网)
UDP  8472  192.168.0.0/24  # Flannel VXLAN (仅内网)

# 所有节点
TCP  10250 192.168.0.0/24
UDP  8472  192.168.0.0/24
TCP  30000-32767 0.0.0.0/0  # NodePort 范围

⚠️ 安全提示 :生产环境请将 API Server (6443) 的源 IP 限制为运维人员 IP,不要对 0.0.0.0/0 开放。


2.5 软件版本一览 (Software Versions)

本次实战使用的真实版本数据

组件 版本 镜像/包来源 说明
OS Ubuntu 24.04.4 LTS 华为云公共镜像 Kernel 6.8.0-106-generic
containerd v2.2.1 Docker CE 仓库 SystemdCgroup = true
runc v1.2.4 随 containerd 安装 OCI 运行时
Kubernetes v1.32.13 阿里云 k8s 镜像站 kubeadm + kubelet + kubectl
CNI Plugins v1.6.2 GitHub Release bridge, host-local, lo
Flannel v0.28.5 ghcr.io/flannel-io/flannel Pod CIDR 10.244.0.0/16
Kuboard v3 swr.cn-east-2.myhuaweicloud.com/kuboard/kuboard:v3 华为云 SWR,约 132MB
kubectl v1.32.13 与 K8s 组件版本一致 客户端命令行工具

为什么选择这些版本?

  • K8s v1.32:最新的稳定版(写作时),包含最新安全补丁
  • containerd v2 :v2.x 系列配置格式有变化(config.toml v2 格式),本章会详细说明
  • Flannel v0.28.5:与 K8s 1.32 兼容的最新版本
  • Kuboard v3:最新稳定版,支持 K8s 1.20+

2.6 准备工作检查清单 (Pre-flight Checklist)

在开始安装前,请确认以下事项:

  • 所有节点已创建并可通过 SSH 登录
  • 所有节点已配置 root 或 sudo NOPASSWD 权限
  • 节点间私网互通(在华为云同 VPC 下默认互通)
  • 节点可访问互联网(用于拉取镜像,或已准备离线镜像)
  • swap 已关闭(K8s 1.22+ 强制要求,第3章详述)
  • 防火墙规则已按 2.4 节配置
  • 所有节点时间同步 (推荐安装 chronyntp
  • 准备一个用于保存 kubeconfig 的本地机器(运行 kubectl)

第3章:系统环境初始化

目标:对 4 台服务器进行统一的系统级初始化,为 K8s 安装做好准备。


3.1 设置主机名 (Set Hostnames)

每台对应节点上执行:

bash 复制代码
# 在 120.46.195.39 (Master) 上执行
sudo hostnamectl set-hostname kuboard-01

# 在 120.46.32.153 (Worker-1) 上执行
sudo hostnamectl set-hostname kuboard-02

# 在 1.94.204.169 (Worker-2) 上执行
sudo hostnamectl set-hostname kuboard-03

# 在 120.46.129.80 (Worker-3) 上执行
sudo hostnamectl set-hostname kuboard-04

验证

bash 复制代码
$ hostname
kuboard-01   # 在 Master 节点上

3.2 配置 /etc/hosts (Configure Hosts File)

所有节点上执行,确保节点间可以通过主机名互相解析:

bash 复制代码
cat << 'EOF' | sudo tee -a /etc/hosts

# Kubernetes Cluster Nodes (ecs-2c98)
192.168.0.85   kuboard-01
192.168.0.28   kuboard-02
192.168.0.153  kuboard-03
192.168.0.51   kuboard-04
EOF

验证(在任意节点上):

bash 复制代码
$ ping -c 2 kuboard-02
PING kuboard-02 (192.168.0.28) 56(84) bytes of data.
64 bytes from kuboard-02 (192.168.0.28): icmp_seq=1 ttl=64 time=0.523 ms
64 bytes from kuboard-02 (192.168.0.28): icmp_seq=2 ttl=64 time=0.341 ms

为什么需要配置 hosts? kubeadm 在某些检查中会使用主机名,且 Flannel 的某些模式(如 host-gw)依赖主机名解析。


3.3 关闭 swap (Disable Swap)

Kubernetes 1.22+ 强制要求关闭 swap,因为 swap 会导致 Pod 的性能不稳定(内存换入换出)。

所有节点上执行:

bash 复制代码
# 1. 临时关闭 swap (立即生效)
sudo swapoff -a

# 2. 永久关闭 swap (注释 /etc/fstab 中的 swap 行)
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

验证

bash 复制代码
$ free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       285Mi       3.2Gi       0.0Ki       328Mi       3.3Gi
Swap:             0B          0B          0B     # <-- Swap 为 0 表示已关闭

⚠️ 踩坑提示 :如果忘记关闭 swap,kubeadm init 会报错:[ERROR Swap]: running with swap on is not supported. Please disable swap。虽然可以通过 --ignore-preflight-errors=Swap 跳过,但强烈不推荐在生产环境开启 swap。


3.4 加载内核模块 (Load Kernel Modules)

Kubernetes 需要以下内核模块支持:

  • br_netfilter:允许 bridged 流量经过 iptables 链(K8s 网络依赖)
  • overlay:Overlay filesystem 支持(容器分层文件系统)
  • ip_vs 系列:Kube-proxy IPVS 模式所需(性能优于 iptables 模式)

所有节点上执行:

bash 复制代码
# 1. 加载当前所需模块
sudo modprobe overlay
sudo modprobe br_netfilter
sudo modprobe ip_vs
sudo modprobe ip_vs_rr
sudo modprobe ip_vs_wrr
sudo modprobe ip_vs_sh
sudo modprobe nf_conntrack

# 2. 验证模块已加载
lsmod | grep -E 'overlay|br_netfilter|ip_vs'

输出示例

复制代码
br_netfilter           32768  0
ip_vs_rr              16384  0
ip_vs                 180224  6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
3.4.1 持久化内核模块

确保重启后模块自动加载:

bash 复制代码
cat << 'EOF' | sudo tee /etc/modules-load.d/k8s.conf
# Kubernetes required kernel modules
overlay
br_netfilter
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
EOF

3.5 配置内核参数 (Configure Kernel Parameters)

K8s 网络需要以下 sysctl 参数:

所有节点上执行:

bash 复制代码
cat << 'EOF' | sudo tee /etc/sysctl.d/k8s.conf
# Kubernetes networking requirements
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1

# Optional: 优化 TCP 连接
net.ipv4.tcp_fin_timeout            = 30
net.ipv4.tcp_tw_reuse               = 1
EOF

# 立即生效
sudo sysctl --system

参数说明

参数 说明
net.bridge.bridge-nf-call-iptables 1 允许 bridge 流量经过 iptables,Kube-proxy 依赖此参数
net.bridge.bridge-nf-call-ip6tables 1 同上,针对 IPv6
net.ipv4.ip_forward 1 开启 IP 转发,Pod 跨节点通信必须

验证

bash 复制代码
$ sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1

$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

3.6 安装基础工具包 (Install Essential Packages)

所有节点上执行:

bash 复制代码
sudo apt-get update
sudo apt-get install -y \
  curl \
  wget \
  apt-transport-https \
  ca-certificates \
  software-properties-common \
  gnupg \
  lsb-release \
  net-tools \
  iproute2 \
  ethtool \
  conntrack \
  ipset \
  jq \
  vim \
  bash-completion

各工具包用途说明

包名 用途
curl / wget 下载工具,拉取 GPG 密钥和 YAML 文件
apt-transport-https 允许 apt 通过 HTTPS 下载包
ca-certificates HTTPS 证书验证
gnupg GPG 密钥管理,添加 Docker/K8s 仓库时需要
iproute2 ip 命令,网络管理
ethtool 网卡工具,Flannel 安装时可能用到
conntrack 连接跟踪工具,kube-proxy 依赖
ipset IP set 工具,kube-proxy IPVS 模式依赖
jq JSON 解析工具,调试 K8s API 响应

3.7 时间同步 (Time Synchronization)

Kubernetes 集群各节点时间必须同步,否则 etcd 会出现问题。

所有节点上执行:

bash 复制代码
# 安装 chrony (比 ntp 更现代)
sudo apt-get install -y chrony

# 启动并设置开机自启
sudo systemctl enable chronyd
sudo systemctl start chronyd

# 验证时间同步状态
chronyc sources -v

输出示例

复制代码
  .-- Source mode  '^' = server, '=' = peer, '#' = local clock.
 / .- Source state '*' = current synced, '+' = combined , '-' = not combined,
| /             '?' = unreachable, 'x' = time may be in error, '~' = time too variable.
||                                                 .- xxxx [ yyyy ] +/- zzzz
||      Reachability flag (Octal) -.             |  xxxx = adjusted offset,
||      Log2(Polling interval) --.  |            |  yyyy = measured offset,
||                                \ |            |  zzzz = estimated error.
||                                 |           \
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* time.google.com               1   6    17    12   +123us[ +456us] +/-   15ms

3.8 系统初始化验证

完成以上步骤后,在所有节点上执行以下验证脚本:

bash 复制代码
echo "=== Hostname ==="
hostname

echo -e "\n=== Swap Status ==="
free -h | grep Swap

echo -e "\n=== Kernel Modules ==="
lsmod | grep -E 'overlay|br_netfilter|ip_vs' | wc -l

echo -e "\n=== Sysctl Parameters ==="
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.ipv4.ip_forward

echo -e "\n=== /etc/hosts ==="
grep kuboard /etc/hosts

echo -e "\n=== Time Sync ==="
timedatectl status | grep "System clock synchronized"

预期输出(所有节点应通过):

复制代码
=== Hostname ===
kuboard-01   (各节点不同)

=== Swap Status ===
Swap:             0B          0B          0B

=== Kernel Modules ===
7   (或更多)

=== Sysctl Parameters ===
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1

=== /etc/hosts ===
192.168.0.85   kuboard-01
192.168.0.28   kuboard-02
...

=== Time Sync ===
               System clock synchronized: yes

第4章:容器运行时 containerd 安装配置

Kubernetes 自 v1.24 起已移除dockershim,推荐使用 containerdCRI-O 作为容器运行时 (Container Runtime Interface, CRI)。本次实战选择 containerd。


4.1 什么是 containerd?

复制代码
┌─────────────────────────────────────────────────────────────┐
│                      Kubernetes                              │
│                   (kubelet)                                 │
└──────────────────────┬──────────────────────────────────────┘
                       │ CRI (Container Runtime Interface)
                       │ gRPC, unix:///run/containerd/containerd.sock
                       ▼
┌─────────────────────────────────────────────────────────────┐
│                   containerd                                │
│  (符合 CRI 标准的容器运行时,负责:                         │
│   - 镜像拉取 (Image Pull)                                   │
│   - 容器生命周期管理 (Create/Start/Stop)                    │
│   - 容器网络接口 (CNI) 调用                                 │
│   - 容器存储接口 (CSI) 调用                                 │
│  )                                                         │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  runc (OCI 运行时)                                  │   │
│  │  - 实际创建和运行容器进程                             │   │
│  │  - 设置 Linux namespace 和 cgroup                    │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

containerd vs Docker

对比 Docker containerd
架构 Docker Engine → containerd → runc containerd → runc (更简洁)
CLI 工具 docker ctr (底层) / nerdctl (用户友好)
CRI 支持 需要 dockershim (已废弃) 原生支持
资源占用 较高 (包含 build/push 等额外功能) 较低 (专注运行时)
K8s 推荐 ❌ v1.24+ 不推荐 ✅ 官方推荐

4.2 安装 containerd

所有节点上执行:

4.2.1 添加 Docker CE 仓库 (containerd 包含在 Docker CE 仓库中)
bash 复制代码
# 1. 添加 Docker 官方 GPG 密钥
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 2. 添加 Docker CE 仓库 (阿里云镜像加速)
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 3. 更新包索引
sudo apt-get update

为什么用阿里云镜像? Docker 官方仓库 download.docker.com 在国内访问极慢,阿里云镜像站提供高速访问。

4.2.2 安装 containerd
bash 复制代码
# 安装 containerd (会同时安装 runc 和 CNI plugins)
sudo apt-get install -y containerd.io

# 验证安装版本
containerd --version

真实输出 (ecs-2c98 环境):

复制代码
containerd containerd.io 2.2.1-1  # <-- v2.2.1

验证 runc 版本

bash 复制代码
runc --version
# runc version 1.2.4
# commit: v1.2.4-0-g6c0748e2
# spec: 1.2.0

4.3 配置 containerd (关键!)

4.3.1 生成默认配置文件
bash 复制代码
# 生成默认配置到 /etc/containerd/config.toml
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

踩坑记录 #3containerd config default 在 v2.x 版本输出的配置格式与 v1.x 不同。v2.x 使用 TOML v2 格式 ,且 SystemdCgroup 的路径有所变化。

4.3.2 修改关键配置参数

需要修改两个关键配置:

① 开启 SystemdCgroup (K8s 要求使用 systemd 作为 cgroup 驱动)

bash 复制代码
# 方法:使用 sed 替换(推荐,避免手动编辑错误)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

② 配置国内镜像加速 (可选,加速镜像拉取)

/etc/containerd/config.toml[plugins."io.containerd.grpc.v1.cri".registry.mirrors] 部分添加:

toml 复制代码
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
  endpoint = ["https://mirrors.aliyun.com"]

[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
  endpoint = ["https://registry.aliyuncs.com"]

注意 :containerd v2 的配置路径与 v1 不同,v2 使用 plugins."io.containerd.grpc.v1.cri" 而不是 plugins."io.containerd.grpc.v1.cri".registry

4.3.3 完整的关键配置项说明
toml 复制代码
# /etc/containerd/config.toml 关键配置解读

# --- 1. 运行时配置 ---
[plugins."io.containerd.grpc.v1.cri".containerd]
  # snapshotter 使用 overlayfs (性能最好)
  snapshotter = "overlayfs"
  # 禁用容器内系统 swap (K8s 要求)
  disable_snapshot_annotations = false

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  # 使用 systemd cgroup 驱动 (与 K8s 保持一致)
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true   # <-- 关键!必须为 true

# --- 2. 镜像仓库加速 (Mirrors) ---
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
  # 阿里云镜像加速
  endpoint = ["https://mirrors.aliyun.com"]

[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
  # 阿里云 K8s 镜像
  endpoint = ["https://registry.aliyuncs.com"]

# --- 3. 沙箱镜像 (Pause Image) ---
[plugins."io.containerd.grpc.v1.cri"]
  # K8s Pod 基础设施镜像 (每个 Pod 的 pause 容器)
  sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.10"

4.4 重启 containerd 并验证

bash 复制代码
# 1. 重启 containerd 使配置生效
sudo systemctl restart containerd

# 2. 设置开机自启
sudo systemctl enable containerd

# 3. 查看状态
sudo systemctl status containerd

预期输出

复制代码
● containerd.service - containerd container runtime
     Loaded: loaded (/lib/systemd/system/containerd.service; enabled; preset: enabled)
     Active: active (running) since Thu 2025-xx-xx 10:00:00 CST; 10s ago
       Docs: https://containerd.io
   Main PID: 12345 (containerd)
      Tasks: 11
     Memory: 15.3M
        CPU: 100ms
     CGroup: /system.slice/containerd.service
             └─12345 /usr/bin/containerd
4.4.1 使用 ctr 验证 containerd 工作正常
bash 复制代码
# 查看 containerd 信息
sudo ctr --namespace k8s.io version

# 列出已拉取的镜像 (此时应为空)
sudo ctr --namespace k8s.io images ls

输出示例

复制代码
Client:
  Version:  2.2.1
  Revision: 

Server:
  Version:  2.2.1
  Revision: 

4.5 (可选) 安装 nerdctl ------ containerd 的 docker 风格 CLI

ctr 是 containerd 的底层 CLI,参数复杂。nerdctl 提供了与 docker 命令兼容的用户体验。

bash 复制代码
# 下载 nerdctl (选择最新版本)
NERDCTL_VERSION="2.1.3"
wget https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz

# 解压并安装
sudo tar -C /usr/local/bin -xzf nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz

# 验证
nerdctl --version

nerdctl 常用命令(与 docker 几乎一致):

bash 复制代码
nerdctl ps              # 列出容器
nerdctl images          # 列出镜像
nerdctl pull nginx      # 拉取镜像
nerdctl run -it --rm nginx bash

4.6 containerd 排错指南

问题 原因 解决方案
containerd: command not found 未安装 apt-get install containerd.io
Failed to connect to containerd containerd 未启动 systemctl start containerd
SystemdCgroup = false 导致 kubelet 启动失败 配置未修改 修改 config.toml 并重启
镜像拉取超时 国内网络问题 配置 mirrors 或使用代理
ctr images ls 看不到镜像 namespace 不对 使用 ctr -n k8s.io images ls

第5章:kubeadm / kubelet / kubectl 安装

kubeadm :K8s 集群引导工具,负责初始化 Master 和将 Worker 加入集群

kubelet :运行在每个节点上的 "节点代理",管理 Pod 生命周期

kubectl:K8s 命令行工具,用于与 API Server 交互


5.1 添加 Kubernetes 阿里云镜像仓库

所有节点上执行:

bash 复制代码
# 1. 添加阿里云 K8s 仓库 GPG 密钥
curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core:/stable:/v1.32/deb/Release.key | \
  sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# 2. 添加 K8s 仓库 (阿里云镜像)
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \
https://mirrors.aliyun.com/kubernetes-new/core:/stable:/v1.32/deb/ /" | \
  sudo tee /etc/apt/sources.list.d/kubernetes.list

# 3. 更新包索引
sudo apt-get update

踩坑记录 #1 (扩展) :K8s 官方仓库 pkgs.k8s.io 在国内访问不稳定。阿里云镜像站同步了官方仓库,速度极快且稳定。


5.2 安装指定版本 kubeadm / kubelet / kubectl

所有节点上执行:

bash 复制代码
# 安装指定版本 (与实战环境一致: v1.32.13)
sudo apt-get install -y \
  kubelet=1.32.13-1.1 \
  kubeadm=1.32.13-1.1 \
  kubectl=1.32.13-1.1 \
  --allow-downgrades

# 锁定版本,防止 apt upgrade 时自动升级
sudo apt-mark hold kubelet kubeadm kubectl

验证安装

bash 复制代码
$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"32", GitVersion:"v1.32.13", ...}

$ kubelet --version
Kubernetes v1.32.13

$ kubectl version --client
Client Version: v1.32.13
5.2.1 关于版本锁定
bash 复制代码
# 查看 hold 状态
sudo apt-mark showhold
# 输出: kubelet kubeadm kubectl

# 如果需要升级,先取消 hold
sudo apt-mark unhold kubelet kubeadm kubectl

⚠️ 重要 :K8s 集群的所有节点必须使用相同版本的 kubelet/kubeadm,否则会出现兼容性问题。


5.3 配置 kubelet 的 cgroup 驱动

kubelet 的 cgroup 驱动必须与 containerd 的 SystemdCgroup 设置一致 (都使用 systemd)。

创建 kubelet 配置文件:

bash 复制代码
cat << 'EOF' | sudo tee /etc/systemd/system/kubelet.service.d/20-kubeadm.conf
# 此文件由 kubeadm 自动生成,此处为手动创建示例
# 通常不需要手动创建,kubeadm init 会自动配置
EOF

# 更推荐的方式:通过 kubeadm 配置
# 见第6章的 kubeadm-config.yaml

实际上,kubeadm 会在 init 时自动配置 kubelet,只需确保 containerd 的 SystemdCgroup = true 即可。


5.4 启用 kubelet (但不要启动)

bash 复制代码
# 重新加载 systemd 配置
sudo systemctl daemon-reload

# 启用 kubelet (开机自启,但此时不要启动,kubeadm init 会启动它)
sudo systemctl enable kubelet

为什么不要手动启动 kubelet?kubeadm init 之前,kubelet 会因为缺少配置文件而启动失败(这是正常的)。kubeadm 会在初始化过程中生成 kubelet 配置。


5.5 安装 CNI 插件 (CNI Plugins)

CNI (Container Network Interface) 插件是 K8s 网络的基础。Flannel 依赖 CNI 插件的可执行文件。

所有节点上执行:

bash 复制代码
# 下载 CNI plugins v1.6.2
CNI_VERSION="v1.6.2"
wget https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-amd64-${CNI_VERSION}.tgz

# 解压到 /opt/cni/bin
sudo mkdir -p /opt/cni/bin
sudo tar -C /opt/cni/bin -xzf cni-plugins-linux-amd64-${CNI_VERSION}.tgz

# 验证 CNI 插件
ls /opt/cni/bin/

输出

复制代码
bandwidth  bridge  dhcp  dummy  firewall  ... host-local  ipvlan  loopback  macvlan  portmap  ptp  sbr  static  tuning  vlan  vrf

关键 CNI 插件说明

插件 用途
bridge 创建桥接设备,Flannel 默认使用
host-local IP 地址分配 (IPAM),Flannel 使用
loopback 配置 lo 网卡
portmap 端口映射 (NodePort 实现依赖)

5.6 验证:所有节点环境检查

在执行 kubeadm init 之前,运行 kubeadm 自带的预检:

bash 复制代码
sudo kubeadm init --dry-run 2>&1 | head -30

如果一切正常 ,会看到 preflight 阶段检查通过。如果有错误,根据错误提示修复(通常是 swap 未关闭、内核模块缺失等)。


第6章:Master 节点初始化与 kubeadm init

本章实战在 Master 节点 (kuboard-01, 192.168.0.85) 上执行


6.1 创建 kubeadm 配置文件

使用配置文件(而不是命令行参数)初始化集群,便于版本控制和重复部署。

Master 节点 上创建 /tmp/kubeadm-config.yaml

yaml 复制代码
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
bootstrapTokens:
- token: "abcdef.0123456789abcdef"
  description: "default bootstrap token"
  ttl: "24h"
nodeRegistration:
  criSocket: "unix:///run/containerd/containerd.sock"
  imagePullPolicy: IfNotPresent
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/control-plane

---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: "v1.32.13"
clusterName: "kuboard-cluster"
networking:
  serviceSubnet: "10.96.0.0/12"
  podSubnet: "10.244.0.0/16"      # <-- 必须与 Flannel 的 --pod-network-cidr 一致
  dnsDomain: "cluster.local"
controlPlaneEndpoint: ""           # 单 Master 不需要指定
apiServer:
  extraArgs:
    ServiceAccount-issuer: "https://kubernetes.default.svc.cluster.local"
    ServiceAccount-signing-key-file: "/etc/kubernetes/pki/sa.key"
controllerManager:
  extraArgs:
    bind-address: "0.0.0.0"
scheduler:
  extraArgs:
    bind-address: "0.0.0.0"
imageRepository: "registry.aliyuncs.com/google_containers"  # <-- 关键!国内镜像加速

---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: "systemd"           # <-- 与 containerd 的 SystemdCgroup 一致
failSwapOn: false
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"                      # 使用 IPVS 模式 (性能优于 iptables)
ipvs:
  scheduler: "rr"

配置参数详细解释

配置项 说明
imageRepository registry.aliyuncs.com/google_containers 从阿里云拉取 K8s 组件镜像,避免 registry.k8s.io 访问超时
podSubnet 10.244.0.0/16 Pod IP 分配范围,必须与 CNI 插件的配置匹配
serviceSubnet 10.96.0.0/12 Service ClusterIP 分配范围
cgroupDriver systemd kubelet 使用 systemd cgroup 驱动
KubeProxyConfiguration.mode ipvs Kube-proxy 使用 IPVS 模式
criSocket unix:///run/containerd/containerd.sock 指定 containerd 的 CRI socket 路径

6.2 执行 kubeadm init

Master 节点 上执行:

bash 复制代码
sudo kubeadm init \
  --config=/tmp/kubeadm-config.yaml \
  --upload-certs \
  --v=5

参数说明

  • --config:指定配置文件路径
  • --upload-certs:将 CA 证书上传到集群 Secret(多 Master 时需要)
  • --v=5:输出详细日志(排错时有用)

踩坑记录 #1 详情 :如果未指定 imageRepository,kubeadm 默认从 registry.k8s.io 拉取镜像。国内服务器访问该地址会超时,报错:[ERROR ImagePull]: failed to pull image registry.k8s.io/kube-apiserver:v1.32.x。解决方案就是在配置文件中指定 imageRepository: "registry.aliyuncs.com/google_containers"


6.3 kubeadm init 输出解读

成功的初始化输出 (关键部分):

复制代码
[init] Using Kubernetes version: v1.32.13
[preflight] Running pre-flight checks
  [WARNING Hostname]: hostname "kuboard-01" could not be reached via DNS
  # ^ 可以忽略,因为我们配置了 /etc/hosts
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take up to a minute or so in case of network slowness
  # ^ 使用阿里云镜像,通常 1-2 分钟完成
[kubelet-start] Writing kubelet configuration to file
[certs] Generating certificates...
  # ^ 生成 CA、API Server、etcd 等证书 (位于 /etc/kubernetes/pki/)
[kubeconfig] Writing kubeconfig files...
  # ^ 生成 admin.conf, kubelet.conf, controller-manager.conf, scheduler.conf
[control-plane] Creating static pod manifests...
  # ^ 创建 API Server, Controller Manager, Scheduler 的静态 Pod 清单
[etcd] Creating static pod manifest for local etcd
  # ^ 创建 etcd 静态 Pod 清单
[upload-config] Storing the configuration...
[mark-control-plane] Marking the node kuboard-01 as control-plane
[kubelet-check] Waiting for the kubelet to boot up the control plane
  # ^ 等待 kubelet 启动控制平面 Pod
[patch-node] Uploading the CRI endpoint...
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a CNI network addon (like Flannel):
  kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.0.85:6443 --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

6.4 配置 kubectl (管理员用)

Master 节点 上执行:

bash 复制代码
# 方法1:非 root 用户
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 方法2:root 用户 (简单直接)
export KUBECONFIG=/etc/kubernetes/admin.conf
echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' >> ~/.bashrc

验证 kubectl 可以连接集群

bash 复制代码
$ kubectl get nodes
NAME         STATUS     ROLES           AGE   VERSION
kuboard-01   NotReady   control-plane   2m    v1.32.13

为什么 STATUS 是 NotReady? 因为还没有安装 CNI 网络插件。安装 Flannel 后,状态会变成 Ready


6.5 查看集群组件状态

bash 复制代码
# 查看所有组件状态
kubectl get componentstatuses

# 查看控制平面 Pod
kubectl get pods -n kube-system

输出示例

复制代码
NAME                                 READY   STATUS    RESTARTS   AGE
etcd-kuboard-01                      1/1     Running   0          3m
kube-apiserver-kuboard-01            1/1     Running   0          3m
kube-controller-manager-kuboard-01   1/1     Running   0          3m
kube-scheduler-kuboard-01            1/1     Running   0          3m
coredns-xxxx-yyyy                    0/1     Pending   0          3m   # 等待网络插件
kube-proxy-zzzz                      1/1     Running   0          3m

注意 :CoreDNS Pod 处于 Pending 状态是正常的,因为 Flannel 尚未安装,Pod 网络未就绪。


6.6 保存 kubeadm join 命令

kubeadm init 输出的 kubeadm join 命令保存到文件,后续 Worker 节点加入时需要:

bash 复制代码
# 在 Master 节点上保存 join 命令
kubeadm token create --print-join-command > /tmp/kubeadm-join.sh
chmod +x /tmp/kubeadm-join.sh
cat /tmp/kubeadm-join.sh

如果忘记了 join 命令,可以在 Master 上重新生成:

bash 复制代码
# 创建新的 bootstrap token 并打印 join 命令
sudo kubeadm token create --print-join-command --ttl=24h

6.7 kubeadm init 排错指南

错误 原因 解决方案
[ERROR Swap] swap 未关闭 swapoff -a + 注释 fstab
[ERROR ImagePull] 无法拉取镜像 使用 --image-repository=registry.aliyuncs.com/google_containers
[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables] sysctl 参数未设置 执行第3章的 sysctl 配置
context deadline exceeded 镜像拉取超时 检查网络、配置 containerd mirrors
Port 6443 is in use API Server 已在运行 kubeadm reset 后重试

重置集群 (排错时使用)

bash 复制代码
sudo kubeadm reset --force
sudo rm -rf /etc/kubernetes /var/lib/etcd ~/.kube

第7章:CNI 网络插件 Flannel 部署

Flannel 是最简单的 K8s CNI 插件之一,适合入门和中小规模集群。它为每个 Node 分配一个子网,通过 VXLAN 或 host-gw 实现跨节点 Pod 通信。


7.1 Flannel 工作原理

复制代码
┌──────────────────────────────────────────────────────────────────┐
│                      Flannel 网络模型                           │
│                                                                │
│  Node-1 (kuboard-01)            Node-2 (kuboard-02)          │
│  Pod CIDR: 10.244.0.0/24      Pod CIDR: 10.244.1.0/24      │
│                                                                │
│  ┌──────────┐                   ┌──────────┐                   │
│  │  Pod-A   │ 10.244.0.2      │  Pod-C   │ 10.244.1.2      │
│  │(eth0)    │──────┐           │(eth0)    │                   │
│  └──────────┘      │           └──────────┘                   │
│                      │ flannel.1 (VXLAN)                       │
│  ┌──────────┐      │           ┌──────────┐                   │
│  │  Pod-B   │ 10.244.0.3      │  Pod-D   │ 10.244.1.3      │
│  │(eth0)    │      │           │(eth0)    │                   │
│  └──────────┘      │           └──────────┘                   │
│        │             ▼                 ▲                          │
│        │     ┌──────────────┐        │                          │
│        └────►│  flanneld    │────────┘                          │
│              │  (Agent)     │    VXLAN tunnel (UDP 8472)      │
│              └──────┬───────┘                                   │
│                     │                                            │
│              ┌──────▼───────┐                                   │
│              │  host eth0   │ 192.168.0.85                     │
│              └──────────────┘                                   │
│                                                                │
└──────────────────────────────────────────────────────────────────┘

Flannel 核心组件

组件 运行方式 功能
flanneld DaemonSet Pod 为每个 Node 分配 Pod CIDR 子网,维护路由表
cni0 / veth 网络接口 将 Pod 连接到 Node 的网络命名空间
flannel.1 VXLAN 接口 跨节点 Pod 通信的 Overlay 隧道 (UDP 8472)
host-gw 模式 直连路由 无需 Overlay,性能更好(要求 Node 同二层网络)

7.2 下载 Flannel YAML 清单

Master 节点 上执行:

bash 复制代码
# 下载最新版 Flannel 安装清单
wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

# 查看文件内容
ls -lh kube-flannel.yml
head -50 kube-flannel.yml

kube-flannel.yml 结构解读

复制代码
kube-flannel.yml 包含以下 K8s 资源:
  1. ServiceAccount: flannel (RBAC 权限)
  2. ClusterRole + ClusterRoleBinding: flannel 权限绑定
  3. ConfigMap: kube-flannel-cfg (NetConf 配置)
  4. DaemonSet: kube-flannel-ds (核心,每个 Node 运行一个 Pod)
  5. NetworkPolicy: 可选的网络策略

7.3 修改 Flannel 配置 (Pod CIDR 匹配)

关键 :Flannel 的 net-conf.json 中的 Network 必须与 kubeadm init 时指定的 podSubnet 完全一致 (10.244.0.0/16)。

bash 复制代码
# 验证当前 kube-flannel.yml 中的 Network 配置
grep -A 5 "net-conf.json" kube-flannel.yml

预期输出 (应显示 "Network": "10.244.0.0/16"):

json 复制代码
  net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "vxlan"
      }
    }

如果不一致 ,需要修改 kube-flannel.yml 中的 net-conf.jsonNetwork 字段,使其与 kubeadm-config.yaml 中的 podSubnet 一致。


7.4 部署 Flannel (踩坑记录 #2 详解)

⚠️ 踩坑记录 #2:Flannel ghcr.io 镜像拉取失败

现象 :在国内服务器执行 kubectl apply -f kube-flannel.yml 后,Flannel Pod 一直 ImagePullBackOff,查看 Pod 详情:

复制代码
Failed to pull image "ghcr.io/flannel-io/flannel:v0.28.5":
rpc error: code = DeadlineExceeded desc = failed to pull and unpack image:
failed to resolve reference "ghcr.io/flannel-io/flannel:v0.28.5":
failed to do request: Head "https://ghcr.io/v2/flannel-io/flannel/manifests/v0.28.5":
dial tcp 20.205.243.166:443: i/o timeout

原因ghcr.io (GitHub Container Registry) 在国内访问极不稳定,经常超时。

解决方案 (二选一)

方案A:使用 hub.rat.dev 代理 (推荐)
bash 复制代码
# 1. 编辑 kube-flannel.yml,替换镜像地址
sed -i 's|ghcr.io/flannel-io/flannel|docker.rainbond.cc/flannel-io/flannel|g' kube-flannel.yml

# 验证替换结果
grep "image:" kube-flannel.yml
# 应显示: image: docker.rainbond.cc/flannel-io/flannel:v0.28.5
方案B:手动拉取 + 导出 + 导入 (离线方案)

在 Master 节点 (有外网代理或能访问 ghcr.io 的机器上)

bash 复制代码
# 1. 拉取 Flannel 镜像 (在有外网访问的机器上)
sudo ctr -n k8s.io images pull ghcr.io/flannel-io/flannel:v0.28.5

# 2. 导出为 tar 包
sudo ctr -n k8s.io images export flannel-v0.28.5.tar \
  ghcr.io/flannel-io/flannel:v0.28.5

# 3. 通过 sftp/scp 传到所有 Worker 节点
scp flannel-v0.28.5.tar root@192.168.0.28:/tmp/
scp flannel-v0.28.5.tar root@192.168.0.153:/tmp/
scp flannel-v0.28.5.tar root@192.168.0.51:/tmp/

# 4. 在所有节点 (包括 Master) 上导入
sudo ctr -n k8s.io images import /tmp/flannel-v0.28.5.tar

# 5. 验证镜像已导入
sudo ctr -n k8s.io images ls | grep flannel

然后修改 kube-flannel.yml ,将 imagePullPolicy 改为 IfNotPresent

yaml 复制代码
# 在 kube-flannel.yml 中,找到 imagePullPolicy
imagePullPolicy: IfNotPresent  # 改为 IfNotPresent (而不是 Always)

7.5 应用 Flannel YAML

bash 复制代码
# 部署 Flannel
kubectl apply -f kube-flannel.yml

输出

复制代码
namespace/kube-flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

7.6 验证 Flannel 部署成功

bash 复制代码
# 1. 查看 Flannel Pod 状态 (等待所有节点 Ready)
kubectl get pods -n kube-flannel -o wide --watch

预期输出 (等待 1-2 分钟):

复制代码
NAMESPACE       NAME                    READY   STATUS    RESTARTS   AGE   NODE
kube-flannel    kube-flannel-ds-abcde  1/1    Running   0          1m    kuboard-01
bash 复制代码
# 2. 查看 Node 状态 (应从 NotReady 变为 Ready)
kubectl get nodes -o wide

预期输出

复制代码
NAME         STATUS   ROLES           AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION         CONTAINER-RUNTIME
kuboard-01   Ready    control-plane   5m    v1.32.13  192.168.0.85   <none>        Ubuntu 24.04.4 LTS   6.8.0-106-generic     containerd://2.2.1

STATUS = Ready 表示 Flannel 工作正常,节点网络已就绪!

bash 复制代码
# 3. 验证 CNI 接口已创建
ip link show | grep flannel
# 或
ip link show | grep cni

输出示例

复制代码
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 ...
7: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 ...

7.7 Flannel 排错指南

问题 诊断命令 解决方案
Flannel Pod Init:0/1 kubectl logs -n kube-flannel ds/kube-flannel-ds 检查 CNI 插件是否已安装 (/opt/cni/bin/bridge)
Flannel Pod ImagePullBackOff kubectl describe pod -n kube-flannel <pod> 参考踩坑#2,使用镜像代理或离线导入
Node 一直是 NotReady kubectl describe node kuboard-01 检查 Conditions 中的 NetworkUnavailable
Pod 跨节点无法通信 kubectl exec -it <pod> -- ping <another-pod-ip> 检查防火墙 UDP 8472 是否开放
cni0 接口不存在 ip link show cni0 重启 Flannel Pod 或检查 bridge CNI 插件

第8章:Worker 节点加入集群

目标:将 kuboard-02、kuboard-03、kuboard-04 三个 Worker 节点加入集群。


8.1 在 Master 节点上准备 join 命令

如果之前保存了 kubeadm init 输出的 join 命令,可以直接使用。否则,在 Master 节点 上重新生成:

bash 复制代码
# 创建新的 token 并打印 join 命令
sudo kubeadm token create --print-join-command

输出示例

复制代码
kubeadm join 192.168.0.85:6443 --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:1a2b3c4d5e6f...

Token 说明kubeadm token 默认 24 小时过期。如果 token 过期,需要重新创建。


8.2 在所有 Worker 节点上执行 join

将上一步得到的 kubeadm join 命令,分别在 kuboard-02、kuboard-03、kuboard-04 上执行:

bash 复制代码
# 在 kuboard-02 (120.46.32.153) 上执行
sudo kubeadm join 192.168.0.85:6443 \
  --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:1a2b3c4d5e6f...

# 在 kuboard-03 (1.94.204.169) 上执行
sudo kubeadm join 192.168.0.85:6443 \
  --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:1a2b3c4d5e6f...

# 在 kuboard-04 (120.46.129.80) 上执行
sudo kubeadm join 192.168.0.85:6443 \
  --token abcdef.0123456789abcdef \
  --discovery-token-ca-cert-hash sha256:1a2b3c4d5e6f...

成功输出 (每个 Worker 节点):

复制代码
[preflight] Running pre-flight checks
  [WARNING Hostname]: hostname "kuboard-02" could not be reached via DNS
[join] Reading configuration from the cluster...
[join] 2025-xx-xx ... [kubelet-start] Starting the kubelet
[join] 2025-xx-xx ... [control-plane] Adding node "kuboard-02" to the cluster
This node has joined the cluster!

8.3 在 Master 节点上验证所有节点已加入

bash 复制代码
kubectl get nodes -o wide

预期输出 (4 个节点全部 Ready):

复制代码
NAME         STATUS   ROLES           AGE   VERSION    INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION
kuboard-01   Ready    control-plane   15m   v1.32.13  192.168.0.85   <none>        Ubuntu 24.04.4 LTS   6.8.0-106-generic
kuboard-02   Ready    <none>          3m    v1.32.13  192.168.0.28   <none>        Ubuntu 24.04.4 LTS   6.8.0-106-generic
kuboard-03   Ready    <none>          2m    v1.32.13  192.168.0.153  <none>        Ubuntu 24.04.4 LTS   6.8.0-106-generic
kuboard-04   Ready    <none>          2m    v1.32.13  192.168.0.51   <none>        Ubuntu 24.04.4 LTS   6.8.0-106-generic

注意 :Worker 节点的 ROLES 列是 <none>,这是正常的。如需添加角色标签,可以执行:

bash 复制代码
kubectl label node kuboard-02 node-role.kubernetes.io/worker=worker

8.4 查看所有系统 Pod 状态

bash 复制代码
kubectl get pods -A -o wide

完整输出示例 (所有 Pod Running):

复制代码
NAMESPACE      NAME                                   READY   STATUS   RESTARTS   AGE   NODE
kube-flannel   kube-flannel-ds-abcde                 1/1     Running  0          10m   kuboard-01
kube-flannel   kube-flannel-ds-bcdef                 1/1     Running  0          5m    kuboard-02
kube-flannel   kube-flannel-ds-cdefg                 1/1     Running  0          5m    kuboard-03
kube-flannel   kube-flannel-ds-defgh                 1/1     Running  0          5m    kuboard-04
kube-system    coredns-668d6bf9b5-xyzab              1/1     Running  0          15m   kuboard-01
kube-system    coredns-668d6bf9b5-wxyza              1/1     Running  0          15m   kuboard-01
kube-system    etcd-kuboard-01                       1/1     Running  0          15m   kuboard-01
kube-system    kube-apiserver-kuboard-01              1/1     Running  0          15m   kuboard-01
kube-system    kube-controller-manager-kuboard-01     1/1     Running  0          15m   kuboard-01
kube-system    kube-proxy-aaaaa                       1/1     Running  0          15m   kuboard-01
kube-system    kube-proxy-bbbbb                       1/1     Running  0          5m    kuboard-02
kube-system    kube-proxy-ccccc                       1/1     Running  0          5m    kuboard-03
kube-system    kube-proxy-ddddd                       1/1     Running  0          5m    kuboard-04
kube-system    kube-scheduler-kuboard-01              1/1     Running  0          15m   kuboard-01

🎉 恭喜!Kubernetes 集群已成功搭建! 接下来部署 Kuboard v3 管理面板。


8.5 Worker 节点加入失败排错

错误 原因 解决方案
token is expired token 超过 24 小时 在 Master 上 kubeadm token create 重新生成
connection refused Master API Server 不可达 检查 Master 防火墙、安全组规则
certificate signed by unknown authority CA 证书 hash 不匹配 重新获取正确的 --discovery-token-ca-cert-hash
Preflight checks failed swap 未关闭等 执行第3章的系统初始化步骤
Worker 节点 NotReady Flannel 未正常运行 检查 Worker 节点上的 Flannel Pod 日志

重置 Worker 节点 (排错时用):

bash 复制代码
sudo kubeadm reset --force
sudo rm -rf /etc/kubernetes /var/lib/kubelet

第9章:Kuboard v3 部署

目标 :在 K8s 集群中部署 Kuboard v3,并通过 NodePort 30080 访问。


9.1 Kuboard 部署架构

复制代码
┌──────────────────────────────────────────────────────────────────┐
│                    Kuboard v3 on Kubernetes                      │
│                                                                  │
│  kuboard Namespace:                                              │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  Deployment: kuboard (replicas: 1)                      │   │
│  │    Pod: kuboard-xxxxxxxxxx-yyyyy                         │   │
│  │      Container: kuboard                                  │   │
│  │        Image: swr.cn-east-2.myhuaweicloud.com/...       │   │
│  │        Port: 80 (HTTP)                                  │   │
│  │        Env: KUBOARD_AGENT_KEY=...                       │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
│  Service: kuboard (NodePort, port 80 → NodePort 30080)         │
│    → 访问: http://任意节点IP:30080                              │
│                                                                  │
│  ConfigMap: kuboard-config (配置文件)                           │
│  ServiceAccount: kuboard (RBAC 权限)                           │
└──────────────────────────────────────────────────────────────────┘

9.2 创建 Kuboard 部署 YAML

Master 节点 上创建 /tmp/kuboard-v3.yaml

yaml 复制代码
---
apiVersion: v1
kind: Namespace
metadata:
  name: kuboard
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kuboard
  namespace: kuboard
  labels:
    app: kuboard
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kuboard
  template:
    metadata:
      labels:
        app: kuboard
    spec:
      # 允许调度到 Master 节点 (control-plane 有 taint)
      tolerations:
      - key: "node-role.kubernetes.io/control-plane"
        operator: "Exists"
        effect: "NoSchedule"
      # 优先调度到 Master 节点 (Kuboard 管理面板通常放 Master)
      nodeSelector:
        kubernetes.io/hostname: "kuboard-01"
      containers:
      - name: kuboard
        image: swr.cn-east-2.myhuaweicloud.com/kuboard/kuboard:v3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        env:
        - name: KUBOARD_AGENT_KEY
          value: "kuboard-register-key-2025"
        - name: KUBOARD_AGENT_PORT
          value: "30080"
        - name: KUBOARD_SERVER_NODE_PORT
          value: "30080"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
  name: kuboard
  namespace: kuboard
  labels:
    app: kuboard
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
    name: http
    protocol: TCP
  selector:
    app: kuboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kuboard-cluster-admin
subjects:
- kind: ServiceAccount
  name: default
  namespace: kuboard
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

踩坑记录 #5 详解 :Control-plane 节点默认有 node-role.kubernetes.io/control-plane:NoSchedule 污点 (taint),普通 Pod 无法调度上去。需要在 PodSpec 中添加对应的 toleration


9.3 部署 Kuboard

bash 复制代码
# 应用 Kuboard YAML
kubectl apply -f /tmp/kuboard-v3.yaml

输出

复制代码
namespace/kuboard created
deployment.apps/kuboard created
service/kuboard created
clusterrolebinding.rbac.authorization.k8s.io/kuboard-cluster-admin created

9.4 验证 Kuboard 部署

bash 复制代码
# 1. 查看 Kuboard Pod 状态
kubectl get pods -n kuboard -o wide --watch

等待约 30 秒,预期输出

复制代码
NAME                       READY   STATUS    RESTARTS   AGE   NODE
kuboard-xxxxxxxxxx-yyyyy   1/1     Running   0          30s   kuboard-01
bash 复制代码
# 2. 查看 Kuboard Service
kubectl get svc -n kuboard

输出

复制代码
NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kuboard   NodePort   10.96.xx.xx      <none>       80:30080/TCP  1m
bash 复制代码
# 3. 查看 Pod 日志 (确认启动正常)
kubectl logs -n kuboard deployment/kuboard --tail=20

关键日志

复制代码
2025/xx/xx ...
Kuboard v3 started successfully!
Access Kuboard at http://<NodeIP>:30080
Default username: admin
Default password: Kuboard123

9.5 访问 Kuboard Web UI

打开浏览器,访问:

复制代码
http://120.46.195.39:30080

注意 :如果使用华为云,确保安全组已开放 TCP 30080 入方向规则。

登录信息 (默认):

  • 用户名:admin
  • 密码:Kuboard123

⚠️ 安全提示:登录后请立即修改默认密码!


9.6 Kuboard 端口名踩坑 (踩坑记录 #6)

踩坑记录 #6:Service 端口名超过 15 字符

现象 :在创建 Service 时,如果 name 字段超过 15 个字符,K8s 会报错:

复制代码
metadata.annotations: Too long: must be no more than 15 characters

解决方案 :端口名使用简短名称,如 http 而非 kuboard-http-server-port

在上面的 YAML 中,端口名已设置为 http(5个字符),符合 K8s 要求。


第10章:Kuboard 界面实战


10.1 首次登录与修改密码

  1. 访问 http://120.46.195.39:30080
  2. 输入用户名 admin,密码 Kuboard123
  3. 系统会强制要求修改密码 → 设置新密码
  4. 进入 Kuboard 主页

10.2 导入当前集群

Kuboard 需要导入 K8s 集群才能管理。由于我们是在集群内部署的 Kuboard,它可以自动发现当前集群。

步骤

  1. 点击左侧导航 集群导入集群
  2. 选择 KubeConfig 方式
  3. 将 Master 节点上的 /etc/kubernetes/admin.conf 内容粘贴到输入框
  4. 点击 导入

或者,使用 ServiceAccount Token 方式 (推荐,更安全):

bash 复制代码
# 获取 default ServiceAccount 的 token
kubectl -n kuboard get secret \
  $(kubectl -n kuboard get sa default -o jsonpath='{.secrets[0].name}') \
  -o jsonpath='{.data.token}' | base64 --decode

将输出的 token 粘贴到 Kuboard 导入界面。


10.3 Kuboard 主要功能导航

复制代码
Kuboard v3 界面结构:

┌─────────────────────────────────────────────────────────────┐
│  Logo  Kuboard v3    [集群: kuboard-cluster]   admin ▼    │
├──────────┬──────────────────────────────────────────────────┤
│          │                                                  │
│ 集群概览  │  节点状态、Pod 数量、资源使用率仪表盘              │
│          │                                                  │
│ 工作负载  │  ┌────────┬────────┬────────┬────────┐        │
│          │  │ 部署    │ 有状态集 │ DaemonSet│ 任务   │       │
│          │  └────────┴────────┴────────┴────────┘        │
│ 配置管理  │  ConfigMap / Secret                           │
│          │                                                  │
│ 网络     │  Service / Ingress                             │
│          │                                                  │
│ 存储     │  PV / PVC / StorageClass                       │
│          │                                                  │
│ 集群管理  │  节点管理 / 命名空间 / 审计日志                  │
│          │                                                  │
└──────────┴──────────────────────────────────────────────────┘

10.4 通过 Kuboard 创建第一个 Nginx 部署

步骤 (通过 Kuboard Web UI):

  1. 左侧导航 → 工作负载部署创建
  2. 填写表单:
  • 名称:nginx-demo
  • 命名空间:default
  • 容器:
    • 名称:nginx
    • 镜像:nginx:1.27
    • 端口:80
  • 副本数:2
  1. 点击 完成
  2. 查看部署状态

验证 (通过 kubectl):

bash 复制代码
kubectl get deployments
kubectl get pods -l app=nginx-demo

10.5 Kuboard 监控功能

Kuboard 集成了 Metrics Server(需先安装)来显示资源使用率:

bash 复制代码
# 安装 Metrics Server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# 如果 Metrics Server 启动失败,可能需要添加 --kubelet-insecure-tls 参数
# 修改 metrics-server deployment:
kubectl patch deployment metrics-server -n kube-system --type='json' \
  -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--kubelet-insecure-tls"}]'

安装完成后,Kuboard 界面即可显示 CPU/内存使用率图表


第11章:国内镜像加速方案汇总


11.1 常用国内镜像加速地址

镜像仓库 加速地址 用途
阿里云容器镜像服务 registry.aliyuncs.com K8s 官方镜像 (k8s.gcr.io / registry.k8s.io)
阿里云 Docker Hub 加速 mirrors.aliyun.com Docker Hub 镜像
中科大 USTC docker.mirrors.ustc.edu.cn Docker Hub 镜像
网易 hub-mirror.c.163.com Docker Hub 镜像
百度 mirror.baidubce.com Docker Hub 镜像
Rainbond (hub.rat.dev) docker.rainbond.cc GitHub Packages / ghcr.io 镜像
华为云 SWR swr.cn-east-2.myhuaweicloud.com 华为云容器镜像 (Kuboard 官方镜像)

11.2 containerd 镜像加速完整配置

编辑 /etc/containerd/config.toml,添加以下配置:

toml 复制代码
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
  endpoint = ["https://mirrors.aliyun.com", "https://docker.mirrors.ustc.edu.cn"]

[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
  endpoint = ["https://registry.aliyuncs.com"]

[plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]
  endpoint = ["https://docker.rainbond.cc"]

[plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]
  endpoint = ["https://quay.mirrors.ustc.edu.cn"]

修改后重启 containerd

bash 复制代码
sudo systemctl restart containerd

11.3 kubeadm 使用国内镜像

kubeadm init 时指定 --image-repository 参数:

bash 复制代码
sudo kubeadm init \
  --image-repository=registry.aliyuncs.com/google_containers \
  --pod-network-cidr=10.244.0.0/16

或在配置文件 (kubeadm-config.yaml) 中指定:

yaml 复制代码
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
imageRepository: "registry.aliyuncs.com/google_containers"

第12章:常见问题排查指南


12.1 Pod 排错命令速查

bash 复制代码
# 1. 查看 Pod 状态
kubectl get pods -A

# 2. 查看 Pod 详情 (事件日志)
kubectl describe pod <pod-name> -n <namespace>

# 3. 查看 Pod 日志
kubectl logs <pod-name> -n <namespace>
kubectl logs <pod-name> -n <namespace> --previous   # 上一次重启前的日志

# 4. 查看多容器 Pod 中指定容器的日志
kubectl logs <pod-name> -n <namespace> -c <container-name>

# 5. 进入 Pod 容器调试
kubectl exec -it <pod-name> -n <namespace> -- /bin/bash
kubectl exec -it <pod-name> -n <namespace> -- /bin/sh   # Alpine 镜像

# 6. 查看 Pod 的资源使用率 (需要 Metrics Server)
kubectl top pod <pod-name> -n <namespace>

12.2 Node 排错

bash 复制代码
# 1. 查看 Node 状态
kubectl get nodes

# 2. 查看 Node 详情 (Conditions, 资源, 事件)
kubectl describe node <node-name>

# 3. 查看 Node 资源使用率
kubectl top node

# 4. 临时标记 Node 为不可调度 (维护前)
kubectl cordon <node-name>

# 5. 驱逐 Node 上的 Pod (维护前)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

# 6. 恢复 Node 可调度
kubectl uncordon <node-name>

12.3 网络排错

bash 复制代码
# 1. 从 Pod 内部测试 DNS 解析
kubectl exec -it <pod-name> -- nslookup kubernetes.default

# 2. 测试 Pod 间通信
kubectl exec -it <pod-a> -- ping <pod-b-ip>

# 3. 测试 Service 连通性
kubectl exec -it <pod-name> -- curl http://<service-name>.<namespace>:port

# 4. 查看 Service 和 Endpoints
kubectl get svc,endpoints -n <namespace>

# 5. 查看 iptables 规则 (kube-proxy iptables 模式)
sudo iptables -t nat -L | grep <service-name>

# 6. 查看 IPVS 规则 (kube-proxy ipvs 模式)
sudo ipvsadm -ln

12.4 kubeadm 和集群排错

bash 复制代码
# 1. 查看 kubelet 日志
sudo journalctl -u kubelet -f

# 2. 查看 kubelet 状态
sudo systemctl status kubelet

# 3. 查看容器运行时日志
sudo journalctl -u containerd -f

# 4. 查看 etcd 日志
kubectl logs -n kube-system etcd-kuboard-01

# 5. 查看 API Server 日志
kubectl logs -n kube-system kube-apiserver-kuboard-01

# 6. 验证集群健康状态
kubectl get componentstatuses
kubectl get --raw '/healthz'

12.5 常用调试工具 Pod

创建一个包含常用网络工具的调试 Pod:

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: netshoot
spec:
  containers:
  - name: netshoot
    image: nicolaka/netshoot:latest
    command: ["/bin/bash", "-c", "sleep 3600"]
    imagePullPolicy: IfNotPresent
  restartPolicy: Always
bash 复制代码
kubectl apply -f netshoot.yaml
kubectl exec -it netshoot -- bash
# 在 netshoot 容器中可以使用: curl, wget, nslookup, dig, ping, traceroute, etc.

附录A:完整部署命令速查表


A.1 系统初始化 (所有节点)

bash 复制代码
# 设置主机名
sudo hostnamectl set-hostname <hostname>

# 配置 /etc/hosts
cat << 'EOF' | sudo tee -a /etc/hosts
192.168.0.85   kuboard-01
192.168.0.28   kuboard-02
192.168.0.153  kuboard-03
192.168.0.51   kuboard-04
EOF

# 关闭 swap
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

# 加载内核模块
sudo modprobe overlay
sudo modprobe br_netfilter

# 配置 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

A.2 安装 containerd (所有节点)

bash 复制代码
# 添加 Docker CE 仓库
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 containerd
sudo apt-get update && sudo apt-get install -y containerd.io

# 生成并修改配置
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

# 重启
sudo systemctl restart containerd
sudo systemctl enable containerd

A.3 安装 K8s 组件 (所有节点)

bash 复制代码
# 添加阿里云 K8s 仓库
curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core:/stable:/v1.32/deb/Release.key | \
  sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] \
  https://mirrors.aliyun.com/kubernetes-new/core:/stable:/v1.32/deb/ /" | \
  sudo tee /etc/apt/sources.list.d/kubernetes.list

# 安装指定版本
sudo apt-get update && sudo apt-get install -y \
  kubelet=1.32.13-1.1 \
  kubeadm=1.32.13-1.1 \
  kubectl=1.32.13-1.1
sudo apt-mark hold kubelet kubeadm kubectl

A.4 Master 初始化

bash 复制代码
# 创建配置文件
cat << 'EOF' > /tmp/kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
nodeRegistration:
  criSocket: "unix:///run/containerd/containerd.sock"
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: "v1.32.13"
networking:
  podSubnet: "10.244.0.0/16"
imageRepository: "registry.aliyuncs.com/google_containers"
EOF

# 执行初始化
sudo kubeadm init --config=/tmp/kubeadm-config.yaml

# 配置 kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

A.5 安装 Flannel

bash 复制代码
# 下载 Flannel YAML
wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

# 替换镜像 (解决国内网络问题)
sed -i 's|ghcr.io/flannel-io/flannel|docker.rainbond.cc/flannel-io/flannel|g' kube-flannel.yml

# 部署
kubectl apply -f kube-flannel.yml

# 验证
kubectl get nodes  # 等待所有节点 Ready

A.6 Worker 加入集群

bash 复制代码
# 在 Master 上生成 join 命令
sudo kubeadm token create --print-join-command

# 在 Worker 节点上执行输出的命令
sudo kubeadm join 192.168.0.85:6443 --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash>

A.7 部署 Kuboard v3

bash 复制代码
# 创建 Kuboard YAML (见第9章完整 YAML)
# 应用
kubectl apply -f /tmp/kuboard-v3.yaml

# 验证
kubectl get pods -n kuboard
kubectl get svc -n kuboard

# 访问
# http://<NodeIP>:30080
# 默认账号: admin / Kuboard123

附录B:containerd 配置详解


B.1 containerd v2 完整配置参考

/etc/containerd/config.toml 关键配置项详解:

toml 复制代码
# ============================================================
# containerd v2 配置详解
# 生成方式: containerd config default > /etc/containerd/config.toml
# ============================================================

# --- 全局配置 ---
version = 2  # <-- TOML 配置版本 (v2)

# --- gRPC 监听地址 ---
[grpc]
  address = "/run/containerd/containerd.sock"  # <-- kubelet 连接的 CRI socket
  # kubeadm 配置中的 criSocket 必须与此一致

# --- CRI 插件配置 (最关键) ---
[plugins."io.containerd.grpc.v1.cri"]
  # 沙箱镜像 (Pause 容器)
  # K8s 每个 Pod 的第一个容器,负责创建网络命名空间
  sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.10"

  # 禁止将容器内 /etc/hosts 文件挂载为 tmpfs (K8s 1.28+ 可设为 true)
  disable_hosts_mount = false

  # --- 容器运行时配置 ---
  [plugins."io.containerd.grpc.v1.cri".containerd]
    # 快照器 (snapshotter): overlayfs 性能最好
    snapshotter = "overlayfs"

    # --- runc 运行时配置 ---
    [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
      # runtime_type: 使用 OCI 运行时 (runc)
      runtime_type = "io.containerd.runc.v2"

      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
        # SystemdCgroup: 必须使用 systemd cgroup 驱动 (K8s 要求)
        SystemdCgroup = true   # <-- 必须为 true!

  # --- 镜像仓库加速配置 ---
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
    endpoint = ["https://mirrors.aliyun.com"]

  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
    endpoint = ["https://registry.aliyuncs.com"]

  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]
    endpoint = ["https://docker.rainbond.cc"]

B.2 containerd 常用 ctr 命令

bash 复制代码
# 列出镜像
sudo ctr -n k8s.io images ls

# 拉取镜像
sudo ctr -n k8s.io images pull registry.aliyuncs.com/google_containers/pause:3.10

# 导出镜像
sudo ctr -n k8s.io images export pause.tar \
  registry.aliyuncs.com/google_containers/pause:3.10

# 导入镜像
sudo ctr -n k8s.io images import pause.tar

# 删除镜像
sudo ctr -n k8s.io images rm registry.aliyuncs.com/google_containers/pause:3.10

# 查看容器
sudo ctr -n k8s.io containers ls

# 查看任务 (运行的容器)
sudo ctr -n k8s.io tasks ls

附录C:Kuboard YAML 完整模板


C.1 Kuboard v3 完整部署 YAML

yaml 复制代码
# ============================================================
# Kuboard v3 完整部署 YAML
# 适用:Kubernetes v1.20+
# 镜像:华为云 SWR (国内加速)
# 访问:http://<NodeIP>:30080
# 默认账号:admin / Kuboard123
# ============================================================

---
apiVersion: v1
kind: Namespace
metadata:
  name: kuboard
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kuboard
  namespace: kuboard
  labels:
    app: kuboard
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kuboard
  template:
    metadata:
      labels:
        app: kuboard
    spec:
      # 容忍 Master 节点污点 (允许调度到 control-plane)
      tolerations:
      - key: "node-role.kubernetes.io/control-plane"
        operator: "Exists"
        effect: "NoSchedule"
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"
      # 节点选择器 (可选,指定运行在 kuboard-01)
      # nodeSelector:
      #   kubernetes.io/hostname: "kuboard-01"
      containers:
      - name: kuboard
        image: swr.cn-east-2.myhuaweicloud.com/kuboard/kuboard:v3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: http
          protocol: TCP
        env:
        - name: KUBOARD_AGENT_KEY
          value: "kuboard-register-key-2025"
        - name: KUBOARD_AGENT_PORT
          value: "30080"
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        volumeMounts:
        - name: kuboard-data
          mountPath: /data
      volumes:
      - name: kuboard-data
        emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: kuboard
  namespace: kuboard
  labels:
    app: kuboard
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
    name: http
    protocol: TCP
  selector:
    app: kuboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kuboard-cluster-admin
subjects:
- kind: ServiceAccount
  name: default
  namespace: kuboard
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

C.2 Flannel v0.28.5 国内镜像版 YAML (节选)

yaml 复制代码
# ============================================================
# kube-flannel.yml 修改版 (使用国内镜像)
# 修改点:将 ghcr.io/flannel-io/flannel 替换为国内可访问的镜像
# ============================================================

# ... (省略 ServiceAccount, ClusterRole 等,与官方相同)

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kube-flannel-ds
  namespace: kube-flannel
spec:
  selector:
    matchLabels:
      app: flannel
  template:
    metadata:
      labels:
        app: flannel
    spec:
      containers:
      - name: kube-flannel
        # 原始: image: ghcr.io/flannel-io/flannel:v0.28.5
        # 修改为国内可访问的镜像:
        image: docker.rainbond.cc/flannel-io/flannel:v0.28.5
        imagePullPolicy: IfNotPresent
        # ... (其余配置与官方相同)


第13章:集群运维实战

本章介绍 K8s 集群日常运维操作,包括健康检查、备份恢复、版本升级、资源管理等实战技巧。


13.1 集群健康检查 (Cluster Health Check)

bash 复制代码
# === 1. 检查所有节点状态 ===
kubectl get nodes -o wide

# 预期输出:
# NAME         STATUS   ROLES           AGE   VERSION    INTERNAL-IP
# kuboard-01   Ready    control-plane   1d    v1.32.13   192.168.0.85
# kuboard-02   Ready    <none>          1d    v1.32.13   192.168.0.28
# kuboard-03   Ready    <none>          1d    v1.32.13   192.168.0.153
# kuboard-04   Ready    <none>          1d    v1.32.13   192.168.0.51

# === 2. 检查所有命名空间中的 Pod ===
kubectl get pods -A

# === 3. 检查组件状态 ===
kubectl get componentstatuses

# === 4. 检查 API Server 健康状态 ===
kubectl get --raw '/healthz'  # 输出: ok

# === 5. 检查节点资源使用率 (需要 Metrics Server) ===
kubectl top nodes

# 预期输出:
# NAME         CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
# kuboard-01   128m         6%     1892Mi           49%
# kuboard-02   45m          2%     856Mi            22%
# kuboard-03   52m          2%     923Mi            24%
# kuboard-04   48m          2%     879Mi            23%

13.2 使用 Kuboard 进行集群监控

登录 Kuboard (http://120.46.195.39:30080) 后:

复制代码
┌──────────────────────────────────────────────────────────────────┐
│  Kuboard 集群概览页面                                           │
│                                                                │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │  节点状态      │  │  Pod 运行数   │  │  异常告警     │      │
│  │  4 / 4 Ready  │  │  28 Running  │  │  0 个        │      │
│  └──────────────┘  └──────────────┘  └──────────────┘      │
│                                                                │
│  节点资源使用率 (实时图表):                                      │
│  kuboard-01: CPU 6%  MEM 49%  ████████░░░░░░░░░░            │
│  kuboard-02: CPU 2%  MEM 22%  ████░░░░░░░░░░░░░░            │
│  kuboard-03: CPU 2%  MEM 24%  ████░░░░░░░░░░░░░░            │
│  kuboard-04: CPU 2%  MEM 23%  ████░░░░░░░░░░░░░░            │
│                                                                │
│  工作负载状态:                                                    │
│  Deployments:  5/5 Ready   ReplicaSets:  5/5 Ready            │
│  StatefulSets: 0/0 Ready   DaemonSets:  4/4 Ready             │
└──────────────────────────────────────────────────────────────────┘

Kuboard 监控功能详解

功能 说明 访问路径
节点监控 查看节点 CPU/内存/磁盘使用率 集群 → 节点 → 选择节点
Pod 监控 查看 Pod 资源使用率和日志 工作负载 → Pod → 选择 Pod
容器日志 查看容器标准输出/错误日志 Pod 详情 → 容器 → 日志
事件查看 查看 K8s Events (排错关键) 任意资源详情 → 事件标签页
YAML 编辑 在线编辑 K8s 资源 YAML 任意资源详情 → YAML 标签页

13.3 备份 etcd 数据 (生产环境必做)

etcd 是 K8s 的唯一数据存储,必须定期备份!

bash 复制代码
# === 方法1: 使用 etcdctl 备份 (推荐) ===

# 1. 安装 etcd-client
sudo apt-get install -y etcd-client

# 2. 执行备份
sudo ETCDCTL_API=3 etcdctl snapshot save /backup/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

# 3. 验证备份文件
sudo ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-snapshot-*.db

# 预期输出:
# Deprecated: A future release will stop checking for this flag. Please use --write-out/-w
# 2025-xx-xx ...
# Snapshot status as of 2025-xx-xx ...
# Hash:  xxxxxxxxxxxxxxxx
# Revision:  xxxxx
# Total Keys:  xxxxx
# Total Size:  x.x MiB

自动化备份脚本 (/usr/local/bin/etcd-backup.sh):

bash 复制代码
#!/bin/bash
# etcd 自动备份脚本
BACKUP_DIR="/backup/etcd"
mkdir -p $BACKUP_DIR
DATE=$(date +%Y%m%d-%H%M%S)
SNAPSHOT="${BACKUP_DIR}/etcd-snapshot-${DATE}.db"

echo "[$(date)] Starting etcd backup..."
sudo ETCDCTL_API=3 etcdctl snapshot save $SNAPSHOT \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

if [ $? -eq 0 ]; then
  echo "[$(date)] Backup successful: $SNAPSHOT"
  # 保留最近 7 天的备份
  find $BACKUP_DIR -name "etcd-snapshot-*.db" -mtime +7 -delete
else
  echo "[$(date)] Backup FAILED!"
  exit 1
fi

设置定时备份 (每天凌晨 2 点):

bash 复制代码
# 添加 cron 任务
echo "0 2 * * * /usr/local/bin/etcd-backup.sh >> /var/log/etcd-backup.log 2>&1" \
  | sudo crontab -

13.4 Kubernetes 版本升级实战

⚠️ 升级前必须备份 etcd! 升级有风险,操作需谨慎。

升级策略 :逐版本升级,例如 v1.32.13v1.33.x (不能跨次要版本升级)。

13.4.1 升级 Master 节点
bash 复制代码
# 1. 查看当前版本
kubectl version --short

# 2. 查看可用版本
sudo apt-get update
apt-cache madison kubeadm | head -10

# 3. 升级 kubeadm (在所有 Master 节点上)
sudo apt-get install -y kubeadm=1.33.0-1.1 kubelet=1.33.0-1.1 kubectl=1.33.0-1.1
sudo apt-mark hold kubelet kubeadm kubectl

# 4. 验证 kubeadm 版本
kubeadm version

# 5. 检查升级计划
sudo kubeadm upgrade plan

# 预期输出:
# [upgrade/config] Making sure the configuration is correct
# [upgrade] Running pre-flight checks
# [upgrade] Making sure the cluster is healthy
# [upgrade] Fetching available versions to upgrade to
# [upgrade/versions] Target version: v1.33.0
# [upgrade/versions] Latest version in the v1.32 series: v1.32.13
# ...
# Components with upgrade available:
# COMPONENT            CURRENT   AVAILABLE
# kube-apiserver      v1.32.13  v1.33.0
# ...

# 6. 执行控制平面升级
sudo kubeadm upgrade apply v1.33.0

# 7. 手动升级 kubelet 配置
sudo systemctl daemon-reload
sudo systemctl restart kubelet

# 8. 取消 Master 节点的调度保护 (以便升级时排空 Pod)
kubectl uncordon kuboard-01
13.4.2 升级 Worker 节点
bash 复制代码
# 在**每个 Worker 节点**上执行:

# 1. 标记节点为不可调度并驱逐 Pod
kubectl drain kuboard-02 --ignore-daemonsets --delete-emptydir-data

# 2. 升级 kubeadm/kubelet/kubectl
sudo apt-get install -y kubeadm=1.33.0-1.1 kubelet=1.33.0-1.1 kubectl=1.33.0-1.1
sudo apt-mark hold kubelet kubeadm kubectl

# 3. 升级 kubelet 配置
sudo systemctl daemon-reload
sudo systemctl restart kubelet

# 4. 恢复节点可调度
kubectl uncordon kuboard-02

# 5. 验证节点版本
kubectl get nodes -o wide

13.5 资源管理:ResourceQuota 和 LimitRange

13.5.1 设置命名空间资源配额 (ResourceQuota)
yaml 复制代码
# resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: production
spec:
  hard:
    requests.cpu: "4"        # CPU 请求总量上限
    requests.memory: 8Gi      # 内存请求总量上限
    limits.cpu: "8"          # CPU 限制总量上限
    limits.memory: 16Gi       # 内存限制总量上限
    pods: "20"               # Pod 数量上限
    services: "10"           # Service 数量上限
    secrets: "20"            # Secret 数量上限
    configmaps: "20"         # ConfigMap 数量上限
bash 复制代码
kubectl apply -f resource-quota.yaml
kubectl describe resourcequota -n production
13.5.2 设置默认资源限制 (LimitRange)
yaml 复制代码
# limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: production
spec:
  limits:
  - default:              # 默认限制 (Limit)
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:        # 默认请求 (Request)
      cpu: "100m"
      memory: "128Mi"
    type: Container
bash 复制代码
kubectl apply -f limit-range.yaml
kubectl describe limitrange -n production

13.6 通过 Kuboard 管理应用 (实战演示)

13.6.1 创建 Nginx 部署 (通过 Kuboard Web UI)
复制代码
步骤详解:

1. 登录 Kuboard → 点击左侧 "工作负载" → "部署" → "创建"

2. 填写基本信息:
   - 名称 (Name): nginx-deployment
   - 命名空间 (Namespace): default
   - 副本数 (Replicas): 3

3. 添加容器:
   - 容器名称: nginx
   - 镜像: nginx:1.27
   - 拉取策略: IfNotPresent
   - 容器端口: 80 (HTTP)

4. 配置资源限制:
   - CPU 请求: 100m
   - CPU 限制: 500m
   - 内存请求: 128Mi
   - 内存限制: 512Mi

5. 配置健康检查:
   - 存活探针 (LivenessProbe): HTTP GET / 端口 80, 初始延迟 30s
   - 就绪探针 (ReadinessProbe): HTTP GET / 端口 80, 初始延迟 5s

6. 点击 "完成",等待部署完成

7. 验证:
   kubectl get deployment nginx-deployment
   kubectl get pods -l app=nginx-deployment
13.6.2 创建 Service 暴露服务
复制代码
1. 在 Kuboard 中,点击左侧 "网络" → "服务" → "创建"

2. 填写基本信息:
   - 名称: nginx-service
   - 命名空间: default
   - 类型: NodePort

3. 配置端口映射:
   - 端口名称: http
   - 协议: TCP
   - 服务端口: 80
   - 目标端口: 80
   - NodePort: 30001

4. 选择 Pod 选择器 (Selector):
   - app: nginx-deployment

5. 点击 "完成"

6. 验证访问:
   curl http://192.168.0.85:30001
   # 应返回 Nginx 默认页面

13.7 实用 kubectl 别名配置 (提升效率)

编辑 ~/.bashrc~/.zshrc,添加以下别名:

bash 复制代码
# kubectl 别名 (k = kubectl)
alias k='kubectl'
alias kgp='kubectl get pods'
alias kgpa='kubectl get pods -A'
alias kgs='kubectl get svc'
alias kgn='kubectl get nodes'
alias kd='kubectl describe'
alias kl='kubectl logs'
alias kex='kubectl exec -it'
alias kdelf='kubectl delete -f'
alias kaf='kubectl apply -f'

# 自动补全 (bash)
source <(kubectl completion bash)
complete -F __start_kubectl k

# 自动补全 (zsh)
# source <(kubectl completion zsh)

使用示例

bash 复制代码
k get pods                    # = kubectl get pods
k describe pod nginx-xxxx     # = kubectl describe pod nginx-xxxx
k logs -f nginx-xxxx          # = kubectl logs -f nginx-xxxx
k exec -it nginx-xxxx -- bash # = kubectl exec -it nginx-xxxx -- bash

13.8 集群安全加固建议

安全项 措施 命令/配置
API Server 访问控制 限制 API Server 6443 端口仅对管理 IP 开放 华为云安全组配置
etcd 加密 启用 etcd 静态加密 (Secret 数据加密) kubeadm init 时配置 EncryptionConfiguration
Pod 安全策略 使用 Pod Security Admission (PSA) 命名空间标签 pod-security.kubernetes.io/enforce=restricted
网络策略 配置 NetworkPolicy 限制 Pod 间通信 见下方 YAML 示例
镜像安全 使用私有镜像仓库 + 镜像签名验证 配置 ImagePolicyWebhook
RBAC 最小权限 避免使用 cluster-admin,按需授权 创建专属 Role/ClusterRole

NetworkPolicy 示例 (限制只允许特定 Pod 访问数据库):

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-access-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: mysql
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: app-frontend
    ports:
    - protocol: TCP
      port: 3306

总结

本文从零开始,在 4 台华为云 ECS 服务器上完成了:

  1. 系统环境初始化 (hostname, swap, 内核模块, sysctl)
  2. containerd 安装与配置 (SystemdCgroup, 国内镜像加速)
  3. Kubernetes v1.32.13 集群搭建 (kubeadm init + Flannel + Worker join)
  4. Kuboard v3 部署 (华为云 SWR 镜像, NodePort 30080)
  5. 踩坑记录与解决方案 (6 个真实踩坑记录)

集群访问信息

  • Kubernetes API Server : https://120.46.195.39:6443
  • Kuboard Web UI : http://120.46.195.39:30080
  • 默认账号 : admin / Kuboard123

后续学习方向

  • 部署 Ingress Controller (Nginx Ingress / Traefik)
  • 配置 StorageClass (持久化存储)
  • 部署监控栈 (Prometheus + Grafana + AlertManager)
  • 配置 CI/CD (Jenkins / GitLab Runner)
  • 多 Master 高可用部署

文档版本 : v1.0 | 最后更新 : 2025年 | 适用 K8s 版本 : v1.32.x

反馈与问题: 请在 Kuboard 官方社区或 GitHub Issues 反馈


常见问题 FAQ (Frequently Asked Questions)

Q1: kubeadm init 时镜像拉取超时怎么办?

A : 这是国内服务器访问 registry.k8s.io 不通导致的。解决方案:

  1. 使用阿里云镜像:--image-repository=registry.aliyuncs.com/google_containers
  2. 如果使用配置文件,设置 imageRepository: "registry.aliyuncs.com/google_containers"
  3. 确保 containerd 的 mirror 配置正确(见第 11 章)

Q2: Flannel Pod 一直 Init:0/1ImagePullBackOff

A : 通常是 ghcr.io 镜像拉取失败(国内网络问题)。解决方案:

  1. 修改 kube-flannel.yml,将 ghcr.io/flannel-io/flannel 替换为 docker.rainbond.cc/flannel-io/flannel
  2. 或者手动拉取镜像后导出,再通过 ctr import 导入到所有节点
  3. 检查 /opt/cni/bin/ 下是否存在 bridgehost-local CNI 插件

Q3: Worker 节点加入集群后一直是 NotReady

A: 可能原因:

  1. Flannel DaemonSet 没有调度到该 Worker 节点 → 检查 kubectl get pods -n kube-flannel -o wide
  2. containerd SystemdCgroup 未设置为 true → 检查 /etc/containerd/config.toml
  3. 防火墙 UDP 8472 (VXLAN) 未开放 → 放行 VXLAN 端口

Q4: Kuboard Pod 无法调度到 Master 节点?

A : Master 节点默认有 node-role.kubernetes.io/control-plane:NoSchedule 污点。解决方案:

在 Kuboard 的 Deployment YAML 中添加 tolerations

yaml 复制代码
tolerations:
- key: "node-role.kubernetes.io/control-plane"
  operator: "Exists"
  effect: "NoSchedule"

Q5: 如何彻底卸载 K8s 集群?

A: 在所有节点上执行:

bash 复制代码
sudo kubeadm reset --force
sudo rm -rf /etc/kubernetes /var/lib/etcd /var/lib/kubelet ~/.kube
sudo apt-get purge -y kubelet kubeadm kubectl
sudo apt-get autoremove -y
sudo systemctl restart containerd

Q6: 生产环境有哪些必须做的安全加固?

A:

  1. API Server 6443 端口仅对管理 IP 开放(安全组规则)
  2. 立即修改 Kuboard 默认密码 (Kuboard123)
  3. 为不同团队创建专属 RBAC 账号,避免使用 cluster-admin
  4. 启用 etcd 静态加密(加密 Secret 数据)
  5. 配置 Pod Security Admission (PSA),限制特权容器
  6. 定期备份 etcd 数据(见第 13 章)

本文档持续更新,欢迎提交 PR 或 Issue 反馈问题。

相关推荐
友莘居士4 小时前
KingbaseES Docker速查表
运维·docker·容器
小肥君5 小时前
docker镜像配置
运维·docker·容器
某林2127 小时前
Isaac Lab (v2.3.2) Docker 本地化部署与底层排障全解析
运维·docker·容器·架构·iassc
iDao技术魔方9 小时前
WSL 配 GPU 用 Docker 的折腾指南(2026 年版)
运维·docker·容器
跳动的世界线9 小时前
WSL 2 + Docker 本地全栈开发环境配置指南
运维·docker·容器
xiaogg367810 小时前
Rancher2.0搭建kubernetes(K8S)集群
云原生·容器·kubernetes
成为你的宁宁10 小时前
【基于 Prometheus Operator 监控 K8s控制器、调度器、代理组件】
kubernetes·prometheus
IT策士10 小时前
第 44篇 k8s之实战:将 Web 应用迁移到 Kubernetes(上)
前端·容器·kubernetes