Kubernetes资源对象详解

很多人刚接触 Kubernetes 时,第一反应往往是:概念太多了,PodDeploymentServiceIngressConfigMapSecretPVC……看起来每个都像是“要学的点”,但不知道它们之间到底是什么关系。

其实可以换个角度理解:Kubernetes 本质上是在管理一组资源对象(Resource / Object)。你不是在“直接启动一个程序”,而是在向 Kubernetes 声明一系列对象,然后由它持续把实际运行状态调整到你期望的状态。

所以,学 Kubernetes 的核心,不是死记 YAML,而是搞清楚:

  • Kubernetes 里常见的资源对象有哪些
  • 每种资源解决什么问题
  • 一个应用真正跑起来时,通常需要哪些资源互相配合

这篇文章就围绕这三个问题展开。


什么是 Kubernetes 资源对象

官方文档对 Kubernetes 对象的定义很明确:对象是 Kubernetes 系统中的持久化实体,用来描述集群的期望状态

可以把它理解成:

  • 你写 YAML
  • Kubernetes 接收 YAML
  • API Server 把这些对象存起来
  • 控制器不断对比“期望状态”和“当前状态”
  • 如果不一致,就自动修正

例如你声明:

  • 我要 3 个 Web 实例
  • 每个实例都跑某个镜像
  • 要通过 Service 暴露访问入口
  • 配置从 ConfigMap 读取
  • 密码从 Secret 读取

那么 Kubernetes 就会持续保证这些对象尽量处于你定义好的状态。这就是它的声明式管理思想。


一、最核心的资源分类

为了降低理解难度,可以把常见资源先分成几类:

1. 工作负载类

这类资源决定“程序怎么跑”:

  • Pod
  • Deployment
  • StatefulSet
  • DaemonSet
  • Job
  • CronJob

2. 服务发现与流量入口类

这类资源决定“程序怎么被访问”:

  • Service
  • Ingress
  • EndpointSlice

3. 配置与敏感信息类

这类资源决定“程序拿什么配置运行”:

  • ConfigMap
  • Secret

4. 存储类

这类资源决定“程序的数据放在哪里”:

  • Volume
  • PersistentVolume(PV)
  • PersistentVolumeClaim(PVC)
  • StorageClass

5. 资源隔离与权限类

这类资源决定“谁能访问什么、资源如何隔离”:

  • Namespace
  • ServiceAccount
  • Role
  • RoleBinding
  • ClusterRole
  • ClusterRoleBinding

6. 弹性与运维辅助类

这类资源决定“如何扩缩容、如何维持运行”:

  • HorizontalPodAutoscaler(HPA)
  • ResourceQuota
  • LimitRange
  • PodDisruptionBudget(PDB)

二、工作负载类资源

1. Pod:最小调度单元

Pod 是 Kubernetes 中最小的可部署、可调度单元。

一个 Pod 里可以包含:

  • 一个主容器
  • 一个或多个辅助容器
  • 共享网络
  • 共享存储卷

最常见的情况是:一个 Pod 跑一个应用容器

但要注意,Pod 通常不是你在生产环境里直接长期维护的对象,因为:

  • Pod 挂了可能会被重建
  • Pod 名称和 IP 可能变化
  • 你需要更高层资源帮你管理副本、升级和自愈

所以 Pod 更像“真正运行容器的载体”。


2. Deployment:无状态应用最常用资源

如果你的应用是无状态的,比如:

  • Web 服务
  • Go API 服务
  • 后台管理系统
  • 普通业务应用

最常用的就是 Deployment

它解决的问题包括:

  • 管理多个 Pod 副本
  • 滚动更新
  • 回滚
  • 自愈恢复

你真正想表达的通常不是“启动一个 Pod”,而是:

帮我保持 3 个副本一直运行,并且后续我要升级镜像时平滑替换。

这正是 Deployment 的职责。


3. StatefulSet:有状态应用

如果应用需要稳定身份或持久化存储,就更适合 StatefulSet,例如:

  • MySQL
  • PostgreSQL
  • Redis Sentinel / Cluster
  • Kafka
  • ZooKeeper

StatefulSet 的特点:

  • Pod 名字稳定,例如 mysql-0mysql-1
  • 网络身份稳定
  • 通常配合 PVC 使用
  • 创建和删除顺序受控

简单说:

  • 无状态服务优先用 Deployment
  • 有状态服务优先看 StatefulSet

4. DaemonSet:每个节点跑一个

