MinIO 核心筆記

Posted by Adam on August 24, 2022
# 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 可以登入。