kubernetes(K8s)学习笔记(第二期):Kubernetes 集群部署实战(kubeadm)

kubernetes(K8s)学习笔记(第二期):Kubernetes 集群部署实战(kubeadm)

本笔记为 Kubernetes 系列第二期,聚焦生产级 Kubernetes 集群的完整部署流程。采用 kubeadm 官方工具,基于 Ubuntu 24.04 操作系统和 containerd 容器运行时,从环境准备到集群初始化、网络插件部署、节点加入,完整搭建一个可用的 Kubernetes 1.30 集群。全文约 6000 字 ,包含 90+ 命令示例15 张对比表格,是一份可直接用于生产环境部署的实战指南。
--- Compiled and Authored by Whisky --- June 23 rd, 2026

目录

  1. 部署方式对比与选型
  2. 环境准备(模板机)
  3. 内核模块与参数配置
  4. 容器运行时配置(containerd)
  5. 安装 Kubernetes 组件
  6. 克隆节点与配置
  7. 集群初始化(Master 节点)
  8. 部署网络插件(Calico)
  9. Worker 节点加入集群
  10. 验证集群
  11. 总结与知识点一览表

一、部署方式对比与选型

1.1 Kubernetes 部署方式全景图

安装方式 核心特点 难度 适用场景 推荐指数
kubeadm 官方标准、无魔改、兼容性强 中等 生产自建、CKA/CKAD 考试、标准集群 ⭐⭐⭐⭐⭐
二进制手工部署 全手动、底层可控、无封装 极高 原理研究、深度定制、教学演示 ⭐⭐
Sealos / KubeKey 一键部署、高可用、自带插件 快速搭建生产/测试环境 ⭐⭐⭐⭐
k3s / k0s 轻量、单二进制、适合边缘 边缘节点、低配机器、开发测试 ⭐⭐⭐⭐
minikube / kind 单机实验环境、一键启动 极低 本地开发、快速验证 ⭐⭐⭐
云厂商托管(ACK/EKS) Master 托管、免运维、高可用 云上生产业务 ⭐⭐⭐⭐

1.2 为什么选择 kubeadm?

kubeadm 是 Kubernetes 官方提供的集群部署工具,其核心优势在于:

  • 官方标准:遵循 Kubernetes 最佳实践,所有组件配置均经过验证
  • 无魔改:没有任何封装和隐藏逻辑,部署过程完全透明
  • 易于升级:支持集群的平滑升级,无需重新部署
  • 生态完善:文档丰富,社区支持广泛,故障排查容易
  • 兼容性强:支持多种操作系统和容器运行时

我们的选择 :对于学习 + 未来上生产,优先选择 kubeadm。它既能让你深入理解 Kubernetes 各组件的协作关系,又能直接用于生产环境。

1.3 部署方式选择建议

场景 推荐方案 理由
学习 + 标准生产 kubeadm 官方标准,兼容性最好,社区支持最强
快速测试/边缘场景 k3s 轻量级,单二进制,资源占用低
云上生产业务 ACK / EKS / TKE Master 免运维,与云服务深度集成
原理学习/深度定制 二进制部署 完全可控,无任何封装

1.4 本期部署方案概览

项目 选择
操作系统 Ubuntu 24.04 LTS
Kubernetes 版本 1.30.2
容器运行时 containerd.io 1.7.20
网络插件 Calico v3.30.7
Pod 网络 CIDR 10.224.0.0/16
集群规模 1 Master + 2 Worker

1.5 部署环境要求

在开始部署之前,需要确认以下硬件和软件要求:

要求项 最低配置 推荐配置
CPU 2 核心 4 核心+
内存 2 GB 4 GB+
磁盘 20 GB 100 GB+
操作系统 Ubuntu 22.04 Ubuntu 24.04
网络 节点间互通 千兆网络
时间同步 NTP 服务 chrony

1.6 本部署方式与生产环境的适配性说明

kubeadm 部署的集群可直接用于生产环境,这也是它区别于 minikube 等本地开发工具的核心特点。生产环境中,只需在此基础上增加:

  • 高可用控制平面:部署 3 个或 5 个 Master 节点,实现控制平面高可用
  • 负载均衡器:在多个 Master 节点前部署 LB(如 HAProxy、云厂商 LB)
  • 持久化存储:部署 CSI 存储插件(如 Ceph、NFS、云厂商存储)
  • 监控告警:部署 Prometheus + Grafana + AlertManager
  • 日志收集:部署 ELK/EFK 日志栈

二、环境准备(模板机)

策略说明:先准备一台"模板机",完成所有基础配置,然后克隆出 Master 和 Worker 节点,避免重复劳动。

