环境准备与集群搭建:用kubeadm搭一个能跑vLLM的K8s集群

说实话,很多人在K8s上栽跟头,不是后面的推理部署有多难,而是第一步集群就没搭稳。我见过太多同学花了两天搭环境,最后发现kubelet起不来,或者网络插件死活装不上。嗯,这节课我们就来把地基打牢。

我个人习惯用kubeadm来搭生产级集群,但如果你只是想在笔记本上快速验证,Kind会更轻量。两种方式我都会讲,你根据场景选就行。

核心目标:搭建一个可用的K8s集群,配置好kubectl和Helm,确保所有组件健康运行。这是后续所有vLLM推理实验的基础。

1. 环境概览:我们需要什么?

先看看整体架构。下面这张图是我自己画的,能帮你快速理解集群的组件关系。

K8s集群搭建核心组件 Master 节点 kube-apiserver kube-controller-manager kube-scheduler etcd(键值存储) kubelet Worker 节点 kubelet kube-proxy 容器运行时(containerd) Pod(vLLM推理实例) kubectl / Helm 客户端工具

说白了,Master节点是大脑,Worker节点是手脚。你通过kubectl发指令,apiserver接收后调度到Worker上跑Pod。vLLM推理任务最终会以Pod的形式运行在Worker节点上。

2. 方式一:用kubeadm搭建(推荐生产环境)

kubeadm是官方推荐的集群搭建工具。我在项目中用过不下20次,稳定性没得说。但要注意,它要求你提前装好容器运行时和kubelet。

2.1 前置条件

  • 两台以上Ubuntu 22.04虚拟机(或物理机),2C4G起步
  • 所有节点能互相ping通,关闭swap
  • 安装Docker或containerd作为容器运行时

注意:K8s从1.24版本开始移除了对Docker的直接支持,改用containerd。如果你用Docker,需要安装cri-dockerd适配器。我个人建议直接用containerd,少一层转换,性能更好。

2.2 安装步骤

先在所有节点上执行基础配置:

# 关闭swap
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

# 加载内核模块
cat <

然后安装kubeadm、kubelet和kubectl:

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/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.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet=1.28.0-1.1 kubeadm=1.28.0-1.1 kubectl=1.28.0-1.1
sudo apt-mark hold kubelet kubeadm kubectl

小技巧:用apt-mark hold锁定版本,防止意外升级导致集群不稳定。我曾经在生产环境吃过这个亏,半夜被报警吵醒,就是因为kubelet自动升级了。

2.3 初始化Master节点

在Master节点上执行:

sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.1.100

这里的--pod-network-cidr要和你后面选的网络插件匹配。我用Flannel,所以用10.244.0.0/16。如果你用Calico,可以换成192.168.0.0/16

初始化成功后,会输出一段kubeadm join命令,记得保存好。那是Worker节点加入集群的凭证。

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

2.4 安装网络插件

没有网络插件,Pod之间是没法通信的。我习惯用Flannel,简单稳定:

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

等一两分钟,检查一下:

kubectl get pods -n kube-flannel

看到所有Pod都是Running状态,就说明网络通了。

2.5 加入Worker节点

在Worker节点上执行刚才保存的join命令:

sudo kubeadm join 192.168.1.100:6443 --token xxxxx --discovery-token-ca-cert-hash sha256:xxxxx

回到Master节点验证:

kubectl get nodes

应该能看到所有节点都是Ready状态。

3. 方式二:用Kind搭建(适合本地开发)

Kind是用Docker容器模拟节点的工具。你想想看,一台笔记本就能跑一个完整的K8s集群,多方便。我平时做原型验证都用它。

3.1 安装Kind

curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

3.2 创建集群

写一个配置文件,把API Server的端口映射出来,方便后面用kubectl访问:

cat < kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 6443
    hostPort: 6443
    protocol: TCP
- role: worker
- role: worker
EOF

kind create cluster --config kind-config.yaml --name vllm-cluster

等几分钟,集群就起来了。验证一下:

kind get clusters
kubectl cluster-info --context kind-vllm-cluster

对比总结:kubeadm适合生产或多人协作场景,Kind适合个人开发测试。如果你只是学vLLM推理,Kind完全够用。但如果你想体验完整的集群运维,建议用kubeadm。

4. 配置kubectl

kubectl是操作K8s的瑞士军刀。配置其实很简单,就是把集群的认证信息放到~/.kube/config里。

如果你用kubeadm,初始化后会自动生成。如果你用Kind,它会自动帮你配置好。但如果你需要手动配置,可以这样:

kubectl config set-cluster my-cluster --server=https://192.168.1.100:6443 --certificate-authority=/path/to/ca.crt
kubectl config set-credentials my-user --client-certificate=/path/to/client.crt --client-key=/path/to/client.key
kubectl config set-context my-context --cluster=my-cluster --user=my-user
kubectl config use-context my-context

验证配置是否生效:

kubectl get nodes
kubectl get pods -A

如果能看到节点和Pod列表,说明配置成功了。

5. 安装Helm

Helm是K8s的包管理器。后面部署vLLM时,我们会用Helm Chart来管理配置,省去手动写YAML的麻烦。

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

验证安装:

helm version
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

个人经验:Helm的模板语法刚开始可能觉得绕,但用熟了会发现它比手写YAML高效得多。尤其是你要部署多个环境(dev/staging/prod)时,一套Chart改改values就能复用。

6. 验证集群健康状态

集群搭好了,怎么确认它真的能用?我一般会跑一套完整的检查流程:

检查项 命令 预期结果
节点状态 kubectl get nodes 所有节点Ready
系统Pod kubectl get pods -n kube-system 所有Pod Running
DNS解析 kubectl run test --image=busybox --rm -it -- nslookup kubernetes.default 返回IP地址
调度测试 kubectl run nginx --image=nginx --replicas=3 3个Pod正常运行
Helm可用 helm list 返回空列表(无报错)

如果DNS解析失败,大概率是CoreDNS没起来。检查一下:

kubectl get pods -n kube-system | grep coredns

如果CoreDNS处于CrashLoopBackOff状态,通常是网络插件没装好。重新apply一下Flannel或Calico就行。

避坑指南:我曾经在部署vLLM时发现Pod一直Pending,查了半天才发现是节点资源不足。建议你在验证阶段就用kubectl describe node看看资源分配情况,别等到跑推理任务了才排查。

7. 小结

到这一步,你应该有了一个健康的K8s集群,kubectl和Helm也都配好了。接下来就可以开始部署vLLM推理服务了。记住,环境准备这一步花点时间打好基础,后面会顺畅很多。

如果你在搭建过程中遇到问题,先检查网络插件和容器运行时。这两个是80%问题的根源。

专注资料整理

专注资料整理