K8s Manifest介绍(清单文件,声明式基础设施,集群中应该存在哪些资源,以及这些资源应该处于什么状态)apiVersion、kind

文章目录

  • [Kubernetes Manifest:从 YAML 文件到声明式基础设施](#Kubernetes Manifest:从 YAML 文件到声明式基础设施)
    • 引言
    • [Manifest 的由来](#Manifest 的由来)
    • [Kubernetes 为什么选择 Manifest](#Kubernetes 为什么选择 Manifest)
    • [Manifest 的基本结构](#Manifest 的基本结构)
      • 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 的作用:
  1. 标识资源类型所属的 API 组与版本

    Kubernetes 将资源按功能分组(如 apps, batch, networking.k8s.io, custom-resource-definition 等),每组下有多个版本(如 v1, v1beta1, v1alpha1)。

  2. 决定 Kubernetes 如何解析和处理该资源

    控制平面(kube-apiserver)根据 apiVersion 找到对应的 API handler 和验证规则。错误的 apiVersion 会导致创建失败(如 the server could not find the requested resource)。

  3. 支持 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 JobCronJob(注意:CronJobbatch/v1beta1 是旧版,v1 是新版)。

💡 提示:可通过命令查看集群支持的 API 组和版本:

bash 复制代码
kubectl api-resources --sort-by=name
kubectl api-versions

⚠️ 常见错误
  • ❌ 写成 apiVersion: deployment/v1 → 错误!Deployment 属于 apps 组,不是 deployment
  • ❌ 使用已废弃的版本(如 extensions/v1beta1Deployment)→ 在 k8s ≥1.16 已移除,会报错。
  • ❌ 混淆 kindapiVersionkind: 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 的设计哲学:声明目标状态,而非描述执行过程。