
架構概覽
graph TD Storage[儲存類型] --> Block[Block Storage<br/>磁碟區塊] Storage --> File[File Storage<br/>檔案系統] Storage --> Object[Object Storage<br/>物件儲存] Block -->|用途| BlockUse[VM 磁碟<br/>資料庫 Data Volume] File -->|用途| FileUse[NFS 共享<br/>容器 Volume Mount] Object -->|用途| ObjectUse[使用者上傳<br/>備份歸檔 / CI Artifact] Object --> Hot[Hot Bucket<br/>SSD / 頻繁存取] Object --> Warm[Warm Bucket<br/>HDD / 偶爾存取] Object --> Cold[Cold Bucket<br/>壓縮歸檔 / 長期保留]
Storage Management:檔案放哪裡、放多久、怎麼備份
當應用服務開始產生大量檔案(使用者上傳、報表輸出、日誌歸檔、備份快照),就需要一個獨立於應用伺服器的儲存層。直接放在 Docker volume 或 Host 檔案系統上,會遇到容量不可控、備份困難、跨服務存取複雜等問題。MinIO 是 S3 相容的開源物件儲存,可以自架在現有的 Host 上,用標準的 S3 API 操作,日後遷移到 AWS S3 也只需要改 endpoint。
架構概覽
flowchart TD App[Application Services] -->|S3 API| MinIO[MinIO Server\n:9000 API / :9001 Console] CI[CI Pipeline] -->|upload artifacts| MinIO Backup[Backup Scripts] -->|mc mirror| MinIO MinIO --> Hot[Hot Bucket\n頻繁存取 / SSD] MinIO --> Warm[Warm Bucket\n偶爾存取 / HDD] MinIO --> Cold[Cold Bucket\n歸檔 / 壓縮後備份] MinIO -->|lifecycle rule| AutoDelete[自動刪除過期物件] MinIO -->|mc mirror| Remote[異地備份\nNAS / 雲端 S3] Admin[Admin] -->|管理| Console[MinIO Console UI]
應用服務透過 S3 API 存取 MinIO,MinIO 內部用 Bucket 分類(Hot/Warm/Cold),lifecycle rule 自動管理物件生命週期。備份透過 mc mirror 同步到異地。
核心概念
-
物件儲存 vs 檔案系統:傳統檔案系統用目錄結構管理檔案,適合小量檔案和頻繁的隨機讀寫。物件儲存把每個檔案當作一個「物件」,用 key(路徑)+ metadata 來管理,適合大量檔案的寫入和讀取。物件儲存沒有目錄的概念(
/只是 key 的一部分),所以不會有目錄鎖定、inode 耗盡等問題。當檔案數量超過數十萬,物件儲存的效能和可管理性遠優於傳統檔案系統。 -
Bucket 分層策略:不是所有資料都需要同等級的存取速度。將 Bucket 按存取頻率分層:Hot(最近 30 天的上傳檔案、活躍的 API 附件)放在 SSD;Warm(30-90 天前的報表、歷史訂單附件)放在 HDD;Cold(超過 90 天的歸檔、法規要求保留的資料)壓縮後備份到 NAS 或雲端。這樣做可以在有限的 SSD 空間下,兼顧效能和成本。
-
Lifecycle Rule(生命週期規則):MinIO 支援 S3 相容的 lifecycle policy,可以設定規則自動處理物件。例如「uploads/ 下的物件超過 90 天自動刪除」、「temp/ 下的物件超過 7 天自動刪除」。這比手動寫 cron job 清理更可靠,而且規則是 Bucket 層級的,不會漏掉任何物件。
-
存取控制:MinIO 支援 IAM-style 的存取控制。每個應用服務用獨立的 Access Key / Secret Key,透過 Policy 限制只能存取特定 Bucket。例如 API 服務只能讀寫
uploadsBucket,備份腳本可以讀取所有 Bucket 但不能刪除。這比所有服務共用一組 root credential 安全得多。
使用情境
-
使用者上傳檔案:電商平台的商品圖片、使用者大頭貼、訂單附件。應用服務收到上傳後,直接透過 S3 API 存到 MinIO 的
uploadsBucket,回傳一個 presigned URL 給前端顯示。圖片不再佔用應用伺服器的磁碟空間。 -
CD Artifact 儲存:CI pipeline 的 build artifact(打包好的前端檔案、測試報告)推到 MinIO。部署時從 MinIO 拉取,而不是從 CI runner 的暫存目錄。這樣即使 CI runner 被重建,artifact 也不會消失。
-
資料庫備份歸檔:每天的 PostgreSQL backup dump 上傳到 MinIO 的
db-backupsBucket。設定 lifecycle rule:保留最近 30 天的每日備份、每月 1 號的備份保留 1 年。超過保留期的自動刪除,不用手動清理。
實作範例 / 設定範例
MinIO 部署(docker-compose)
# docker-compose.yml
version: "3.8"
services:
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
restart: unless-stopped
ports:
- "9000:9000" # S3 API
- "9001:9001" # Web Console
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: ChangeMeToStrongPassword
volumes:
- minio-data:/data
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 30s
timeout: 5s
retries: 3
volumes:
minio-data:
driver: localmc(MinIO Client)基本操作
# 設定 alias
mc alias set myminio http://minio.example.com:9000 minioadmin ChangeMeToStrongPassword
# 建立 Bucket
mc mb myminio/uploads
mc mb myminio/db-backups
mc mb myminio/temp
# 設定 lifecycle rule:temp bucket 7 天後自動刪除
mc ilm rule add myminio/temp --expire-days 7
# 設定 lifecycle rule:db-backups 保留 90 天
mc ilm rule add myminio/db-backups --expire-days 90
# 上傳 / 下載
mc cp ./report.pdf myminio/uploads/2024/09/report.pdf
mc cp myminio/uploads/2024/09/report.pdf ./downloaded-report.pdf
# 列出 Bucket 內容
mc ls myminio/uploads/2024/09/
# 查看 Bucket 使用量
mc du myminio/uploads建立應用專用 Access Key
# 建立 policy:只允許讀寫 uploads bucket
cat > uploads-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::uploads",
"arn:aws:s3:::uploads/*"
]
}
]
}
EOF
# 建立使用者並套用 policy
mc admin user add myminio app-api-user AppApiSecretKey123
mc admin policy create myminio uploads-readwrite uploads-policy.json
mc admin policy attach myminio uploads-readwrite --user app-api-user異地備份(mc mirror)
# 設定遠端 alias(NAS 上的另一台 MinIO,或 AWS S3)
mc alias set nas-backup http://nas.internal:9000 backupuser BackupSecret
# 同步整個 db-backups bucket 到 NAS
mc mirror myminio/db-backups nas-backup/db-backups
# 加入 crontab 每天凌晨 4 點同步
# 0 4 * * * mc mirror --overwrite myminio/db-backups nas-backup/db-backups常見問題與風險
-
磁碟空間耗盡:MinIO 本身不會限制 Bucket 容量,如果沒設 lifecycle rule,資料量會無限增長。MinIO 的 data volume 滿了,所有 PUT 操作會失敗,連帶影響應用服務的檔案上傳功能。避免方式:設定 lifecycle rule 自動清理、監控磁碟使用率在 80% 時告警、定期用
mc du檢查各 Bucket 使用量。 -
Credential 外洩:MinIO 的 root credential 或應用的 Access Key 如果寫在程式碼裡被推到 Git,等於任何人都能存取所有資料。避免方式:Credential 透過環境變數注入,不寫在程式碼或 docker-compose.yml 裡。應用服務用最小權限的 Access Key,不要直接用 root credential。
-
單節點故障:單台 MinIO 掛了,所有依賴它的服務都無法存取檔案。和 Harbor 類似,已經下載到本地的檔案不受影響,但新的上傳和下載會失敗。避免方式:用
mc mirror定期備份到異地。對可用性要求高的場景,考慮 MinIO 的 Distributed Mode(多節點 erasure coding)。 -
效能瓶頸:MinIO 單節點的效能受限於磁碟 I/O。如果大量服務同時讀寫,可能出現延遲。避免方式:Hot data 放 SSD、Cold data 放 HDD。大檔案上傳使用 multipart upload。在應用層加上 CDN 或快取,減少直接存取 MinIO 的次數。
優點
- S3 相容 API,應用程式碼日後遷移到 AWS/GCP 只需改 endpoint
- Lifecycle rule 自動管理資料生命週期,減少手動維護
- Web Console 提供視覺化管理,降低操作門檻
缺點 / 限制
- 單節點模式沒有資料冗餘,磁碟壞了資料就沒了
- Distributed Mode 至少需要 4 個節點,小團隊可能資源不足
- MinIO 的 IAM 功能不如 AWS IAM 完整,複雜的權限需求可能需要額外設計