2.1 虚拟机硬件配置

配置项 规格 说明
CPU 2 核心 最少 2 核,否则 kubelet 可能启动失败
内存 4 GB 至少 2GB,推荐 4GB+
网卡 1 个 NAT 网卡 用于节点间通信
磁盘 100 GB 至少 20GB,用于存储镜像和日志
分区 /boot 2GB,/ 90GB 不需要 swap 分区

2.2 配置软件仓库源

操作系统仓库换成华为云镜像(速度更快):

bash 复制代码
[root@ubuntu2404 ~]# cat > /etc/apt/sources.list.d/ubuntu.sources <<'EOF'
Types: deb
URIs: http://mirrors.huaweicloud.com/ubuntu/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
EOF

配置 containerd 仓库(来自 Docker CE 源,版本更新):

bash 复制代码
# 导入 containerd 仓库 key
[root@ubuntu2404 ~]# curl -fsSL https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu/gpg | gpg --dearmour -o /etc/apt/trusted.gpg.d/containerd.gpg

# 添加 containerd 仓库
[root@ubuntu2404 ~]# cat << 'EOF' > /etc/apt/sources.list.d/docker-ce.list
deb [arch=amd64] https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu noble stable
EOF

配置 Kubernetes 仓库(阿里云镜像,支持 v1.24-v1.35):

bash 复制代码
# 添加 kubernetes 仓库 key
[root@ubuntu2404 ~]# curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# 添加 kubernetes 仓库
[root@ubuntu2404 ~]# echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/ /" > /etc/apt/sources.list.d/kubernetes.list

版本替换说明 :如需安装其他版本(如 v1.29),将上述配置中的 v1.30 替换为 v1.29 即可。目前该源支持 v1.24 - v1.35 版本。

2.3 安装基础软件包

bash 复制代码
[root@ubuntu2404 ~]# apt update && apt install -y \
    vim \                    # 强大的终端文本编辑器
    lrzsz \                  # 便于 Xshell 上传/下载文件
    bash-completion \        # 命令行自动补全
    open-vm-tools \          # VMware 虚拟机工具(时间同步、文件拖拽)
    apt-transport-https \    # 让 apt 支持 HTTPS 下载
    sshpass                  # 非交互式 SSH 登录(脚本自动化用)

2.4 设置静态 IP 地址

bash 复制代码
[root@ubuntu2404 ~]# mkdir /etc/netplan/origin
[root@ubuntu2404 ~]# mv /etc/netplan/*yaml /etc/netplan/origin
[root@ubuntu2404 ~]# cat > /etc/netplan/00-static.yaml <<EOF
network:
  ethernets:
    ens32:
      dhcp4: no
      addresses:
        - 10.1.8.30/24
      routes:
        - to: default
          via: 10.1.8.2
      nameservers:
        addresses:
          - 223.5.5.5
  version: 2
EOF
[root@ubuntu2404 ~]# chmod 600 /etc/netplan/00-static.yaml
[root@ubuntu2404 ~]# netplan apply

2.5 配置 /etc/hosts(集群 DNS 解析)

bash 复制代码
[root@ubuntu2404 ~]# cat << 'EOF' >> /etc/hosts

###### kubernetes #####
10.1.8.30 master30.whisky.cloud master30
10.1.8.31 worker31.whisky.cloud worker31
10.1.8.32 worker32.whisky.cloud worker32
EOF

为什么要配置 hosts? 集群内部组件通过主机名互相通信,配置 hosts 可以避免依赖外部 DNS,提高集群稳定性。特别是在内网 DNS 不稳定的情况下,hosts 解析是最可靠的方式。Kubernetes 的 TLS 证书中包含主机名信息,如果主机名无法解析,API Server 会拒绝连接。可以这样理解:hosts 文件相当于集群内部的"电话簿",每个节点需要知道其他节点的"联系方式"(IP 地址)。

2.6 关闭 swap

Kubernetes 要求关闭 swap,原因如下:

  • kubelet 的 QoS(服务质量)保障机制依赖于内存的确定性
  • 开启 swap 会导致 Pod 内存统计不准确,影响调度决策
  • 容器运行时(containerd)也建议关闭 swap
  • 简单来说:swap 让内存看起来比实际更大,但会拖慢性能,Kubernetes 需要精确的内存管理

bash

bash 复制代码
[root@ubuntu2404 ~]# swapoff -a && sed -i '/^.*swap/d' /etc/fstab
[root@ubuntu2404 ~]# rm -f /swap.img

2.7 配置时间同步(chrony)

