前言
还记得我第一次部署 Kubernetes 的场景。
那时候听说 K8s 很火,想学习一下。网上找教程,大部分都是推荐二进制部署,说这样"更灵活"、"更底层"。好嘛,那我就跟着做。
结果这一折腾就是整整3天:
- etcd 证书生成失败,报错信息模糊不清
- kubelet 和 kube-apiserver 版本不匹配
- 各种依赖包缺这少那
- 网络插件装完,Pod 就是连不通
- ...
最后一天深夜,我实在受不了,搜了下 "Kubernetes 最简单的安装方式",才发现有 kubeadm 这个神器。
10分钟,一个可用的集群就搭起来了。
当时我那个心情啊------既高兴又懊恼。高兴的是终于跑通了,懊恼的是为什么不早点知道 kubeadm。
所以今天这篇文章,把我用 kubeadm 部署集群的完整流程分享出来,帮你少走3天弯路。
一、环境准备
1.1 服务器配置要求
在开始之前,先确认你的环境满足以下条件:
| 配置项 | 最低要求 | 推荐配置 |
|---|---|---|
| 操作系统 | CentOS 7+ / Ubuntu 18.04+ | CentOS 7.9 / Ubuntu 20.04 |
| CPU | 2核 | 4核+ |
| 内存 | 2GB | 4GB+ |
| 硬盘 | 20GB | 50GB+ |
| 网络 | 节点间互通 | 内网互通,可访问外网 |
| 节点数 | 1 Master + 1 Worker | 1 Master + 2+ Worker |
⚠️ 注意:如果只有一台机器,也可以部署单节点集群(Master 同时作为 Worker),但生产环境不推荐这样做。
1.2 节点规划示例
我的测试环境配置:
| 角色 | IP地址 | 主机名 | 配置 |
|---|---|---|---|
| Master | 192.168.0.112 | k8s-master | 4C8G |
| Worker1 | 192.168.0.113 | k8s-worker1 | 2C4G |
| Worker2 | 192.168.0.114 | k8s-worker2 | 2C4G |
二、前置准备工作
2.1 修改主机名(所有节点)
首先,给每个节点设置一个有意义的主机名,方便后续管理。
bash
# 在 Master 节点执行
hostnamectl set-hostname k8s-master
# 在 Worker1 节点执行
hostnamectl set-hostname k8s-worker1
# 在 Worker2 节点执行
hostnamectl set-hostname k8s-worker2
# 查看修改结果
hostnamectl status
2.2 配置 hosts 解析(所有节点)
确保每个节点都能通过主机名访问其他节点:
bash
# 编辑 /etc/hosts 文件,添加以下内容
cat >> /etc/hosts << EOF
192.168.0.112 k8s-master
192.168.0.113 k8s-worker1
192.168.0.114 k8s-worker2
EOF
# 验证
ping k8s-master -c 3
💡 小贴士:生产环境建议使用内网 DNS 或 Consul 等服务发现方案,而不是手动配置 hosts。
2.3 关闭防火墙和 SELinux(所有节点)
Kubernetes 需要开放很多端口,为避免网络问题,先关闭防火墙:
bash
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭 SELinux
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
# 验证
getenforce # 应该显示 Disabled 或 Permissive
🔥 坑点警示:我第一次部署时没关 SELinux,结果 kubelet 一直启动失败,报错信息还不明显。折腾了2小时才发现是 SELinux 的问题。务必关闭!
2.4 关闭 swap(所有节点)
Kubernetes 要求关闭 swap,否则 kubelet 无法启动:
bash
# 临时关闭
swapoff -a
# 永久关闭(注释掉 swap 相关的行)
sed -i '/swap/d' /etc/fstab
# 验证
free -h # 确认 swap 显示为 0
⚠️ 为什么必须关闭 swap? 因为 K8s 需要精确控制内存分配,swap 会干扰资源调度。不过 K8s 1.22+ 版本开始支持在特定场景下启用 swap。
2.5 配置内核参数(所有节点)
bash
# 加载必要的内核模块
cat > /etc/modules-load.d/k8s.conf << EOF
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
# 配置 sysctl 参数
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
EOF
# 生效
sysctl --system
三、安装容器运行时(所有节点)
Kubernetes 需要一个容器运行时(Container Runtime)。常见的选择有:
- Docker:最常用,生态完善
- containerd:更轻量,K8s 1.24+ 的默认选择
这里我们使用 Docker:
bash
# 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加阿里云镜像源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装 Docker
yum install -y docker-ce-20.10.17 docker-ce-cli-20.10.17 containerd.io
# 启动 Docker
systemctl start docker
systemctl enable docker
# 验证
docker version
3.1 配置镜像加速器
国内访问 Docker Hub 很慢,建议配置镜像加速器:
bash
# 创建 Docker 配置文件
mkdir -p /etc/docker
# 配置阿里云镜像加速器(换成你自己的)
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://registry.cn-hangzhou.aliyuncs.com",
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
# 重启 Docker
systemctl daemon-reload
systemctl restart docker
💡 获取个人加速器 :登录 阿里云容器镜像服务,左侧菜单找到"镜像工具"-"镜像加速器",复制你的专属地址。
四、安装 kubeadm、kubelet、kubectl(所有节点)
这三个工具是 Kubernetes 的核心:
- kubeadm:集群初始化和管理工具
- kubelet:运行在每个节点上,管理 Pod 生命周期
- kubectl:K8s 命令行工具,用于操作集群
4.1 使用一键安装脚本
为了简化安装,我用了一个开源的安装脚本:
bash
# 设置镜像仓库(使用阿里云镜像)
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
# 执行安装脚本(安装 v1.21.0 版本)
# 最后一个参数 1.21.0 用于指定 Kubernetes 版本,支持所有 1.21.x 版本
curl -sSL https://kuboard.cn/install-script/v1.21.x/install_kubelet.sh | sh -s 1.21.0
🔥 坑点警示 :不设置
REGISTRY_MIRROR的话,默认从 Google 仓库拉镜像,在国内基本拉不下来。务必配置国内镜像!
脚本会自动完成以下工作:
- 配置 Kubernetes yum 源
- 安装指定版本的 kubeadm、kubelet、kubectl
- 启动 kubelet 服务
4.2 验证安装
bash
# 查看版本
kubeadm version
kubectl version --client
kubelet --version
# 设置 kubelet 开机自启
systemctl enable kubelet
💡 为什么 kubelet 启动失败是正常的? 因为 kubelet 需要连接 API Server,而此时集群还没有初始化。等 Master 初始化完成后,kubelet 会自动恢复正常。
五、初始化 Master 节点
5.1 配置环境变量
bash
# 替换为你的 Master 节点实际内网 IP
export MASTER_IP=192.168.0.112
# 设置 API Server 的域名(可以自定义)
export APISERVER_NAME=apiserver.demo
# Kubernetes Pod 网段(确保该网段不与你的物理网络冲突)
export POD_SUBNET=10.100.0.0/16
# 添加 hosts 解析
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
⚠️ 重要提示 :
POD_SUBNET必须是你的物理网络中没有使用的网段。如果你的内网是 10.x.x.x,可能需要改成 172.16.0.0/16 或 192.168.x.x。
5.2 执行初始化
bash
# 执行初始化脚本
curl -sSL https://kuboard.cn/install-script/v1.21.x/init_master.sh | sh -s 1.21.0
脚本会自动:
- 使用 kubeadm 初始化集群
- 安装网络插件(Flannel 或 Calico)
- 配置 kubectl
- 输出加入集群的命令
5.3 保存加入命令
初始化成功后,你会看到类似这样的输出:
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
Then, you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.0.112:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxx
务必保存好这个 join 命令,Worker 节点需要用它加入集群。
5.4 配置 kubectl(Master 节点)
bash
# 配置 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,不要着急,等网络插件启动完成:
bash
# 查看系统 Pod 状态
kubectl get pods -n kube-system
# 等待所有 Pod 状态变为 Running
watch kubectl get pods -n kube-system
⏱️ 时间参考:网络插件初始化通常需要 1-3 分钟。
六、Worker 节点加入集群
6.1 配置 hosts(Worker 节点)
bash
# 配置环境变量
export MASTER_IP=192.168.0.112
export APISERVER_NAME=apiserver.demo
# 添加 hosts 解析
echo "${MASTER_IP} ${APISERVER_NAME}" >> /etc/hosts
6.2 执行加入命令
在每个 Worker 节点上,执行 Master 初始化时保存的 join 命令:
bash
kubeadm join 192.168.0.112:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxx
如果成功,会看到:
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.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
6.3 验证集群状态(Master 节点)
bash
# 查看所有节点
kubectl get nodes
# 预期输出:
# NAME STATUS ROLES AGE VERSION
# k8s-master Ready control-plane,master 5m v1.21.0
# k8s-worker1 Ready <none> 1m v1.21.0
# k8s-worker2 Ready <none> 1m v1.21.0
🎉 恭喜!你的 Kubernetes 集群已经搭建完成!
七、验证集群功能
7.1 部署一个测试应用
bash
# 创建一个 Nginx Deployment
kubectl create deployment nginx --image=nginx:alpine --replicas=3
# 暴露为 Service
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看 Pod 状态
kubectl get pods -o wide
# 查看 Service
kubectl get svc nginx
7.2 访问测试应用
bash
# 获取 NodePort
NODE_PORT=$(kubectl get svc nginx -o jsonpath='{.spec.ports[0].nodePort}')
echo "Nginx 访问地址: http://<NodeIP>:$NODE_PORT"
# 测试访问
curl http://192.168.0.112:$NODE_PORT
如果能看到 Nginx 的欢迎页面,说明集群工作正常!
八、我踩过的坑(避坑指南)
坑 1:镜像拉取失败
现象 :Pod 状态一直是 ImagePullBackOff
原因:Docker 没有配置镜像加速器,从 Docker Hub 拉镜像超时
解决:
bash
# 配置阿里云镜像加速器
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://registry.cn-hangzhou.aliyuncs.com"]
}
EOF
systemctl restart docker
坑 2:Node 无法加入集群
现象 :执行 kubeadm join 报错:connection refused
原因:Worker 节点无法访问 Master 的 6443 端口
解决:
bash
# 在 Worker 节点测试连通性
telnet 192.168.0.112 6443
# 如果不通,检查:
# 1. Master 防火墙是否放行 6443
# 2. hosts 配置是否正确
坑 3:Coredns Pod 一直 Pending
现象 :kubectl get pods -n kube-system 看到 coredns 状态为 Pending
原因:网络插件(如 Flannel)没有正确安装
解决:
bash
# 手动安装 Flannel
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
# 或者安装 Calico
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
坑 4:忘记保存 join token
现象:初始化 Master 后,没有保存 join 命令,Worker 无法加入
解决:
bash
# 在 Master 节点重新生成 token
kubeadm token create --print-join-command
坑 5:Pod 无法跨 Node 通信
现象:Pod 在同节点内可以通信,跨节点不通
原因:网络插件配置问题,或者节点间网络策略限制
解决:
bash
# 检查网络插件是否正常
kubectl get pods -n kube-system -l app=flannel
# 检查节点间连通性(从 Worker ping Master 的 POD_CIDR)
ping 10.100.0.1
九、常用命令速查
| 命令 | 说明 |
|---|---|
kubectl get nodes |
查看所有节点 |
kubectl get pods -A |
查看所有命名空间的 Pod |
kubectl get pods -o wide |
查看 Pod 详细信息(包括 IP、Node) |
kubectl describe node <node-name> |
查看节点详情 |
kubectl logs <pod-name> |
查看 Pod 日志 |
kubectl exec -it <pod-name> -- /bin/sh |
进入 Pod 容器 |
kubectl get svc |
查看所有 Service |
kubectl delete pod <pod-name> |
删除 Pod |
kubeadm token create --print-join-command |
重新生成 join 命令 |
十、清理集群(如需重建)
如果你想重新部署,可以先清理:
bash
# 在 Worker 节点执行
kubeadm reset -f
# 在 Master 节点执行
kubeadm reset -f
rm -rf $HOME/.kube/config
rm -rf /etc/cni/net.d
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
ipvsadm --clear
总结
跟着这篇指南,你应该已经在 10 分钟内搭建好了一个可用的 Kubernetes 集群。
关键步骤回顾:
- ✅ 环境准备(修改主机名、关闭防火墙/swap)
- ✅ 安装 Docker 并配置镜像加速器
- ✅ 安装 kubeadm、kubelet、kubectl
- ✅ 初始化 Master 节点
- ✅ Worker 节点加入集群
- ✅ 验证集群功能