Kubernetes

使用 kubeadm 创建集群

·14 分钟阅读·5222 字

从零到一的 kubeadm 实战指南,涵盖核心原理、手把手操作步骤、面试高频考点、生产环境高可用搭建

📋 目录

🚀 使用 kubeadm 创建集群

关于本文档

本文档从官方文档提炼+个人学习角度重新编排,将枯燥的官方步骤转化为:

  • 原理先行 — 先理解”为什么”,再执行”怎么做”
  • 实操步骤 — 可直接复制的命令和配置
  • 面试考点 — 每个环节标注常见面试题
  • 生产高可用 — 完整 HA 搭建流程
  • 避坑指南 — 真实踩坑经验总结

📋 学习路线图

flowchart LR
    A[环境准备] --> B[安装容器运行时]
    B --> C[安装 kubeadm/kubelet/kubectl]
    C --> D{搭建模式}
    D -->|学习/测试| E[单控制平面]
    D -->|生产环境| F[高可用 HA]
    E --> G[安装 Pod 网络]
    F --> H[搭建负载均衡器]
    H --> I[初始化首节点<br/>--control-plane-endpoint]
    I --> J[加入其他<br/>控制平面节点]
    J --> K[加入 Worker 节点]
    G --> L[加入 Worker 节点]
    K --> M[验证集群]
    L --> M
    
    style M fill:#4CAF50,color:#fff
    style I fill:#2196F3,color:#fff
    style F fill:#FF9800,color:#fff

🎯 学习目标

等级目标面试价值
🌟 基础能在一台机器上搭建单控制平面集群必备操作题
🌟🌟 进阶理解 kubeadm init 每个步骤背后的原理高频理论题
🌟🌟🌟 深入能排查集群启动失败、证书过期等问题加分进阶题
🏭 生产能搭建多控制平面高可用集群架构师必备

📖 :前置知识 — 理解 kubeadm

1.1 什么是 kubeadm?

kubeadm 是 Kubernetes 官方提供的集群快速搭建工具,它的定位是:

“一个能创建符合最佳实践的最小化 Kubernetes 集群的工具”

不是一键安装脚本,而是帮你完成了集群初始化的标准化流程

1.2 kubeadm 能做什么 / 不能做什么

✅ 能做❌ 不做
初始化控制平面安装容器运行时(需手动)
生成证书和 kubeconfig安装 Pod 网络插件(需手动)
启动 etcd、API Server 等组件管理节点上的 kubelet 版本
生成 join 令牌供节点加入高可用部署(需额外配置)
支持集群升级一键生产环境(需加固)

1.3 环境要求

最低硬件要求

资源要求说明
内存≥ 2GB不足则应用受限制
CPU≥ 2 核(控制平面)kubeadm 检测到 1 核会拒绝
网络节点间完全互通公网或私有网络均可
操作系统Linux(deb/rpm)Ubuntu / CentOS 等

1.4 版本兼容性(面试重点 🎯)

面试高频题:kubeadm 与控制平面组件的版本关系是?

组件版本偏差示例
kubeadm → API Server必须 ≤ 控制平面版本kubeadm 1.36 → API Server 1.36
kubeadm → kubelet可差 3 个小版本kubeadm 1.36 → kubelet 1.33~1.36
kubelet → API Server可差 2 个小版本kubelet 1.34 → API Server 1.36

记忆口诀:kubeadm 不能比 kubelet 新超过 3 个版本,kubelet 不能比 API Server 旧超过 2 个版本。


⚡ :环境准备 🛠️

2.1 安装容器运行时

为什么需要?Kubernetes 需要容器运行时才能运行 Pod。常见选择:

  • containerd(推荐,K8s 1.24+ 默认移除 dockershim)
  • CRI-O
  • Docker(需安装 cri-dockerd 适配器)
## ----- 以 containerd 为例 -----

## 📖 启用内核模块
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

## ⚡ 设置 sysctl 参数(让节点能正确转发网络流量)
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system