bash 复制代码
[root@ubuntu2404 ~]# apt-get install -y chrony
[root@ubuntu2404 ~]# systemctl enable chrony --now

为什么需要时间同步? Kubernetes 集群中的证书(如 API Server 证书)依赖时间戳验证,时间不一致会导致证书校验失败。证书验证失败则 kubelet 无法与 API Server 正常通信,集群会处于异常状态。节点间时间差超过 5 分钟(默认)会导致 TLS 握手失败。可以这样理解:证书是有"有效期"的,节点之间时间不一致,就会像两个人手表时间不同,导致"预约"(连接)失败。

2.8 优化 SSH 配置

bash 复制代码
# 禁用 SSH 反向 DNS 解析(加速连接)
[root@ubuntu2404 ~]# echo 'UseDNS no' >> /etc/ssh/sshd_config

# 禁用客户端 SSH 主机密钥检查(自动化脚本免交互)
[root@ubuntu2404 ~]# echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config

# 生成 SSH 密钥对
[root@ubuntu2404 ~]# ssh-keygen -N '' -f ~/.ssh/id_rsa -t rsa

# 配置本机免密登录(替换 password 为实际密码)
[root@ubuntu2404 ~]# sshpass -p password ssh-copy-id root@localhost

SSH 优化的作用

  • UseDNS no:避免每次 SSH 连接时进行反向 DNS 查询,提升连接速度
  • StrictHostKeyChecking no:自动化脚本中无需手动确认主机密钥,便于批量操作

三、内核模块与参数配置

3.1 加载基础网络模块

bash 复制代码
# 临时加载(立即生效)
[root@ubuntu2404 ~]# modprobe overlay
[root@ubuntu2404 ~]# modprobe br_netfilter

# 永久加载(重启生效)
[root@ubuntu2404 ~]# cat > /etc/modules-load.d/k8s-net.conf << EOF
br_netfilter
overlay
EOF

模块功能说明

模块 功能
overlay Overlay 文件系统,容器镜像分层存储必需
br_netfilter 允许 Linux 网桥上的流量经过 iptables 过滤,K8s 网络通信必需

3.2 加载 IPVS 内核模块

IPVS(IP Virtual Server) 是 Linux 内核的负载均衡模块,kube-proxy 的 IPVS 模式比 iptables 模式性能更高,适合大规模集群(1000+ Service)。

IPVS vs iptables 性能对比

对比维度 iptables 模式 IPVS 模式
规则复杂度 线性链表,规则越多越慢 哈希表,O(1) 查询
Service 数量限制 2000 以下 50000+
负载均衡算法 仅轮询 支持 8 种算法
连接跟踪 有(nf_conntrack)
适用场景 小规模集群 大规模、高并发集群
bash 复制代码
# 临时加载
[root@ubuntu2404 ~]# modprobe ip_vs
[root@ubuntu2404 ~]# modprobe ip_vs_rr
[root@ubuntu2404 ~]# modprobe ip_vs_wrr
[root@ubuntu2404 ~]# modprobe ip_vs_lc
[root@ubuntu2404 ~]# modprobe ip_vs_sh
[root@ubuntu2404 ~]# modprobe nf_conntrack

# 永久加载
[root@ubuntu2404 ~]# cat >> /etc/modules-load.d/k8s-net.conf << EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_lc
ip_vs_sh
nf_conntrack
EOF

IPVS 调度算法说明

模块 算法 说明 适用场景
ip_vs_rr 轮询 按顺序轮流分发请求 后端能力均衡
ip_vs_wrr 加权轮询 按权重比例分发请求 后端能力不均
ip_vs_lc 最少连接 优先发给连接数最少的后端 长连接场景
ip_vs_sh 源地址哈希 同一客户端始终访问同一后端 需要会话保持

3.3 配置 sysctl 内核参数

bash 复制代码
[root@ubuntu2404 ~]# cat > /etc/sysctl.d/k8s.conf << 'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
EOF

[root@ubuntu2404 ~]# sysctl -p /etc/sysctl.d/k8s.conf

参数说明

参数 作用 类比
bridge-nf-call-iptables 1 网桥流量经过 iptables 规则 桥梁上的车经过检查站
bridge-nf-call-ip6tables 1 网桥流量经过 ip6tables 规则 IPv6 版本的检查站
ip_forward 1 开启路由转发,Pod 间跨节点通信必需 路由器允许数据包转发
swappiness 0 禁止使用 swap,保证内存确定性 宁可内存不足也不用慢速磁盘

四、容器运行时配置(containerd)

4.1 安装 containerd.io

bash 复制代码
[root@ubuntu2404 ~]# apt-get install -y containerd.io=1.7.20-1 cri-tools

