
一、OSS簡介
1.1、Object Storage Service
- 何為對象存儲?我們來看下阿里雲 OSS (Object Storage Service)的介紹:https://link.zhihu.com/?target=https%3A//helpcdn.aliyun.com/product/31815.html
對象存儲服務(Object Storage Service,OSS)是一種海量、安全、低成本、高可靠的雲存儲服務,適合存放任意類型的文件。容量和處理能力彈性擴展,多種存儲類型供選擇,全面優化存儲成本。
- 對於中小型企業,如果不選擇存儲上雲,那么 Minio 是個不錯的選擇,麻雀雖小,五臟俱全。當然 Minio 除了直接作為對象存儲使用,還可以作為雲上對象存儲服務的網關層,無縫對接到 Amazon S3、MicroSoft Azure。
1.2、OSS相關概念
- 存儲類型(Storage Class)
- OSS提供標准、低頻訪問、歸檔、冷歸檔四種存儲類型,全面覆蓋從熱到冷的各種數據存儲場景。其中標准存儲類型提供高持久、高可用、高性能的對象存儲服務,能夠支持頻繁的數據訪問;低頻訪問存儲類型適合長期保存不經常訪問的數據(平均每月訪問頻率1到2次),存儲單價低於標准類型;歸檔存儲類型適合需要長期保存(建議半年以上)的歸檔數據;冷歸檔存儲適合需要超長時間存放的極冷數據。更多信息,請參見存儲類型介紹。
- 存儲空間(Bucket)
- 存儲空間是您用於存儲對象(Object)的容器,所有的對象都必須隸屬於某個存儲空間。存儲空間具有各種配置屬性,包括地域、訪問權限、存儲類型等。您可以根據實際需求,創建不同類型的存儲空間來存儲不同的數據。
- 對象(Object)
- 對象是OSS存儲數據的基本單元,也被稱為OSS的文件。對象由元信息(Object Meta)、用戶數據(Data)和文件名(Key)組成。對象由存儲空間內部唯一的Key來標識。對象元信息是一組鍵值對,表示了對象的一些屬性,例如最后修改時間、大小等信息,同時您也可以在元信息中存儲一些自定義的信息。
- 地域(Region)
- 地域表示OSS的數據中心所在物理位置。您可以根據費用、請求來源等選擇合適的地域創建Bucket。更多信息,請參見OSS已開通的地域。
- 訪問域名(Endpoint)
- Endpoint表示OSS對外服務的訪問域名。OSS以HTTP RESTful API的形式對外提供服務,當訪問不同地域的時候,需要不同的域名。通過內網和外網訪問同一個地域所需要的域名也是不同的。更多信息,請參見各個Region對應的Endpoint。
- 訪問密鑰(AccessKey)
- AccessKey簡稱AK,指的是訪問身份驗證中用到的AccessKey ID和AccessKey Secret。OSS通過使用AccessKey ID和AccessKey Secret對稱加密的方法來驗證某個請求的發送者身份。AccessKey ID用於標識用戶;AccessKey Secret是用戶用於加密簽名字符串和OSS用來驗證簽名字符串的密鑰,必須保密。關於獲取AccessKey的方法,請參見創建AccessKey。
二、Minio簡介
2.1、Minio
- Minio 是一個基於Apache License v2.0開源協議的對象存儲服務。它兼容亞馬遜S3雲存儲服務接口,非常適合於存儲大容量非結構化的數據,例如圖片、視頻、日志文件、備份數據和容器/虛擬機鏡像等,而一個對象文件可以是任意大小,從幾kb到最大5T不等。
- Minio是一個非常輕量的服務,可以很簡單的和其他應用的結合;
- Minio 是個基於 Golang 編寫的開源對象存儲套件,雖然輕量,卻擁有着不錯的性能。
- 官網地址:MinIO | High Performance, Kubernetes Native Object Storage
2.2、Minio應用場景
- 單主機單硬盤模式

- 單主機多硬盤模式

- 多主機多硬盤分布式

