wth2jhl.online

Back

“Welcome to the official Kubernetes Examples repository! This curated collection, stewarded by SIG Apps, provides high-quality, educational examples for running a diverse range of applications and workloads on Kubernetes.” —— kubernetes/examples README 第一行


一、为什么我会去翻这个仓库#

起因是我在 GKE 上跑 vLLM 想加 GPU 弹性扩缩容,搜出来一篇 Google Cloud 博客引到一个示例仓库:kubernetes/examples ↗。

我点进去一看——6.6K stars、Shell 主语言、17MB。比起 OpenViking 100MB 和 TencentDB Agent Memory 44MB 算是轻量,但 40 个 YAML + 11 个 README + 32 个 archived 历史目录 的密度很高。

最让我在意的是 README 第一段不写 “What is X” 而写 “How do you reduce repetitive work”——它故意把”例子”和”模板”区分开。

读完之后我给的判断:这是一个”Kubernetes 实战手册”,不是”Kubernetes 教程”。它的工作不是解释每个 API 字段,而是给你看 4-5 个真实生产场景怎么跑通。


二、目录长得很稀疏,但每个目录都是”完整场景”#

kubernetes/examples/
├── AI/                      # AI/ML 推理场景
│   ├── vllm-deployment/     # vLLM + GPU HPA + Prometheus
│   └── model-serving-tensorflow/  # TF Serving + PV + Ingress
├── databases/               # 有状态数据库
│   ├── cassandra/           # StatefulSet 经典案例
│   └── mysql-cinder-pd/     # OpenStack 块存储
├── web/                     # Web 应用
│   ├── guestbook/           # PHP 多层应用
│   └── guestbook-go/        # Go 版 controller 模式
├── nginx-platform-app/      # 单 nginx 演示
├── _archived/               # 32 个已归档历史示例
├── guidelines.md            # 贡献者必读
└── README.md
text

一共 4 个活跃类别 + 1 个 nginx 演示 + 32 个 archived 目录。表面看很小,但每个活跃目录都做”完整”:

  • vLLM 不是只给个 Deployment,而是从 Deployment → Service → Prometheus → ServiceMonitor → PrometheusRule → PrometheusAdapter → HPA 8 个 YAML 全套
  • Cassandra 不只给 StatefulSet,而是带 Go/Java/image 三种语言 client + 完整测试
  • Guestbook 提供 PHP 版 + Go controller 版两个完整对照

这是”examples”和”snippets”的根本区别——snippets 给你看一个 yaml 字段,examples 给你看一个能跑通的生产场景。


三、vLLM 部署:把”AI 推理 + GPU 弹性”做成 Kubernetes 一等公民#

这是仓库里最值得拆的一个例子。AI/vllm-deployment/ 包含两个子案例:

  1. 基础部署:vllm-deployment.yaml + vllm-service.yaml
  2. GPU 弹性扩缩:hpa/ 子目录 8 个 YAML + 2 个 MD 完成完整监控回路

3.1 基础部署#

vllm-deployment.yaml 是个典型 AI 推理 Pod 模板,但有 4 个关键设计值得看:

# vllm-deployment.yaml 关键参数
resources:
  requests:
    nvidia.com/gpu: "1"
  limits:
    nvidia.com/gpu: "1"
yaml

注意:GPU 资源是 requests/limits 都设 1——这是 Kubernetes GPU 调度的硬约束,少一个 pod 就不能调度。

command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --gpu-memory-utilization=0.85
- --max-num-seqs=64
yaml

--gpu-memory-utilization=0.85 不是默认——这是为了防 OOM 的”内存保留”。注释里写”添加这行修复可能 OOM 错误”。

volumes:
- name: dshm
  emptyDir:
    medium: Memory
yaml

emptyDir.medium: Memory 走 tmpfs——vLLM 用 /dev/shm 做 PyTorch 多进程通信,磁盘会慢 10 倍。

env:
- name: HUGGING_FACE_HUB_TOKEN
  valueFrom:
    secretKeyRef:
      name: hf-secret
      key: hf_token
yaml

HF token 从 K8s Secret 注入——不是 bake 进镜像。这避免了”镜像泄漏 token”。

3.2 GPU HPA:用”业务指标”驱动弹性#

这是真正精彩的部分。AI/vllm-deployment/hpa/ 给了两个 HPA 案例:

Case A:基于 DCGM GPU 利用率(gpu-horizontal-pod-autoscaler.yaml)

metrics:
- type: Pods
  pods:
    metric:
      name: gpu_utilization_percent
    target:
      type: AverageValue
      averageValue: 20
yaml

但 HPA 不直接接 DCGM Exporter,中间需要 3 层翻译:

DCGM Prometheus Exporter
       ↓ 暴露 DCGM_FI_DEV_GPU_UTIL
Prometheus
       ↓ 抓 + PrometheusRule 用 label_replace 重打标签
dcgm_fi_dev_gpu_util_relabelled
       ↓ Prometheus Adapter 翻译成 Kubernetes API
gpu_utilization_percent
       ↓ HPA 读取
按平均 GPU 利用率 20% 扩缩
text

这个链路在 prometheus-rule.yaml 顶部注释里写得很清楚:

“The raw ‘DCGM_FI_DEV_GPU_UTIL’ metric scraped by Prometheus does not have the standard ‘pod’ and ‘namespace’ labels that the Prometheus Adapter needs to associate the metric with a specific workload pod.”

这是一个被低估的 K8s 知识点:DCGM exporter 直接出来的 metric 没有 pod / namespace 标签,Prometheus Adapter 没法做关联。必须用 label_replace() 把标签重打。

Case B:基于 vLLM 业务指标(vllm-hpa.md)

vllm:num_requests_running{model_name="google/gemma-3-1b-it"}
plaintext

直接用 vLLM 自己暴露的 /metrics,按”并发请求数”扩缩。这比 GPU 利用率更准——GPU 利用率 100% 可能是正常 batch 跑满,扩缩毫无意义;并发请求数才是真的”用户压力”。

这两个案例并列放在 hpa/ 下的意义是 “给你两个选择,看你的业务是什么”:

  • GPU 利用率:硬件资源视角(适合算力贵场景)
  • 业务指标:负载视角(适合用户体验优先场景)

3.3 HPA 的 stabilizationWindow 写得也很到位#

scaleUp 立即扩 + scaleDown 30s 稳定——这是”宁可浪费 GPU 也不能让用户等”的弹性策略。注释里写明 trade-off:

“A non-zero value would make the scaling less sensitive to short-lived spikes, but could introduce latency if the load persists.”

policies 写 Pods: 4 + Percent: 100 + selectPolicy: Max ——两个策略取最大,15 秒内最多扩 1 倍或 4 个 Pod。这是”激进 + 保守”的双保险。


四、TensorFlow Serving:把”模型仓库”的标准范式落到 K8s#

AI/model-serving-tensorflow/ 是个对照案例——同样做 AI 推理,用完全不同的方式:

vllm-deployment/        # 模型从 HF 拉,Pod 启动时下载
model-serving-tensorflow/  # 模型用 PV 挂载到 Pod
text

deployment.yaml 关键片段:

volumes:
- name: model-storage
  persistentVolumeClaim:
    claimName: model-pvc
containers:
- name: tensorflow-serving
  image: tensorflow/serving:latest
  args:
  - --model_name=resnet
  - --model_base_path=/models/resnet
  volumeMounts:
  - name: model-storage
    mountPath: /models
yaml

配套文件 pvc.yaml + pv.yaml + service.yaml + ingress.yaml 完整一条龙。这是 K8s 传统做法:模型和 Pod 分离,PV 持久化。

两种方式的对比:

维度vLLM (HF 拉)TF Serving (PV 挂)
启动时间慢(首次下载 5GB+ 模型)快(PV 已就绪)
存储成本高(每 Pod 缓存)低(一份共享)
模型更新改 env 重启改 PV 内容
适合临时实验 / 单租户生产 / 多 Pod 共享

README.md 写明:

“Use a PersistentVolume to mount your model directory.”

这是 K8s 1.0 时代就有的范式,但放在 TF Serving 上下文里依然是最优解。


五、Cassandra StatefulSet:K8s 早期教科书写过的”作业正确性”#

databases/cassandra/ 是仓库里最”老派”的一个例子——完整 Go/Java 客户端 + 镜像构建,但核心是 cassandra-statefulset.yaml 的 9 个设计决策。

5.1 经典 StatefulSet 写法#

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: cassandra
spec:
  serviceName: cassandra
  replicas: 3