DaemonSet 的语义非常直接:确保每个节点上都运行一个指定 Pod

常见场景:

  • 日志采集器
  • 节点监控 agent
  • CNI 网络插件
  • 存储插件 agent

也就是说,它不是按“副本数”部署,而是按“节点数”部署。


5. Job 与 CronJob:一次性任务与定时任务

Job 用于一次性任务,比如:

  • 数据迁移
  • 初始化脚本
  • 离线计算
  • 备份任务

CronJob 是定时运行的 Job,比如:

  • 每天凌晨备份数据库
  • 每小时清理日志
  • 每周执行报表汇总

所以你可以简单记忆:

  • Job:执行一次直到成功
  • CronJob:按计划周期性执行

三、服务发现与流量入口类资源

1. Service:给 Pod 提供稳定访问入口

Pod 的 IP 不是稳定的,重建后可能变化。所以 Kubernetes 需要一个稳定入口,这就是 Service

Service 解决的问题是:

  • 给一组 Pod 提供固定访问方式
  • 基于标签选择后端 Pod
  • 在集群内部做服务发现和负载均衡

常见类型:

  • ClusterIP:默认类型,只在集群内部访问
  • NodePort:通过节点端口对外暴露
  • LoadBalancer:云厂商环境下申请外部负载均衡器

如果你把 Deployment 理解成“跑起来”,那 Service 就是“能被访问”。


2. Ingress:HTTP/HTTPS 七层入口

当应用需要对外提供 Web 访问时,通常不会直接暴露很多 NodePort,而是通过 Ingress 来统一管理入口流量。

Ingress 常用于:

  • 根据域名转发
  • 根据路径转发
  • 配置 HTTPS 证书
  • 做统一入口管理

例如:

  • api.example.com 转到 API 服务
  • www.example.com 转到前端服务
  • /admin 转到后台管理服务

它通常要配合 Ingress Controller 使用,比如 NGINX Ingress Controller。


四、配置与敏感信息类资源

1. ConfigMap:保存普通配置

应用运行时经常要用到:

  • 配置文件
  • 环境变量
  • 应用参数
  • 外部地址

这些“非敏感配置”通常存到 ConfigMap 中。

常见用途:

  • 注入为环境变量
  • 挂载为文件
  • 提供应用配置

典型例子:

  • APP_ENV=prod
  • LOG_LEVEL=info
  • SERVER_PORT=8080

2. Secret:保存敏感信息

密码、令牌、证书、密钥等敏感信息不应该直接写到 Deployment 里,这类内容通常放到 Secret

常见用途:

  • 数据库密码
  • API Token
  • TLS 证书
  • 镜像仓库凭据

需要注意的是:Secret 不是“天然绝对安全”。它只是比直接明文写在 Pod 配置里更规范,生产中还要配合:

  • 最小权限控制
  • etcd 加密
  • 外部 Secret 管理方案

五、存储类资源

1. Volume:Pod 内部卷

Pod 里的容器通常是短暂的,但很多场景需要文件或数据卷,于是 Kubernetes 提供了各种 Volume

常见类型:

  • emptyDir:Pod 生命周期内的临时目录
  • configMap:把 ConfigMap 挂到文件系统
  • secret:把 Secret 挂到文件系统

如果数据不需要跨 Pod 重建保留,emptyDir 就够用;如果需要长期保存,就要进一步使用持久化存储。


2. PV、PVC、StorageClass:持久化存储三件套

这三个对象是很多初学者最容易混淆的部分。

可以这样理解:

  • PV:集群中的一块实际存储资源
  • PVC:用户对存储的申请单
  • StorageClass:动态创建存储时的模板或供应方式

推荐的理解方式是:

  • 应用开发者通常写 PVC
  • 集群管理员提供 StorageClass
  • 底层系统根据 PVC 自动创建或绑定 PV

也就是说,应用通常不直接关心底层磁盘细节,而是“声明我要 10Gi 存储”。


六、隔离、身份与权限类资源

1. Namespace:逻辑隔离

Namespace 用来把一个集群划分成多个逻辑空间。

你可以按:

  • 团队
  • 环境
  • 项目
  • 业务线

来做隔离。

例如:

  • dev
  • test
  • prod
  • monitoring

这样做的好处是资源更清晰,也更方便做权限控制和配额限制。


2. ServiceAccount:Pod 的身份

在 Kubernetes 中,Pod 访问 API Server 或其他受控资源时,也需要身份。这个身份通常就是 ServiceAccount

它经常和 RBAC 配合使用。