2.3、Minio特點
- 高性能:作為高性能對象存儲,在標准硬件條件下它能達到55GB/s的讀、35GG/s的寫速率
- 可擴容:不同MinIO集群可以組成聯邦,並形成一個全局的命名空間,並跨越多個數據中心
- 雲原生:容器化、基於K8S的編排、多租戶支持
- Amazon S3兼容:Minio使用Amazon S3 v2 / v4 API。可以使用Minio SDK,Minio Client,AWS SDK和AWS CLI訪問Minio服務器。
- 可對接后端存儲: 除了Minio自己的文件系統,還支持DAS、 JBODs、NAS、Google雲存儲和Azure Blob存儲。
- SDK支持: 基於Minio輕量的特點,它得到類似Java、Python或Go等語言的sdk支持
- Lambda計算: Minio服務器通過其兼容AWS SNS / SQS的事件通知服務觸發Lambda功能。支持的目標是消息隊列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等數據庫。
- 有操作頁面
- 功能簡單: 這一設計原則讓MinIO不容易出錯、更快啟動
- 支持糾刪碼:MinIO使用糾刪碼、Checksum來防止硬件錯誤和靜默數據污染。在最高冗余度配置下,即使丟失1/2的磁盤也能恢復數據
2.4、存儲機制(數據編碼)
- Minio使用糾刪碼erasure code和校驗和checksum。 即便丟失一半數量(N/2)的硬盤,仍然可以恢復數據。
- 校驗和
- 保護數據免受硬件故障和無聲數據損壞
- 糾刪碼
- 糾刪碼是一種恢復丟失和損壞數據的數學算法,目前,糾刪碼技術在分布式存儲系統中的應用主要有三類,陣列糾刪碼(Array Code: RAID5、RAID6等)、RS(Reed-Solomon)里德-所羅門類糾刪碼和LDPC(LowDensity Parity Check Code)低密度奇偶校驗糾刪碼。Erasure Code是一種編碼技術,它可以將n份原始數據,增加m份數據,並能通過n+m份中的任意n份數據,還原為原始數據。即如果有任意小於等於m份的數據失效,仍然能通過剩下的數據還原出來。
- Reed-Solomon算法
- Minio采用Reed-Solomon code將對象拆分成N/2數據和N/2 奇偶校驗塊。 這就意味着如果是12塊盤,一個對象會被分成6個數據塊、6個奇偶校驗塊,可以丟失任意6塊盤(不管其是存放的數據塊還是奇偶校驗塊),仍可以從剩下的盤中的數據進行恢復。
- RS code編碼數據恢復原理
- RS編碼以word為編碼和解碼單位,大的數據塊拆分到字長為w(取值一般為8或者16位)的word,然后對word進行編解碼。 數據塊的編碼原理與word編碼原理相同,后文中以word為例說明,變量Di, Ci將代表一個word。
- 把輸入數據視為向量D=(D1,D2,..., Dn), 編碼后數據視為向量(D1, D2,..., Dn, C1, C2,.., Cm),RS編碼可視為如下(圖1)所示矩陣運算。
- 圖1最左邊是編碼矩陣(或稱為生成矩陣、分布矩陣,Distribution Matrix),編碼矩陣需要滿足任意n*n子矩陣可逆。為方便數據存儲,編碼矩陣上部是單位陣(n行n列),下部是m行n列矩陣。下部矩陣可以選擇范德蒙德矩陣或柯西矩陣。

