Kubernetes 新手部署避坑指南:利用宿主机代理搭建 K8s 集群


Kubernetes 新手部署避坑指南:利用宿主机代理搭建 K8s 集群

前言

对于 Kubernetes(K8s)新手来说,在国内环境搭建第一个集群往往是“从入门到放弃”的第一步。最大的拦路虎莫过于网络问题k8s.gcr.ioghcr.io 等镜像仓库在国内无法直接访问,导致 kubeadm init 时镜像拉取失败。

本文将介绍一种最稳妥、最通用的解决方案:利用宿主机的代理节点,让虚拟机中的 K8s 集群顺利访问外网。此外,文章还整理了新手必须知道的系统配置原理,助你避开部署路上的各种深坑。

一、 环境准备

我们要搭建的是一个“一主一从”的小型集群。

角色 IP 地址 主机名 操作系统
宿主机 (代理节点) 192.168.88.1 - Windows/Mac/Linux
Master 节点 192.168.88.133 k8s-master CentOS/RHEL/Ubuntu
Worker 节点 192.168.88.131 k8s-node CentOS/RHEL/Ubuntu

关键前提:
宿主机上已运行代理服务(如 Clash、V2Ray 等),监听端口为 10808,并开启了“允许局域网连接”


二、 核心步骤:配置网络代理 (关键避坑点)

这是解决“镜像拉取失败”的核心步骤。很多新手只在 Shell 终端配置了代理,但 kubeadm 调用的容器运行时后台服务并不知道代理的存在。

我们需要做两件事:

  1. 让当前终端能访问外网(用于下载工具和配置文件)。
  2. 让容器运行时后台服务能访问外网(用于拉取 K8s 核心镜像)。

1. 配置终端代理环境变量

所有节点 执行以下命令:

1
2
3
4
5
6
7
8
9
# 配置代理环境变量,指向宿主机 IP
export http_proxy="http://192.168.88.1:10808"
export https_proxy="http://192.168.88.1:10808"
# 内网地址不走代理,避免访问虚拟机自身也绕弯
export no_proxy="localhost,127.0.0.1,192.168.88.0/24"

# 验证代理是否生效
curl -I https://www.google.com
# 如果返回 HTTP/1.1 200 OK,说明终端网络通畅

三、 系统环境初始化 (所有节点执行)

K8s 对系统环境有严格要求,如果不配置,kubelet 服务将无法启动或网络异常。

1. 关闭 Swap

原理: Kubernetes 认为内存交换到磁盘会严重影响性能,为了防止容器在内存交换时发生不可预测的行为,K8s 强制要求关闭 Swap。

1
2
3
4
5
# 临时关闭
swapoff -a

# 永久关闭:注释掉 /etc/fstab 中包含 swap 的行
sed -i 's/.*swap.*/#&/' /etc/fstab

2. 关闭防火墙与 SELinux

原理: 新手部署时,很难准确配置防火墙规则(如 kube-proxy 的随机端口、Calico/Flannel 的 overlay 网络等)。为了避免连接超时等问题,建议先关闭防火墙。SELinux 同样会限制 kubelet 对系统资源的访问。

1
2
3
4
5
6
# 关闭防火墙
systemctl stop firewalld && systemctl disable firewalld

# 关闭 SELinux
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config

3. 配置主机名与 Hosts

原理: K8s 节点间通信依赖主机名。如果不修改 /etc/hosts,节点可能无法解析彼此的主机名,导致集群状态变为 NotReady

1
2
3
4
5
6
7
8
9
10
11
# 在 Master (133) 上执行
hostnamectl set-hostname k8s-master

# 在 Node (131) 上执行
hostnamectl set-hostname k8s-node

# 在所有节点 /etc/hosts 添加映射
cat >> /etc/hosts << EOF
192.168.88.133 k8s-master
192.168.88.131 k8s-node
EOF

4. 配置内核参数

原理: 默认情况下,Linux 内核不会将网桥(bridge)上的流量转发到 iptables 链。K8s 的网络插件(如 Flannel)大量依赖 iptables 规则来管理容器网络,如果不开启此参数,网络将无法打通。

1
2
3
4
5
6
7
8
9
10
11
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

# 应用配置
sudo sysctl --system

四、 安装容器运行时与 K8s 组件 (所有节点执行)

K8s 1.24 版本之后,默认移除了对 Docker 的直接支持,转而使用 containerd 作为标准容器运行时。

1. 安装并配置 Containerd

避坑点: 必须为 containerd 的后台服务配置代理,否则它无法拉取 registry.k8s.io 的镜像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 安装 containerd (以 CentOS 为例)
yum install -y containerd

