最近在本地环境搭建了一套 Kubernetes 1.27 集群(1 Master + 2 Node),整个过程踩了不少坑,尤其是国内网络环境下镜像拉取、Containerd 配置等问题。本文把完整的搭建步骤和避坑经验记录下来,方便以后参考,也希望能帮到有需要的朋友。
一、环境说明
- 操作系统:CentOS 7.9(三台虚拟机)
- Kubernetes 版本:1.27.0
- 容器运行时:Containerd(K8s 官方推荐,已取代 Docker)
- 网络插件:Calico
- 节点规划:k8s-master (192.168.1.100)、k8s-node1 (192.168.1.101)、k8s-node2 (192.168.1.102)
二、所有节点前置操作(关键!)
以下操作每个节点都必须执行,少一步都可能导致后续初始化失败。建议开三个终端窗口同步操作。
1. 关闭防火墙
K8s 组件之间通过多个端口通信(API Server 6443、etcd 2379-2380、kubelet 10250 等),防火墙会阻断这些通信。直接关掉最简单:
# 临时关闭(立即生效)
systemctl stop firewalld
# 永久关闭(重启后不恢复)
systemctl disable firewalld
# 验证:显示 inactive 即可
systemctl status firewalld
2. 关闭 SELinux
SELinux 的安全策略会限制容器进程的权限,导致 Pod 启动失败。关掉它:
# 临时关闭
setenforce 0
# 永久关闭
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 验证:显示 Permissive
getenforce
3. 关闭 Swap
这是 K8s 的硬性要求。开启 Swap 会影响 kubelet 的资源调度精度,kubelet 会直接拒绝启动。所以必须关:
# 临时关闭
swapoff -a
# 永久关闭(注释掉 fstab 中的 swap 行)
sed -i '/swap/s/^/#/' /etc/fstab
# 验证:Swap 行显示 0 即可
free -h
4. 配置主机名和 Hosts 映射
K8s 节点之间通过主机名互相通信,所以每台机器需要一个唯一的主机名,并在所有节点上配好映射关系。
设置主机名(按节点分别执行):
# Master 节点
hostnamectl set-hostname k8s-master
# Node1 节点
hostnamectl set-hostname k8s-node1
# Node2 节点
hostnamectl set-hostname k8s-node2
执行后建议重新连接终端,让新主机名生效。
配置 Hosts(所有节点执行,IP 换成你自己的):
cat >> /etc/hosts << EOF
192.168.1.100 k8s-master
192.168.1.101 k8s-node1
192.168.1.102 k8s-node2
EOF
# 验证:在 Master 上 ping node1,能通就行
ping k8s-node1 -c 3
5. 安装 Containerd(容器运行时)
从 K8s 1.24 开始,官方移除了对 Docker 的原生支持,改用 Containerd 作为默认容器运行时。这里有两个关键配置一定要注意,否则 kubelet 启动会报错:
- SystemdCgroup = true:Containerd 默认使用 cgroupfs,而 kubelet 使用 systemd,两者不一致会导致资源管理混乱,必须统一。
- sandbox_image 替换为国内镜像:默认的
k8s.gcr.io/pause:3.6在国内拉不下来,换成阿里云的。
# 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加 Docker 官方源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装 Containerd
yum install -y containerd.io
# 生成默认配置
containerd config default > /etc/containerd/config.toml
# 修改两个关键参数
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's#sandbox_image = "k8s.gcr.io/pause:3.6"#sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"#' /etc/containerd/config.toml
# 启动并设置开机自启
systemctl start containerd
systemctl enable containerd
# 验证:active (running) 即成功
systemctl status containerd
6. 配置内核参数
K8s 网络需要内核开启 bridge-nf-call 和 ip_forward,否则 Pod 之间无法正常通信:
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
# 让配置生效
sysctl --system
# 验证:有 br_netfilter 输出即可
lsmod | grep br_netfilter
三、安装 K8s 核心组件(所有节点)
三个组件必须版本一致,这里统一用 1.27.0:
- kubeadm:集群初始化工具
- kubelet:节点上管理容器的代理
- kubectl:命令行管理工具
1. 配置阿里云 YUM 源
国内网络环境,必须用国内源,否则慢到怀疑人生:
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-$basearch/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF
2. 安装并启动
# 安装 1.27.0 版本
yum install -y kubelet-1.27.0 kubeadm-1.27.0 kubectl-1.27.0 --disableexcludes=kubernetes
# 启动 kubelet
systemctl enable kubelet && systemctl start kubelet
# 验证:active (running) 或 waiting 都正常(初始化前 kubelet 会等待)
systemctl status kubelet
四、初始化 Master 节点(仅 Master 执行)
这是集群搭建的核心步骤。注意替换 --apiserver-advertise-address 为你的 Master 节点实际 IP。
1. 执行初始化
kubeadm init
--apiserver-advertise-address=192.168.1.100
--image-repository registry.aliyuncs.com/google_containers
--kubernetes-version v1.27.0
--service-cidr=10.96.0.0/12
--pod-network-cidr=10.244.0.0/16
参数说明:
--image-repository:指定阿里云镜像源,国内必加--service-cidr:Service 的 IP 网段,默认就行--pod-network-cidr:Pod 网段,需要和 Calico 默认配置匹配
等待 3-5 分钟,看到以下输出说明成功了:
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 can now join any number of machines by running the following on each node
as root:
kubeadm join 192.168.1.100:6443 --token xxxxx ...
⚠️ 重要:把最后那行 kubeadm join ... 命令完整复制保存下来!这是 Node 加入集群的唯一凭证,丢了要重新生成。
如果初始化失败,执行 kubeadm reset 清理配置后重新来过。
2. 配置 kubectl 权限
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# 查看节点状态(此时应该是 NotReady,因为还没装网络插件)
kubectl get nodes
3. 安装 Calico 网络插件
网络插件是必须的,否则所有节点永远处于 NotReady 状态。Calico 是目前最成熟稳定的选择:
kubectl apply -f https://docs.projectcalico.org/v3.26/manifests/calico.yaml
# 等 3-5 分钟后查看,所有 Pod 为 Running 即可
kubectl get pods -n kube-system
# 再看节点,应该变成 Ready 了
kubectl get nodes
Master 状态变 Ready 后,才能继续加入 Node 节点。
五、Node 节点加入集群(仅 Node 执行)
在两个 Node 节点上分别执行之前保存的 kubeadm join 命令,每个人的 token 和 CA 哈希值不同,以自己 Master 初始化时输出的为准:
# 示例命令(替换为你自己的!)
kubeadm join 192.168.1.100:6443
--token abcdef.0123456789abcdef
--discovery-token-ca-cert-hash sha256:xxxxx...
如果 join 失败(比如 token 过期、配置残留),先在 Node 上执行 kubeadm reset 清理,然后用新 token 重新加入。
回到 Master 节点验证:
kubectl get nodes
看到三个节点状态都是 Ready,集群就搭建完成了。
六、集群功能验证:部署 Nginx 测试
部署一个 Nginx 来验证集群是否真的能正常工作:
# 创建 Nginx 部署(3 个副本)
kubectl create deployment nginx --image=nginx:1.21
# 暴露为 NodePort 服务
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看 Pod 状态(全部 Running 才行)
kubectl get pods -o wide
# 查看 Service 分配的端口
kubectl get svc nginx
浏览器访问 http://任意Node节点IP:分配的端口号,能看到 Nginx 欢迎页就说明集群完全正常。
# 测试完清理
kubectl delete deployment nginx
kubectl delete svc nginx
七、常见报错及解决方案
以下是我实际搭建过程中遇到的几个典型问题:
| 报错现象 | 原因 | 解决方案 |
|---|---|---|
| 节点状态一直 NotReady | Calico 网络插件未就绪 | kubectl get pods -n kube-system 检查 Calico Pod;若异常则 delete 后重新 apply |
| join 提示 token 过期 | token 默认 24h 有效 | Master 上执行 kubeadm token create --print-join-command 生成新的 |
| 镜像拉取超时 | 未使用国内镜像源 | kubeadm reset 后重新 init,确保 --image-repository 指向阿里云 |
| kubectl: command not found | 组件未安装 | 重新 yum install kubectl |
| Containerd 启动失败 | config.toml 配置有误 | 删除配置文件重新生成,再改 SystemdCgroup 和 sandbox_image |
| 节点间无法通信 | /etc/hosts 配置不一致 | 检查所有节点的 hosts 文件,确保 IP 和主机名对应正确 |
八、命令速查手册
把常用命令按场景整理在一起,方便查找。
所有节点通用(前置 + 组件安装一键脚本)
# 1. 关防火墙
systemctl stop firewalld && systemctl disable firewalld
# 2. 关 SELinux
setenforce 0 && sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 3. 关 Swap
swapoff -a && sed -i '/swap/s/^/#/' /etc/fstab
# 4. 配 Hosts(替换为自己的 IP)
cat >> /etc/hosts < /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sed -i 's#sandbox_image = "k8s.gcr.io/pause:3.6"#sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"#' /etc/containerd/config.toml
systemctl start containerd && systemctl enable containerd
# 6. 内核参数
cat > /etc/sysctl.d/k8s.conf < /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-$basearch/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF
yum install -y kubelet-1.27.0 kubeadm-1.27.0 kubectl-1.27.0 --disableexcludes=kubernetes
systemctl enable kubelet && systemctl start kubelet
Master 专属
# 设置主机名
hostnamectl set-hostname k8s-master
# 初始化集群(替换 IP)
kubeadm init
--apiserver-advertise-address=192.168.1.100
--image-repository registry.aliyuncs.com/google_containers
--kubernetes-version v1.27.0
--service-cidr=10.96.0.0/12
--pod-network-cidr=10.244.0.0/16
# 配置 kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# 安装 Calico
kubectl apply -f https://docs.projectcalico.org/v3.26/manifests/calico.yaml
# token 过期时重新生成 join 命令
kubeadm token create --print-join-command
Node 专属
# 设置主机名
hostnamectl set-hostname k8s-node1 # Node2 改为 k8s-node2
# 加入集群(用 Master 输出的实际命令)
kubeadm join 192.168.1.100:6443
--token xxxxx
--discovery-token-ca-cert-hash sha256:xxxxx
# 需要重新加入时先清理
kubeadm reset
排错命令
# 重置 K8s
kubeadm reset && rm -rf $HOME/.kube/config && systemctl restart kubelet
# 重装 Calico
kubectl delete -f https://docs.projectcalico.org/v3.26/manifests/calico.yaml
kubectl apply -f https://docs.projectcalico.org/v3.26/manifests/calico.yaml
# 重启 Containerd
systemctl restart containerd && systemctl status containerd
# 查看 kubelet 日志
journalctl -u kubelet -f
验证命令
# 节点状态
kubectl get nodes
# 系统 Pod 状态
kubectl get pods -n kube-system
# 部署测试
kubectl create deployment nginx --image=nginx:1.21
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pods && kubectl get svc nginx
# 清理测试
kubectl delete deployment nginx && kubectl delete svc nginx
以上就是 K8s 1.27 集群的完整搭建过程。核心就三点:前置操作一个不漏、镜像源全部用国内、Containerd 两个参数一定改对。掌握了这些,整个搭建过程应该会很顺利。
共有 0 条评论