简单说:

  • 用户有用户身份
  • Pod 也有 Pod 的身份
  • Pod 的身份默认就是 ServiceAccount

3. Role / RoleBinding / ClusterRole / ClusterRoleBinding:权限控制

这些资源用于做 RBAC 权限管理。

核心含义:

  • Role:某个命名空间内的权限集合
  • RoleBinding:把 Role 绑定给用户或 ServiceAccount
  • ClusterRole:集群级权限集合
  • ClusterRoleBinding:把 ClusterRole 绑定出去

这部分在入门阶段不一定要写很多 YAML,但至少要知道:

  • Kubernetes 有完整的权限体系
  • 不应该让应用默认拿过大的权限

七、弹性与运维辅助资源

1. HPA:水平自动扩缩容

HorizontalPodAutoscaler 会根据指标自动调整副本数。

常见依据:

  • CPU 使用率
  • 内存使用率
  • 自定义业务指标

例如:

  • 平时 2 个副本
  • 高峰期自动扩到 6 个
  • 低峰期再缩回去

它通常与 Deployment 联动使用。


2. ResourceQuota 与 LimitRange

这两个对象主要用于命名空间层面的资源治理。

ResourceQuota 控制总量,比如:

  • 这个 namespace 最多能创建多少 Pod
  • 最多能用多少 CPU / 内存

LimitRange 控制单个对象的默认值和上下限,比如:

  • 单个容器默认内存申请
  • 单个 Pod 最大可申请的 CPU

这类资源在多人共享集群时非常重要。


八、最常见的一组“应用部署资源”

如果我们要在 Kubernetes 中运行一个普通 Web 应用,最常见的资源组合大致如下:

资源 作用
Namespace 隔离应用环境
Deployment 部署应用副本
Service 为应用提供稳定访问入口
Ingress 对外暴露 HTTP/HTTPS
ConfigMap 存放普通配置
Secret 存放密码、令牌等敏感信息
PVC 提供持久化存储(如上传文件、数据库数据)
HPA 根据负载自动扩缩容
ServiceAccount 赋予 Pod 身份与权限

这也是面试里非常常见的一类问题:

如果让你把一个应用部署到 Kubernetes,上线至少会涉及哪些资源?

比较稳妥的回答就是:

至少要考虑运行载体、访问方式、配置管理、敏感信息、存储、权限和扩缩容。


九、案例:部署一个简单的 Web 应用

下面用一个比较典型的场景来串起这些资源。

假设我们要部署一个博客后台 API 服务,镜像是:

registry.example.com/blog-api:v1.0.0

需求如下:

  • 运行 2 个副本
  • 应用监听 8080 端口
  • 需要数据库地址和运行环境配置
  • 需要数据库密码
  • 要通过域名 api.blog.example.com 对外访问
  • 需要 10Gi 持久化存储保存上传文件
  • 后续希望支持自动扩缩容

那么一个比较典型的资源组合会是:

  1. Namespace
  2. ConfigMap
  3. Secret
  4. PersistentVolumeClaim
  5. Deployment
  6. Service
  7. Ingress
  8. HorizontalPodAutoscaler

1. 创建 Namespace

apiVersion: v1
kind: Namespace
metadata:
name: blog-prod

作用:把博客应用相关资源统一放在 blog-prod 命名空间中,便于管理和隔离。


2. 创建 ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
name: blog-api-config
namespace: blog-prod
data:
APP_ENV: "production"
SERVER_PORT: "8080"
DB_HOST: "mysql.blog-prod.svc.cluster.local"
DB_NAME: "blog"

作用:保存普通配置,不包含敏感信息。


3. 创建 Secret

apiVersion: v1
kind: Secret
metadata:
name: blog-api-secret
namespace: blog-prod
type: Opaque
stringData:
DB_USER: "blog_user"
DB_PASSWORD: "change-me"

作用:保存数据库账号密码等敏感信息。


4. 创建 PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: blog-api-uploads
namespace: blog-prod
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi

作用:给应用申请 10Gi 持久化存储,用于文件上传目录。


5. 创建 Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: blog-api
namespace: blog-prod
spec:
replicas: 2
selector:
matchLabels:
app: blog-api
template:
metadata:
labels:
app: blog-api
spec:
containers:
- name: blog-api
image: registry.example.com/blog-api:v1.0.0
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: blog-api-config
- secretRef:
name: blog-api-secret
volumeMounts:
- name: uploads
mountPath: /data/uploads
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
volumes:
- name: uploads
persistentVolumeClaim:
claimName: blog-api-uploads