- RS最多能容忍m個數據塊被刪除。 數據恢復的過程如下:
- 1、假設D1、D4、C2丟失,從編碼矩陣中刪掉丟失的數據塊/編碼塊對應的行。(圖2、3)
- 2、由於B' 是可逆的,記B'的逆矩陣為 (B'^-1),則B' * (B'^-1) = I 單位矩陣。兩邊左乘B' 逆矩陣。 (圖4、5)
- 3、得到如下原始數據D的計算公式 。

- 4、對D重新編碼,可得到丟失的編碼
-
存儲形式

-
上圖直觀地展示了每個節點上的數據存放形式。所有對象的編碼塊和meta信息,最終是以目錄和文件的形式,存儲在文件系統上的。
-
比如My Bucket就是在所有節點的頂級目錄創建了對應的目錄叫My Bucket。然后當我們上傳一個對象的時候,就會在這個對象所對應的Set上面創建一個目錄叫My Object,之后把所有編碼塊的數據跟meta信息都保存在此目錄下面,這就是MinIO的真實存儲數據的方式。
-
meta數據是json文件,編碼塊是part.1文件。黑色的右圖是meta信息示例圖,里面除了包含正常的meta信息外,還包括了怎樣做ec編碼,以便之后可以解碼出來。
2.5、分布式
分布式好處
- 分布式Minio可以讓你將多塊硬盤(甚至在不同的機器上)組成一個對象存儲服務。由於硬盤分布在不同的節點上,分布式Minio避免了單點故障
數據保護
- 分布式Minio采用 糾刪碼來防范多個節點宕機和位衰減bit rot。
- 分布式Minio至少需要4個硬盤,使用分布式Minio自動引入了糾刪碼功能。
高可用
- 單機Minio服務存在單點故障,相反,如果是一個有N塊硬盤的分布式Minio,只要有N/2硬盤在線,你的數據就是安全的。不過你需要至少有N/2+1個硬盤來創建新的對象。
- 例如,一個16節點的Minio集群,每個節點16塊硬盤,就算8台服務器宕機,這個集群仍然是可讀的,不過你需要9台服務器才能寫數據。
- 注意,只要遵守分布式Minio的限制,你可以組合不同的節點和每個節點幾塊硬盤。比如,你可以使用2個節點,每個節點4塊硬盤,也可以使用4個節點,每個節點兩塊硬盤,諸如此類。
一致性
- Minio在分布式和單機模式下,所有讀寫操作都嚴格遵守read-after-write一致性模型。
糾刪碼
- Minio使用糾刪碼erasure code和校驗和checksum來保護數據免受硬件故障和無聲數據損壞。 即便您丟失一半數量(N/2)的硬盤,您仍然可以恢復數據。
什么是糾刪碼erasure code?
- 糾刪碼是一種恢復丟失和損壞數據的數學算法, Minio采用Reed-Solomon code將對象拆分成N/2數據和N/2 奇偶校驗塊。 這就意味着如果是12塊盤,一個對象會被分成6個數據塊、6個奇偶校驗塊,你可以丟失任意6塊盤(不管其是存放的數據塊還是奇偶校驗塊),你仍可以從剩下的盤中的數據進行恢復,是不是很NB,感興趣的同學請自行google。
為什么糾刪碼有用?
- 糾刪碼的工作原理和RAID或者復制不同,像RAID6可以在損失兩塊盤的情況下不丟數據,而Minio糾刪碼可以在丟失一半的盤的情況下,仍可以保證數據安全。 而且Minio糾刪碼是作用在對象級別,可以一次恢復一個對象,而RAID是作用在卷級別,數據恢復時間很長。 Minio對每個對象單獨編碼,存儲服務一經部署,通常情況下是不需要更換硬盤或者修復。Minio糾刪碼的設計目標是為了性能和盡可能的使用硬件加速。
什么是位衰減bit rot保護?
- 位衰減又被稱為數據腐化Data Rot、無聲數據損壞Silent Data Corruption,是目前硬盤數據的一種嚴重數據丟失問題。硬盤上的數據可能會神不知鬼不覺就損壞了,也沒有什么錯誤日志。正所謂明槍易躲,暗箭難防,這種背地里犯的錯比硬盤直接咔咔宕了還危險。 不過不用怕,Minio糾刪碼采用了高速 HighwayHash 基於哈希的校驗和來防范位衰減。
三、Minio部署
3.1、docker部署
docker pull minio/minio
docker run -p 9000:9000 minio/minio server /data
3.2、helm部署minio
3.2.1、創建持久化存儲
1、給node打標簽
# kubectl label node aliyun_beijing_node01 minio_role=standalone
2、創建storage、PV
# pv 、torageclass是集群資源,不區分名稱空間,這里使用了節點親和性
# cat storage-minio.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage-minio
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv-minio
spec:
capacity:
storage: 500Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: local-storage-minio
local:
path: /storage/data/minio
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: minio_role
operator: In
values:
- standalone
- distributed
3.2.2、helm部署
- 更多配置請閱讀官網配置示例 :https://artifacthub.io/packages/helm/minio/minio
helm upgrade --install minio \
--set persistence.storageClass=local-storage-minio,mode=standalone,accessKey=ACCESSKEY,secretKey=SECRETKEY \
./minio --namespace test-ns
# 更多配置示例
helm install \
--set persistence.enabled=true \
--set service.externalIPs[0]=192.168.1.7 \
--set accessKey=xxxxxxx \
--set secretKey=yyyyyyy \
--set persistence.size=1Gi \
--set resources.requests.memory=1Gi \
--set persistence.storageClass=managed-nfs-storage \
--set mode=distributed,replicas=4 \
minio/minio --generate-name
# 設置persistence.enabled=false 表示不使用持久卷存儲數據
--set persistence.existingClaim=minio-pvc --set persistence.enabled=false
# 分布式創建mode=distributed表示分布式創建, 節點數為4個
# externalIPs外部訪問IP
--set service.externalIPs[0]=192.168.1.7
3.3.3、配置Ingress外部訪問
- http
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: minio
annotations:
kubernetes.io/ingress.class: "nginx-alpha"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/proxy-body-size: 2048m
namespace: test-ns
spec:
rules:
- host: "minio.toptops.top"
http:
paths:
- backend:
serviceName: minio
servicePort: 9000
path: /
- 如果使用cert-manager自動生成的證書,https域名訪問,需要調整values.yaml
[root@master minio]# cat <<EOF> values.yaml
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
path: /
hosts:
- minio.xxxxxx.xxx
tls:
- secretName: minio-tls
hosts:
- minio.xxxxxx.xxx
accessKey: "xxxxxx"
secretKey: "yyyyyy"
resources:
requests:
memory: 1Gi
persistence:
storageClass: minio-data
size: 3Gi
EOF