yaml

serviceName: cassandra 是 StatefulSet 强制的——必须先有 headless Service,Pod 才有 stable DNS 解析。

5.2 4 个端口和它们的历史#

ports:
- containerPort: 7000
  name: intra-node
- containerPort: 7001
  name: tls-intra-node
- containerPort: 7199
  name: jmx
- containerPort: 9042
  name: cql
yaml

7000/7001 节点间通信、7199 JMX 监控、9042 CQL 业务端口。这是 Cassandra 4 端口的”祖传”配置——10 年没变。

5.3 优雅关闭#

terminationGracePeriodSeconds: 1800   # 30 分钟
lifecycle:
  preStop:
    exec:
      command:
      - /bin/sh
      - -c
      - nodetool drain
yaml

terminationGracePeriodSeconds: 1800 + preStop: nodetool drain——这是 Cassandra 关闭时”先把数据 flush 到磁盘再退出”的标准操作。30 分钟是因为有状态数据库关闭就是慢。

securityContext:
  capabilities:
    add:
      - IPC_LOCK
yaml

IPC_LOCK capability——Cassandra mmap 文件需要锁内存,不加这个 capability 会被内核 swap。

5.4 节点发现写得很”毒”#

env:
- name: CASSANDRA_SEEDS
  value: "cassandra-0.cassandra.default.svc.cluster.local"
yaml

cassandra-0.cassandra.default.svc.cluster.local——这是 K8s StatefulSet 给 Pod 分配的稳定 DNS:

<POD_NAME>.<SERVICE_NAME>.<NAMESPACE>.svc.cluster.local
text

第一个 Pod 永远是 cassandra-0,第二个是 cassandra-1……用 Pod 序号做种子节点发现,这是 K8s StatefulSet 最经典的设计。

cassandra.yaml 里还写明 MAX_HEAP_SIZE=512M + HEAP_NEWSIZE=100M——JVM 调优显然不是 K8s 知识点,但这个 examples 教了:Stack 与 Heap 比例要预先设好。


六、MySQL + OpenStack Cinder:展示”云原生存储插件”怎么工作#

databases/mysql-cinder-pd/ 是仓库里最”小众”的例子——演示如何用 OpenStack Cinder 做 Kubernetes PersistentVolume。

volumes:
- name: mysql-persistent-storage
  cinder:
    volumeID: 9a461d06-...-f8c5b8d33
    fsType: ext4
yaml

cinder 是 OpenStack 块存储的 volume 类型——Kubernetes 通过 cloud-provider 集成,调用 Cinder API 把 volume 挂到 Pod 所在的虚拟机。

README 列了 4 个 kubelet 依赖:

/bin/lsblk                  # 找 fs type
/sbin/mkfs.ext3, mkfs.ext4  # 必要时格式
/usr/bin/udevadm            # 探测设备挂载
text

这是 K8s 1.0 时代的 PV 写法——现在已经被 StorageClass + Dynamic Provisioning 替代。

这个 examples 留它不是因为它”现在还实用”,而是因为它演示了”云提供商的存储插件怎么和 K8s 集成”——这是理解 K8s 存储子系统的最好教材。


七、Guestbook Classic:K8s 教程的”Hello World”#

web/guestbook/ 是 K8s 官网教程的原始配套——PHP + Redis Master + Redis Replica + Frontend 的 4 层应用。

7.1 历史演化#

guestbook/         # PHP 版 + 多 deployment + service
├── legacy/        # 旧版 controller 模式(archived)
└── all-in-one/    # 单文件版本(学习用)
guestbook-go/      # Go 版 + controller 模式
├── main.go
└── guestbook-controller.yaml
text

legacy/ 留了旧 controller 模式的 deployment——这是 K8s 早期 kubectl run 命令生成的 YAML,后来被 kubectl create deployment 替代。

all-in-one/ 提供单文件运行版——所有 deployment + service 塞一个 YAML,方便速跑。

7.2 多语言版本的对照价值#

guestbook-go/ 给了一个完整 Go 实现 + Dockerfile + Makefile + controller.yaml。这是”用 Deployment vs 用 Controller”两种写法的对比——新人看 Deployment,老 K8s 用户看 Controller。

两面读,5 分钟就能理解 K8s workload 模型的演化。