为什么选择 containerd.io 而不是 Ubuntu 仓库的 containerd? containerd.io 由 Docker Inc. 维护,版本更新更快,与 Kubernetes 的兼容性更好。生产环境建议使用此版本。

4.2 配置 crictl 对接 containerd

bash 复制代码
[root@ubuntu2404 ~]# crictl config runtime-endpoint unix:///var/run/containerd/containerd.sock

crictl 的作用:crictl 是 CRI(容器运行时接口)的客户端工具,用于调试 K8s 节点上的容器和镜像。它不依赖 kubectl,直接在节点上操作 containerd。当 Pod 无法启动时,可以使用 crictl 排查节点上的容器状态。可以这样理解:kubectl 是"管理员的遥控器",从集群层面控制;crictl 是"维修工的工具箱",在节点本地排查问题。

4.3 生成并修改 containerd 配置

生成默认配置

bash 复制代码
[root@ubuntu2404 ~]# containerd config default > /etc/containerd/config.toml

修改 SystemdCgroup(与系统 cgroup 驱动保持一致):

bash 复制代码
[root@ubuntu2404 ~]# sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

为什么要改 SystemdCgroup? Kubernetes 使用 systemd 作为 cgroup 驱动,containerd 必须与 kubelet 保持一致。不一致会导致 Pod 资源限制失效,甚至节点异常。具体错误表现为 Pod 的内存限制不生效或 CPU 配额无法正确分配。简单来说:cgroup 是 Linux 限制资源的方式,systemd 是管理这些限制的工具,两者必须匹配,否则"管理员"和"工具"说的不是同一种语言。

修改 sandbox_image(Pause 容器镜像):

bash 复制代码
[root@ubuntu2404 ~]# sed -i 's|sandbox_image = ".*"|sandbox_image = "registry.k8s.io/pause:3.9"|' /etc/containerd/config.toml

Pause 容器的作用:在 Kubernetes 中,每个 Pod 会先启动一个 Pause 容器,它负责持有 Pod 的网络命名空间(Network Namespace),其他业务容器共享这个网络命名空间,从而实现 Pod 内多个容器共享 IP 和端口空间。Pause 容器虽小(约 700KB),但却是 Pod 网络的基础。如果 Pause 容器无法启动,整个 Pod 都无法运行。Pause 容器就像"公寓的公共门厅",业务容器是"各个房间",所有房间共享同一个门牌号(IP 地址)。

4.4 配置镜像加速(CRI 插件方式)

编辑 /etc/containerd/config.toml,在 mirrors 部分添加:

toml 复制代码
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
    endpoint = ["https://docker.m.daocloud.io","https://docker.1ms.run","https://docker.xuanyuan.me"]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
    endpoint = ["https://k8s.m.daocloud.io","https://registry.cn-hangzhou.aliyuncs.com/google_containers"]

提示 :这种 mirrors 配置方式只对 CRI 接口生效 (即 crictl 和 Kubernetes 节点),nerdctl 需要独立的 certs.d 配置(见下一节)。两者分工不同,不能互相替代。

重启 containerd

bash 复制代码
[root@ubuntu2404 ~]# systemctl restart containerd.service

验证镜像加速

bash 复制代码
[root@ubuntu2404 ~]# crictl pull busybox
Image is up to date for sha256:925ff61909...

4.5 安装 nerdctl 和 CNI 插件

下载并安装 nerdctl

bash 复制代码
[root@ubuntu2404 ~]# wget http://192.168.42.200/course-materials/softwares/stage03/nerdctl-1.7.7-linux-amd64.tar.gz
[root@ubuntu2404 ~]# tar -xf nerdctl-1.7.7-linux-amd64.tar.gz -C /usr/bin/

下载并安装 CNI 插件

bash 复制代码
[root@ubuntu2404 ~]# wget http://192.168.42.200/course-materials/softwares/stage03/cni-plugins-linux-amd64-v1.6.0.tgz
[root@ubuntu2404 ~]# mkdir -p /opt/cni/bin
[root@ubuntu2404 ~]# tar -xf cni-plugins-linux-amd64-v1.6.0.tgz -C /opt/cni/bin

配置 nerdctl 镜像加速certs.d 方式):

bash 复制代码
# 配置 docker.io 加速
mkdir -p /etc/containerd/certs.d/docker.io
cat > /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://registry-1.docker.io"
[host."https://09def58152000fc00ff0c00057bad7e0.mirror.swr.myhuaweicloud.com"]
  capabilities = ["pull", "resolve"]
EOF