## 🔧 安装 containerd
sudo apt-get update
sudo apt-get install -y containerd

## ⚙️ 配置 containerd(使用 systemd cgroup 驱动)
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

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

sudo systemctl restart containerd

面试常问:为什么需要 br_netfilternet.bridge.bridge-nf-call-iptables

因为 Kubernetes 的 Pod 网络使用了 bridge 网络模式,数据包在 bridge 上传输时需要经过 iptables 规则过滤,才能正确实现 NetworkPolicy 等功能。

2.2 安装 kubeadm / kubelet / kubectl

## ----- Ubuntu 示例 -----

## 📖 添加 K8s 官方源
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list

## ⚡ 安装指定版本(面试常问:为什么需要固定版本?)
sudo apt-get update
sudo apt-get install -y kubelet=1.36.0-1.1 kubeadm=1.36.0-1.1 kubectl=1.36.0-1.1

## 🔧 锁定版本,防止意外升级
sudo apt-mark hold kubelet kubeadm kubectl

面试高频题:为什么生产中要执行 apt-mark hold

因为 kubelet节点级服务,意外升级可能导致版本不兼容,甚至整个集群 kubelet 停止工作。生产环境必须锁定版本,通过灰度升级流程来管理版本变化。

2.3 关闭交换分区

sudo swapoff -a
## 并注释 /etc/fstab 中的 swap 条目使其持久化

面试高频题:Kubernetes 为什么要关闭 swap?

  1. 稳定性:Pod 应基于资源 requests/limits 调度,swap 会导致性能不可预测
  2. kubelet 设计前提:kubelet 假设节点上每个 Pod 有稳定的内存上限
  3. 历史原因:早期 kubelet 在有 swap 的情况下甚至无法启动

最新的 K8s 版本开始实验性支持 swap(Alpha 特性),但生产仍推荐关闭。


🔧 :初始化控制平面 🔥

3.1 kubeadm init 核心概念

kubeadm init 到底做了什么?(面试高频!)

flowchart TD
    A[kubeadm init] --> B[运行预检 Preflight Checks]
    B --> C[生成 CA 证书]
    C --> D[生成各组件证书]
    D --> E[生成 kubeconfig 文件]
    E --> F[生成 Static Pod Manifests]
    F --> G[启动 etcd]
    G --> H[启动 API Server]
    H --> I[启动 Controller Manager]
    I --> J[启动 Scheduler]
    J --> K[生成 bootstrap token]
    K --> L[安装核心附加组件]

每一步都对应着 /etc/kubernetes/manifests/ 目录下的一个静态 Pod YAML 文件。

3.2 执行初始化

## ----- 最简单的初始化 -----
sudo kubeadm init

## ----- 常用参数形式 -----
sudo kubeadm init \
  --apiserver-advertise-address=192.168.1.100 \  # 控制节点 IP
  --pod-network-cidr=10.244.0.0/16 \              # Pod 网段
  --service-cidr=10.96.0.0/12 \                   # Service 网段
  --control-plane-endpoint=cluster-endpoint       # 高可用时使用

注意

--pod-network-cidr 的选择必须与后面安装的 Pod 网络插件要求一致。

网络插件推荐 CIDR
Flannel10.244.0.0/16
Calico192.168.0.0/16
Weave10.32.0.0/12

3.3 init 成功后的输出解读

Your Kubernetes control-plane has been 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 can now join any number of worker nodes by running the following on each node:

kubeadm join 192.168.1.100:6443 --token <token> \
    --discovery-token-ca-cert-hash sha256:<hash>

这段输出包含了三个核心信息:

  1. kubeconfig 配置 — 配置 kubectl 才能管理集群
  2. join 命令 — Worker 节点加入集群的凭证
  3. Token 和 Hash — 一次性安全凭证

3.4 配置 kubectl

## 作为普通用户执行
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

## 验证
kubectl get nodes
## 输出:master节点状态为 NotReady(因为还没装网络插件)

3.5 重新生成 join 令牌

## Token 默认 24 小时后过期
kubeadm token create --print-join-command