Storage-Minio的原理和K8S部署

image

一、OSS简介

1.1、Object Storage Service

对象存储服务(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应用场景

  • 单主机单硬盘模式
    image
  • 单主机多硬盘模式
    image
  • 多主机多硬盘分布式
    image

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列矩阵。下部矩阵可以选择范德蒙德矩阵或柯西矩阵。

image

  • RS最多能容忍m个数据块被删除。 数据恢复的过程如下:
    • 1、假设D1、D4、C2丢失,从编码矩阵中删掉丢失的数据块/编码块对应的行。(图2、3)
    • 2、由于B' 是可逆的,记B'的逆矩阵为 (B'^-1),则B' * (B'^-1) = I 单位矩阵。两边左乘B' 逆矩阵。 (图4、5)
    • 3、得到如下原始数据D的计算公式 。
      image
    • 4、对D重新编码,可得到丢失的编码

  • 存储形式
    image

  • 上图直观地展示了每个节点上的数据存放形式。所有对象的编码块和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部署

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

四、SDK

posted @ 2021-05-07 17:25  SRE运维充电站  阅读(3862)  评论(0编辑  收藏  举报