# 配置 registry.k8s.io 加速
mkdir -p /etc/containerd/certs.d/registry.k8s.io
cat > /etc/containerd/certs.d/registry.k8s.io/hosts.toml << EOF
server = "https://registry.k8s.io"
[host."https://k8s.m.daocloud.io"]
  capabilities = ["pull", "resolve"]
[host."https://registry.cn-hangzhou.aliyuncs.com/google_containers"]
  capabilities = ["pull", "resolve"]
  override_path = true
EOF

五、安装 Kubernetes 组件

5.1 查看可用版本

bash 复制代码
[root@ubuntu2404 ~]# apt list kubeadm -a | head
kubeadm/unknown 1.30.2-1.1 amd64
kubeadm/unknown 1.30.1-1.1 amd64
kubeadm/unknown 1.30.0-1.1 amd64

5.2 安装 kubeadm、kubelet、kubectl

bash 复制代码
[root@ubuntu2404 ~]# apt install -y \
    kubeadm=1.30.2-1.1 \
    kubelet=1.30.2-1.1 \
    kubectl=1.30.2-1.1

# 设置 kubelet 开机自启(此时会处于等待状态,集群初始化后变为 active)
[root@ubuntu2404 ~]# systemctl enable kubelet --now

组件说明

  • kubeadm:集群部署工具,用于初始化和加入集群
  • kubelet:节点代理,管理 Pod 生命周期
  • kubectl:命令行客户端,与集群交互

kubelet 状态说明:安装完成后 kubelet 会不断重启等待集群初始化,这是正常现象。可以这样理解:kubelet 是"雇佣兵",必须等"指挥官"(kubeadm)下达指令后才开始正式工作。

5.3 配置命令补全

bash 复制代码
# crictl 补全
[root@ubuntu2404 ~]# mkdir -p /etc/bash_completion.d
[root@ubuntu2404 ~]# crictl completion bash > /etc/bash_completion.d/crictl
[root@ubuntu2404 ~]# source /etc/bash_completion.d/crictl

# nerdctl 补全(关键:设置命名空间为 k8s.io)
[root@ubuntu2404 ~]# nerdctl completion bash > /etc/bash_completion.d/nerdctl
[root@ubuntu2404 ~]# echo 'export CONTAINERD_NAMESPACE=k8s.io' >> /etc/bash_completion.d/nerdctl
[root@ubuntu2404 ~]# source /etc/bash_completion.d/nerdctl

# kubectl 补全
[root@ubuntu2404 ~]# kubectl completion bash > /etc/bash_completion.d/kubectl
[root@ubuntu2404 ~]# source /etc/bash_completion.d/kubectl

# kubeadm 补全
[root@ubuntu2404 ~]# kubeadm completion bash > /etc/bash_completion.d/kubeadm
[root@ubuntu2404 ~]# source /etc/bash_completion.d/kubeadm

⚠️ 重要 :设置 CONTAINERD_NAMESPACE=k8s.io 非常关键!Kubernetes 默认使用 k8s.io 命名空间中的镜像。如果不设置,nerdctl 默认将镜像导入到 default 命名空间,会导致 kubelet 无法找到镜像(会报 failed to pull image 错误)。在 K8s 节点上使用 nerdctl 时,务必确认命名空间为 k8s.io。命名空间可以理解为"冰箱里的不同隔层",kubelet 只认 k8s.io 这个隔层里的东西。

5.4 关闭模板机

bash 复制代码
[root@ubuntu2404 ~]# init 0

六、克隆节点与配置

6.1 克隆虚拟机

采用 VMware 完全克隆方法,克隆出 3 台虚拟机(1 Master + 2 Worker)。

6.2 Master 节点配置(10.1.8.30)

yaml 复制代码
# 设置主机名
[root@master30 ~]# hostnamectl set-hostname master30.whisky.cloud

# 配置静态 IP
[root@master30 ~]# cat > /etc/netplan/00-static.yaml <<EOF
network:
  ethernets:
    ens32:
      dhcp4: no
      addresses:
        - 10.1.8.30/24
      routes:
        - to: default
          via: 10.1.8.2
      nameservers:
        addresses:
          - 223.5.5.5
  version: 2
EOF
[root@master30 ~]# netplan apply

6.3 Worker 节点配置(10.1.8.31 / 10.1.8.32)

Worker31

yaml 复制代码
[root@worker31 ~]# hostnamectl set-hostname worker31.whisky.cloud
[root@worker31 ~]# cat > /etc/netplan/00-static.yaml <<EOF
network:
  ethernets:
    ens32:
      dhcp4: no
      addresses:
        - 10.1.8.31/24
      routes:
        - to: default
          via: 10.1.8.2
      nameservers:
        addresses:
          - 223.5.5.5
  version: 2
