🚀 使用 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_netfilter和net.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?
- 稳定性:Pod 应基于资源 requests/limits 调度,swap 会导致性能不可预测
- kubelet 设计前提:kubelet 假设节点上每个 Pod 有稳定的内存上限
- 历史原因:早期 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 Flannel 10.244.0.0/16Calico 192.168.0.0/16Weave 10.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>
这段输出包含了三个核心信息:
- kubeconfig 配置 — 配置 kubectl 才能管理集群
- join 命令 — Worker 节点加入集群的凭证
- 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