对象存储
对象存储是云原生架构中存放海量非结构化数据(图片、视频、文档、备份、模型文件)的标准方案,几乎所有现代系统都把 DB 之外的大文件放在对象存储上。
为什么需要对象存储
文件存储(NFS / 本地盘):
- 容量受限单机/单卷
- 难以全球分发
- 不适合海量小文件
块存储(EBS / Ceph RBD):
- 必须挂载到 VM/Pod
- 单挂载点,不可共享
- 价格昂贵
对象存储:
- 无限容量,按用量付费
- HTTP API 访问(S3 协议)
- 天然分布式 + 多副本
- 配合 CDN 全球分发
核心模型
Bucket(桶)
│
├── Object(对象)
│ ├── Key(唯一路径,如 user/123/avatar.png)
│ ├── Value(二进制数据)
│ └── Metadata(Content-Type、ETag、自定义头)
│
└── Policy / ACL(权限)
关键特性:
| 特性 | 说明 |
|---|---|
| 扁平命名空间 | 无目录概念,靠 Key 前缀模拟(user/123/…) |
| 不可变对象 | 修改 = 覆盖整个对象,没有 in-place 修改 |
| 强一致性 | S3 2020 后支持读写强一致 |
| 版本控制 | 同一 Key 可保留多个版本 |
| 生命周期 | 自动转冷存储、自动删除 |
主流方案对比
| 方案 | 特点 | 适用场景 |
|---|---|---|
| AWS S3 | 业界标准,生态最完善 | 全球部署 |
| 阿里云 OSS | 国内首选,与 CDN 深度集成 | 国内业务 |
| 腾讯云 COS | 国内,价格便宜 | 中小企业 |
| MinIO | 开源、S3 兼容、可私有化部署 | 自建/混合云 |
| Ceph RGW | 开源,三种存储模型统一 | 大规模私有云 |
| Cloudflare R2 | 零出口流量费 | 公开内容分发 |
存储类型分层
为了降本,对象存储分多种存储类型:
┌──────────────────────────────────────────────────┐
│ 标准存储(Standard) │
│ 毫秒级访问,最贵 │
│ 适用:热数据、网站静态资源 │
├──────────────────────────────────────────────────┤
│ 低频访问(IA, Infrequent Access) │
│ 按容量便宜,但每次访问收费 │
│ 适用:备份、日志归档(每月偶尔读取) │
├──────────────────────────────────────────────────┤
│ 归档存储(Archive / Glacier) │
│ 极便宜,恢复需要数分钟~数小时 │
│ 适用:合规归档、长期备份 │
├──────────────────────────────────────────────────┤
│ 深度归档(Deep Archive) │
│ 最便宜,恢复 12 小时以上 │
│ 适用:法律法规要求长期保留 │
└──────────────────────────────────────────────────┘
生命周期策略示例(S3):
{
"Rules": [{
"Filter": { "Prefix": "logs/" },
"Transitions": [
{ "Days": 30, "StorageClass": "STANDARD_IA" },
{ "Days": 90, "StorageClass": "GLACIER" }
],
"Expiration": { "Days": 365 }
}]
}30 天后转低频,90 天后转归档,365 天后删除。
与 CDN 协作
用户请求图片 https://cdn.example.com/avatar.png
│
▼
CDN 节点
├── 命中缓存 → 直接返回(毫秒级)
└── 未命中 → 回源到对象存储
│
▼
S3 / OSS Bucket
│
▼
返回 + 缓存到 CDN
回源优化:
- 设置合适的
Cache-Control,让 CDN 长时间缓存 - 文件名带 hash(如
app.a3f5c2.js),永久缓存,更新文件名即可失效 - 使用 OSS 的”私有 Bucket + 签名 URL”防盗链
K8s 中使用对象存储
应用直接调用 SDK
S3Client s3 = S3Client.builder()
.region(Region.AP_SOUTHEAST_1)
.credentialsProvider(DefaultCredentialsProvider.create())
.build();
s3.putObject(
PutObjectRequest.builder().bucket("mybucket").key("file.png").build(),
RequestBody.fromFile(Paths.get("file.png"))
);作为 PVC 挂载(s3fs / CSI 驱动)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: model-storage
spec:
storageClassName: s3-csi
accessModes: [ReadWriteMany]
resources:
requests:
storage: 100Gi适用于 AI 模型加载、共享数据集等场景。
备份目标
Velero(K8s 备份工具)
│
├── 备份 Pod / Volume / 配置到 S3
└── 跨集群恢复
常见使用场景
| 场景 | 说明 |
|---|---|
| 静态资源托管 | 图片、视频、JS/CSS,配合 CDN |
| 用户上传文件 | 头像、附件、视频上传 |
| 数据库备份 | MySQL binlog、PostgreSQL WAL 归档 |
| 大数据原始数据 | 数据湖(Iceberg / Delta Lake) |
| AI 模型存储 | LLM 权重文件(数十 GB) |
| 日志归档 | 冷日志从 ES 转存 S3 |
| 容器镜像 | Harbor / Distribution 后端存储 |
上传方式
| 方式 | 说明 | 适用 |
|---|---|---|
| PUT Object | 单次上传 | < 100MB |
| 分片上传(Multipart) | 大文件并行分片,断点续传 | > 100MB |
| 预签名 URL | 后端生成临时 URL,前端直传 | 用户上传,减少后端流量 |
| 流式上传 | 边读边上传 | 视频转码、大文件处理 |
预签名 URL(前端直传):
1. 前端请求后端:「我要上传 avatar.png」
2. 后端生成 S3 预签名 URL(15 分钟有效)
3. 前端直接 PUT 到 S3
4. 前端通知后端「上传完成」
5. 后端记录 DB(仅保存路径,不存文件)
优势: 后端不经手文件数据,节省带宽和 CPU。
性能优化
| 优化 | 说明 |
|---|---|
| 多 Region 加速 | 国内多地域复制(OSS 跨区域复制) |
| 传输加速 | S3 Transfer Acceleration,走 CloudFront 边缘 |
| 并发分片 | 大文件用多线程上传/下载 |
| 智能分层 | S3 Intelligent-Tiering 自动迁移冷热数据 |
| 边缘缓存 | CloudFront / 阿里云 CDN 前置 |
MinIO(自建首选)
完全开源、S3 兼容,可在 K8s 上部署:
┌────────────────────────────────────┐
│ MinIO Cluster │
│ │
│ Node1 Node2 Node3 Node4 │
│ Disk1 Disk1 Disk1 Disk1 │
│ │
│ 纠删码(Erasure Coding) │
│ 4+2 模式:损失 2 个节点仍可读 │
└────────────────────────────────────┘
特点:
- S3 协议 100% 兼容,应用无需改代码
- 纠删码代替副本,存储成本低
- 配合 K8s Operator 自动化运维
- 支持版本控制、生命周期、对象锁定(合规)
注意事项
- 路径不要带敏感信息:URL 一旦泄露就能访问,敏感文件必须用签名 URL
- Bucket 默认私有:公共读权限要谨慎开放
- 小文件性能:对象存储不适合海量小文件(< 4KB),考虑合并打包
- 删除不可逆:开启版本控制和 MFA Delete 防误删
- 跨区下载收费:S3 跨 Region 下载比同 Region 贵很多