八、guidelines.md:隐藏在仓库里的”教学哲学”#

guidelines.md 不长,但每条都值得读。我抽几条最关键的:

8.1 “An example is NOT…”#

- Minimalistic Feature Snippets: 应展示"完整应用",不是单个 YAML 字段
- Pure Kubernetes Feature Demonstrations: 应展示"应用运行在 K8s 上",不是"展示 K8s 某个功能"
markdown

第二条特别重要——这不是”教集群管理员怎么用 HPA”的仓库,是”教应用开发者怎么把自己应用跑在 K8s”的仓库。

8.2 README 强制结构#

- Purpose / What You'll Learn
- Prerequisites
- Quick Start / TL;DR
- Detailed Steps & Explanation
- Verification / Seeing it Work
- Configuration Customization
- Cleanup
- Troubleshooting (Optional)
- Further Reading / Next Steps
- Maintainer(s) (Optional)
- Last Validated Kubernetes Version (Recommended)
markdown

“Last Validated Kubernetes Version” 是非常工程化的要求——因为 K8s API 一直在变(apps/v1beta2 → apps/v1),不验证版本就是埋雷。

8.3 Manifest 的硬要求#

- Each example should use standard kubectl apply or kustomize, not be tied to a specific tool
- Use namespaces for resource isolation
- Pin image versions (no:latest)
- Include resource requests/limits
markdown

“no:latest”——一个 examples 仓库如果用 latest 标签,今天能跑明天可能挂。必须 pin 版本。


九、_archived/:32 个”样本库”是 K8s 生态的化石#

_archived/ 目录下有 32 个历史例子:

cockroachdb, elasticsearch, javaee, meteor, newrelic, oms,
openshift-origin, persistent-volume-provisioning, phabricator,
pod, podsecuritypolicy, scheduler-policy, selenium, sharing-clusters,
spark, storm, ...
text

这是 K8s 生态的”考古层”——phabricator(Meta 的 code review 工具)、openshift-origin(红帽 K8s 发行版)、javaee(Java 企业版)——这些例子记录了 2014-2020 年 K8s 生态的演化。

最有考古价值的:

  • pod/:K8s 早期连 Deployment 都没有,只有裸 Pod
  • scheduler-policy/:早期自定义调度器范式
  • podsecuritypolicy/:PSP 已于 1.25 移除,是 K8s 安全模型演化的活标本
  • sharing-clusters/:多租户 K8s 早期实践

这是 90% 的 K8s 教程不会告诉你的”黑暗历史”。


十、为什么这个仓库只有 6.6K stars?#

仔细看 README 的贡献者:

kubernetes-sigs contributors
SIG Apps maintainers
text

它是 SIG Apps 维护的”教学仓库”,不是产品仓库。教学方法的价值往往不被 star 数量反映。

但它给的价值是:

  1. 每个 example 都是”完整生产场景”——不是 snippet
  2. README 强制 11 节结构——质量保证
  3. 附带历史归档——生态演化的时间轴
  4. AI/ML 案例占快速增长的 50%——vLLM + TF Serving

和 OpenViking、TencentDB Agent Memory 相比:

维度OpenVikingTencentDB Agent Memorykubernetes/examples
类型框架框架示例库
受众Agent 开发者Agent 团队K8s 应用开发者
抽象层上下文数据库记忆资产实际部署
语言Python + RustTypeScriptShell + YAML
教学价值中(架构)中(设计)极高(手把手)
生产可用性高高高(直接 copy)

kubernetes/examples 的教学价值我认为是三者最高的——因为它不跟你讲架构,直接给你能跑的 YAML。


十一、5 个 “我读完才发现” 的隐藏细节#

11.1 Image Pull Policy 写 Always#

imagePullPolicy: Always
yaml

YAML 里写 Always 而不是默认——刻意防止 image 缓存导致更新不生效。

11.2 Headless Service 必要性#

Cassandra StatefulSet 配套的 cassandra-service.yaml 是 headless(clusterIP: None),没有 headless service 设不出 cassandra-0.cassandra.default.svc.cluster.local 这种 DNS。

11.3 README 里的 Last Validated#

README.md 末尾要求标注:

- Last Validated Kubernetes Version (Recommended)
markdown