EOF
[root@worker31 ~]# netplan apply

Worker32(同理,IP 设为 10.1.8.32)。

七、集群初始化(Master 节点)

7.1 预下载镜像(可选但推荐)

方式一:使用官方仓库

bash 复制代码
[root@master30 ~]# kubeadm config images pull --kubernetes-version=v1.30.2
[config/images] Pulled registry.k8s.io/kube-apiserver:v1.30.2
[config/images] Pulled registry.k8s.io/kube-controller-manager:v1.30.2
[config/images] Pulled registry.k8s.io/kube-scheduler:v1.30.2
[config/images] Pulled registry.k8s.io/kube-proxy:v1.30.2
[config/images] Pulled registry.k8s.io/coredns/coredns:v1.11.1
[config/images] Pulled registry.k8s.io/pause:3.9
[config/images] Pulled registry.k8s.io/etcd:3.5.12-0

方式二:使用阿里云镜像仓库(国内网络更快):

bash 复制代码
[root@master30 ~]# kubeadm config images pull \
    --kubernetes-version=v1.30.2 \
    --image-repository registry.aliyuncs.com/google_containers

7.2 Worker 节点预下载必要镜像

Worker 节点只需 kube-proxy 和 pause 镜像:

bash 复制代码
[root@worker31 ~]# nerdctl pull registry.k8s.io/kube-proxy:v1.30.2
[root@worker31 ~]# nerdctl pull registry.k8s.io/pause:3.9

[root@worker32 ~]# nerdctl pull registry.k8s.io/kube-proxy:v1.30.2
[root@worker32 ~]# nerdctl pull registry.k8s.io/pause:3.9

7.3 初始化集群

bash 复制代码
[root@master30 ~]# kubeadm init \
    --kubernetes-version=v1.30.2 \
    --pod-network-cidr=10.224.0.0/16

参数说明

参数 说明
--kubernetes-version 指定 Kubernetes 版本
--pod-network-cidr 指定 Pod 网络地址范围,必须与网络插件配置一致
--image-repository (可选)指定镜像仓库,默认 registry.k8s.io
--apiserver-advertise-address (可选)指定 API Server 通信 IP,默认自动选择

7.4 初始化过程详解

初始化过程包含以下关键阶段,每个阶段都有明确的职责:

  1. [preflight] --- 执行预检查
    • 检查系统版本、内核参数、swap 是否关闭
    • 检查端口是否被占用(6443、2379、2380、10250 等)
    • 检查容器运行时是否可用
  2. [certs] --- 生成证书
    • CA 证书(集群根证书)
    • API Server 证书
    • kubelet 客户端证书
    • etcd 相关证书
    • 证书有效期默认为 1 年
  3. [kubeconfig] --- 生成 kubeconfig 配置文件
    • admin.conf(管理员用)
    • kubelet.conf(kubelet 用)
    • controller-manager.conf、scheduler.conf
  4. [etcd] --- 部署 etcd 静态 Pod
    • etcd 作为集群数据库,存储所有集群状态数据
  5. [control-plane] --- 部署控制平面组件
    • kube-apiserver、kube-controller-manager、kube-scheduler
    • 以静态 Pod 形式运行在 /etc/kubernetes/manifests/ 目录下
  6. [addons] --- 部署 CoreDNS 和 kube-proxy
    • CoreDNS 为集群提供内部 DNS 解析
    • kube-proxy 为 Service 提供网络代理

7.5 初始化成功输出

bash 复制代码
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

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 10.1.8.30:6443 --token mi0yt8.1tzza4q64dr8y3pc \
    --discovery-token-ca-cert-hash sha256:5606e09618330aee8859abe3ea4cd8734f9b540630048a6e1c3aaf6c54d486fd

7.6 配置 kubectl 凭据

方式一:默认位置(推荐):

bash 复制代码
[root@master30 ~]# mkdir -p $HOME/.kube
[root@master30 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master30 ~]# chown $(id -u):$(id -g) $HOME/.kube/config

方式二:环境变量

bash 复制代码
[root@master30 ~]# export KUBECONFIG=/etc/kubernetes/admin.conf

方式三:命令行参数

bash 复制代码
[root@master30 ~]# kubectl get nodes --kubeconfig /etc/kubernetes/admin.conf

八、部署网络插件(Calico)

8.1 为什么需要网络插件?

Kubernetes 集群初始化后,CoreDNS 等 Pod 会处于 Pending 状态,节点状态为 NotReady。这是因为缺少网络插件(CNI),Pod 无法获得 IP 地址。

