文章目录
- [Kubernetes Manifest:从 YAML 文件到声明式基础设施](#Kubernetes Manifest:从 YAML 文件到声明式基础设施)
-
- 引言
- [Manifest 的由来](#Manifest 的由来)
- [Kubernetes 为什么选择 Manifest](#Kubernetes 为什么选择 Manifest)
- [Manifest 的基本结构](#Manifest 的基本结构)
-
- apiVersion
-
- [🔍 详细解释 apiVersion:](#🔍 详细解释 apiVersion:)
-
- [✅ `apiVersion` 的作用:](#✅
apiVersion的作用:)
- [✅ `apiVersion` 的作用:](#✅
- [📌 示例解析](#📌 示例解析)
- [⚠️ 常见错误](#⚠️ 常见错误)
- [🧩 为什么强调"不同资源可能属于不同 API Group"?](#🧩 为什么强调“不同资源可能属于不同 API Group”?)
- kind
- metadata
- spec
- [常见 Manifest 类型](#常见 Manifest 类型)
- [一个完整服务通常包含哪些 Manifest](#一个完整服务通常包含哪些 Manifest)
- [Manifest 与 kubectl 的关系](#Manifest 与 kubectl 的关系)
- [Manifest 的优势](#Manifest 的优势)
- [Manifest 的局限性](#Manifest 的局限性)
- [Manifest、Helm 与 Kustomize 的关系](#Manifest、Helm 与 Kustomize 的关系)
- [Kubernetes Manifest 的最佳实践](#Kubernetes Manifest 的最佳实践)
- 总结
Kubernetes Manifest:从 YAML 文件到声明式基础设施
引言
在接触 Kubernetes 的过程中,开发者最先遇到的往往不是 Pod、Service 或 Ingress,而是一堆 YAML 文件:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
这些 YAML 文件通常被称为 Manifest(清单文件)。
对于初学者来说,它们看起来只是配置文件;但从 Kubernetes 的设计理念来看,Manifest 实际上是 Kubernetes 整个声明式管理模型的核心。
理解 Manifest,不仅是在学习 YAML 语法,更是在理解 Kubernetes 如何管理基础设施。
Manifest 的由来
Manifest 一词最早来源于航运和物流领域。
例如:
- Cargo Manifest(货物清单)
- Shipping Manifest(装运清单)
用于记录:
这艘船上应该装载哪些货物。
Kubernetes 借用了这一概念。
Manifest 描述的是:
集群中应该存在哪些资源,以及这些资源应该处于什么状态。
例如:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: profile-service
spec:
replicas: 3
这表示:
希望集群中始终运行 3 个 profile-service 实例。
至于如何创建、调度、重启和恢复,则由 Kubernetes 自己负责。
Kubernetes 为什么选择 Manifest
在 Kubernetes 出现之前,运维通常采用命令式(Imperative)管理方式。
例如:
bash
docker run nginx
docker run redis
docker run mysql
或者:
bash
systemctl start nginx
管理员告诉系统:
现在执行这个操作。
这种方式简单直接,但随着系统规模扩大,会出现一些问题:
状态难以追踪
执行过的命令可能已经无法复现。
例如:
bash
kubectl scale deployment api --replicas=5
半年后可能没人知道为什么副本数变成了 5。
环境难以复制
开发环境:
text
2 个实例
测试环境:
text
4 个实例
生产环境:
text
6 个实例
如果依赖人工操作,很容易出现配置漂移(Configuration Drift)。
自动恢复能力不足
如果某个服务崩溃:
text
管理员发现问题
↓
登录服务器
↓
重启服务
恢复过程依赖人工介入。
因此 Kubernetes 采用了声明式(Declarative)模型:
yaml
replicas: 3
系统持续检查:
text
当前状态 ≠ 目标状态
就自动进行修正。
这种模式也被称为:
Desired State Management(目标状态管理)
Manifest 正是描述目标状态的载体。
Manifest 的基本结构
一个典型 Manifest 通常包含几个部分:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
apiVersion
指定资源 API 版本。
例如:
yaml
apiVersion: v1
或:
yaml
apiVersion: apps/v1
不同资源可能属于不同 API Group。
🔍 详细解释 apiVersion:
✅ apiVersion 的作用:
-
标识资源类型所属的 API 组与版本
Kubernetes 将资源按功能分组(如
apps,batch,networking.k8s.io,custom-resource-definition等),每组下有多个版本(如v1,v1beta1,v1alpha1)。 -
决定 Kubernetes 如何解析和处理该资源
控制平面(kube-apiserver)根据
apiVersion找到对应的 API handler 和验证规则。错误的apiVersion会导致创建失败(如the server could not find the requested resource)。 -
支持 API 演进与兼容性
新功能可能先在
v1beta1中引入,稳定后升级到v1;旧版本逐步废弃(deprecation),避免破坏性变更。
📌 示例解析
| 写法 | 含义 |
|---|---|
apiVersion: v1 |
属于 核心 API 组(core group) ,即无前缀的默认组。例如:Pod, Service, ConfigMap, Secret 都用这个。 |
apiVersion: apps/v1 |
属于 apps API 组 ,版本为 v1。例如:Deployment, StatefulSet, DaemonSet, ReplicaSet。 |
apiVersion: networking.k8s.io/v1 |
属于 networking.k8s.io API 组 ,版本 v1。例如:Ingress(自 v1.22+ 推荐使用此版本)。 |
apiVersion: batch/v1 |
Job 和 CronJob(注意:CronJob 在 batch/v1beta1 是旧版,v1 是新版)。 |
💡 提示:可通过命令查看集群支持的 API 组和版本:
bashkubectl api-resources --sort-by=name kubectl api-versions
⚠️ 常见错误
- ❌ 写成
apiVersion: deployment/v1→ 错误!Deployment属于apps组,不是deployment。 - ❌ 使用已废弃的版本(如
extensions/v1beta1的Deployment)→ 在 k8s ≥1.16 已移除,会报错。 - ❌ 混淆
kind和apiVersion:kind: Deployment必须配apiVersion: apps/v1,不能随便改。
🧩 为什么强调"不同资源可能属于不同 API Group"?
因为 Kubernetes 架构是模块化的:
- 核心资源(Pod、Node)→
v1(core group) - 应用工作负载 →
apps/v1 - 网络策略 →
networking.k8s.io/v1 - 存储卷 →
storage.k8s.io/v1 - 自定义资源(CRD)→ 可能是
mygroup.example.com/v1
这使得 Kubernetes 可扩展性强,第三方也可注册自己的 API Group。
✅ 总结一句话:
apiVersion就像资源的"身份证号",告诉 Kubernetes:"我是哪个组织(Group)、哪个版本(Version)的成员",从而正确识别和处理它。
kind
资源类型。
例如:
yaml
kind: Pod
kind: Deployment
kind: Service
kind: ConfigMap
Kubernetes 根据 kind 知道要创建什么对象。
metadata
资源元数据。
例如:
yaml
metadata:
name: user-service
namespace: production
包含:
- 名称
- 标签
- 注解
- Namespace
等信息。
spec
资源期望状态。
例如:
yaml
spec:
replicas: 3
这是 Manifest 最核心的部分。
不同资源的 spec 结构完全不同。
常见 Manifest 类型
Namespace
用于资源隔离。
yaml
kind: Namespace
例如:
text
dev
staging
prod
不同环境通常会放在不同 Namespace 中。
Deployment
最常见的应用部署方式。
yaml
kind: Deployment
负责:
- 创建 Pod
- 自动重启
- 滚动升级
- 扩缩容
例如:
yaml
spec:
replicas: 3
表示始终保持 3 个副本运行。
Service
解决 Pod 地址不稳定的问题。
yaml
kind: Service
Pod 会频繁重建:
text
10.0.0.5
↓
删除
↓
10.0.0.8
Service 提供稳定访问入口:
text
user-service
应用只需要访问 Service。
Ingress
负责 HTTP/HTTPS 流量入口。
yaml
kind: Ingress
例如:
text
api.example.com
↓
user-service
Ingress 是 Kubernetes 对外暴露 Web 服务的标准方案之一。
ConfigMap
用于保存配置。
yaml
kind: ConfigMap
例如:
yaml
DATABASE_HOST: postgres
REDIS_HOST: redis
配置与镜像解耦。
Secret
用于保存敏感信息。
yaml
kind: Secret
例如:
yaml
DATABASE_PASSWORD
JWT_SECRET
虽然 Secret 默认只是 Base64 编码,并非真正加密,但仍然是 Kubernetes 管理敏感配置的基础机制。
一个完整服务通常包含哪些 Manifest
一个微服务通常对应多份 Manifest:
text
user-service
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── configmap.yaml
└── secret.yaml
职责分别为:
text
Deployment -> 运行程序
Service -> 服务发现
Ingress -> 外部访问
ConfigMap -> 普通配置
Secret -> 敏感配置
这也是大多数生产环境的基本结构。
Manifest 与 kubectl 的关系
Manifest 本身不会执行。
真正执行的是:
bash
kubectl apply -f deployment.yaml
Kubernetes 会:
text
读取 Manifest
↓
保存到 etcd
↓
Controller 持续对比状态
↓
自动修正差异
因此:
text
Manifest = 目标状态描述
kubectl = 提交工具
Controller = 执行者
三者共同构成 Kubernetes 的工作模式。
Manifest 的优势
可版本管理
Manifest 本质是文本文件。
因此可以直接放入 Git:
text
infra/
└── k8s/
结合 GitHub、GitLab 进行版本追踪。
环境可复现
新的集群只需要:
bash
kubectl apply -f .
即可重建环境。
支持 GitOps
例如:
- Argo CD
- Flux
会持续同步 Git 与集群状态。
形成:
text
Git
↓
Manifest
↓
Kubernetes
的自动化管理流程。
易于审计
任何变更都有记录:
text
谁修改了副本数
谁修改了镜像版本
谁新增了服务
都能追踪。
Manifest 的局限性
虽然 Manifest 是 Kubernetes 的基础,但并非完美。
YAML 容易变复杂
小项目:
yaml
30 行
大型项目:
yaml
500+
维护成本迅速上升。
重复配置严重
多个服务可能拥有大量重复内容:
yaml
resources:
requests:
cpu: 100m
需要不断复制粘贴。
缺乏模板能力
原生 Manifest 不支持变量:
yaml
image: user-service:v1.2.3
升级版本时需要手工修改。
因此出现了:
- Helm
- Kustomize
等工具。
Manifest、Helm 与 Kustomize 的关系
很多人误以为 Helm 可以替代 Manifest。
实际上:
text
Helm
↓
生成 Manifest
↓
提交 Kubernetes
Kubernetes 最终接收的仍然是 Manifest。
同理:
text
Kustomize
↓
生成 Manifest
↓
提交 Kubernetes
因此:
Manifest 是 Kubernetes 的基础抽象,Helm 和 Kustomize 只是 Manifest 的生成工具。
Kubernetes Manifest 的最佳实践
一个资源一个文件
推荐:
text
deployment.yaml
service.yaml
ingress.yaml
而不是把所有内容塞进一个巨大 YAML。
按环境隔离
例如:
text
k8s/
├── base
├── dev
├── staging
└── prod
方便管理不同环境配置。
避免在 Manifest 中硬编码敏感信息
不要:
yaml
password: 123456
应使用:
yaml
Secret
External Secrets
Vault
等方案。
与 GitOps 配合
生产环境推荐:
text
Git
↓
Pull Request
↓
Argo CD
↓
Kubernetes
而非人工执行 kubectl。
总结
Manifest 是 Kubernetes 最核心的概念之一。
它并不是简单的 YAML 配置文件,而是 Kubernetes 声明式管理模型的具体体现。
通过 Manifest,开发者描述:
集群应该是什么样子。
而 Kubernetes 持续保证:
集群最终变成那个样子。
无论未来使用 Helm、Kustomize、Argo CD 还是其他平台工具,最终都会回到 Manifest 这一基础抽象。因此,理解 Manifest,不仅是在学习 Kubernetes 配置文件,更是在理解 Kubernetes 的设计哲学:声明目标状态,而非描述执行过程。