Kubernetes¶
约 1012 个字 124 行代码 预计阅读时间 6 分钟
安装 ¶
安装 kubectl ¶
sudo apt-get update
# apt-transport-https 可以是一个虚拟包;如果是这样,你可以跳过这个包
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg # allow unprivileged APT programs to read this keyring
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.34/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list # 有助于让诸如 command-not-found 等工具正常工作
sudo apt-get update
sudo apt-get install -y kubectl
安装 minikube ¶
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_arm64.deb
sudo dpkg -i minikube_latest_arm64.deb
sudo usermod -aG docker $USER && newgrp docker
minikube start
kubectl cluster-info
kubectl get nodes
应该看到类似下面的输出:
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 1m v1.30.0
部署验证 —— 部署第一个应用 ¶
Deployment¶
先创建一个 Deployment 文件:
nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
kubectl apply -f nginx-deploy.yaml
kubectl get pods -l app=nginx
你应该看到类似:
nginx-5c68965b8f-bvzfm 1/1 Running 0 10s
nginx-5c68965b8f-k92lg 1/1 Running 0 10s
Service¶
创建文件:
nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30080
部署:
kubectl apply -f nginx-svc.yaml
查看:
kubectl get svc
你会看到:
nginx-svc NodePort ... 80:30080/TCP
访问 ¶
curl http://localhost:30080
minikube service nginx-svc
它会自动打开浏览器访问。
滚动更新(Rolling Update)¶
修改 Deployment,将镜像改为:
image: nginx:1.21.0
重新 apply:
kubectl apply -f nginx-deploy.yaml
kubectl rollout status deployment/nginx
kubectl rollout undo deployment/nginx
调试 ¶
查看 Pod 日志:
kubectl logs nginx-xxxxxx
kubectl exec -it nginx-xxxxxx -- bash
kubectl describe pod nginx-xxxxxx
最常用来排查镜像拉取失败、CrashLoopBackOff 等。
kubectl delete deployment nginx
初始化 ¶
层级与命名空间 ¶
Kubernetes 对象层级 ¶
| 层级 | 说明 | 示例 |
|---|---|---|
| Cluster | 整个 Kubernetes 控制平面与节点集合 | minikube、生产集群 |
| Namespace | Cluster 内的逻辑隔离边界 | default、kube-system、rbgs-test |
| Workload/Resource | 以 YAML 定义的 Kubernetes 对象 | Deployment、Service、RoleBasedGroup |
| Pod | 最小运行单元,真正承载容器 | 运行 nginx 的 Pod |
RoleBasedGroup 的 namespace ¶
RoleBasedGroup(缩写rbg)属于workloads.x-k8s.io/v1alpha1的 CRD,作用类似一个“多角色工作负载控制器”。- 若 YAML
metadata中未声明namespace,对象创建时会默认落在default命名空间;可用以下命令核对:
kubectl get rbg -n default
kubectl get rolebasedgroup -n default
RBG 与底层 Workload 的关系 ¶
Cluster
└─ Namespace (e.g., default)
└─ RoleBasedGroup
├─ Role "sts" → StatefulSet → Pods
├─ Role "deployment" → Deployment → Pods
└─ Role "lws" → LeaderWorkerSet → Pods
- RBG 自身不会直接运行容器,而是交给对应 controller 创建各 Role 的 Deployment / StatefulSet / LeaderWorkerSet,再由这些对象拉起 Pod。
- 每个 Role 共享所在 Namespace,因此同一个 RBG 下的所有衍生资源也归属于 RBG 的命名空间。
关键理解 ¶
- RBG 是顶层 CRD 资源,属于 Workload 层级,并受 Namespace 约束。
- Namespace 是逻辑分组,除非 CRD 声明为
ClusterScope,否则所有实例都需要 namespace。 - 想查看 RBG 创建的角色状态,直接查询对应的 Deployment/StatefulSet,或使用
kubectl describe rbg/<name>追踪 controller 事件。
删除 Service:
kubectl delete svc nginx-svc
minikube delete
进阶原理 ¶
调度器(Scheduler)¶
当你创建一个 Pod 或 Deployment 时:
kubectl apply -f xxx.yaml
K8s 的 scheduler 会将 Pod 分配到一个合适的 Node。
Pending → (scheduler) → Node assigned → kubelet 启动容器
如果调度失败,Pod 会卡住:
Pending
调度器的三步流程(非常重要)
排除掉不满足条件的节点,比如:
- 节点资源不足(CPU / 内存 / GPU)
- 有污点(taint)
- 不匹配 nodeSelector
- 不匹配 affinity
- 端口冲突
- 节点 not ready
例如 GPU Pod:
resources:
limits:
nvidia.com/gpu: 1
→ scheduler 只会考虑有 GPU 的节点。
在筛选后的节点上打分:
- CPU、内存利用率
- 负载均衡
- 网络拓扑
- anti-affinity
- 自定义调度插件
得分最高的节点被选中。
最后 scheduler 调用:
POST /binding
把 Pod 绑定到节点。
K8s 允许你表达复杂的调度需求:
Gang Scheduling¶
大模型并行(Tensor Parallel)必须多个 Pod 同时启动。 普通 scheduler 不支持这种逻辑,会造成死锁:
- 4 卡模型:需要 4 个 worker
- 但调度器调到 2 个卡后剩余卡不足 → 永远 Pending
解决方案:
- PodGroup(CRD)
- Volcano Scheduler
- RBG 内部集成
StatefulSet —— 有状态应用的核心机制 ¶
StatefulSet 出现就是为了解决 Deployment 不能解决的 3 个问题:
| 能力 | Deployment | StatefulSet |
|---|---|---|
| Pod 固定名称 | ❌ | ✔(nginx-0, nginx-1) |
| 稳定持久化存储 | ❌ | ✔(PVC 自动绑定) |
| Headless DNS | ❌ | ✔ |
| 有序创建 / 删除 | ❌ | ✔ |
StatefulSet 的 Pod 命名
app=redis
Pod 不会叫redis-xxxxxx
而是redis-0、redis-1、redis-2。
顺序固定不变。
StatefulSet 必须配合 Headless Service:
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
clusterIP: None
selector:
app: redis
这样每个 Pod 会有独立的 DNS:
redis-0.redis.default.svc.cluster.local
redis-1.redis.default.svc.cluster.local
分布式系统(如 Etcd、Zookeeper、Redis Sentinel)都要用它。
有序滚动更新
StatefulSet 必须按顺序更新:
redis-2 → redis-1 → redis-0
最适合:
- 数据库
- leader/follower 系统
- 分布式本地存储
HPA (Horizontal Pod Autoscaler)¶
HPA = 自动横向扩容
目标——根据负载自动增加 / 减少 Pod 数
kubectl autoscale deployment nginx --cpu-percent=50 --min=1 --max=10
K8s 会读取metrics-server:
当前副本数 * (当前 CPU 使用率 / 目标 CPU 使用率)
对 LLM 服务更有意义:
- qps
- request in queue
- pending tokens
- KV cache 使用量
需要Prometheus Adapter,并在 HPA 中定义:
type: Pods
metric:
name: queue_length
target:
type: AverageValue
averageValue: 10
CRD(Custom Resource Definition)—— 自定义资源 ¶
K8s 是一个高度可扩展系统。 你可以自定义一个新的资源类型:
kubectl get <myresource>
一个CRD定义类似:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: podgroups.scheduling.sigs.k8s.io
spec:
group: scheduling.sigs.k8s.io
names:
kind: PodGroup
plural: podgroups
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: true
安装后,K8s 会有新的资源:
kubectl get podgroups
Operator¶
Operator = Controller + CRD
目的:把复杂系统的运维逻辑自动化
Operator 会持续检测资源:
Desired State(CRD YAML)
→
Controller reconcile loop
→
Actual State 实现
watch(crd) → reconcile() → 更新 pod / config / svc / pvc
这就是 K8s 的自愈机制扩展到 Custom Resource。
| 能力 | 用途 |
|---|---|
| 调度器 | 控制 Pod 运行在哪 |
| StatefulSet | 分布式有状态系统 |
| HPA | 自动扩缩容 |
| CRD | 拓展 K8s API |
| Operator | 自动化复杂 LLM 服务 |