CNI(Container Network Interface) 是 Kubernetes 的网络标准,所有网络插件都遵循此规范。可以这样理解:CNI 是"网络插座的统一规格",Calico、Flannel 等是"不同品牌的插头",都遵循同一个标准,所以可以即插即用。

Calico 是 Kubernetes 最流行的网络插件之一,支持网络策略(Network Policy),性能优秀,适合生产环境。它基于 BGP 协议实现跨节点 Pod 通信,无需 NAT,性能损耗小。

8.2 下载 Calico 配置

bash 复制代码
[root@master30 ~]# wget --no-check-certificate \
    https://raw.githubusercontent.com/projectcalico/calico/v3.30.7/manifests/calico.yaml

8.3 修改 Pod 网络 CIDR

确认集群 Pod 网络范围

bash 复制代码
[root@master30 ~]# kubectl get cm -n kube-system kubeadm-config -o yaml | grep podSubnet
      podSubnet: 10.224.0.0/16

修改 calico.yaml ,确保 CALICO_IPV4POOL_CIDR 与集群配置一致:

bash 复制代码
[root@master30 ~]# sed -i "s|# - name: CALICO_IPV4POOL_CIDR|- name: CALICO_IPV4POOL_CIDR|g" calico.yaml
[root@master30 ~]# sed -i "s|#   value: \"192.*|  value: \"10.224.0.0/16\"|g" calico.yaml

8.4 所有节点下载 Calico 镜像

bash 复制代码
[root@master30 ~]# grep image: calico.yaml | uniq
          image: docker.io/calico/cni:v3.30.7
          image: docker.io/calico/node:v3.30.7
          image: docker.io/calico/kube-controllers:v3.30.7

# 所有节点执行
[root@master30 ~]# nerdctl pull docker.io/calico/cni:v3.30.7
[root@master30 ~]# nerdctl pull docker.io/calico/node:v3.30.7
[root@master30 ~]# nerdctl pull docker.io/calico/kube-controllers:v3.30.7

8.5 部署 Calico

bash 复制代码
[root@master30 ~]# kubectl apply -f calico.yaml

8.6 验证网络插件部署

bash 复制代码
[root@master30 ~]# kubectl get pods -n kube-system -l k8s-app=calico-node
NAME                READY   STATUS    RESTARTS   AGE
calico-node-vc9v6   1/1     Running   0          2m

九、Worker 节点加入集群

9.1 获取加入命令

如果忘记保存初始化输出,可通过以下命令重新生成:

bash 复制代码
[root@master30 ~]# kubeadm token create --print-join-command
kubeadm join 10.1.8.30:6443 --token dzpuca.8lqxqqydwskroabx --discovery-token-ca-cert-hash sha256:5606e09618330aee8859abe3ea4cd8734f9b540630048a6e1c3aaf6c54d486fd

9.2 Worker 节点加入

bash 复制代码
# Worker31
[root@worker31 ~]# kubeadm join 10.1.8.30:6443 \
    --token mi0yt8.1tzza4q64dr8y3pc \
    --discovery-token-ca-cert-hash sha256:5606e09618330aee8859abe3ea4cd8734f9b540630048a6e1c3aaf6c54d486fd