# 生成默认配置
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# 修改 Cgroup 驱动为 systemd (Kubelet 默认使用 systemd,两者必须一致)
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

# === 核心步骤:为 Containerd 服务配置代理 ===
sudo mkdir -p /etc/systemd/system/containerd.service.d
cat <<EOF | sudo tee /etc/systemd/system/containerd.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://192.168.88.1:10808"
Environment="HTTPS_PROXY=http://192.168.88.1:10808"
Environment="NO_PROXY=localhost,127.0.0.1,192.168.88.0/24"
EOF

# 重启服务使配置生效
systemctl daemon-reload
systemctl restart containerd && systemctl enable containerd

2. 安装 Kubeadm, Kubelet, Kubectl

这里使用阿里云镜像源来加速安装包的下载。

1
2
3
4
5
6
7
8
9
10
11
12
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
EOF

# 安装指定版本 (这里以 1.28.0 为例)
yum install -y kubeadm-1.28.0 kubelet-1.28.0 kubectl-1.28.0 --disableexcludes=kubernetes

systemctl enable --now kubelet

五、 初始化 Master 节点 (仅在 Master 执行)

1. 预拉取镜像

在初始化前先拉取镜像,可以验证代理配置是否正确。

1
2
3
4
5
# 查看所需镜像版本
kubeadm config images list

# 拉取镜像 (此时 Containerd 会走上面配置的 http-proxy.conf)
kubeadm config images pull

如果报错超时,请检查宿主机代理是否允许局域网连接,以及宿主机防火墙是否放行 10808 端口。

2. 执行初始化

指定 Master 的 IP 和 Pod 网段。

1
2
3
4
kubeadm init \
--apiserver-advertise-address=192.168.88.133 \
--pod-network-cidr=10.244.0.0/16 \
--kubernetes-version=v1.28.0

注意:--pod-network-cidr=10.244.0.0/16 是 Flannel 网络插件的默认网段,必须一致。

3. 配置 kubectl 权限

初始化成功后,按提示执行命令,将管理配置文件复制到用户目录,这样普通用户才能使用 kubectl 管理集群。

1
2
3
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

六、 安装网络插件 (仅在 Master 执行)

K8s 集群必须安装网络插件,节点状态才会从 NotReady 变为 Ready。这里使用 Flannel。

1
2
3
4
5
6
7
8
# 下载 Flannel 配置文件 (利用之前配置的终端代理)
curl -o kube-flannel.yml https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

# 应用配置
kubectl apply -f kube-flannel.yml

# 查看状态,等待一会直到变为 Running
kubectl get pods -n kube-flannel

当 Flannel Pod 运行后,再次查看节点状态:

1
2
kubectl get nodes
# 此时 Master 状态应为 Ready

七、 加入 Worker 节点 (在 Node 节点执行)

1. 确保 Node 节点网络通畅

避坑点: Node 节点加入集群时,也需要拉取镜像(如 kube-proxy, pause 等)。请务必确保 Node 节点也配置了代理(参考第三步和第四步,特别是 Containerd 的代理配置)。

2. 执行加入命令

在 Master 初始化成功时输出的命令,复制到 Node 节点执行:

1
2
kubeadm join 192.168.88.133:6443 --token <your-token> \
--discovery-token-ca-cert-hash sha256:<your-hash>

(如果 token 过期,可在 Master 上执行 kubeadm token create --print-join-command 重新生成)

3. 验证集群

回到 Master 节点,查看最终结果:

1
kubectl get nodes

预期输出:

1
2
3
NAME         STATUS   ROLES           AGE   VERSION
k8s-master Ready control-plane 10m v1.28.0
k8s-node Ready <none> 1m v1.28.0

八、 总结与排错思路

恭喜你完成了 K8s 集群的搭建!回顾整个过程,我们主要解决了以下几个核心问题:

  1. 网络连通性:通过配置宿主机代理,彻底解决了“GFW 拦截镜像”的问题。这是最关键的一步,containerd 的 systemd 代理配置是新手最容易忽略的。
  2. 系统兼容性:关闭 Swap、SELinux 和配置内核参数,是 Linux 运行容器编排工具的基础要求。
  3. 组件一致性:确保 kubelet 和 containerd 使用相同的 cgroup 驱动。

后续如果遇到问题,排查思路如下:

  • **Pod 状态一直是 PendingImagePullBackOff**:通常是镜像拉不下来,检查代理配置。
  • **节点状态 NotReady**:检查网络插件 是否正常运行。
  • **kubectl get nodes 报错 connection refused**:检查你是否在 Node 节点执行了该命令,或者 Master 的 kubelet 是否挂了。kubectl 命令通常只需在 Master 节点执行。

希望这篇博客能成为你 K8s 学习之路的坚实基石!