# MinIO 核心筆記
## 1. MinIO 是什麼?
> **MinIO 是可自行部署、相容 S3 API 的 Object Storage。**
適合儲存:
```text
PDF、圖片、影片、附件、報表、備份檔
```
基本架構:
```text
Spring Boot
│
│ S3 API / HTTP
▼
MinIO
│
▼
Storage
```
## 2. 資料結構
MinIO 不使用傳統檔案路徑概念,而是:
```text
Bucket
└── Object Key
例如:
Bucket = reports
Key = 2026/report.pdf
```
看起來像:
```text
reports/2026/report.pdf
```
但 `2026/` 不是真正的 filesystem directory。
## 3. PVC、NFS、MinIO 差異
| 技術 | 本質 | Application 如何使用 |
|---|---|---|
| PVC | K8s 儲存抽象 | mount |
| NFS | 共享 Filesystem | 檔案 I/O |
| MinIO | Object Storage | S3 API |
它們不是完全互斥:
```text
Spring Boot
│
│ S3 API
▼
MinIO
│
▼
PVC
│
▼
實際 Storage
```
## 4. MinIO 的並行特性
這是最重要的觀念:
```text
共讀同一 Object ✅ 適合
共寫不同 Object ✅ 適合
共改同一 Object ❌ 不適合
```
例如:
```text
Pod A ──PUT──► a.pdf
Pod B ──PUT──► b.pdf
Pod C ──PUT──► c.pdf
```
非常適合。
但:
```text
Pod A ─┐
Pod B ─┼──► 同時修改 report.pdf
Pod C ─┘
不適合
```
MinIO 偏向 **Object 整體 PUT / GET**,而不是 POSIX filesystem 的 `seek / append / partial write`。
## 5. MinIO vs Oracle
很實用的分工:
```text
Oracle
└── Business Data / Metadata
├── FILE_ID
├── FILE_NAME
└── OBJECT_KEY
│
▼
MinIO
└── 真正的 PDF / Image / ZIP
```
簡單記:
> **會頻繁修改的結構化資料 → Oracle**
>
> **完成後的 Binary Object → MinIO**
## 6. MinIO 為什麼值得用?
Local Disk:
```text
Spring Boot → Local Disk
```
速度快,但多 Pod 很麻煩。
MinIO:
```text
Pod A ─┐
Pod B ─┼──► MinIO
Pod C ─┘
```
犧牲一些 Network I/O latency,換來:
```text
跨 Pod 共用
集中管理
Application Stateless
S3 API
權限控制
水平擴展
```
所以:
> **MinIO 不是為了比 Local Disk 快,而是為了解決分散式儲存。**
## 7. K3s 上的 MinIO
你的 Lab 可以:
```text
K3s
│
├── Spring Boot
│ │
│ │ S3 API
│ ▼
├── MinIO
│ │
│ ▼
└──── PVC
│
▼
VM Disk
```
安全上:
```text
MinIO Service = ClusterIP
9000 → S3 API
9001 → Console
不要開 NodePort / 公開 Ingress
Console 用 port-forward
```
因此外部:
```text
Internet ──X──► MinIO
```
Cluster 內:
```text
Spring Boot ──► MinIO ✅
```
## 8. 最終心智模型
只要記這張:
```text
資料要放哪?
│
├─ Business Data
│ └─ Oracle
│
├─ Cache
│ └─ Redis
│
├─ 需要真正 Filesystem
│ └─ PVC / NFS
│
└─ PDF / 圖片 / 附件 / 備份
└─ MinIO
```
### 一句話總結
> **MinIO = 自己架的 S3。**
>
> 適合「**共讀同 Object、共寫不同 Object**」,不適合「**多人共改同一 Object**」;在 K8s 中讓 Application 不必依賴某一台機器的本地檔案系統。
---
```text
K3s
├── Namespace: minio
├── Secret ← 管理帳密
├── PVC 10Gi ← 保存 Object
├── Deployment ← MinIO 單 Pod
└── ClusterIP ← 只允許 Cluster 內存取
```
MinIO 官方目前仍提供 S3 相容 API 與 Java SDK 相關介面文件;你的學習環境不需要先碰 Operator 或分散式部署。
## 1. 建立 `minio.yaml`
```yaml
# 建立 MinIO 專用 Namespace。
apiVersion: v1
# 資源類型為 Namespace。
kind: Namespace
# 定義 Namespace metadata。
metadata:
# Namespace 名稱。
name: minio
# 開始下一個 Kubernetes Resource。
---
# 使用 Kubernetes Core API。
apiVersion: v1
# 建立 Secret 保存 MinIO 管理帳密。
kind: Secret
# 定義 Secret metadata。
metadata:
# Secret 名稱。
name: minio-secret
# Secret 建立於 minio Namespace。
namespace: minio
# 使用一般字串輸入,Kubernetes 會轉成 Secret Data。
stringData:
# MinIO 管理者帳號,請自行修改。
MINIO_ROOT_USER: minioadmin
# MinIO 管理者密碼,請自行改成強密碼。
MINIO_ROOT_PASSWORD: CHANGE_ME_TO_A_STRONG_PASSWORD
# 開始下一個 Kubernetes Resource。
---
# 使用 Kubernetes Core API。
apiVersion: v1
# 建立 PersistentVolumeClaim。
kind: PersistentVolumeClaim
# 定義 PVC metadata。
metadata:
# PVC 名稱。
name: minio-data
# PVC 建立於 minio Namespace。
namespace: minio
# 定義儲存需求。
spec:
# 單一 Node 可讀寫此 Volume。
accessModes:
# 使用 ReadWriteOnce。
- ReadWriteOnce
# 定義容量需求。
resources:
# 宣告需要的 Storage。
requests:
# Lab 環境先配置 10Gi。
storage: 10Gi
# 開始下一個 Kubernetes Resource。
---
# 使用 Deployment API。
apiVersion: apps/v1
# 建立 Deployment。
kind: Deployment
# 定義 Deployment metadata。
metadata:
# Deployment 名稱。
name: minio
# Deployment 建立於 minio Namespace。
namespace: minio
# 定義 Deployment 行為。
spec:
# Lab 只建立一個 MinIO Pod。
replicas: 1
# 定義 Deployment 如何找到自己的 Pod。
selector:
# 使用 Label 選擇 Pod。
matchLabels:
# Pod Label。
app: minio
# 定義 Pod Template。
template:
# 定義 Pod metadata。
metadata:
# 設定 Pod Label。
labels:
# Label 名稱。
app: minio
# 定義 Pod。
spec:
# 定義 Container。
containers:
# 建立 MinIO Container。
- name: minio
# 使用 MinIO 官方 Container Image。
image: quay.io/minio/minio:latest
# 定義啟動參數。
args:
# 啟動 MinIO Server。
- server
# Object 資料保存位置。
- /data
# 指定 Console Address。
- --console-address
# Console 使用 9001 Port。
- ":9001"
# 從 Kubernetes Secret 注入環境變數。
envFrom:
# 使用 Secret。
- secretRef:
# Secret 名稱。
name: minio-secret
# 宣告 Container Port。
ports:
# S3 API Port。
- containerPort: 9000
# Port 名稱。
name: api
# MinIO Console Port。
- containerPort: 9001
# Port 名稱。
name: console
# 掛載 Persistent Volume。
volumeMounts:
# 使用 minio-data Volume。
- name: minio-data
# 掛載至 MinIO 的資料目錄。
mountPath: /data
# 定義 Pod 使用的 Volume。
volumes:
# Volume 名稱。
- name: minio-data
# Volume 來源為 PVC。
persistentVolumeClaim:
# 指向前面建立的 PVC。
claimName: minio-data
# 開始下一個 Kubernetes Resource。
---
# 使用 Kubernetes Core API。
apiVersion: v1
# 建立 Service。
kind: Service
# 定義 Service metadata。
metadata:
# Service 名稱。
name: minio
# Service 建立於 minio Namespace。
namespace: minio
# 定義 Service。
spec:
# 僅 Cluster 內部可以存取。
type: ClusterIP
# 找到具有 app=minio Label 的 Pod。
selector:
# Pod Label。
app: minio
# 定義 Service Ports。
ports:
# S3 API。
- name: api
# Cluster 內使用 9000。
port: 9000
# 導向 Container 9000。
targetPort: 9000
# MinIO Console。
- name: console
# Cluster 內使用 9001。
port: 9001
# 導向 Container 9001。
targetPort: 9001
```
Lab 可以先用 `latest`;正式環境則應固定版本 Tag,避免 Image 更新後產生不可預期變更。
## 2. 安裝
先確認 K3s Storage:
```bash
# 查看目前 Kubernetes StorageClass。
kubectl get storageclass
```
正常 K3s 通常會看到類似:
```text
NAME PROVISIONER
local-path (default) rancher.io/local-path
```
接著安裝:
```bash
# 建立 Namespace、Secret、PVC、Deployment 與 Service。
kubectl apply -f minio.yaml
```
如果你目前 K3s 的 `kubectl` 仍需要 root 權限,上面的命令就在前面加 `sudo` 即可。
## 3. 確認是否啟動成功
```bash
# 查看 MinIO Pod。
kubectl get pod -n minio
# 查看 MinIO PVC。
kubectl get pvc -n minio
# 查看 MinIO Service。
kubectl get svc -n minio
```
理想狀況:
```text
Pod
minio-xxxxxxxxxx-xxxxx 1/1 Running
PVC
minio-data Bound
Service
minio ClusterIP
```
這裡最重要的是:
```text
Pod = Running
PVC = Bound
```
## 4. 登入 MinIO Console
我們**不開 NodePort**。
所以你的 Mac 外部不能:
```text
Ubuntu-IP:9001 ❌
```
需要管理時才做 port-forward:
```bash
# 將 Ubuntu 本機的 9001 暫時轉到 MinIO Console。
kubectl port-forward -n minio service/minio 9001:9001
```
如果你是在 **Ubuntu VM 的 Terminal** 執行,那 `localhost:9001` 指的是 Ubuntu VM,不是你的 Mac。
因為你的架構是:
```text
Mac
│
▼
Ubuntu VM
│
▼
K3s
│
▼
MinIO
```
最簡單可以先在 Ubuntu 裡測:
```bash
# 確認 MinIO Console 有回應。
curl -I http://localhost:9001
```
如果你希望 **Mac 瀏覽器直接開 Console**,後面我們再把 UTM → Ubuntu → K3s 這段連線處理好即可。
## 5. MinIO 在 Cluster 內的網址
安裝成功後,同 Namespace:
```text
http://minio:9000
```
其他 Namespace 比較完整:
```text
http://minio.minio.svc.cluster.local:9000
```
所以未來 Spring Boot:
```text
Spring Boot Pod
│
│ http://minio.minio:9000
▼
MinIO Service
│
▼
MinIO Pod
│
▼
PVC 10Gi
│
▼
K3s local-path
```
外部的人則沒有:
```text
Internet
│
X
│
MinIO :9000/:9001
```
因為我們只有 `ClusterIP`,沒有 `NodePort` / 公開 Ingress。
## 6. 第一階段你只做這四步
```text
① kubectl get storageclass
② kubectl apply -f minio.yaml
③ kubectl get pod,pvc,svc -n minio
④ kubectl port-forward -n minio service/minio 9001:9001
```
**先不要急著接 Spring Boot。**
這階段的目標只有:
> MinIO Pod 成功 `Running`、PVC 成功 `Bound`、Console 可以登入。