[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[kubelet-start] Writing kubelet configuration...
[kubelet-start] Starting the kubelet
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

# Worker32 同理

十、验证集群

10.1 查看集群信息

bash 复制代码
[root@master30 ~]# kubectl cluster-info
Kubernetes control plane is running at https://10.1.8.30:6443
CoreDNS is running at https://10.1.8.30:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

10.2 查看版本

bash 复制代码
[root@master30 ~]# kubectl version
Client Version: v1.30.2
Server Version: v1.30.2

10.3 查看节点状态

bash 复制代码
[root@master30 ~]# kubectl get nodes
NAME                  STATUS   ROLES           AGE   VERSION
master30.whisky.cloud   Ready    control-plane   9h    v1.30.2
worker31.whisky.cloud   Ready    <none>          8h    v1.30.2
worker32.whisky.cloud   Ready    <none>          8h    v1.30.2

节点状态为 Ready 的前提条件

  • ✅ 网络插件部署成功(Calico/Flannel)
  • ✅ kubelet 服务正常运行
  • ✅ swap 已关闭
  • ✅ 内核参数正确

10.4 查看 Pod 状态

bash 复制代码
[root@master30 ~]# kubectl get pods -A
NAMESPACE     NAME                                          READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-7cb4fd5784-jx2xl      1/1     Running   0          11m
kube-system   calico-node-4b6s8                             1/1     Running   0          11m
kube-system   calico-node-bsr7v                             1/1     Running   0          11m
kube-system   calico-node-v8jdn                             1/1     Running   0          11m
kube-system   coredns-66f779496c-4j88h                      1/1     Running   0          13m
kube-system   coredns-66f779496c-fnb8m                      1/1     Running   0          13m
kube-system   etcd-master30.whisky.cloud                     1/1     Running   0          13m
kube-system   kube-apiserver-master30.whisky.cloud           1/1     Running   0          13m
kube-system   kube-controller-manager-master30.whisky.cloud  1/1     Running   0          13m
kube-system   kube-proxy-27vl2                              1/1     Running   0          11m
kube-system   kube-proxy-npv9h                              1/1     Running   0          11m
kube-system   kube-proxy-q2qrs                              1/1     Running   0          11m
kube-system   kube-scheduler-master30.whisky.cloud           1/1     Running   0          13m

10.5 部署测试应用验证集群功能

bash 复制代码
[root@master30 ~]# kubectl create deployment nginx-test --image=nginx --replicas=2
deployment.apps/nginx-test created

[root@master30 ~]# kubectl expose deployment nginx-test --port=80 --type=NodePort
service/nginx-test exposed

[root@master30 ~]# kubectl get pods -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP               NODE
nginx-test-xxxxxxxxx-xxxxx   1/1     Running   0          30s   10.224.113.xxx   worker31
nginx-test-xxxxxxxxx-xxxxx   1/1     Running   0          30s   10.224.114.xxx   worker32

[root@master30 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx-test   NodePort    10.96.xxx.xxx    <none>        80:30080/TCP   10s

# 测试访问(在集群内任一节点执行)
[root@master30 ~]# curl http://10.224.113.xxx:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</html>

十一、总结与知识点一览表

11.1 部署流程速查表

阶段 关键操作 关键命令
环境准备 配置仓库、安装软件、关闭 swap apt update, swapoff -a
内核配置 加载模块、配置 sysctl modprobe, sysctl -p
容器运行时 安装 containerd、配置加速 crictl config, containerd config default
安装 K8s 安装 kubeadm/kubelet/kubectl apt install kubeadm
克隆节点 克隆 VM、配置 IP/主机名 hostnamectl, netplan apply
集群初始化 kubeadm init kubeadm init --pod-network-cidr
网络插件 部署 Calico kubectl apply -f calico.yaml
加入节点 worker 加入集群 kubeadm join

11.2 核心配置汇总

组件 配置文件 关键参数
containerd /etc/containerd/config.toml SystemdCgroup=true, sandbox_image
kubelet /var/lib/kubelet/config.yaml 由 kubeadm 自动生成
Calico calico.yaml CALICO_IPV4POOL_CIDR=10.224.0.0/16
kubectl ~/.kube/config 从 admin.conf 复制

11.3 常见错误排查

错误 原因 解决方法
[ERROR Swap] swap 未关闭 swapoff -a 并注释 fstab
[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables] 内核参数未配置 sysctl -p /etc/sysctl.d/k8s.conf
crictl 连接失败 runtime-endpoint 未配置 crictl config runtime-endpoint unix:///...
kubelet 无法启动 命名空间配置错误 确认 CONTAINERD_NAMESPACE=k8s.io
kubectl get nodes 显示 NotReady 网络插件未部署 部署 Calico 并等待 Pod 就绪
failed to pull image 镜像拉取超时或命名空间错误 配置镜像加速,检查命名空间
节点加入超时 token 过期或网络不通 重新生成 token,检查网络连通性

11.4 节点状态说明

状态 含义 可能原因
Ready 节点正常 所有组件健康
NotReady 节点不可用 kubelet 未运行、网络插件未部署
Unknown 状态未知 网络中断、节点宕机
SchedulingDisabled 调度禁用 节点被 cordon(维护模式)

11.5 扩容与后续步骤

集群部署完成后,你可以:

  1. 增加 Worker 节点:重复"克隆节点 → 配置 IP → kubeadm join"流程
  2. 部署应用:通过 Deployment 部署 Nginx 等测试应用
  3. 配置存储:部署 CSI 存储插件(如 NFS、Ceph)
  4. 配置 Ingress:部署 Ingress Controller(如 Nginx Ingress)
  5. 启用 Dashboard:部署 Kubernetes Dashboard 可视化界面
  6. 配置监控:部署 Prometheus + Grafana 监控体系

下一期预告:Kubernetes 集群基础管理------节点管理、Namespace 隔离、上下文切换、多集群配置等日常运维操作。
--- Compiled and Authored by Whisky --- June 23 rd, 2026