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
  5. 安装 Kubernetes 组件
  6. 初始化 Master 节点
  7. 加入 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-apiservermasterKubernetes API 入口,所有操作都通过它
kube-schedulermaster负责调度 Pod 到合适的节点
kube-controller-managermaster运行控制器,维护集群状态
etcdmaster分布式键值存储,保存集群所有数据
kubeletmaster + node节点代理,管理本节点上的 Pod
kube-proxymaster + node网络代理,实现 Service 功能
containerdmaster + 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 节点端口:

端口协议组件说明
6443TCPkube-apiserverAPI Server(必须开放)
2379-2380TCPetcdetcd 服务端口
10250TCPkubeletKubelet API
10251TCPkube-schedulerScheduler
10252TCPkube-controllerController Manager
10257TCPkube-controllerController Manager (v1.22+)
10259TCPkube-schedulerScheduler (v1.22+)

Worker 节点端口:

端口协议组件说明
10250TCPkubeletKubelet API
10256TCPkube-proxyKube Proxy
30000-32767TCPNodePortNodePort Service 端口范围

3. 环境准备

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

3.1 登录节点

# 登录 master 节点
ssh root@master1_ip

# 登录 worker 节点
ssh root@node1_ip

3.2 设置主机名

在 master1 上执行:

hostnamectl set-hostname master1

# 验证
hostname
# 输出: master1

在 node1 上执行:

hostnamectl set-hostname node1

# 验证
hostname
# 输出: node1

3.3 配置 hosts 文件

在所有节点上执行:

# 编辑 hosts 文件
cat >> /etc/hosts << EOF
192.168.x.x  master1
192.168.y.y  node1
EOF

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

验证:

# 测试解析
ping master1
ping node1

3.4 关闭 Swap

为什么要关闭 Swap?

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

执行关闭:

# 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:

# 检查防火墙状态
ufw status

# 关闭防火墙
ufw disable

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

CentOS/RHEL:

# 停止并禁用防火墙
systemctl stop firewalld
systemctl disable firewalld

# 验证
systemctl status firewalld

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

3.6 关闭 SELinux(CentOS/RHEL)

# 临时关闭
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:
# Ubuntu/Debian
apt update
apt install -y chrony

# CentOS/RHEL
yum install -y chrony

配置时间同步服务器:

# 编辑配置文件
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

手动同步时间(可选):

# 安装 ntpdate
apt install -y ntpdate   # Ubuntu/Debian
yum install -y ntpdate   # CentOS/RHEL

# 同步时间
ntpdate ntp.aliyun.com

# 查看时间
date
简化验证
# 在 master1 上查看时间
date

# 在 node1 上查看时间
date

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

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


3.8 配置内核参数

为什么要配置?

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

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

执行配置:

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

# 立即加载模块
modprobe overlay
modprobe br_netfilter

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

配置内核网络参数:

# 设置 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 环境准备验证脚本

一键验证脚本:

#!/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========== 检查完成 =========="

保存并执行:

# 保存脚本
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:

# 更新软件源
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:

# 安装依赖
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

验证安装:

# 查看版本
containerd --version

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

4.3 配置 Containerd

生成默认配置:

# 创建配置目录
mkdir -p /etc/containerd

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

修改配置(重要):

# 编辑配置文件
vi /etc/containerd/config.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"  # 使用阿里云镜像

一键配置脚本:

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

# 重启 containerd 服务
systemctl daemon-reload
systemctl restart containerd

# 设置开机自启
systemctl enable containerd

# 查看状态
systemctl status containerd

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

4.5 安装 nerdctl(可选)

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

# 下载 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:

# 更新软件源并安装依赖
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:

# 添加 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:

# 更新软件源
apt update

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

# 设置 kubelet 开机自启
systemctl enable kubelet

CentOS/RHEL:

# 安装组件
yum install -y kubeadm kubelet kubectl

# 设置 kubelet 开机自启
systemctl enable kubelet

5.4 验证安装

# 查看版本
kubeadm version
kubelet --version
kubectl version --client

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

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

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

# 查看需要的镜像
kubeadm config images list

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

使用阿里云镜像:

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

6. 初始化 Master 节点

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

6.1 初始化前检查

# 检查 kubelet 状态
systemctl status kubelet

# 检查 containerd 状态
systemctl status containerd

# 检查网络
ping node1

6.2 初始化集群

基础初始化命令:

# 初始化集群(替换为实际 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-addressAPI Server 监听地址(master 的 IP)
--image-repository镜像仓库地址(国内使用阿里云)
--kubernetes-versionKubernetes 版本
--service-cidrService 网段
--pod-network-cidrPod 网段(需与 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 用户配置:

# 设置 KUBECONFIG 环境变量
export KUBECONFIG=/etc/kubernetes/admin.conf

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

为普通用户配置:

# 创建 .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 节点

# 查看节点状态
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 加入集群的命令:

# 获取 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 上获取:

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

# 执行 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 上执行:

# 查看节点
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(推荐)

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

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

等待 Calico Pod 启动:

# 查看 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(备选)

# 下载 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 验证网络插件

# 等待所有 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 检查集群状态

# 查看节点
kubectl get nodes -o wide

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

# 查看组件状态
kubectl get cs

9.2 测试部署应用

创建测试 Deployment:

# 创建 nginx deployment
kubectl create deployment nginx --image=nginx

# 查看 deployment
kubectl get deployments

# 查看 pod
kubectl get pods

暴露服务:

# 暴露端口
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

访问测试:

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

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

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

9.3 查看集群信息

# 集群信息
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

排查步骤:

# 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

排查步骤:

# 查看 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

解决方案:

# 手动拉取镜像
crictl pull xxx

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

10.4 kubelet 启动失败

排查步骤:

# 查看 kubelet 状态
systemctl status kubelet

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

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

10.5 重置集群

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

# 重置节点(在所有节点执行)
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 环境准备脚本

#!/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 初始化脚本

#!/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 中执行
$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.iohttps://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.iohttps://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 批量下载:

# 设置下载目录
$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:

# 添加 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:

# 添加 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/releasesGitHub 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 为例):

组件架构下载地址
kubeadmamd64https://dl.k8s.io/release/v1.33.12/bin/linux/amd64/kubeadm
kubeletamd64https://dl.k8s.io/release/v1.33.12/bin/linux/amd64/kubelet
kubectlamd64https://dl.k8s.io/release/v1.33.12/bin/linux/amd64/kubectl
kubeadmarm64https://dl.k8s.io/release/v1.33.12/bin/linux/arm64/kubeadm
kubeletarm64https://dl.k8s.io/release/v1.33.12/bin/linux/arm64/kubelet
kubectlarm64https://dl.k8s.io/release/v1.33.12/bin/linux/arm64/kubectl

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 上安装二进制文件:

# 复制到系统目录
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:使用阿里云镜像

# 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. 搜索以下包名:
依赖包搜索关键词说明
conntrackconntrack连接追踪工具
libnetfilter-conntrack3libnetfilter-conntrackconntrack 库依赖
libnfnetlink0libnfnetlink底层网络库
socatsocatSocket 工具
ipsetipsetIP 集合工具
libipset13libipsetipset 库依赖
ebtablesebtables以太网桥防火墙
  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 机器上下载(最可靠)

# 在有网络的 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 仓库:

$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 兼容替代)

$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 中执行:

# 设置版本
$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 网络插件镜像

# 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 文件

# 设置导出目录
$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

一键导出脚本:

# 保存为 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 下载:

$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 中创建脚本
$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:

$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(环境准备):

$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 压缩
$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 服务:

# 在离线包目录启动 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 解压离线包
# 进入目录
cd /root

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

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

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

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

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

Ubuntu/Debian:

./scripts/install-ubuntu.sh

CentOS/RHEL:

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

# 验证镜像
crictl images

# 验证 containerd
systemctl status containerd
C.3.5 初始化集群
# 初始化 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 创建工作目录
# 创建离线包目录
mkdir -p /root/k8s-offline/{packages,images,scripts}

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

Ubuntu/Debian 系统:

# 安装下载工具
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 系统:

# 安装下载工具
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:

# 添加 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:

# 添加 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:

# 添加 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:

# 添加 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 镜像

创建镜像下载脚本:

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 下载镜像(备选):

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)
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 配置
# 下载 Calico 配置文件
cd ./images
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml

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

创建离线安装主脚本:

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 创建环境准备脚本
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 打包离线安装包
# 创建打包脚本
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 传输示例
# 传输到 master 节点
scp k8s-offline-*.tar.gz root@master1:/root/

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

在所有节点执行:

# 进入目录
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 在所有节点执行
# 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 节点)
# 在 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 节点加入集群
# 在 node1 上执行

# 从 master 获取 join 命令后执行
kubeadm join 192.168.x.x:6443 --token xxxx --discovery-token-ca-cert-hash sha256:xxxx
C.4.5 安装网络插件
# 在 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 验证检查清单
#!/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 集群状态验证
# 查看节点状态
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 依赖包缺失

问题: 安装时报依赖缺失

解决:

# Ubuntu/Debian
dpkg -i --force-depends package.deb
apt-get install -f

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

问题: 镜像导入失败

解决:

# 方法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 时版本不匹配

解决:

# 检查已安装版本
kubeadm version
kubelet --version

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

附录 D:参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值