Kubernetes 集群安装指南(2 节点架构)

Kubernetes 集群安装指南(2 节点架构)

本文档详细介绍如何在 2 个节点(1 master + 1 node)上安装 Kubernetes 集群。

文档内容详尽,适合新手从零开始部署。


⚠️ 版本说明(2026年6月更新)

Kubernetes 版本会持续更新,本文档以 v1.33.12 为示例版本。

当前可用版本:v1.36.1、v1.35.5、v1.34.8、v1.33.12

请根据实际需求选择版本,建议使用稳定版本。安装时将文档中的 v1.33.12 替换为您选择的版本号即可。


目录

  1. 架构概述
  2. 系统要求
  3. 环境准备
  4. [安装 Containerd](#安装 Containerd)
  5. [安装 Kubernetes 组件](#安装 Kubernetes 组件)
  6. [初始化 Master 节点](#初始化 Master 节点)
  7. [加入 Worker 节点](#加入 Worker 节点)
  8. 安装网络插件
  9. 验证集群
  10. 常见问题排查

1. 架构概述

1.1 集群架构图

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                      Kubernetes 集群                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   ┌────────────────────────┐    ┌────────────────────────┐      │
│   │       master1          │    │        node1           │      │
│   │     (控制面节点)         │    │     (工作节点)          │      │
│   ├────────────────────────┤    ├────────────────────────┤      │
│   │                        │    │                        │      │
│   │  ┌──────────────────┐  │    │  ┌──────────────────┐  │      │
│   │  │   kube-apiserver  │  │    │  │    kubelet       │  │      │
│   │  │   (API 服务)       │  │    │  │   (节点代理)      │  │      │
│   │  └──────────────────┘  │    │  └──────────────────┘  │      │
│   │                        │    │                        │      │
│   │  ┌──────────────────┐  │    │  ┌──────────────────┐  │      │
│   │  │  kube-scheduler  │  │    │  │  kube-proxy      │  │      │
│   │  │   (调度器)         │  │    │  │  (网络代理)       │  │      │
│   │  └──────────────────┘  │    │  └──────────────────┘  │      │
│   │                        │    │                        │      │
│   │  ┌──────────────────┐  │    │  ┌──────────────────┐  │      │
│   │  │ kube-controller  │  │    │  │  containerd      │  │      │
│   │  │   (控制器)         │  │    │  │  (容器运行时)     │  │      │
│   │  └──────────────────┘  │    │  └──────────────────┘  │      │
│   │                        │    │                        │      │
│   │  ┌──────────────────┐  │    │  ┌──────────────────┐  │      │
│   │  │      etcd         │  │    │  │     Pods         │  │      │
│   │  │  (数据存储)        │  │    │  │   (工作负载)      │  │      │
│   │  └──────────────────┘  │    │  └──────────────────┘  │      │
│   │                        │    │                        │      │
│   └────────────────────────┘    └────────────────────────┘      │
│                                                                  │
│   IP: 192.168.x.x                    IP: 192.168.x.y             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

1.2 组件说明

组件 所在节点 说明
kube-apiserver master Kubernetes API 入口,所有操作都通过它
kube-scheduler master 负责调度 Pod 到合适的节点
kube-controller-manager master 运行控制器,维护集群状态
etcd master 分布式键值存储,保存集群所有数据
kubelet master + node 节点代理,管理本节点上的 Pod
kube-proxy master + node 网络代理,实现 Service 功能
containerd master + node 容器运行时,负责运行容器

1.3 节点角色

节点 角色 职责
master1 控制面 (Control Plane) 管理集群状态、调度、API 服务
node1 工作节点 (Worker Node) 运行应用 Pod

2. 系统要求

2.1 硬件要求

节点 CPU 内存 磁盘
master1 ≥ 2 核 ≥ 4 GB ≥ 50 GB
node1 ≥ 2 核 ≥ 4 GB ≥ 100 GB

2.2 软件要求

项目 要求
操作系统 Ubuntu 20.04/22.04、CentOS 7/8、Debian 10+
内核版本 ≥ 4.18(推荐 5.x)
架构 amd64 或 arm64

2.3 网络要求

项目 要求
节点互通 所有节点之间网络互通
端口开放 见下方端口表
唯一 IP 每个节点有唯一 IP 地址
主机名 每个节点有唯一主机名

2.4 端口要求

Master 节点端口:

端口 协议 组件 说明
6443 TCP kube-apiserver API Server(必须开放)
2379-2380 TCP etcd etcd 服务端口
10250 TCP kubelet Kubelet API
10251 TCP kube-scheduler Scheduler
10252 TCP kube-controller Controller Manager
10257 TCP kube-controller Controller Manager (v1.22+)
10259 TCP kube-scheduler Scheduler (v1.22+)

Worker 节点端口:

端口 协议 组件 说明
10250 TCP kubelet Kubelet API
10256 TCP kube-proxy Kube Proxy
30000-32767 TCP NodePort NodePort Service 端口范围

3. 环境准备

⚠️ 重要 :以下步骤需要在 所有节点(master1 和 node1)上执行!

3.1 登录节点

bash 复制代码
# 登录 master 节点
ssh root@master1_ip

# 登录 worker 节点
ssh root@node1_ip

3.2 设置主机名

在 master1 上执行:

bash 复制代码
hostnamectl set-hostname master1

# 验证
hostname
# 输出: master1

在 node1 上执行:

bash 复制代码
hostnamectl set-hostname node1

# 验证
hostname
# 输出: node1

3.3 配置 hosts 文件

在所有节点上执行:

bash 复制代码
# 编辑 hosts 文件
cat >> /etc/hosts << EOF
192.168.x.x  master1
192.168.y.y  node1
EOF

⚠️ 注意 :将 192.168.x.x192.168.y.y 替换为实际的 IP 地址。

验证:

bash 复制代码
# 测试解析
ping master1
ping node1

3.4 关闭 Swap

为什么要关闭 Swap?

原因 说明
性能 Swap 会导致内存交换,影响 Kubernetes 性能
调度 Kubernetes 调度器假设节点有固定内存
官方要求 Kubernetes 官方文档明确要求

执行关闭:

bash 复制代码
# 1. 立即关闭所有 swap
swapoff -a

# 2. 永久关闭(修改 fstab)
sed -i 's|^/swap.img|# /swap.img|' /etc/fstab
# 或者注释所有 swap 行
sed -i '/swap/s/^/#/' /etc/fstab

# 3. 验证(Swap 应该为 0)
free -h | grep Swap
# 期望输出: Swap:            0B          0B          0B

3.5 关闭防火墙

Ubuntu/Debian:

bash 复制代码
# 检查防火墙状态
ufw status

# 关闭防火墙
ufw disable

# 验证
ufw status
# 输出: Status: inactive

CentOS/RHEL:

bash 复制代码
# 停止并禁用防火墙
systemctl stop firewalld
systemctl disable firewalld

# 验证
systemctl status firewalld

💡 提示:如果生产环境需要防火墙,请配置规则开放所需端口,而不是直接关闭。

3.6 关闭 SELinux(CentOS/RHEL)

bash 复制代码
# 临时关闭
setenforce 0

# 永久关闭
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

# 验证
getenforce
# 输出: Disabled 或 Permissive

3.7 时间同步

为什么需要时间同步?

核心目的:保证所有节点时间一致。

场景 如果时间不同步会发生什么
TLS 证书验证 证书有效期验证失败,导致节点无法加入集群
日志分析 不同节点日志时间戳对不上,排查问题困难
调度决策 调度器可能做出错误判断
etcd 数据 分布式数据一致性出问题
时间同步示意图
复制代码
时间同步的作用:
──────────────────────────────────────────────
master1 时间: 2026-06-17 10:00:00
node1    时间: 2026-06-17 10:00:00  ← 必须一致
──────────────────────────────────────────────

如果不一致:
──────────────────────────────────────────────
master1 时间: 2026-06-17 10:00:00
node1    时间: 2026-06-17 09:50:00  ← 相差 10 分钟
──────────────────────────────────────────────
→ TLS 证书验证失败
→ 节点无法加入集群
→ 日志时间戳错乱
安装并配置 NTP:
bash 复制代码
# Ubuntu/Debian
apt update
apt install -y chrony

# CentOS/RHEL
yum install -y chrony

配置时间同步服务器:

bash 复制代码
# 编辑配置文件
cat > /etc/chrony/chrony.conf << EOF
server ntp.aliyun.com iburst
server ntp.tencent.com iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
logdir /var/log/chrony
EOF

# 重启服务
systemctl restart chronyd
systemctl enable chronyd

# 验证时间同步
chronyc sources -v

手动同步时间(可选):

bash 复制代码
# 安装 ntpdate
apt install -y ntpdate   # Ubuntu/Debian
yum install -y ntpdate   # CentOS/RHEL

# 同步时间
ntpdate ntp.aliyun.com

# 查看时间
date
简化验证
bash 复制代码
# 在 master1 上查看时间
date

# 在 node1 上查看时间
date

# 两者时间应该基本一致(误差最好在 1 秒内)
结论
场景 建议
生产环境 使用 chrony 自动同步,长期保持一致
测试环境 手动同步一次即可,或简单验证时间一致
时间误差要求 最好在 1 秒内,最多不超过几分钟

💡 一句话理解:时间同步的核心目的就是保证所有节点时间一致,防止 TLS 证书验证失败和日志时间戳错乱。


3.8 配置内核参数

为什么要配置?

Kubernetes 需要特定的内核参数来支持:

  • 网络功能(网桥、IP 转发)
  • 容器网络通信

执行配置:

bash 复制代码
# 加载必要的内核模块
cat << EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

# 立即加载模块
modprobe overlay
modprobe br_netfilter

# 验证模块加载
lsmod | grep -E "overlay|br_netfilter"

配置内核网络参数:

bash 复制代码
# 设置 sysctl 参数
cat << EOF | tee /etc/sysctl.d/k8s.conf
# 网桥网络调用 iptables
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
# IPv4 转发
net.ipv4.ip_forward                 = 1
# 禁用 IPv6(可选)
net.ipv6.conf.all.disable_ipv6      = 1
EOF

# 应用配置
sysctl --system

# 验证关键参数
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.bridge.bridge-nf-call-ip6tables
sysctl net.ipv4.ip_forward
# 以上三个参数都应该输出 1

3.9 环境准备验证脚本

一键验证脚本:

bash 复制代码
#!/bin/bash
echo "========== 环境检查 =========="

# 检查 Swap
echo -e "\n[1] Swap 状态:"
swap_total=$(free -m | awk '/Swap/{print $2}')
if [ "$swap_total" -eq 0 ]; then
    echo "✅ Swap 已关闭"
else
    echo "❌ Swap 未关闭,当前: ${swap_total}MB"
fi

# 检查防火墙
echo -e "\n[2] 防火墙状态:"
if command -v ufw &> /dev/null; then
    ufw_status=$(ufw status | grep -o "inactive\|active")
    [ "$ufw_status" == "inactive" ] && echo "✅ UFW 已关闭" || echo "❌ UFW 未关闭"
elif command -v firewall-cmd &> /dev/null; then
    fw_status=$(systemctl is-active firewalld)
    [ "$fw_status" == "inactive" ] && echo "✅ Firewalld 已关闭" || echo "❌ Firewalld 未关闭"
else
    echo "✅ 未检测到防火墙"
fi

# 检查内核模块
echo -e "\n[3] 内核模块:"
lsmod | grep -q overlay && echo "✅ overlay 已加载" || echo "❌ overlay 未加载"
lsmod | grep -q br_netfilter && echo "✅ br_netfilter 已加载" || echo "❌ br_netfilter 未加载"

# 检查内核参数
echo -e "\n[4] 内核参数:"
[ "$(sysctl -n net.bridge.bridge-nf-call-iptables)" -eq 1 ] && echo "✅ bridge-nf-call-iptables = 1" || echo "❌ bridge-nf-call-iptables 未设置"
[ "$(sysctl -n net.ipv4.ip_forward)" -eq 1 ] && echo "✅ ip_forward = 1" || echo "❌ ip_forward 未设置"

# 检查时间同步
echo -e "\n[5] 时间同步:"
systemctl is-active chronyd &> /dev/null && echo "✅ chrony 运行中" || echo "⚠️ chrony 未运行"

echo -e "\n========== 检查完成 =========="

保存并执行:

bash 复制代码
# 保存脚本
cat > /root/check_env.sh << 'EOF'
# ... 上面的脚本内容 ...
EOF

# 添加执行权限
chmod +x /root/check_env.sh

# 执行检查
/root/check_env.sh

4. 安装 Containerd

⚠️ 重要 :以下步骤需要在 所有节点 上执行!

4.1 Containerd 简介

什么是 Containerd?

Containerd 是一个工业级的容器运行时,它是 Kubernetes 运行容器所必需的组件。

复制代码
┌─────────────────────────────────────────────────────────────┐
│                      容器运行时架构                          │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   Kubernetes ──────► containerd ──────► runc ──────► 容器    │
│      (编排)            (运行时)        (执行)       (进程)    │
│                                                              │
└─────────────────────────────────────────────────────────────┘

为什么选择 Containerd?

原因 说明
官方推荐 Kubernetes 官方推荐的标准运行时
性能优秀 比 Docker 更轻量,性能更好
稳定可靠 由 CNCF 维护,生产级别稳定

4.2 安装 Containerd

Ubuntu/Debian:

bash 复制代码
# 更新软件源
apt update

# 安装依赖
apt install -y ca-certificates curl gnupg lsb-release

# 添加 Docker 官方 GPG 密钥
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 添加软件源
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

# 更新并安装 containerd
apt update
apt install -y containerd.io

CentOS/RHEL:

bash 复制代码
# 安装依赖
yum install -y yum-utils

# 添加 Docker 软件源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 安装 containerd
yum install -y containerd.io

验证安装:

bash 复制代码
# 查看版本
containerd --version

# 输出示例:
# containerd github.com/containerd/containerd v1.7.2 ...

4.3 配置 Containerd

生成默认配置:

bash 复制代码
# 创建配置目录
mkdir -p /etc/containerd

# 生成默认配置
containerd config default > /etc/containerd/config.toml

修改配置(重要):

bash 复制代码
# 编辑配置文件
vi /etc/containerd/config.toml

需要修改的内容:

toml 复制代码
# 1. 设置 SystemdCgroup = true(使用 systemd cgroup)
[plugins."io.containerd.grpc.v1.cri"]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd]
    ...
    [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
      ...
      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
        SystemdCgroup = true    # 改为 true

# 2. 设置 sandbox 镜像(国内网络需要修改)
[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"  # 使用阿里云镜像

一键配置脚本:

bash 复制代码
# 自动配置 containerd
cat > /etc/containerd/config.toml << EOF
version = 2

[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"

  [plugins."io.containerd.grpc.v1.cri".containerd]
    snapshotter = "overlayfs"

    [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

  [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://registry.aliyuncs.com"]
EOF

4.4 启动 Containerd

bash 复制代码
# 重启 containerd 服务
systemctl daemon-reload
systemctl restart containerd

# 设置开机自启
systemctl enable containerd

# 查看状态
systemctl status containerd

# 验证运行状态
# Active: active (running) 表示正常运行

4.5 安装 nerdctl(可选)

nerdctl 是 containerd 的命令行工具,类似 docker 命令:

bash 复制代码
# 下载 nerdctl
wget https://github.com/containerd/nerdctl/releases/download/v1.5.0/nerdctl-1.5.0-linux-amd64.tar.gz

# 解压
tar -xzf nerdctl-1.5.0-linux-amd64.tar.gz -C /usr/local/bin/

# 验证
nerdctl --version

5. 安装 Kubernetes 组件

⚠️ 重要 :以下步骤需要在 所有节点 上执行!

5.1 Kubernetes 组件说明

组件 说明 安装位置
kubeadm 集群初始化工具 所有节点
kubelet 节点代理,管理 Pod 所有节点
kubectl 命令行管理工具 master(可选 node)

5.2 添加 Kubernetes 软件源

Ubuntu/Debian:

bash 复制代码
# 更新软件源并安装依赖
apt update
apt install -y ca-certificates curl

# 添加 Kubernetes GPG 密钥
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# 添加软件源
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list

CentOS/RHEL:

bash 复制代码
# 添加 Kubernetes 软件源
cat << EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/repodata/repomd.xml.key
EOF

5.3 安装 Kubernetes 组件

Ubuntu/Debian:

bash 复制代码
# 更新软件源
apt update

# 安装 kubeadm、kubelet、kubectl
apt install -y kubeadm kubelet kubectl

# 设置 kubelet 开机自启
systemctl enable kubelet

CentOS/RHEL:

bash 复制代码
# 安装组件
yum install -y kubeadm kubelet kubectl

# 设置 kubelet 开机自启
systemctl enable kubelet

5.4 验证安装

bash 复制代码
# 查看版本
kubeadm version
kubelet --version
kubectl version --client

# 输出示例:
# kubeadm version: &version.Info{Major:"1", Minor:"28", ...}
# Kubernetes v1.33.x

5.5 配置镜像加速(可选但推荐)

由于国内网络原因,建议配置镜像加速:

bash 复制代码
# 查看需要的镜像
kubeadm config images list

# 输出示例:
# registry.k8s.io/kube-apiserver:v1.33.12
# registry.k8s.io/kube-controller-manager:v1.33.12
# ...

使用阿里云镜像:

bash 复制代码
# 拉取镜像(使用阿里云镜像源)
kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers

6. 初始化 Master 节点

⚠️ 重要 :以下步骤 只在 master1 上执行

6.1 初始化前检查

bash 复制代码
# 检查 kubelet 状态
systemctl status kubelet

# 检查 containerd 状态
systemctl status containerd

# 检查网络
ping node1

6.2 初始化集群

基础初始化命令:

bash 复制代码
# 初始化集群(替换为实际 IP)
kubeadm init \
  --apiserver-advertise-address=192.168.x.x \
  --image-repository registry.aliyuncs.com/google_containers \
  --kubernetes-version v1.33.12 \
  --service-cidr=10.96.0.0/12 \
  --pod-network-cidr=10.244.0.0/16

参数说明:

参数 说明
--apiserver-advertise-address API Server 监听地址(master 的 IP)
--image-repository 镜像仓库地址(国内使用阿里云)
--kubernetes-version Kubernetes 版本
--service-cidr Service 网段
--pod-network-cidr Pod 网段(需与 CNI 插件匹配)

6.3 初始化过程详解

执行初始化后,你会看到类似输出:

复制代码
[init] Using Kubernetes version: v1.33.12
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kube-apiserver to be up and running
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[mark-control-plane] Marking the node master1 as control-plane
[mark-control-plane] Marking the node master1 as control-plane by adding the labels: [node-role.kubernetes.io/control-plane]
[bootstraptoken] Using tokens: ["abcdef.0123456789abcdef"]
[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to get CSRs
[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs
[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 pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

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

kubeadm join 192.168.x.x:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

6.4 配置 kubectl

为 root 用户配置:

bash 复制代码
# 设置 KUBECONFIG 环境变量
export KUBECONFIG=/etc/kubernetes/admin.conf

# 永久配置(写入 bashrc)
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bashrc
source ~/.bashrc

为普通用户配置:

bash 复制代码
# 创建 .kube 目录
mkdir -p $HOME/.kube

# 复制配置文件
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

# 修改所有者
sudo chown $(id -u):$(id -g) $HOME/.kube/config

6.5 验证 Master 节点

bash 复制代码
# 查看节点状态
kubectl get nodes

# 输出示例:
# NAME      STATUS     ROLES           AGE   VERSION
# master1   NotReady   control-plane   1m    v1.33.12

# 查看集群组件状态
kubectl get cs

# 输出示例:
# NAME                 STATUS    MESSAGE            ERROR
# controller-manager   Healthy   ok
# scheduler            Healthy   ok
# etcd-0               Healthy   {"health":"true"}

# 查看 Pod 状态
kubectl get pods -n kube-system

# 输出示例:
# NAME                              READY   STATUS    RESTARTS   AGE
# coredns-xxxx-xxxx                 0/1     Pending   0          1m
# coredns-xxxx-xxxx                 0/1     Pending   0          1m
# etcd-master1                      1/1     Running   0          1m
# kube-apiserver-master1            1/1     Running   0          1m
# kube-controller-manager-master1   1/1     Running   0          1m
# kube-proxy-xxxx                   1/1     Running   0          1m
# kube-scheduler-master1            1/1     Running   0          1m

⚠️ 注意 :此时节点状态为 NotReady,CoreDNS 为 Pending,这是正常的,因为还没有安装网络插件。

6.6 保存 join 命令

重要!保存 node 加入集群的命令:

bash 复制代码
# 获取 join 命令
kubeadm token create --print-join-command

# 输出示例:
# kubeadm join 192.168.x.x:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:xxx

# 保存到文件
kubeadm token create --print-join-command > /root/k8s-join-command.sh
chmod +x /root/k8s-join-command.sh

7. 加入 Worker 节点

⚠️ 重要 :以下步骤 只在 node1 上执行

7.1 获取 join 命令

在 master1 上获取:

bash 复制代码
kubeadm token create --print-join-command

输出示例:

复制代码
kubeadm join 192.168.x.x:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

7.2 在 node1 上执行 join

bash 复制代码
# 执行 join 命令(从 master 获取的完整命令)
kubeadm join 192.168.x.x:6443 --token abcdef.0123456789abcdef \
        --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

成功输出:

复制代码
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config map with 'kubectl -n kube-system get cm kubeadm-config'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to 'apiserver' and a reply was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

7.3 验证节点加入

在 master1 上执行:

bash 复制代码
# 查看节点
kubectl get nodes

# 输出示例:
# NAME      STATUS     ROLES           AGE   VERSION
# master1   NotReady   control-plane   10m   v1.33.12
# node1     NotReady   <none>          1m    v1.33.12

⚠️ 注意 :节点状态仍为 NotReady,需要安装网络插件后才会变为 Ready


8. 安装网络插件

⚠️ 重要 :以下步骤 只在 master1 上执行

8.1 网络插件选择

插件 特点 适用场景
Calico 性能好,功能全,支持网络策略 生产环境推荐
Flannel 简单易用,资源占用少 开发测试推荐
Cilium 基于 eBPF,功能强大 高级网络需求

8.2 安装 Calico(推荐)

bash 复制代码
# 下载 Calico 配置文件
curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O

# 应用配置
kubectl apply -f calico.yaml

等待 Calico Pod 启动:

bash 复制代码
# 查看 Calico Pod 状态
kubectl get pods -n kube-system | grep calico

# 输出示例:
# calico-node-xxxxx                 1/1     Running   0          1m
# calico-kube-controllers-xxxxx     1/1     Running   0          1m

8.3 安装 Flannel(备选)

bash 复制代码
# 下载 Flannel 配置
curl https://raw.githubusercontent.com/flannel-io/flannel/v0.22.3/manifest/kube-flannel.yml -O

# 应用配置
kubectl apply -f kube-flannel.yml

8.4 验证网络插件

bash 复制代码
# 等待所有 Pod 运行
kubectl get pods -n kube-system

# 查看节点状态(应该变为 Ready)
kubectl get nodes

# 输出示例:
# NAME      STATUS   ROLES           AGE   VERSION
# master1   Ready    control-plane   15m   v1.33.12
# node1     Ready    <none>          5m    v1.33.12

9. 验证集群

9.1 检查集群状态

bash 复制代码
# 查看节点
kubectl get nodes -o wide

# 查看所有系统 Pod
kubectl get pods -n kube-system

# 查看组件状态
kubectl get cs

9.2 测试部署应用

创建测试 Deployment:

bash 复制代码
# 创建 nginx deployment
kubectl create deployment nginx --image=nginx

# 查看 deployment
kubectl get deployments

# 查看 pod
kubectl get pods

暴露服务:

bash 复制代码
# 暴露端口
kubectl expose deployment nginx --port=80 --type=NodePort

# 查看 service
kubectl get svc

# 输出示例:
# NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
# kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        20m
# nginx        NodePort    10.96.xxx.xxx   <none>        80:300xx/TCP   1m

访问测试:

bash 复制代码
# 获取 NodePort 端口
NODE_PORT=$(kubectl get svc nginx -o jsonpath='{.spec.ports[0].nodePort}')

# 访问测试(在任意节点执行)
curl http://node1:$NODE_PORT

# 或者直接访问
curl http://node1:300xx

9.3 查看集群信息

bash 复制代码
# 集群信息
kubectl cluster-info

# 输出示例:
# Kubernetes control plane is running at https://192.168.x.x:6443
# CoreDNS is running at https://192.168.x.x:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

# 查看资源使用
kubectl top nodes

# 查看所有资源
kubectl get all --all-namespaces

10. 常见问题排查

10.1 节点状态 NotReady

现象:

复制代码
kubectl get nodes
NAME      STATUS     ROLES           AGE   VERSION
master1   NotReady   control-plane   10m   v1.33.12

排查步骤:

bash 复制代码
# 1. 检查网络插件是否安装
kubectl get pods -n kube-system | grep -E "calico|flannel"

# 2. 检查 kubelet 日志
journalctl -u kubelet -f

# 3. 检查节点详情
kubectl describe node master1

10.2 Pod 状态 Pending

现象:

复制代码
kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
nginx-xxxxx-xxxx         0/1     Pending   0          5m

排查步骤:

bash 复制代码
# 查看 Pod 详情
kubectl describe pod nginx-xxxxx-xxxx

# 常见原因:
# - 网络插件未安装
# - 资源不足(CPU/内存)
# - PVC 未绑定

10.3 Image Pull Failed

现象:

复制代码
Failed to pull image "xxx": rpc error: code = Unknown desc = Error response from daemon: pull access denied

解决方案:

bash 复制代码
# 手动拉取镜像
crictl pull xxx

# 或使用国内镜像源
crictl pull registry.aliyuncs.com/google_containers/xxx

10.4 kubelet 启动失败

排查步骤:

bash 复制代码
# 查看 kubelet 状态
systemctl status kubelet

# 查看日志
journalctl -u kubelet -n 100

# 常见原因:
# - Swap 未关闭
# - containerd 未运行
# - 配置文件错误

10.5 重置集群

如果初始化失败,可以重置后重新初始化:

bash 复制代码
# 重置节点(在所有节点执行)
kubeadm reset -f

# 清理文件
rm -rf /etc/kubernetes/
rm -rf /var/lib/etcd/
rm -rf /var/lib/kubelet/
rm -rf $HOME/.kube/config

# 重启 containerd
systemctl restart containerd

附录 A:一键安装脚本

A.1 环境准备脚本

bash 复制代码
#!/bin/bash
# 文件名: prepare_env.sh
# 用途: 准备 Kubernetes 安装环境

set -e

echo "========== Kubernetes 环境准备 =========="

# 1. 关闭 Swap
echo "[1/7] 关闭 Swap..."
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab

# 2. 关闭防火墙
echo "[2/7] 关闭防火墙..."
if command -v ufw &> /dev/null; then
    ufw disable
fi
if command -v firewall-cmd &> /dev/null; then
    systemctl stop firewalld
    systemctl disable firewalld
fi

# 3. 配置内核模块
echo "[3/7] 配置内核模块..."
cat << EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter

# 4. 配置内核参数
echo "[4/7] 配置内核参数..."
cat << EOF | 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
sysctl --system

# 5. 时间同步
echo "[5/7] 配置时间同步..."
apt install -y chrony || yum install -y chrony
systemctl restart chronyd
systemctl enable chronyd

# 6. 安装 containerd
echo "[6/7] 安装 containerd..."
apt install -y containerd.io || yum install -y containerd.io
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd
systemctl enable containerd

# 7. 安装 Kubernetes 组件
echo "[7/7] 安装 Kubernetes 组件..."
apt install -y kubeadm kubelet kubectl || yum install -y kubeadm kubelet kubectl
systemctl enable kubelet

echo "========== 环境准备完成 =========="
echo "请执行 kubeadm init 初始化集群"

A.2 Master 初始化脚本

bash 复制代码
#!/bin/bash
# 文件名: init_master.sh
# 用途: 初始化 Kubernetes Master 节点

set -e

# 配置变量
MASTER_IP="${1:-$(hostname -I | awk '{print $1}')}"
K8S_VERSION="${2:-v1.33.12}"
POD_CIDR="${3:-10.244.0.0/16}"

echo "========== 初始化 Master 节点 =========="
echo "Master IP: $MASTER_IP"
echo "K8s Version: $K8S_VERSION"
echo "Pod CIDR: $POD_CIDR"

# 初始化集群
kubeadm init \
  --apiserver-advertise-address=$MASTER_IP \
  --image-repository registry.aliyuncs.com/google_containers \
  --kubernetes-version $K8S_VERSION \
  --pod-network-cidr=$POD_CIDR

# 配置 kubectl
export KUBECONFIG=/etc/kubernetes/admin.conf
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bashrc

# 保存 join 命令
kubeadm token create --print-join-command > /root/k8s-join-command.sh
chmod +x /root/k8s-join-command.sh

echo "========== Master 初始化完成 =========="
echo "Join 命令已保存到: /root/k8s-join-command.sh"

附录 B:常用命令速查

命令 说明
kubectl get nodes 查看节点
kubectl get pods -A 查看所有 Pod
kubectl get svc -A 查看所有 Service
kubectl describe node <name> 查看节点详情
kubectl describe pod <name> 查看 Pod 详情
kubectl logs <pod> 查看 Pod 日志
kubectl exec -it <pod> -- bash 进入 Pod
kubectl apply -f xxx.yaml 应用配置
kubectl delete -f xxx.yaml 删除资源
kubeadm token create --print-join-command 获取 join 命令
kubeadm reset -f 重置节点

附录 C:离线安装指南

本章节详细介绍如何在无网络环境下安装 Kubernetes 集群。

C.1 离线安装概述

适用场景
场景 说明
内网环境 服务器无法访问外网
安全要求 生产环境不允许连接互联网
批量部署 多套环境统一安装包
离线安装流程图
复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                          离线安装流程                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  ┌─────────────────┐      ┌─────────────────┐      ┌─────────────────┐ │
│  │  第一步:准备    │      │  第二步:传输    │      │  第三步:安装    │ │
│  │  (有网机器)     │      │  (移动介质)     │      │  (无网机器)     │ │
│  └────────┬────────┘      └────────┬────────┘      └────────┬────────┘ │
│           │                        │                        │          │
│           ▼                        ▼                        ▼          │
│  ┌─────────────────┐      ┌─────────────────┐      ┌─────────────────┐ │
│  │ • 下载系统包     │      │ • 打包离线文件   │      │ • 安装 RPM/DEB  │ │
│  │ • 下载 K8s 组件  │  ──► │ • 拷贝到 U 盘   │  ──► │ • 导入容器镜像  │ │
│  │ • 下载容器镜像   │      │   或内网传输    │      │ • 初始化集群    │ │
│  └─────────────────┘      └─────────────────┘      └─────────────────┘ │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

C.2 在 Windows 上下载离线包(推荐)

💡 推荐场景:使用有网络的 Windows 电脑下载,然后传输到无网络的 Linux 服务器安装。

C.2.1 Windows 下载方式概述
复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                    Windows 下载离线包流程                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  ┌─────────────────┐      ┌─────────────────┐      ┌─────────────────┐ │
│  │  Windows 电脑   │      │   移动介质       │      │  Linux 服务器   │ │
│  │  (有网络)       │      │  (U盘/移动硬盘)  │      │  (无网络)       │ │
│  └────────┬────────┘      └────────┬────────┘      └────────┬────────┘ │
│           │                        │                        │          │
│           ▼                        ▼                        ▼          │
│  ┌─────────────────┐      ┌─────────────────┐      ┌─────────────────┐ │
│  │ • 浏览器下载     │      │ • 复制整个目录   │      │ • 解压安装包    │ │
│  │ • 下载工具下载   │  ──► │   到移动介质    │  ──► │ • 执行安装脚本  │ │
│  │ • 直链批量下载   │      │ • 或网络传输    │      │ • 导入镜像      │ │
│  └─────────────────┘      └─────────────────┘      └─────────────────┘ │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘
C.2.2 创建 Windows 目录结构

在 Windows 上创建以下目录结构:

复制代码
D:\k8s-offline\
├── packages\
│   ├── ubuntu\                    # Ubuntu/Debian 安装包
│   ├── centos\                    # CentOS/RHEL 安装包
│   ├── containerd\                # Containerd 安装包
│   └── kubernetes\                # Kubernetes 组件
├── images\                        # 容器镜像 tar 包
├── scripts\                       # 安装脚本
└── configs\                       # 配置文件

创建目录(PowerShell):

powershell 复制代码
# 在 PowerShell 中执行
$basePath = "D:\k8s-offline"

# 创建目录结构
New-Item -ItemType Directory -Path "$basePath\packages\ubuntu" -Force
New-Item -ItemType Directory -Path "$basePath\packages\centos" -Force
New-Item -ItemType Directory -Path "$basePath\packages\containerd" -Force
New-Item -ItemType Directory -Path "$basePath\packages\kubernetes" -Force
New-Item -ItemType Directory -Path "$basePath\images" -Force
New-Item -ItemType Directory -Path "$basePath\scripts" -Force
New-Item -ItemType Directory -Path "$basePath\configs" -Force

# 查看目录结构
Get-ChildItem -Path $basePath -Recurse -Directory
C.2.3 下载 Containerd 安装包

Ubuntu/Debian (amd64 架构):

组件 下载地址
containerd.io https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/containerd.io_1.7.2-1_amd64.deb
containerd.io (arm64) https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/arm64/containerd.io_1.7.2-1_arm64.deb

CentOS/RHEL 8 (x86_64 架构):

组件 下载地址
containerd.io https://download.docker.com/linux/centos/8/x86_64/stable/Packages/containerd.io-1.7.2-3.1.el8.x86_64.rpm
containerd.io (aarch64) https://download.docker.com/linux/centos/8/aarch64/stable/Packages/containerd.io-1.7.2-3.1.el8.aarch64.rpm

使用 PowerShell 批量下载:

powershell 复制代码
# 设置下载目录
$downloadPath = "D:\k8s-offline\packages\containerd"

# Ubuntu 22.04 amd64 下载链接
$ubuntuUrls = @(
    "https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/containerd.io_1.7.2-1_amd64.deb"
)

# CentOS 8 x86_64 下载链接
$centosUrls = @(
    "https://download.docker.com/linux/centos/8/x86_64/stable/Packages/containerd.io-1.7.2-3.1.el8.x86_64.rpm"
)

# 下载 Ubuntu 包
foreach ($url in $ubuntuUrls) {
    $fileName = Split-Path $url -Leaf
    $output = Join-Path $downloadPath $fileName
    Write-Host "下载: $fileName"
    Invoke-WebRequest -Uri $url -OutFile $output
}

# 下载 CentOS 包
foreach ($url in $centosUrls) {
    $fileName = Split-Path $url -Leaf
    $output = Join-Path $downloadPath $fileName
    Write-Host "下载: $fileName"
    Invoke-WebRequest -Uri $url -OutFile $output
}

Write-Host "Containerd 下载完成!"
Get-ChildItem $downloadPath
C.2.4 下载 Kubernetes 安装包

⚠️ 重要提示:Kubernetes 官方 CDN 有访问限制,推荐使用"在有网Linux机器上下载"或"下载二进制文件"方式。

方法1:在有网络的 Linux 机器上下载(推荐)

Ubuntu/Debian:

bash 复制代码
# 添加 Kubernetes 软件源
mkdir -p /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list

# 更新并下载
apt-get update
mkdir -p /root/k8s-packages
cd /root/k8s-packages

# 下载指定版本
apt-get download kubeadm=1.33.12-1.1
apt-get download kubelet=1.33.12-1.1
apt-get download kubectl=1.33.12-1.1

# 打包
tar -czvf k8s-packages.tar.gz *.deb

CentOS/RHEL:

bash 复制代码
# 添加 Kubernetes 软件源
cat << EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/
enabled=1
gpgcheck=0
EOF

# 下载
mkdir -p /root/k8s-packages
yumdownloader --destdir=/root/k8s-packages kubeadm-1.33.12-1.1
yumdownloader --destdir=/root/k8s-packages kubelet-1.33.12-1.1
yumdownloader --destdir=/root/k8s-packages kubectl-1.33.12-1.1

# 打包
cd /root/k8s-packages
tar -czvf k8s-packages.tar.gz *.rpm

方法2:下载二进制文件(Windows 可直接下载)

Kubernetes 官方提供二进制文件,无需通过包管理器。

官方下载站点:

网站 说明
https://dl.k8s.io/ Kubernetes 官方二进制文件下载站,可浏览所有版本
https://github.com/kubernetes/kubernetes/releases GitHub Release 页面

访问 https://dl.k8s.io/ 自行搜索下载步骤:

  1. 打开浏览器,访问 https://dl.k8s.io/

  2. 查看当前可用版本(截至 2026年6月):

    • v1.36.1(最新)
    • v1.35.5
    • v1.34.8
    • v1.33.12
  3. 目录结构说明:

    复制代码
    dl.k8s.io/
    ├── release/                    # 正式发布版本
    │   ├── v1.33.12/              # 具体版本(示例)
    │   │   └── bin/
    │   │       └── linux/
    │   │           ├── amd64/     # x86_64 架构
    │   │           │   ├── kubeadm
    │   │           │   ├── kubelet
    │   │           │   └── kubectl
    │   │           └── arm64/     # ARM64 架构
    │   │               ├── kubeadm
    │   │               ├── kubelet
    │   │               └── kubectl
    │   └── ...
    ├── ci/                         # CI 构建(开发测试用)
    └── stable.txt                  # 当前稳定版本号
  4. 点击进入对应版本目录,如 release/v1.33.12/bin/linux/amd64/arm64/

  5. 下载需要的文件:kubeadmkubeletkubectl

💡 提示:选择版本时建议使用稳定版本(如 v1.33.12),避免使用最新版本可能存在的不稳定问题。

直接下载地址(以 v1.33.12 为例):

组件 架构 下载地址
kubeadm amd64 https://dl.k8s.io/release/v1.33.12/bin/linux/amd64/kubeadm
kubelet amd64 https://dl.k8s.io/release/v1.33.12/bin/linux/amd64/kubelet
kubectl amd64 https://dl.k8s.io/release/v1.33.12/bin/linux/amd64/kubectl
kubeadm arm64 https://dl.k8s.io/release/v1.33.12/bin/linux/arm64/kubeadm
kubelet arm64 https://dl.k8s.io/release/v1.33.12/bin/linux/arm64/kubelet
kubectl arm64 https://dl.k8s.io/release/v1.33.12/bin/linux/arm64/kubectl

PowerShell 批量下载二进制文件:

powershell 复制代码
$downloadPath = "D:\k8s-offline\packages\kubernetes"
$version = "v1.33.12"  # 根据需要修改版本号,可选:v1.36.1, v1.35.5, v1.34.8, v1.33.12
$arch = "amd64"        # 改为 arm64 下载 ARM 版本

# 创建目录
New-Item -ItemType Directory -Path $downloadPath -Force | Out-Null

# 下载链接
$urls = @(
    "https://dl.k8s.io/release/$version/bin/linux/$arch/kubeadm",
    "https://dl.k8s.io/release/$version/bin/linux/$arch/kubelet",
    "https://dl.k8s.io/release/$version/bin/linux/$arch/kubectl"
)

Write-Host "========== 下载 Kubernetes 二进制文件 =========="

foreach ($url in $urls) {
    $fileName = Split-Path $url -Leaf
    $output = Join-Path $downloadPath $fileName

    Write-Host "下载: $fileName"
    try {
        Invoke-WebRequest -Uri $url -OutFile $output -ErrorAction Stop
        Write-Host "  ✓ 完成" -ForegroundColor Green
    } catch {
        Write-Host "  ✗ 失败: $_" -ForegroundColor Red
    }
}

Write-Host "`n下载完成!文件列表:"
Get-ChildItem $downloadPath

在目标 Linux 上安装二进制文件:

bash 复制代码
# 复制到系统目录
cp kubeadm kubelet kubectl /usr/local/bin/

# 添加执行权限
chmod +x /usr/local/bin/kubeadm /usr/local/bin/kubelet /usr/local/bin/kubectl

# 创建 kubelet systemd 服务(必须)
cat > /etc/systemd/system/kubelet.service << 'EOF'
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/
After=network.target

[Service]
ExecStart=/usr/local/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

# 重载 systemd
systemctl daemon-reload
systemctl enable kubelet

# 验证
kubeadm version
kubelet --version
kubectl version --client

方法3:使用阿里云镜像

bash 复制代码
# Ubuntu/Debian
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
echo 'deb https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main' | tee /etc/apt/sources.list.d/kubernetes.list

apt-get update
apt-get download kubeadm=1.33.12-00
apt-get download kubelet=1.33.12-00
apt-get download kubectl=1.33.12-00

Get-ChildItem $downloadPath

复制代码
#### C.2.5 下载 Kubernetes 依赖包(Ubuntu)

> ⚠️ **重要提示**:Ubuntu 依赖包版本会更新,建议使用"在有网Linux机器上下载"的方法最可靠。

**方法1:在有网络的 Linux 机器上下载(最可靠)**

```bash
# 在有网络的 Ubuntu 机器上执行
mkdir -p /root/ubuntu-deps
cd /root/ubuntu-deps

# 更新软件源
apt-get update

# 下载所有依赖
apt-get download conntrack
apt-get download libnetfilter-conntrack3
apt-get download libnfnetlink0
apt-get download socat
apt-get download ipset
apt-get download libipset13
apt-get download ebtables

# 下载依赖的依赖
apt-cache depends conntrack | grep Depends | awk '{print $2}' | xargs apt-get download
apt-cache depends ipset | grep Depends | awk '{print $2}' | xargs apt-get download

# 打包
tar -czvf ubuntu-deps.tar.gz *.deb

# 然后将 ubuntu-deps.tar.gz 拷贝到 Windows,再传输到目标 Linux

方法2:手动搜索下载

  1. 访问 Ubuntu Packages 网站:https://packages.ubuntu.com/
  2. 搜索以下包名:
依赖包 搜索关键词 说明
conntrack conntrack 连接追踪工具
libnetfilter-conntrack3 libnetfilter-conntrack conntrack 库依赖
libnfnetlink0 libnfnetlink 底层网络库
socat socat Socket 工具
ipset ipset IP 集合工具
libipset13 libipset ipset 库依赖
ebtables ebtables 以太网桥防火墙
  1. 选择对应版本(jammy=22.04, focal=20.04)和架构(amd64/arm64)
  2. 下载 .deb 文件

方法3:阿里云镜像浏览下载

访问:https://mirrors.aliyun.com/ubuntu/pool/main/

按目录浏览:

  • c/conntrack-tools/ - conntrack
  • s/socat/ - socat
  • i/ipset/ - ipset
  • e/ebtables/ - ebtables
C.2.6 下载 Kubernetes 依赖包(CentOS)

⚠️ 重要提示:CentOS 8 已停止维护,建议使用"在有网Linux机器上下载"的方法。

方法1:在有网络的 Linux 机器上下载(最可靠)

bash 复制代码
# 在有网络的 CentOS/RHEL 机器上执行
mkdir -p /root/centos-deps
cd /root/centos-deps

# 安装下载工具
yum install -y yum-utils

# 下载依赖包(自动解决依赖)
yumdownloader --resolve --destdir=/root/centos-deps conntrack
yumdownloader --resolve --destdir=/root/centos-deps socat
yumdownloader --resolve --destdir=/root/centos-deps ipset
yumdownloader --resolve --destdir=/root/centos-deps ebtables

# 打包
tar -czvf centos-deps.tar.gz *.rpm

# 然后将 centos-deps.tar.gz 拷贝到 Windows,再传输到目标 Linux

方法2:CentOS Vault 镜像(CentOS 8 已归档)

CentOS 8 包已迁移到 vault 仓库:

powershell 复制代码
$downloadPath = "D:\k8s-offline\packages\centos"

# 使用阿里云 vault 镜像
$centosUrls = @(
    "https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/Packages/conntrack-tools-1.4.4-10.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/Packages/libnetfilter_conntrack-1.0.6-5.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/Packages/libnfnetlink-1.0.1-7.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/Packages/socat-1.7.4.1-1.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/Packages/ipset-7.1-1.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/Packages/ipset-libs-7.1-1.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/Packages/ebtables-2.0.11-5.el8.x86_64.rpm"
)

foreach ($url in $centosUrls) {
    $fileName = Split-Path $url -Leaf
    $output = Join-Path $downloadPath $fileName

    Write-Host "下载: $fileName"
    try {
        Invoke-WebRequest -Uri $url -OutFile $output -ErrorAction Stop
        Write-Host "  ✓ 完成" -ForegroundColor Green
    } catch {
        Write-Host "  ✗ 失败,请手动下载" -ForegroundColor Red
        Write-Host "  访问: https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/Packages/"
    }
}

Get-ChildItem $downloadPath

方法3:使用 Rocky Linux 镜像(CentOS 兼容替代)

powershell 复制代码
$downloadPath = "D:\k8s-offline\packages\centos"

# Rocky Linux 8 与 CentOS 8 完全兼容
$rockyUrls = @(
    "https://mirrors.aliyun.com/rockylinux/8/BaseOS/x86_64/os/Packages/c/conntrack-tools-1.4.4-10.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/rockylinux/8/BaseOS/x86_64/os/Packages/l/libnetfilter_conntrack-1.0.6-5.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/rockylinux/8/BaseOS/x86_64/os/Packages/l/libnfnetlink-1.0.1-7.el8.x86_64.rpm",
    "https://mirrors.aliyun.com/rockylinux/8/BaseOS/x86_64/os/Packages/s/socat-1.7.4.1-1.el8.x86_64.rpm"
)

foreach ($url in $rockyUrls) {
    $fileName = Split-Path $url -Leaf
    $output = Join-Path $downloadPath $fileName

    Write-Host "下载: $fileName"
    try {
        Invoke-WebRequest -Uri $url -OutFile $output -ErrorAction Stop
        Write-Host "  ✓ 完成" -ForegroundColor Green
    } catch {
        Write-Host "  ✗ 失败: $_" -ForegroundColor Red
    }
}

方法4:pkgs.org 网站搜索下载

  1. 访问:https://pkgs.org/
  2. 搜索包名(如 conntrack-tools
  3. 选择 CentOS 8 或 Rocky Linux 8 版本
  4. 下载 RPM 包
C.2.7 下载容器镜像(使用 Docker Desktop)

前提条件:

  • 安装 Docker Desktop for Windows
  • Docker Desktop 已启动并运行

步骤1:拉取 Kubernetes 核心镜像

在 PowerShell 或 CMD 中执行:

powershell 复制代码
# 设置版本
$k8sVersion = "v1.33.12"

# 使用阿里云镜像加速
$registry = "registry.aliyuncs.com/google_containers"

# 拉取 Kubernetes 核心镜像
docker pull ${registry}/kube-apiserver:${k8sVersion}
docker pull ${registry}/kube-controller-manager:${k8sVersion}
docker pull ${registry}/kube-scheduler:${k8sVersion}
docker pull ${registry}/kube-proxy:${k8sVersion}
docker pull ${registry}/pause:3.9
docker pull ${registry}/etcd:3.5.9-0
docker pull ${registry}/coredns:v1.10.1

# 查看已拉取镜像
docker images

步骤2:拉取 Calico 网络插件镜像

powershell 复制代码
# Calico 版本
$calicoVersion = "v3.26.1"

# 拉取 Calico 镜像
docker pull docker.io/calico/cni:${calicoVersion}
docker pull docker.io/calico/node:${calicoVersion}
docker pull docker.io/calico/kube-controllers:${calicoVersion}

# 查看镜像
docker images | Select-String "calico"

步骤3:导出镜像为 tar 文件

powershell 复制代码
# 设置导出目录
$exportPath = "D:\k8s-offline\images"
$k8sVersion = "v1.33.12"
$calicoVersion = "v3.26.1"
$registry = "registry.aliyuncs.com/google_containers"

# 导出 Kubernetes 核心镜像
docker save -o "${exportPath}\kube-apiserver.tar" ${registry}/kube-apiserver:${k8sVersion}
docker save -o "${exportPath}\kube-controller-manager.tar" ${registry}/kube-controller-manager:${k8sVersion}
docker save -o "${exportPath}\kube-scheduler.tar" ${registry}/kube-scheduler:${k8sVersion}
docker save -o "${exportPath}\kube-proxy.tar" ${registry}/kube-proxy:${k8sVersion}
docker save -o "${exportPath}\pause.tar" ${registry}/pause:3.9
docker save -o "${exportPath}\etcd.tar" ${registry}/etcd:3.5.9-0
docker save -o "${exportPath}\coredns.tar" ${registry}/coredns:v1.10.1

# 导出 Calico 镜像
docker save -o "${exportPath}\calico-cni.tar" docker.io/calico/cni:${calicoVersion}
docker save -o "${exportPath}\calico-node.tar" docker.io/calico/node:${calicoVersion}
docker save -o "${exportPath}\calico-kube-controllers.tar" docker.io/calico/kube-controllers:${calicoVersion}

Write-Host "镜像导出完成!"
Get-ChildItem $exportPath

一键导出脚本:

powershell 复制代码
# 保存为 export-images.ps1
$exportPath = "D:\k8s-offline\images"
$k8sVersion = "v1.33.12"
$calicoVersion = "v3.26.1"
$registry = "registry.aliyuncs.com/google_containers"

# 定义镜像列表
$images = @(
    @{Name="kube-apiserver"; Image="${registry}/kube-apiserver:${k8sVersion}"},
    @{Name="kube-controller-manager"; Image="${registry}/kube-controller-manager:${k8sVersion}"},
    @{Name="kube-scheduler"; Image="${registry}/kube-scheduler:${k8sVersion}"},
    @{Name="kube-proxy"; Image="${registry}/kube-proxy:${k8sVersion}"},
    @{Name="pause"; Image="${registry}/pause:3.9"},
    @{Name="etcd"; Image="${registry}/etcd:3.5.9-0"},
    @{Name="coredns"; Image="${registry}/coredns:v1.10.1"},
    @{Name="calico-cni"; Image="docker.io/calico/cni:${calicoVersion}"},
    @{Name="calico-node"; Image="docker.io/calico/node:${calicoVersion}"},
    @{Name="calico-kube-controllers"; Image="docker.io/calico/kube-controllers:${calicoVersion}"}
)

Write-Host "========== 开始拉取和导出镜像 =========="

foreach ($img in $images) {
    Write-Host "`n处理: $($img.Name)" -ForegroundColor Cyan

    # 拉取镜像
    Write-Host "  拉取镜像..."
    docker pull $img.Image

    # 导出镜像
    $output = Join-Path $exportPath "$($img.Name).tar"
    Write-Host "  导出到: $output"
    docker save -o $output $img.Image

    if ($LASTEXITCODE -eq 0) {
        Write-Host "  ✓ 完成" -ForegroundColor Green
    } else {
        Write-Host "  ✗ 失败" -ForegroundColor Red
    }
}

Write-Host "`n========== 导出完成 =========="
Get-ChildItem $exportPath | Format-Table Name, Length
C.2.8 下载 Calico YAML 配置

直接下载:

在浏览器中访问:

复制代码
https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml

保存到 D:\k8s-offline\configs\calico.yaml

PowerShell 下载:

powershell 复制代码
$downloadPath = "D:\k8s-offline\configs"
$calicoUrl = "https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml"

Write-Host "下载 Calico YAML 配置..."
Invoke-WebRequest -Uri $calicoUrl -OutFile "$downloadPath\calico.yaml"

Write-Host "下载完成!"
Get-Content "$downloadPath\calico.yaml" | Select-Object -First 10
C.2.9 创建安装脚本

在 Windows 上创建安装脚本,保存到 D:\k8s-offline\scripts\ 目录:

install-ubuntu.sh

powershell 复制代码
# 在 PowerShell 中创建脚本
$scriptPath = "D:\k8s-offline\scripts\install-ubuntu.sh"

$scriptContent = @'
#!/bin/bash
# Ubuntu/Debian 离线安装脚本

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_DIR="$(dirname "$SCRIPT_DIR")"

echo "========== Ubuntu 离线安装 =========="

# 1. 安装依赖包
echo "[1/4] 安装系统依赖..."
dpkg -i ${BASE_DIR}/packages/ubuntu/*.deb 2>/dev/null || true
apt-get install -f -y

# 2. 安装 containerd
echo "[2/4] 安装 Containerd..."
dpkg -i ${BASE_DIR}/packages/containerd/*.deb 2>/dev/null || true
apt-get install -f -y

# 配置 containerd
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's|sandbox_image = "registry.k8s.io/pause:.*"|sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"|' /etc/containerd/config.toml

systemctl daemon-reload
systemctl enable containerd
systemctl restart containerd

# 3. 安装 Kubernetes
echo "[3/4] 安装 Kubernetes 组件..."
dpkg -i ${BASE_DIR}/packages/kubernetes/kubelet*.deb
dpkg -i ${BASE_DIR}/packages/kubernetes/kubectl*.deb
dpkg -i ${BASE_DIR}/packages/kubernetes/kubeadm*.deb
apt-get install -f -y

systemctl enable kubelet

# 4. 导入镜像
echo "[4/4] 导入容器镜像..."
for tar in ${BASE_DIR}/images/*.tar; do
    echo "导入: $(basename $tar)"
    ctr -n k8s.io images import $tar 2>/dev/null || \
    nerdctl -n k8s.io load -i $tar 2>/dev/null
done

echo "========== 安装完成 =========="
echo "验证: kubeadm version"
echo "下一步: kubeadm init 初始化集群"
'@

Set-Content -Path $scriptPath -Value $scriptContent -Encoding UTF8
Write-Host "脚本已创建: $scriptPath"

install-centos.sh

powershell 复制代码
$scriptPath = "D:\k8s-offline\scripts\install-centos.sh"

$scriptContent = @'
#!/bin/bash
# CentOS/RHEL 离线安装脚本

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_DIR="$(dirname "$SCRIPT_DIR")"

echo "========== CentOS 离线安装 =========="

# 1. 安装依赖包
echo "[1/4] 安装系统依赖..."
yum localinstall -y ${BASE_DIR}/packages/centos/*.rpm

# 2. 安装 containerd
echo "[2/4] 安装 Containerd..."
yum localinstall -y ${BASE_DIR}/packages/containerd/*.rpm

# 配置 containerd
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's|sandbox_image = "registry.k8s.io/pause:.*"|sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"|' /etc/containerd/config.toml

systemctl daemon-reload
systemctl enable containerd
systemctl restart containerd

# 3. 安装 Kubernetes
echo "[3/4] 安装 Kubernetes 组件..."
yum localinstall -y ${BASE_DIR}/packages/kubernetes/*.rpm

systemctl enable kubelet

# 4. 导入镜像
echo "[4/4] 导入容器镜像..."
for tar in ${BASE_DIR}/images/*.tar; do
    echo "导入: $(basename $tar)"
    ctr -n k8s.io images import $tar 2>/dev/null || \
    nerdctl -n k8s.io load -i $tar 2>/dev/null
done

echo "========== 安装完成 =========="
echo "验证: kubeadm version"
echo "下一步: kubeadm init 初始化集群"
'@

Set-Content -Path $scriptPath -Value $scriptContent -Encoding UTF8
Write-Host "脚本已创建: $scriptPath"

prepare-env.sh(环境准备):

powershell 复制代码
$scriptPath = "D:\k8s-offline\scripts\prepare-env.sh"

$scriptContent = @'
#!/bin/bash
# 环境准备脚本

echo "========== 环境准备 =========="

# 1. 关闭 Swap
echo "[1/4] 关闭 Swap..."
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab

# 2. 关闭防火墙
echo "[2/4] 关闭防火墙..."
if command -v ufw &> /dev/null; then
    ufw disable
fi
if command -v firewall-cmd &> /dev/null; then
    systemctl stop firewalld
    systemctl disable firewalld
fi

# 3. 配置内核模块
echo "[3/4] 配置内核模块..."
cat << EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter

# 4. 配置内核参数
echo "[4/4] 配置内核参数..."
cat << EOF | 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
sysctl --system

echo "========== 环境准备完成 =========="
'@

Set-Content -Path $scriptPath -Value $scriptContent -Encoding UTF8
Write-Host "脚本已创建: $scriptPath"
C.2.10 打包并传输到 Linux

打包离线安装包:

powershell 复制代码
# 使用 PowerShell 压缩
$sourcePath = "D:\k8s-offline"
$destinationPath = "D:\k8s-offline-$(Get-Date -Format 'yyyyMMdd').zip"

Write-Host "打包离线安装包..."

# 压缩目录
Compress-Archive -Path "$sourcePath\*" -DestinationPath $destinationPath -Force

Write-Host "打包完成!"
Write-Host "文件: $destinationPath"
Write-Host "大小: $([math]::Round((Get-Item $destinationPath).Length / 1GB, 2)) GB"

传输方式:

方式 操作步骤
U盘/移动硬盘 1. 将 zip 文件复制到移动介质 2. 在 Linux 上挂载并复制
SCP 传输 scp D:\k8s-offline.zip root@linux-server:/root/
FTP/SFTP 工具 使用 WinSCP、FileZilla 等工具上传
HTTP 服务 在 Windows 上启动临时 HTTP 服务

Windows 启动临时 HTTP 服务:

powershell 复制代码
# 在离线包目录启动 HTTP 服务(Python 需要安装)
cd D:\
python -m http.server 8080

# 或者使用 PowerShell(需要管理员权限)
# 在 Linux 上使用 wget 下载:
# wget http://windows-ip:8080/k8s-offline.zip

C.3 在 Linux 上安装离线包

⚠️ 重要:将离线包传输到 Linux 后,按以下步骤安装。

C.3.1 解压离线包
bash 复制代码
# 进入目录
cd /root

# 解压 zip 文件(需要安装 unzip)
unzip k8s-offline.zip

# 或者解压 tar.gz 文件
tar -xzvf k8s-offline.tar.gz

# 查看文件结构
ls -la k8s-offline/
C.3.2 执行环境准备
bash 复制代码
cd k8s-offline

# 添加执行权限
chmod +x scripts/*.sh

# 执行环境准备
./scripts/prepare-env.sh
C.3.3 执行离线安装

Ubuntu/Debian:

bash 复制代码
./scripts/install-ubuntu.sh

CentOS/RHEL:

bash 复制代码
./scripts/install-centos.sh
C.3.4 验证安装
bash 复制代码
# 验证版本
kubeadm version
kubelet --version
kubectl version --client

# 验证镜像
crictl images

# 验证 containerd
systemctl status containerd
C.3.5 初始化集群
bash 复制代码
# 初始化 Master
kubeadm init \
  --apiserver-advertise-address=192.168.x.x \
  --kubernetes-version=v1.33.12 \
  --pod-network-cidr=10.244.0.0/16

# 配置 kubectl
export KUBECONFIG=/etc/kubernetes/admin.conf

# 安装网络插件
kubectl apply -f /root/k8s-offline/configs/calico.yaml

C.4 准备离线安装包(在有网 Linux 机器上执行)

C.2.1 创建工作目录
bash 复制代码
# 创建离线包目录
mkdir -p /root/k8s-offline/{packages,images,scripts}

# 进入工作目录
cd /root/k8s-offline
C.2.2 下载系统依赖包

Ubuntu/Debian 系统:

bash 复制代码
# 安装下载工具
apt update
apt install -y apt-utils

# 创建依赖包下载脚本
cat > download_ubuntu_packages.sh << 'EOF'
#!/bin/bash
# 下载 Ubuntu/Debian 系统依赖包

PACKAGES_DIR="./packages/ubuntu"

mkdir -p $PACKAGES_DIR

# 系统基础依赖
BASE_PACKAGES=(
    "ca-certificates"
    "curl"
    "wget"
    "gnupg"
    "lsb-release"
    "apt-transport-https"
    "software-properties-common"
    "conntrack"
    "socat"
    "git"
    "ntpdate"
    "chrony"
)

echo "下载基础依赖包..."
for pkg in "${BASE_PACKAGES[@]}"; do
    echo "下载: $pkg"
    apt-get download $pkg 2>/dev/null || echo "跳过: $pkg"
done

# 下载依赖
apt-get install --print-uris ${BASE_PACKAGES[@]} | awk -F "'" '/http/ {print $2}' | xargs -r wget -P $PACKAGES_DIR

echo "基础依赖包下载完成!"
ls -lh $PACKAGES_DIR
EOF

chmod +x download_ubuntu_packages.sh
./download_ubuntu_packages.sh

CentOS/RHEL 系统:

bash 复制代码
# 安装下载工具
yum install -y yum-utils

# 创建依赖包下载脚本
cat > download_centos_packages.sh << 'EOF'
#!/bin/bash
# 下载 CentOS/RHEL 系统依赖包

PACKAGES_DIR="./packages/centos"

mkdir -p $PACKAGES_DIR

# 系统基础依赖
BASE_PACKAGES=(
    "ca-certificates"
    "curl"
    "wget"
    "gnupg2"
    "yum-utils"
    "conntrack"
    "socat"
    "git"
    "ntpdate"
    "chrony"
)

echo "下载基础依赖包..."
for pkg in "${BASE_PACKAGES[@]}"; do
    echo "下载: $pkg"
    yumdownloader --resolve --destdir=$PACKAGES_DIR $pkg
done

echo "基础依赖包下载完成!"
ls -lh $PACKAGES_DIR
EOF

chmod +x download_centos_packages.sh
./download_centos_packages.sh
C.2.3 下载 Containerd 安装包

Ubuntu/Debian:

bash 复制代码
# 添加 Docker 软件源
apt update
apt install -y ca-certificates curl gnupg
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list
apt update

# 下载 containerd 及依赖
mkdir -p ./packages/containerd
cd ./packages/containerd

# 下载 containerd
apt-get download containerd.io

# 下载依赖
apt-cache depends containerd.io | grep Depends | awk '{print $2}' | xargs apt-get download

cd ../..
echo "Containerd 包下载完成!"
ls -lh ./packages/containerd/

CentOS/RHEL:

bash 复制代码
# 添加 Docker 软件源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 下载 containerd 及依赖
mkdir -p ./packages/containerd
yumdownloader --resolve --destdir=./packages/containerd containerd.io

echo "Containerd 包下载完成!"
ls -lh ./packages/containerd/
C.2.4 下载 Kubernetes 安装包

Ubuntu/Debian:

bash 复制代码
# 添加 Kubernetes 软件源
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list
apt update

# 下载 Kubernetes 组件
mkdir -p ./packages/kubernetes
cd ./packages/kubernetes

# 指定版本下载(可根据需要修改版本号)
K8S_VERSION="1.33.12-1.1"

# 下载 kubeadm、kubelet、kubectl
apt-get download kubeadm=$K8S_VERSION
apt-get download kubelet=$K8S_VERSION
apt-get download kubectl=$K8S_VERSION

# 下载依赖
apt-cache depends kubeadm | grep Depends | awk '{print $2}' | xargs apt-get download 2>/dev/null
apt-cache depends kubelet | grep Depends | awk '{print $2}' | xargs apt-get download 2>/dev/null
apt-cache depends kubectl | grep Depends | awk '{print $2}' | xargs apt-get download 2>/dev/null

cd ../..
echo "Kubernetes 包下载完成!"
ls -lh ./packages/kubernetes/

CentOS/RHEL:

bash 复制代码
# 添加 Kubernetes 软件源
cat << EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.33/rpm/
enabled=1
gpgcheck=0
EOF

# 下载 Kubernetes 组件
mkdir -p ./packages/kubernetes

# 指定版本下载
K8S_VERSION="1.33.12"

yumdownloader --resolve --destdir=./packages/kubernetes kubeadm-$K8S_VERSION
yumdownloader --resolve --destdir=./packages/kubernetes kubelet-$K8S_VERSION
yumdownloader --resolve --destdir=./packages/kubernetes kubectl-$K8S_VERSION

echo "Kubernetes 包下载完成!"
ls -lh ./packages/kubernetes/
C.2.5 下载 Kubernetes 镜像

创建镜像下载脚本:

bash 复制代码
cat > download_k8s_images.sh << 'EOF'
#!/bin/bash
# 下载 Kubernetes 所需镜像

IMAGES_DIR="./images"
mkdir -p $IMAGES_DIR

# Kubernetes 版本
K8S_VERSION="v1.33.12"

# 镜像仓库(使用阿里云镜像加速)
REGISTRY="registry.aliyuncs.com/google_containers"

# Kubernetes 核心镜像列表
K8S_IMAGES=(
    "kube-apiserver:${K8S_VERSION}"
    "kube-controller-manager:${K8S_VERSION}"
    "kube-scheduler:${K8S_VERSION}"
    "kube-proxy:${K8S_VERSION}"
    "pause:3.9"
    "etcd:3.5.9-0"
    "coredns:v1.10.1"
)

echo "========== 下载 Kubernetes 核心镜像 =========="

for image in "${K8S_IMAGES[@]}"; do
    echo "下载: ${REGISTRY}/${image}"
    crictl pull "${REGISTRY}/${image}"
done

echo "========== 导出镜像为 tar 包 =========="

for image in "${K8S_IMAGES[@]}"; do
    # 获取镜像 ID
    image_id=$(crictl images | grep "${image}" | awk '{print $3}' | head -1)

    if [ -n "$image_id" ]; then
        # 生成文件名(替换特殊字符)
        filename=$(echo "${image}" | sed 's/[:/]/-/g')
        output_file="${IMAGES_DIR}/k8s-${filename}.tar"

        echo "导出: ${image} -> ${output_file}"
        ctr -n k8s.io image export "${output_file}" "${REGISTRY}/${image}"
    fi
done

echo "========== Kubernetes 镜像下载完成 =========="
ls -lh $IMAGES_DIR
EOF

chmod +x download_k8s_images.sh
./download_k8s_images.sh

使用 Docker 下载镜像(备选):

bash 复制代码
cat > download_k8s_images_docker.sh << 'EOF'
#!/bin/bash
# 使用 Docker 下载并导出镜像

IMAGES_DIR="./images"
mkdir -p $IMAGES_DIR

K8S_VERSION="v1.33.12"
REGISTRY="registry.aliyuncs.com/google_containers"

K8S_IMAGES=(
    "kube-apiserver:${K8S_VERSION}"
    "kube-controller-manager:${K8S_VERSION}"
    "kube-scheduler:${K8S_VERSION}"
    "kube-proxy:${K8S_VERSION}"
    "pause:3.9"
    "etcd:3.5.9-0"
    "coredns:v1.10.1"
)

for image in "${K8S_IMAGES[@]}"; do
    echo "拉取: ${REGISTRY}/${image}"
    docker pull "${REGISTRY}/${image}"

    filename=$(echo "${image}" | sed 's/[:/]/-/g')
    output_file="${IMAGES_DIR}/k8s-${filename}.tar"

    echo "导出: ${output_file}"
    docker save -o "${output_file}" "${REGISTRY}/${image}"
done

echo "镜像下载完成!"
ls -lh $IMAGES_DIR
EOF

chmod +x download_k8s_images_docker.sh
./download_k8s_images_docker.sh
C.2.6 下载网络插件镜像(Calico)
bash 复制代码
cat > download_calico_images.sh << 'EOF'
#!/bin/bash
# 下载 Calico 网络插件镜像

IMAGES_DIR="./images"

# Calico 版本
CALICO_VERSION="v3.26.1"

# Calico 镜像列表
CALICO_IMAGES=(
    "docker.io/calico/cni:${CALICO_VERSION}"
    "docker.io/calico/node:${CALICO_VERSION}"
    "docker.io/calico/kube-controllers:${CALICO_VERSION}"
)

echo "========== 下载 Calico 镜像 =========="

for image in "${CALICO_IMAGES[@]}"; do
    echo "拉取: ${image}"
    crictl pull "${image}" || docker pull "${image}"

    filename=$(echo "${image}" | sed 's/[:/]/-/g' | sed 's/docker.io-//')
    output_file="${IMAGES_DIR}/calico-${filename}.tar"

    echo "导出: ${output_file}"
    if command -v ctr &> /dev/null; then
        ctr -n k8s.io image export "${output_file}" "${image}"
    else
        docker save -o "${output_file}" "${image}"
    fi
done

echo "========== Calico 镜像下载完成 =========="
ls -lh $IMAGES_DIR
EOF

chmod +x download_calico_images.sh
./download_calico_images.sh
C.2.7 下载 Calico YAML 配置
bash 复制代码
# 下载 Calico 配置文件
cd ./images
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml

cd ..
C.2.8 创建离线安装脚本

创建离线安装主脚本:

bash 复制代码
cat > scripts/install_offline.sh << 'EOF'
#!/bin/bash
# Kubernetes 离线安装脚本
# 用途: 在无网络环境下安装 Kubernetes

set -e

echo "=========================================="
echo "    Kubernetes 离线安装脚本"
echo "=========================================="

# 当前脚本目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_DIR="$(dirname "$SCRIPT_DIR")"
PACKAGES_DIR="${BASE_DIR}/packages"
IMAGES_DIR="${BASE_DIR}/images"

echo "安装包目录: $PACKAGES_DIR"
echo "镜像目录: $IMAGES_DIR"

# 检测系统类型
if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$ID
else
    echo "无法检测系统类型"
    exit 1
fi

echo "系统类型: $OS"

# 函数:安装 Ubuntu/Debian 包
install_ubuntu_packages() {
    echo "========== 安装系统依赖 =========="

    # 安装基础依赖
    if [ -d "${PACKAGES_DIR}/ubuntu" ]; then
        dpkg -i ${PACKAGES_DIR}/ubuntu/*.deb 2>/dev/null || true
        apt-get install -f -y
    fi

    # 安装 containerd
    echo "安装 Containerd..."
    if [ -d "${PACKAGES_DIR}/containerd" ]; then
        dpkg -i ${PACKAGES_DIR}/containerd/*.deb 2>/dev/null || true
        apt-get install -f -y
    fi

    # 安装 Kubernetes 组件
    echo "安装 Kubernetes 组件..."
    if [ -d "${PACKAGES_DIR}/kubernetes" ]; then
        # 先安装依赖
        for pkg in conntrack socat; do
            if ls ${PACKAGES_DIR}/kubernetes/${pkg}*.deb 1> /dev/null 2>&1; then
                dpkg -i ${PACKAGES_DIR}/kubernetes/${pkg}*.deb 2>/dev/null || true
            fi
        done

        # 安装 kubeadm、kubelet、kubectl
        dpkg -i ${PACKAGES_DIR}/kubernetes/kubelet*.deb 2>/dev/null || true
        dpkg -i ${PACKAGES_DIR}/kubernetes/kubectl*.deb 2>/dev/null || true
        dpkg -i ${PACKAGES_DIR}/kubernetes/kubeadm*.deb 2>/dev/null || true

        # 修复依赖
        apt-get install -f -y
    fi
}

# 函数:安装 CentOS/RHEL 包
install_centos_packages() {
    echo "========== 安装系统依赖 =========="

    # 安装基础依赖
    if [ -d "${PACKAGES_DIR}/centos" ]; then
        yum localinstall -y ${PACKAGES_DIR}/centos/*.rpm
    fi

    # 安装 containerd
    echo "安装 Containerd..."
    if [ -d "${PACKAGES_DIR}/containerd" ]; then
        yum localinstall -y ${PACKAGES_DIR}/containerd/*.rpm
    fi

    # 安装 Kubernetes 组件
    echo "安装 Kubernetes 组件..."
    if [ -d "${PACKAGES_DIR}/kubernetes" ]; then
        yum localinstall -y ${PACKAGES_DIR}/kubernetes/*.rpm
    fi
}

# 函数:配置 Containerd
configure_containerd() {
    echo "========== 配置 Containerd =========="

    mkdir -p /etc/containerd

    # 生成默认配置
    containerd config default > /etc/containerd/config.toml

    # 修改配置
    sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

    # 修改 sandbox 镜像
    sed -i 's|sandbox_image = "registry.k8s.io/pause:.*"|sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"|' /etc/containerd/config.toml

    # 启动服务
    systemctl daemon-reload
    systemctl enable containerd
    systemctl restart containerd

    echo "Containerd 配置完成!"
}

# 函数:导入镜像
import_images() {
    echo "========== 导入容器镜像 =========="

    if [ -d "${IMAGES_DIR}" ]; then
        for tar_file in ${IMAGES_DIR}/*.tar; do
            if [ -f "$tar_file" ]; then
                echo "导入镜像: $(basename $tar_file)"
                ctr -n k8s.io images import "$tar_file" 2>/dev/null || \
                nerdctl -n k8s.io load -i "$tar_file" 2>/dev/null || \
                docker load -i "$tar_file" 2>/dev/null || \
                echo "警告: 导入失败 $tar_file"
            fi
        done
    fi

    echo "镜像导入完成!"

    # 查看已导入镜像
    echo "已导入镜像列表:"
    ctr -n k8s.io images ls 2>/dev/null || crictl images
}

# 主安装流程
main() {
    case $OS in
        ubuntu|debian)
            install_ubuntu_packages
            ;;
        centos|rhel|rocky|almalinux)
            install_centos_packages
            ;;
        *)
            echo "不支持的系统: $OS"
            exit 1
            ;;
    esac

    configure_containerd
    import_images

    # 启用 kubelet
    systemctl enable kubelet

    echo ""
    echo "=========================================="
    echo "    离线安装完成!"
    echo "=========================================="
    echo ""
    echo "验证安装:"
    echo "  kubeadm version"
    echo "  kubelet --version"
    echo "  kubectl version --client"
    echo "  crictl images"
    echo ""
    echo "下一步:执行 kubeadm init 初始化集群"
}

main
EOF

chmod +x scripts/install_offline.sh
C.2.9 创建环境准备脚本
bash 复制代码
cat > scripts/prepare_env.sh << 'EOF'
#!/bin/bash
# 环境准备脚本(无需网络)

set -e

echo "========== 环境准备 =========="

# 1. 关闭 Swap
echo "[1/5] 关闭 Swap..."
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
echo "✅ Swap 已关闭"

# 2. 关闭防火墙
echo "[2/5] 关闭防火墙..."
if command -v ufw &> /dev/null; then
    ufw disable
    echo "✅ UFW 已关闭"
fi
if command -v firewall-cmd &> /dev/null; then
    systemctl stop firewalld
    systemctl disable firewalld
    echo "✅ Firewalld 已关闭"
fi

# 3. 关闭 SELinux (CentOS/RHEL)
echo "[3/5] 配置 SELinux..."
if command -v setenforce &> /dev/null; then
    setenforce 0 2>/dev/null || true
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config 2>/dev/null || true
    echo "✅ SELinux 已配置"
fi

# 4. 配置内核模块
echo "[4/5] 配置内核模块..."
cat << EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

modprobe overlay 2>/dev/null || true
modprobe br_netfilter 2>/dev/null || true

# 5. 配置内核参数
echo "[5/5] 配置内核参数..."
cat << EOF | 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

sysctl --system

echo "========== 环境准备完成 =========="
EOF

chmod +x scripts/prepare_env.sh
C.2.10 打包离线安装包
bash 复制代码
# 创建打包脚本
cat > pack_offline.sh << 'EOF'
#!/bin/bash
# 打包离线安装包

PACKAGE_NAME="k8s-offline-$(date +%Y%m%d).tar.gz"

echo "打包离线安装包..."

# 确保目录存在
mkdir -p packages images scripts

# 打包
tar -czvf ${PACKAGE_NAME} \
    packages/ \
    images/ \
    scripts/ \
    README.md 2>/dev/null || \
tar -czvf ${PACKAGE_NAME} \
    packages/ \
    images/ \
    scripts/

echo "========== 打包完成 =========="
echo "文件: ${PACKAGE_NAME}"
echo "大小: $(ls -lh ${PACKAGE_NAME} | awk '{print $5}')"

# 计算校验和
sha256sum ${PACKAGE_NAME} > ${PACKAGE_NAME}.sha256
echo "校验文件: ${PACKAGE_NAME}.sha256"
EOF

chmod +x pack_offline.sh
./pack_offline.sh

C.3 传输离线安装包

C.3.1 传输方式
方式 适用场景 操作
U 盘/移动硬盘 物理隔离环境 复制文件到移动介质
SCP 传输 内网可通 scp k8s-offline.tar.gz root@node1:/root/
HTTP 服务 批量传输 搭建临时 HTTP 服务
NFS 共享 内网共享 挂载 NFS 目录
C.3.2 SCP 传输示例
bash 复制代码
# 传输到 master 节点
scp k8s-offline-*.tar.gz root@master1:/root/

# 传输到 worker 节点
scp k8s-offline-*.tar.gz root@node1:/root/
C.3.3 解压安装包

在所有节点执行:

bash 复制代码
# 进入目录
cd /root

# 解压
tar -xzvf k8s-offline-*.tar.gz

# 查看文件结构
ls -la
# 输出:
# drwxr-xr-x  packages/
# drwxr-xr-x  images/
# drwxr-xr-x  scripts/

C.4 离线安装步骤(在无网机器上执行)

C.4.1 安装流程图
复制代码
┌─────────────────────────────────────────────────────────────┐
│                    离线安装流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  步骤 1: 解压安装包                                          │
│     tar -xzvf k8s-offline.tar.gz                            │
│              ↓                                               │
│  步骤 2: 执行环境准备脚本                                    │
│     ./scripts/prepare_env.sh                                │
│              ↓                                               │
│  步骤 3: 执行离线安装脚本                                    │
│     ./scripts/install_offline.sh                            │
│              ↓                                               │
│  步骤 4: 验证安装                                            │
│     kubeadm version                                         │
│     crictl images                                           │
│              ↓                                               │
│  步骤 5: 初始化集群(仅 master)                             │
│     kubeadm init ...                                        │
│                                                              │
└─────────────────────────────────────────────────────────────┘
C.4.2 在所有节点执行
bash 复制代码
# 1. 解压安装包
cd /root
tar -xzvf k8s-offline-*.tar.gz

# 2. 执行环境准备
cd k8s-offline
./scripts/prepare_env.sh

# 3. 执行离线安装
./scripts/install_offline.sh

# 4. 验证安装
kubeadm version
kubelet --version
kubectl version --client
crictl images
C.4.3 初始化集群(仅 Master 节点)
bash 复制代码
# 在 master1 上执行

# 初始化集群
kubeadm init \
  --apiserver-advertise-address=192.168.x.x \
  --kubernetes-version=v1.33.12 \
  --pod-network-cidr=10.244.0.0/16 \
  --image-repository=registry.aliyuncs.com/google_containers \
  --skip-phases=preflight  # 跳过预检(镜像已导入)

# 配置 kubectl
export KUBECONFIG=/etc/kubernetes/admin.conf
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bashrc

# 获取 join 命令
kubeadm token create --print-join-command > /root/k8s-join-command.sh
chmod +x /root/k8s-join-command.sh
C.4.4 Worker 节点加入集群
bash 复制代码
# 在 node1 上执行

# 从 master 获取 join 命令后执行
kubeadm join 192.168.x.x:6443 --token xxxx --discovery-token-ca-cert-hash sha256:xxxx
C.4.5 安装网络插件
bash 复制代码
# 在 master1 上执行

# 应用 Calico 配置(需要提前下载好 YAML 文件)
kubectl apply -f /root/k8s-offline/images/calico.yaml

# 等待 Pod 启动
kubectl get pods -n kube-system -w

C.5 离线安装验证

C.5.1 验证检查清单
bash 复制代码
#!/bin/bash
# 离线安装验证脚本

echo "========== 验证检查 =========="

echo "[1] 检查 Swap"
swap_total=$(free -m | awk '/Swap/{print $2}')
[ "$swap_total" -eq 0 ] && echo "✅ Swap 已关闭" || echo "❌ Swap 未关闭"

echo "[2] 检查 Containerd"
systemctl is-active containerd &>/dev/null && echo "✅ Containerd 运行中" || echo "❌ Containerd 未运行"

echo "[3] 检查 Kubelet"
systemctl is-enabled kubelet &>/dev/null && echo "✅ Kubelet 已启用" || echo "❌ Kubelet 未启用"

echo "[4] 检查 Kubeadm"
command -v kubeadm &>/dev/null && echo "✅ Kubeadm 已安装: $(kubeadm version -o short)" || echo "❌ Kubeadm 未安装"

echo "[5] 检查 Kubectl"
command -v kubectl &>/dev/null && echo "✅ Kubectl 已安装" || echo "❌ Kubectl 未安装"

echo "[6] 检查镜像数量"
image_count=$(crictl images 2>/dev/null | wc -l)
echo "✅ 已导入镜像: $((image_count - 1)) 个"

echo "[7] 检查内核模块"
lsmod | grep -q overlay && echo "✅ overlay 已加载" || echo "❌ overlay 未加载"
lsmod | grep -q br_netfilter && echo "✅ br_netfilter 已加载" || echo "❌ br_netfilter 未加载"

echo "[8] 检查内核参数"
[ "$(sysctl -n net.ipv4.ip_forward)" -eq 1 ] && echo "✅ ip_forward = 1" || echo "❌ ip_forward 未设置"

echo "========== 验证完成 =========="
C.5.2 集群状态验证
bash 复制代码
# 查看节点状态
kubectl get nodes -o wide

# 查看所有 Pod
kubectl get pods -A

# 查看组件状态
kubectl get cs

# 测试部署
kubectl create deployment test-nginx --image=nginx
kubectl get pods

C.6 离线安装目录结构

复制代码
k8s-offline/
├── packages/
│   ├── ubuntu/                    # Ubuntu 系统依赖包
│   │   ├── ca-certificates_*.deb
│   │   ├── curl_*.deb
│   │   └── ...
│   ├── centos/                    # CentOS 系统依赖包
│   │   ├── ca-certificates-*.rpm
│   │   ├── curl-*.rpm
│   │   └── ...
│   ├── containerd/                # Containerd 安装包
│   │   ├── containerd.io_*.deb   # Ubuntu
│   │   └── containerd.io-*.rpm   # CentOS
│   └── kubernetes/                # Kubernetes 组件
│       ├── kubeadm_*.deb
│       ├── kubelet_*.deb
│       ├── kubectl_*.deb
│       ├── kubeadm-*.rpm
│       ├── kubelet-*.rpm
│       └── kubectl-*.rpm
├── images/
│   ├── k8s-kube-apiserver-v1.33.12.tar
│   ├── k8s-kube-controller-manager-v1.33.12.tar
│   ├── k8s-kube-scheduler-v1.33.12.tar
│   ├── k8s-kube-proxy-v1.33.12.tar
│   ├── k8s-pause-3.9.tar
│   ├── k8s-etcd-3.5.9-0.tar
│   ├── k8s-coredns-v1.10.1.tar
│   ├── calico-cni-v3.26.1.tar
│   ├── calico-node-v3.26.1.tar
│   ├── calico-kube-controllers-v3.26.1.tar
│   └── calico.yaml                # Calico 配置文件
├── scripts/
│   ├── prepare_env.sh             # 环境准备脚本
│   ├── install_offline.sh         # 离线安装脚本
│   └── verify_install.sh          # 验证脚本
└── README.md                      # 说明文档

C.7 常见问题

C.7.1 依赖包缺失

问题: 安装时报依赖缺失

解决:

bash 复制代码
# Ubuntu/Debian
dpkg -i --force-depends package.deb
apt-get install -f

# CentOS/RHEL
yum localinstall --nogpgcheck package.rpm
C.7.2 镜像导入失败

问题: 镜像导入失败

解决:

bash 复制代码
# 方法1: 使用 ctr
ctr -n k8s.io images import image.tar

# 方法2: 使用 nerdctl
nerdctl -n k8s.io load -i image.tar

# 方法3: 使用 docker
docker load -i image.tar

# 方法4: 使用 crictl(需要先导入到 containerd)
ctr -n k8s.io images import image.tar
crictl images
C.7.3 版本不匹配

问题: kubeadm init 时版本不匹配

解决:

bash 复制代码
# 检查已安装版本
kubeadm version
kubelet --version

# 指定正确版本初始化
kubeadm init --kubernetes-version=v1.33.12

附录 D:参考链接