这是工程化最佳实践——例子能跑不能只靠”现在能跑”,要标记”在 X.Y 版本验证过”。

11.4 平台兼容性注释#

vllm-deployment.yaml 顶部注释:

# Node selectors are the main difference among the cloud providers,
# making sure vLLM pods land on Nodes with the correct GPU. The
# following are node selector examples for three cloud providers.
yaml

不同云厂商的 GPU 标签都不一样——GKE cloud.google.com/gke-accelerator / EKS node.kubernetes.io/instance-type / AKS agentpiscasi.com/gpu。这是 K8s 生态最痛的问题。

11.5 CPU Manager 隐含的硬件要求#

archived/cpu-manager/ 留了一整个目录讲 CPU Manager(K8s 静态绑核)——这个功能只有少数工作负载真需要(NFV、低延迟交易),普通应用忽略。


十二、复制这个仓库的方式#

仓库 README 的 Quick Start 模式极简:

# 找一个例子
cd AI/vllm-deployment
# 跟着 README TL;DR 跑
kubectl create namespace vllm-example
kubectl apply -f vllm-deployment.yaml -n vllm-example
kubectl wait --for=condition=Available --timeout=900s deployment/vllm-gemma-deployment -n vllm-example
bash

克隆到本地都不需要——直接 kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/AI/vllm-deployment/vllm-deployment.yaml。

这种”例子即 URL”的设计哲学,是 SIG Apps 的精髓:例子不是私有模板,是公共契约。


十三、读完之后我换了一个角度看”examples”#

我之前看 examples 仓库默认思路是:

examples = 给新手看的入门教程
text

读完之后我换了个角度:

examples = 维护者用贡献门槛筛选出来的高质量实战案例
text

注意 guidelines.md 的措辞:

“An example demonstrates running an application… must be: Meaningful, Educational, Illustrative of Best Practices, Focused.”

这四条不仅是给贡献者的要求,也是给所有”想给项目写 examples”的工程师的清单——

  1. Meaningful:解决真实问题,不是技术 demo
  2. Educational:解释为什么这么写,不只是”这是什么”
  3. Best Practices:用当前推荐做法,不用旧的 deprecated API
  4. Focused:聚焦一个具体场景,不过度扩展

这是 Kubernetes 社区给我示范的”软件工程美学”——例子不是免费的,每一个例子都要回答”为什么我存在”。

我下一篇博客可能会写怎么用这个仓库的范式给我自己的 K8s 项目写 examples(一篇博客可能写不完,会分系列)。如果你想先动手,最短路径:

# 直接看 vLLM 那个例子
git clone https://github.com/kubernetes/examples.git
cd examples/AI/vllm-deployment
# 跟着 README 的 TL;DR 跑
bash

或者直接看 官方教程列表 ↗——examples 仓库 + 官方教程是配对的。


附录:关键源码定位速查#

模块路径
README 自我介绍README.md:1-5
贡献指南guidelines.md
vLLM 部署AI/vllm-deployment/vllm-deployment.yaml
vLLM ServiceAI/vllm-deployment/vllm-service.yaml
GPU HPAAI/vllm-deployment/hpa/gpu-horizontal-pod-autoscaler.yaml
vLLM HPA(业务指标)AI/vllm-deployment/hpa/vllm-hpa.md
PrometheusRuleAI/vllm-deployment/hpa/prometheus-rule.yaml
Prometheus AdapterAI/vllm-deployment/hpa/prometheus-adapter.yaml
TF Serving 部署AI/model-serving-tensorflow/deployment.yaml
TF Serving PVAI/model-serving-tensorflow/pv.yaml
Cassandra StatefulSetdatabases/cassandra/cassandra-statefulset.yaml
Cassandra Servicedatabases/cassandra/cassandra-service.yaml
Cassandra Go clientdatabases/cassandra/go/
MySQL + Cinderdatabases/mysql-cinder-pd/mysql.yaml
Guestbook PHPweb/guestbook/redis-master-deployment.yaml
Guestbook Goweb/guestbook-go/main.go
AI 目录愿景AI/README.md
Archived 演进_archived/(32 个目录)

📘 项目信息

Kubernetes 官方 examples 仓库:6.6K stars 装着的 K8s 实战样本
https://wth2jhl.online/blog/kubernetes-examples/
Author 小吴同学
Published at August 19, 2026