这一步是整个案例的核心。

Deployment 做了这些事:

  • 声明要 2 个副本
  • 指定镜像版本
  • 暴露应用端口
  • 从 ConfigMap 和 Secret 注入环境变量
  • 挂载 PVC 到容器目录
  • 设置资源请求和上限

6. 创建 Service

apiVersion: v1
kind: Service
metadata:
name: blog-api
namespace: blog-prod
spec:
selector:
app: blog-api
ports:
- port: 80
targetPort: 8080
type: ClusterIP

作用:为 blog-api 这组 Pod 提供一个稳定的集群内访问入口。

这里暴露的是 80 端口,但后端真正转发到容器的 8080。


7. 创建 Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: blog-api
namespace: blog-prod
spec:
ingressClassName: nginx
rules:
- host: api.blog.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: blog-api
port:
number: 80

作用:把域名流量转发给 Service,再由 Service 转发给后端 Pod。

这样外部用户就可以通过:

https://api.blog.example.com

访问应用。


8. 创建 HPA

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: blog-api
namespace: blog-prod
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: blog-api
minReplicas: 2
maxReplicas: 6
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70

作用:当 CPU 平均使用率过高时,自动把 Deployment 副本数从 2 扩到更多。


十、把案例串起来理解

上面这些资源组合在一起,完整表达了一套应用上线方案:

  • Namespace 负责隔离
  • ConfigMap 提供普通配置
  • Secret 提供敏感配置
  • PVC 提供持久化数据卷
  • Deployment 负责真正跑应用
  • Service 负责集群内访问
  • Ingress 负责集群外访问
  • HPA 负责自动扩缩容

如果把它翻译成一句人话,就是:

在一个独立环境里,部署一个有两个副本的 Web 服务,它带配置、带密码、带存储、可以从域名访问,并且流量大时能自动扩容。

这就是 Kubernetes 资源对象协同工作的方式。


十一、哪些资源是初学者必须掌握的

如果你刚开始学 Kubernetes,不要试图一次把所有资源都背下来。优先顺序建议是:

第一阶段:必须掌握

  • Pod
  • Deployment
  • Service
  • Ingress
  • ConfigMap
  • Secret
  • Namespace

第二阶段:继续深入

  • PVC
  • StatefulSet
  • DaemonSet
  • Job
  • CronJob
  • HPA

第三阶段:面向生产环境

  • ServiceAccount
  • RBAC
  • ResourceQuota
  • LimitRange
  • PDB
  • StorageClass

十二、面试中如何回答“你了解 Kubernetes 资源吗”

如果面试官问这个问题,不建议你把一堆名词直接背出来,更好的回答方式是分类讲。

例如可以这样回答:

Kubernetes 本质上是通过资源对象来管理应用的。最核心的资源可以分成几类:
第一类是工作负载,比如 Pod、Deployment、StatefulSet,用来决定程序怎么跑;
第二类是服务发现和入口,比如 Service、Ingress,用来解决访问问题;
第三类是配置和敏感信息,比如 ConfigMap 和 Secret;
第四类是存储,比如 PVC、PV、StorageClass;
第五类是权限和隔离,比如 Namespace、ServiceAccount、RBAC;
另外还有 HPA 这类扩缩容资源。
如果我要上线一个应用,最典型的资源组合通常是 Deployment + Service + Ingress + ConfigMap + Secret,涉及持久化时再加 PVC。

这种回答方式的优点是:

  • 结构清晰
  • 有分类能力
  • 能体现你不是死记概念,而是知道这些对象如何配合工作

总结

Kubernetes 资源看起来很多,但本质并不复杂。你可以把它们理解成一套“声明应用应该如何运行”的对象系统。

真正重要的不是把所有 YAML 字段都背下来,而是搞清楚每个资源的职责边界:

  • 谁负责运行
  • 谁负责访问
  • 谁负责配置
  • 谁负责存储
  • 谁负责权限
  • 谁负责扩缩容

一旦你把这几层关系理顺,再去看具体 YAML,就不会再觉得 Kubernetes 只是“很多配置文件”,而会理解它为什么能把应用运行、暴露、扩缩容、存储和权限管理统一起来。

对于初学者来说,最实用的学习路径不是从所有资源平铺开始,而是从一个完整案例出发,反过来理解:

为了让一个应用在 Kubernetes 上真正可用,我到底需要哪些资源对象?

当你能回答这个问题,Kubernetes 的资源体系就算真正入门了。