跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

集成

以下页面提供 MinIO 与部分第三方软件的集成指南。 本页中的指南此前托管在旧版文档的 Cookbook 栏目下。

所有提供的指南均假定读者已熟悉相关第三方软件,这些指南不能替代对应软件的官方文档。

1 - 将 Silo 与 Veeam 搭配使用

在使用 Veeam Backup and Replication 时,可以将 Silo 这类 S3 兼容对象存储用作备份容量层。这会将 Veeam 基础设施中的存储解耦,并让你继续掌控自己的数据。Silo 简洁的部署与管理方式,便于 Veeam 备份管理员自行部署容量分层所需的对象存储。

前置条件

  • 安装以下一个或两个产品:支持 S3 兼容对象存储的 Veeam Backup and Replication(例如 9.5.4),以及 Veeam Backup for Office365(VBO)
  • 按照部署流程完成 Silo 对象存储部署
  • Veeam 要求到对象存储的连接使用 TLS。请按照网络加密指南配置 TLS。
  • 必须在 Veeam 之外、且在接入前先创建好 S3 存储桶、Access Key 和 Secret Key。
  • 按照 mc 命令参考为 Veeam 对接的 Silo endpoint 配置 Silo 客户端。

为 Veeam Backup and Replication 设置 S3 兼容对象存储

为 Veeam 备份创建 bucket

为 Veeam Backup 创建 bucket,例如:

mc mb myminio/veeambackup

NOTE: 对于启用 Immutability 的 Veeam Backup,请在创建 bucket 时启用 object lock,例如:

mc mb -l myminio/veeambackup

Object Lock 依赖 Silo Server 启用纠删码。更多信息见纠删码文档

将 Silo 添加为 Veeam 的对象存储

按照 Veeam 文档中的添加对象存储流程,将 Silo 作为 S3 兼容对象存储接入。

对于启用 Immutability 的 Veeam Backup,选择希望备份保持不可变的天数

Choose Immutability Days for Object Store

创建 Scale-out Backup Repository

  • 在 Backup Infrastructure 视图下,点击 Scale-out Repositories,然后在功能区点击 Add Scale-out Repository 按钮。
  • 按照屏幕向导完成配置
  • 在 Capacity Tier 页面,勾选 Extend scale-out backup repository capacity with object storage 复选框并选择对象存储。如果你希望作业运行后可立即测试备份数据,请在对象存储选择下勾选 “Copy” 并取消勾选 “Move”。

创建备份作业

使用 Veeam Backup and Replication 备份虚拟机

  • 在导航窗格的 Home > Jobs > Backup 下,点击功能区中的 Backup Job 按钮并选择 Virtual Machine。然后按屏幕向导继续。
  • 在 Storage 页面,选择前面已配置的 Scale-out Backup Repository。
  • 继续创建备份作业。在 Summary 页面,勾选 Run the Job when I click Finish 复选框并点击 Finish 按钮。备份作业会立即启动。这会为该作业中的 VM 创建一次 Active Full 备份。
  • 由于我们在创建 SOBR 时选择了 Copy 模式,备份在性能层创建后会立即复制到容量层。
  • 对于启用 Immutability 的 Veeam Backup,你可以选择按还原点数量或按天数将备份设为不可变。
Choose Immutability Options for Backups

使用 VBO 备份 Office 365

  • 为 VBO 备份创建一个新 bucket
mc mb -l myminio/vbo
  • 在 Backup Infrastructure 下,右键 Object Storage Repositories 并选择 “Add object storage”
Adding Object Storage to VBO Step 1
  • 按照上文 Veeam Backup and Replication 的向导继续执行,这两个产品的步骤相同
  • 在 Backup Infrastructure -> Backup Repositories 下,右键并选择 “Add Backup Repository”
  • 按向导操作。在 “Object Storage Backup Repository” 部分,选择你上面创建的 Silo 对象存储
Adding Object Storage to VBO Backup Repository
  • 创建备份作业时,选择你上面创建的备份仓库。

测试设置

下次备份作业运行时,你可以使用 mc admin trace myminio 命令,确认流量正在进入 Silo 节点。对于 Veeam Backup and Replication,需要先等待备份在性能层完成,然后数据才会迁移到 Silo 容量层。

20:09:10.216 [200 OK] s3.GetObject veeam-minio01:9000/vbo/Veeam/Backup365/vbotest/Organizations/6571606ecbc4455dbfe23b83f6f45597/Webs/ca2d0986229b4ec88e3a217ef8f04a1d/Items/efaa67764b304e77badb213d131beab6/f4f0cf600f494c3eb702d8eafe0fabcc.aac07493e6cd4c71845d2495a4e1e19b 139.178.68.158    9.789ms      ↑ 90 B ↓ 8.5 KiB
20:09:10.244 [200 OK] s3.GetObject veeam-minio01:9000/vbo/Veeam/Backup365/vbotest/RepositoryLock/cad99aceb50c49ecb9e07246c3b9fadc_bfd985e5deec4cebaf481847f2c34797 139.178.68.158    16.21ms      ↑ 90 B ↓ 402 B
20:09:10.283 [200 OK] s3.PutObject veeam-minio01:9000/vbo/Veeam/Backup365/vbotest/CommonInfo/WebRestorePoints/18f1aba8f55f4ac6b805c4de653eb781 139.178.68.158    29.787ms     ↑ 1005 B ↓ 296 B

2 - 使用 Silo 的解耦 HDP Spark 和 Hive

1. 云原生架构

cloud-native

Kubernetes 在计算节点上以弹性方式管理无状态的 Spark 和 Hive 容器。Spark 与 Kubernetes 具有原生调度器集成。出于历史原因,Hive 在 Kubernetes 之上使用 YARN 调度器。

对 MinIO 对象存储的所有访问都通过 S3/SQL SELECT API 完成。除计算节点外,MinIO 容器也由 Kubernetes 以有状态容器方式管理,并将本地存储(JBOD/JBOF)映射为持久化本地卷。该架构支持多租户 MinIO,实现客户间数据隔离。

MinIO 还支持类似 AWS 区域与层级的多集群、多站点联邦。通过 MinIO Information Lifecycle Management(ILM),可以将数据分层到基于 NVMe 的热存储和基于 HDD 的温存储之间。所有数据都采用按对象密钥加密。租户之间的访问控制与身份管理由 MinIO 通过 OpenID Connect 或 Kerberos/LDAP/AD 进行管理。

2. 前置条件

3. 配置 Hadoop、Spark、Hive 使用 MinIO

安装成功后,访问 Ambari UI http://<ambari-server>:8080/,并使用默认凭据登录:[username: admin, password: admin]

ambari-login

3.1 配置 Hadoop

按下图进入 Services -> HDFS -> CONFIGS -> ADVANCED

hdfs-configs

进入 Custom core-site,为 _s3a_ 连接器配置 MinIO 参数

s3a-config
sudo pip install yq
alias kv-pairify='yq ".configuration[]" | jq ".[]" | jq -r ".name + \"=\" + .value"'

以 12 个计算节点、总内存 1.2TiB 的集群为例,为获得最佳结果,需要进行以下设置。向 core-site.xml 添加以下优化项,以便为 MinIO 配置 s3a。其中最重要的选项如下:

cat ${HADOOP_CONF_DIR}/core-site.xml | kv-pairify | grep "mapred"

mapred.maxthreads.generate.mapoutput=2 # Num threads to write map outputs
mapred.maxthreads.partition.closer=0 # Asynchronous map flushers
mapreduce.fileoutputcommitter.algorithm.version=2 # Use the latest committer version
mapreduce.job.reduce.slowstart.completedmaps=0.99 # 99% map, then reduce
mapreduce.reduce.shuffle.input.buffer.percent=0.9 # Min % buffer in RAM
mapreduce.reduce.shuffle.merge.percent=0.9 # Minimum % merges in RAM
mapreduce.reduce.speculative=false # Disable speculation for reducing
mapreduce.task.io.sort.factor=999 # Threshold before writing to drive
mapreduce.task.sort.spill.percent=0.9 # Minimum % before spilling to drive

S3A 是用于访问 S3 及其他兼容 S3 的对象存储(如 MinIO)的连接器。MapReduce 工作负载通常以与 HDFS 相同的方式与对象存储交互。这类工作负载依赖 HDFS 的原子 rename 功能来完成向数据存储写入。对象存储操作天然是原子的,不需要也不实现 rename API。默认的 S3A committer 会通过 copy 和 delete API 模拟 rename。由于写放大,这种交互模式会带来明显的性能损失。例如,Netflix 开发了两个新的 staging committer:Directory staging committer 和 Partitioned staging committer,以充分利用对象存储的原生操作能力。这两个 committer 不需要 rename 操作。除此之外,还对另一个新增的 Magic committer 进行了基准测试。

测试结果显示,Directory staging committer 在三者中速度最快。为获得最佳结果,S3A 连接器应配置以下参数:

cat ${HADOOP_CONF_DIR}/core-site.xml | kv-pairify | grep "s3a"

fs.s3a.access.key=minio
fs.s3a.secret.key=minio123
fs.s3a.path.style.access=true
fs.s3a.block.size=512M
fs.s3a.buffer.dir=${hadoop.tmp.dir}/s3a
fs.s3a.committer.magic.enabled=false
fs.s3a.committer.name=directory
fs.s3a.committer.staging.abort.pending.uploads=true
fs.s3a.committer.staging.conflict-mode=append
fs.s3a.committer.staging.tmp.path=/tmp/staging
fs.s3a.committer.staging.unique-filenames=true
fs.s3a.connection.establish.timeout=5000
fs.s3a.connection.ssl.enabled=false
fs.s3a.connection.timeout=200000
fs.s3a.endpoint=http://minio:9000
fs.s3a.impl=org.apache.hadoop.fs.s3a.S3AFileSystem

fs.s3a.committer.threads=2048 # Number of threads writing to MinIO
fs.s3a.connection.maximum=8192 # Maximum number of concurrent conns
fs.s3a.fast.upload.active.blocks=2048 # Number of parallel uploads
fs.s3a.fast.upload.buffer=disk # Use drive as the buffer for uploads
fs.s3a.fast.upload=true # Turn on fast upload mode
fs.s3a.max.total.tasks=2048 # Maximum number of parallel tasks
fs.s3a.multipart.size=512M # Size of each multipart chunk
fs.s3a.multipart.threshold=512M # Size before using multipart uploads
fs.s3a.socket.recv.buffer=65536 # Read socket buffer hint
fs.s3a.socket.send.buffer=65536 # Write socket buffer hint
fs.s3a.threads.max=2048 # Maximum number of threads for S3A

其余优化选项请参考以下链接:

应用配置变更后,继续重启 Hadoop 服务。

hdfs-services

3.2 配置 Spark2

按下图进入 Services -> Spark2 -> CONFIGS

spark-config

进入“Custom spark-defaults”,为 _s3a_ 连接器配置 MinIO 参数

spark-config

spark-defaults.conf 添加以下优化项,以便将 Spark 配置为使用 MinIO

spark.hadoop.fs.s3a.access.key minio
spark.hadoop.fs.s3a.secret.key minio123
spark.hadoop.fs.s3a.path.style.access true
spark.hadoop.fs.s3a.block.size 512M
spark.hadoop.fs.s3a.buffer.dir ${hadoop.tmp.dir}/s3a
spark.hadoop.fs.s3a.committer.magic.enabled false
spark.hadoop.fs.s3a.committer.name directory
spark.hadoop.fs.s3a.committer.staging.abort.pending.uploads true
spark.hadoop.fs.s3a.committer.staging.conflict-mode append
spark.hadoop.fs.s3a.committer.staging.tmp.path /tmp/staging
spark.hadoop.fs.s3a.committer.staging.unique-filenames true
spark.hadoop.fs.s3a.committer.threads 2048 # number of threads writing to MinIO
spark.hadoop.fs.s3a.connection.establish.timeout 5000
spark.hadoop.fs.s3a.connection.maximum 8192 # maximum number of concurrent conns
spark.hadoop.fs.s3a.connection.ssl.enabled false
spark.hadoop.fs.s3a.connection.timeout 200000
spark.hadoop.fs.s3a.endpoint http://minio:9000
spark.hadoop.fs.s3a.fast.upload.active.blocks 2048 # number of parallel uploads
spark.hadoop.fs.s3a.fast.upload.buffer disk # use disk as the buffer for uploads
spark.hadoop.fs.s3a.fast.upload true # turn on fast upload mode
spark.hadoop.fs.s3a.impl org.apache.hadoop.spark.hadoop.fs.s3a.S3AFileSystem
spark.hadoop.fs.s3a.max.total.tasks 2048 # maximum number of parallel tasks
spark.hadoop.fs.s3a.multipart.size 512M # size of each multipart chunk
spark.hadoop.fs.s3a.multipart.threshold 512M # size before using multipart uploads
spark.hadoop.fs.s3a.socket.recv.buffer 65536 # read socket buffer hint
spark.hadoop.fs.s3a.socket.send.buffer 65536 # write socket buffer hint
spark.hadoop.fs.s3a.threads.max 2048 # maximum number of threads for S3A

应用配置变更后,继续重启 Spark 服务。

spark-config

3.3 配置 Hive

按下图进入 Services -> Hive -> CONFIGS-> ADVANCED

hive-config

进入“Custom hive-site”,为 _s3a_ 连接器配置 MinIO 参数

hive-config

hive-site.xml 添加以下优化项,以便将 Hive 配置为使用 MinIO

hive.blobstore.use.blobstore.as.scratchdir=true
hive.exec.input.listing.max.threads=50
hive.load.dynamic.partitions.thread=25
hive.metastore.fshandler.threads=50
hive.mv.files.threads=40
mapreduce.input.fileinputformat.list-status.num-threads=50

有关这些选项的更多信息,请访问 https://www.cloudera.com/documentation/enterprise/5-11-x/topics/admin_hive_on_s3_tuning.html

hive-config

应用配置变更后,继续重启所有 Hive 服务。

hive-config

4. 运行示例应用

在 Hive、Hadoop 和 Spark 安装完成后,可以继续运行一些示例应用,验证配置是否正确。我们可以使用 Spark Pi 和 Spark WordCount 程序来验证 Spark 安装。也可以进一步了解如何通过命令行和 Spark shell 运行 Spark 作业。

4.1 Spark Pi

通过运行下面这个计算密集型示例来测试 Spark 安装。该示例通过向圆内“投掷飞镖”来计算 pi。程序会在单位正方形((0,0) 到 (1,1))内生成点,并统计落在该正方形内单位圆中的点数,结果即为 pi 的近似值。

按以下步骤运行 Spark Pi 示例:

  • ‘spark’ 用户登录。
  • 作业运行时,相关库可在中间处理阶段使用 MinIO
  • 进入安装了 Spark client 的节点,并切换到 spark2-client 目录:
cd /usr/hdp/current/spark2-client
su spark
  • 以 yarn-client 模式运行 Apache Spark Pi 作业,使用 org.apache.spark 中的代码:
./bin/spark-submit --class org.apache.spark.examples.SparkPi \
    --master yarn-client \
    --num-executors 1 \
    --driver-memory 512m \
    --executor-memory 512m \
    --executor-cores 1 \
    examples/jars/spark-examples*.jar 10

作业应产生如下输出。请关注输出中的 pi 值。

17/03/22 23:21:10 INFO DAGScheduler: Job 0 finished: reduce at SparkPi.scala:38, took 1.302805 s
Pi is roughly 3.1445191445191445

也可以在浏览器中访问 YARN ResourceManager Web UI,点击 job history server 信息来查看作业状态。

4.2 WordCount

WordCount 是一个简单程序,用于统计文本文件中各单词的出现次数。代码会构建一个名为 counts 的 (String, Int) 对数据集,并将该数据集保存到文件。

以下示例将 WordCount 代码提交到 Scala shell。请为 Spark WordCount 示例选择一个输入文件。可以使用任意文本文件作为输入。

  • ‘spark’ 用户登录。
  • 作业运行时,相关库可在中间处理阶段使用 MinIO
  • 进入安装了 Spark client 的节点,并切换到 spark2-client 目录:
cd /usr/hdp/current/spark2-client
su spark

以下示例使用 log4j.properties 作为输入文件:

4.2.1 将输入文件上传到 HDFS:

hadoop fs -copyFromLocal /etc/hadoop/conf/log4j.properties
          s3a://testbucket/testdata

4.2.2 运行 Spark shell:

./bin/spark-shell --master yarn-client --driver-memory 512m --executor-memory 512m

该命令应产生如下输出(包含额外状态信息):

Spark context Web UI available at http://172.26.236.247:4041
Spark context available as 'sc' (master = yarn, app id = application_1490217230866_0002).
Spark session available as 'spark'.
Welcome to


      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 2.1.0.2.6.0.0-598
      /_/

Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_112)
Type in expressions to have them evaluated.
Type :help for more information.

scala>
  • scala> 提示符下,输入以下命令提交作业。请将节点名、文件名和文件位置替换为实际值:
scala> val file = sc.textFile("s3a://testbucket/testdata")
file: org.apache.spark.rdd.RDD[String] = s3a://testbucket/testdata MapPartitionsRDD[1] at textFile at <console>:24

scala> val counts = file.flatMap(line => line.split(" ")).map(word => (word, 1)).reduceByKey(_ + _)
counts: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[4] at reduceByKey at <console>:25

scala> counts.saveAsTextFile("s3a://testbucket/wordcount")

使用以下任一方式查看作业输出:

在 Scala shell 中查看输出:

scala> counts.count()
364

若要在 MinIO 中查看输出,请退出 Scala shell。查看 WordCount 作业状态:

hadoop fs -ls s3a://testbucket/wordcount

输出应类似如下:

Found 3 items
-rw-rw-rw-   1 spark spark          0 2019-05-04 01:36 s3a://testbucket/wordcount/_SUCCESS
-rw-rw-rw-   1 spark spark       4956 2019-05-04 01:36 s3a://testbucket/wordcount/part-00000
-rw-rw-rw-   1 spark spark       5616 2019-05-04 01:36 s3a://testbucket/wordcount/part-00001

3 - AWS CLI 与 Silo 服务端

Slack

AWS CLI 是一个用于管理 AWS 服务的统一工具。它也常用于在 AWS S3 中导入和导出数据。它可用于任何兼容 S3 的云存储服务。

在本教程中,我们将学习如何配置并使用 AWS CLI 通过 MinIO Server 管理数据。

1. 前提条件

按照 SILO 安装指南 安装 MinIO Server。

2. 安装

https://aws.amazon.com/cli/ 安装 AWS CLI。

3. 配置

要配置 AWS CLI,请执行 aws configure 并填写 MinIO 密钥信息。

本示例中展示的访问凭据属于 https://play.min.io:9000。 这些凭据是公开的。你可以将该服务用于测试和开发。在生产部署中请替换为你自己的 MinIO 密钥。

aws configure
AWS Access Key ID [None]: Q3AM3UQ867SPQQA43P2F
AWS Secret Access Key [None]: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG
Default region name [None]: us-east-1
Default output format [None]: ENTER

此外,还需要为 MinIO Server 启用 AWS Signature Version ‘4’。

aws configure set default.s3.signature_version s3v4

4. 命令

列出你的存储桶

aws --endpoint-url https://play.min.io:9000 s3 ls
2016-03-27 02:06:30 deebucket
2016-03-28 21:53:49 guestbucket
2016-03-29 13:34:34 mbtest
2016-03-26 22:01:36 mybucket
2016-03-26 15:37:02 testbucket

列出存储桶中的内容

aws --endpoint-url https://play.min.io:9000 s3 ls s3://mybucket
2016-03-30 00:26:53      69297 argparse-1.2.1.tar.gz
2016-03-30 00:35:37      67250 simplejson-3.3.0.tar.gz

创建存储桶

aws --endpoint-url https://play.min.io:9000 s3 mb s3://mybucket
make_bucket: s3://mybucket/

向存储桶添加对象

aws --endpoint-url https://play.min.io:9000 s3 cp simplejson-3.3.0.tar.gz s3://mybucket
upload: ./simplejson-3.3.0.tar.gz to s3://mybucket/simplejson-3.3.0.tar.gz

从存储桶删除对象

aws --endpoint-url https://play.min.io:9000 s3 rm s3://mybucket/argparse-1.2.1.tar.gz
delete: s3://mybucket/argparse-1.2.1.tar.gz

删除存储桶

aws --endpoint-url https://play.min.io:9000 s3 rb s3://mybucket
remove_bucket: s3://mybucket/

4 - 为 Silo 服务端配置 NGINX 代理

以下文档提供了在 Linux 环境中配置 NGINX 将请求代理到 MinIO 的基线方案。 这并非一份关于 NGINX、代理或反向代理的一般性完整指南。 请根据你的基础设施需要调整配置。

本文档基于以下前提:

  • 已有 NGINX 部署
  • 已有 MinIO 部署
  • 一个可唯一标识该 MinIO 部署的 DNS 主机名

将请求代理到 MinIO 服务端 API 和 MinIO Console 有两种模式:

为 MinIO 服务创建或配置一个专用 DNS 名称。

对于 MinIO Server S3 API,将请求代理到该域名的根路径。 对于 MinIO Console Web GUI,将请求代理到 /minio 子路径。

例如,给定主机名 minio.example.net

  • 将对根路径 https://minio.example.net 的请求代理到监听于 https://minio.local:9000 的 MinIO Server。
  • 将对 https://minio.example.net/minio/ui 子路径的请求代理到监听于 https://minio.local:9001 的 MinIO Console。

以下 location 块提供了模板,可在你的环境中进一步定制:

upstream minio_s3 {
   least_conn;
   server minio-01.internal-domain.com:9000;
   server minio-02.internal-domain.com:9000;
   server minio-03.internal-domain.com:9000;
   server minio-04.internal-domain.com:9000;
}

upstream minio_console {
   least_conn;
   server minio-01.internal-domain.com:9001;
   server minio-02.internal-domain.com:9001;
   server minio-03.internal-domain.com:9001;
   server minio-04.internal-domain.com:9001;
}

server {
   listen       80;
   listen  [::]:80;
   server_name  minio.example.net;

   # Allow special characters in headers
   ignore_invalid_headers off;
   # Allow any size file to be uploaded.
   # Set to a value such as 1000m; to restrict file size to a specific value
   client_max_body_size 0;
   # Disable buffering
   proxy_buffering off;
   proxy_request_buffering off;

   location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_connect_timeout 300;
      # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
      proxy_http_version 1.1;
      proxy_set_header Connection "";
      chunked_transfer_encoding off;

      proxy_pass https://minio_s3; # This uses the upstream directive definition to load balance
   }

   location /minio/ui/ {
      rewrite ^/minio/ui/(.*) /$1 break;
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-NginX-Proxy true;

      # This is necessary to pass the correct IP to be hashed
      real_ip_header X-Real-IP;

      proxy_connect_timeout 300;

      # To support websockets in MinIO versions released after January 2023
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress)
      # Uncomment the following line to set the Origin request to an empty string
      # proxy_set_header Origin '';

      chunked_transfer_encoding off;

      proxy_pass https://minio_console; # This uses the upstream directive definition to load balance
   }
}

S3 API 签名计算算法 支持将 MinIO Server API 托管在 example.net/s3/ 这类路径上的代理方案。

你还必须为 MinIO 部署设置以下环境变量:

为 MinIO Server S3 API 和 MinIO Console Web GUI 分别创建或配置独立且唯一的子域名。

例如,给定根域 example.net

  • 将对 minio.example.net 子域名的请求代理到监听于 https://minio.local:9000 的 MinIO Server
  • 将对 console.example.net 子域名的请求代理到监听于 https://minio.local:9001 的 MinIO Console

以下 location 块提供了模板,可在你的环境中进一步定制:

upstream minio_s3 {
   least_conn;
   server minio-01.internal-domain.com:9000;
   server minio-02.internal-domain.com:9000;
   server minio-03.internal-domain.com:9000;
   server minio-04.internal-domain.com:9000;
}

upstream minio_console {
   least_conn;
   server minio-01.internal-domain.com:9001;
   server minio-02.internal-domain.com:9001;
   server minio-03.internal-domain.com:9001;
   server minio-04.internal-domain.com:9001;
}

server {
   listen       80;
   listen  [::]:80;
   server_name  minio.example.net;

   # Allow special characters in headers
   ignore_invalid_headers off;
   # Allow any size file to be uploaded.
   # Set to a value such as 1000m; to restrict file size to a specific value
   client_max_body_size 0;
   # Disable buffering
   proxy_buffering off;
   proxy_request_buffering off;

   location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_connect_timeout 300;
      # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
      proxy_http_version 1.1;
      proxy_set_header Connection "";
      chunked_transfer_encoding off;

      proxy_pass http://minio_s3; # This uses the upstream directive definition to load balance
   }
}

server {

   listen       80;
   listen  [::]:80;
   server_name  console.example.net;

   # Allow special characters in headers
   ignore_invalid_headers off;
   # Allow any size file to be uploaded.
   # Set to a value such as 1000m; to restrict file size to a specific value
   client_max_body_size 0;
   # Disable buffering
   proxy_buffering off;
   proxy_request_buffering off;

   location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-NginX-Proxy true;

      # This is necessary to pass the correct IP to be hashed
      real_ip_header X-Real-IP;

      proxy_connect_timeout 300;

      # To support websocket
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";

      chunked_transfer_encoding off;

      proxy_pass http://minio_console/; # This uses the upstream directive definition to load balance
   }
}

S3 API 签名计算算法 支持将 MinIO Server API 托管在子路径上的代理方案,例如 minio.example.net/s3/

你还必须为 MinIO 部署设置以下环境变量:

5 - 使用 Pre-signed URL 上传文件

Slack

使用 pre-signed URL,客户端可以直接将文件上传到兼容 S3 的云存储服务器(S3),而无需向用户暴露 S3 凭证。

本文介绍如何使用 MinIO JavaScript Library 中的 presignedPutObject API 生成 pre-signed URL。文中通过一个 JavaScript 示例进行演示:由 Express Node.js 服务器暴露一个用于生成 pre-signed URL 的端点,客户端 Web 应用再使用该 URL 将文件上传到 MinIO Server。

1. 创建服务端

服务端由一个 Express Node.js 服务器组成,并暴露名为 /presignedUrl 的端点。该端点使用 Minio.Client 对象生成短时有效的 pre-signed URL,用于将文件上传到 MinIO Server。

// In order to use the MinIO JavaScript API to generate the pre-signed URL, begin by instantiating
// a `Minio.Client` object and pass in the values for your server.
// The example below uses values for play.min.io:9000

const Minio = require('minio')

var client = new Minio.Client({
    endPoint: 'play.min.io',
    port: 9000,
    useSSL: true,
    accessKey: 'Q3AM3UQ867SPQQA43P2F',
    secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG'
})

// Instantiate an `express` server and expose an endpoint called `/presignedUrl` as a `GET` request that
// accepts a filename through a query parameter called `name`. For the implementation of this endpoint,
// invoke [`presignedPutObject`](https://github.com/minio/minio-js/blob/master/docs/zh_CN/API.md#presignedputobjectbucketname-objectname-expiry-callback)
// on the `Minio.Client` instance to generate a pre-signed URL, and return that URL in the response:

// express is a small HTTP server wrapper, but this works with any HTTP server
const server = require('express')()

server.get('/presignedUrl', (req, res) => {
    client.presignedPutObject('uploads', req.query.name, (err, url) => {
        if (err) throw err
        res.end(url)
    })
})

server.get('/', (req, res) => {
    res.sendFile(__dirname + '/index.html');
})

server.listen(8080)

2. 创建客户端 Web 应用

客户端 Web 应用的用户界面包含一个选择器字段,允许用户选择要上传的文件,以及一个用于触发名为 uploadonclick 处理函数的按钮:

<input type="file" id="selector" multiple>
<button onclick="upload()">Upload</button>

<div id="status">No uploads</div>

<script type="text/javascript">
  // `upload` iterates through all files selected and invokes a helper function called `retrieveNewURL`.
  function upload() {
        // Get selected files from the input element.
        var files = document.querySelector("#selector").files;
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            // Retrieve a URL from our server.
            retrieveNewURL(file, (file, url) => {
                // Upload the file to the server.
                uploadFile(file, url);
            });
        }
    }

    // `retrieveNewURL` accepts the name of the current file and invokes the `/presignedUrl` endpoint to
    // generate a pre-signed URL for use in uploading that file: 
    function retrieveNewURL(file, cb) {
        fetch(`/presignedUrl?name=${file.name}`).then((response) => {
            response.text().then((url) => {
                cb(file, url);
            });
        }).catch((e) => {
            console.error(e);
        });
    }

    // ``uploadFile` accepts the current filename and the pre-signed URL. It then uses `Fetch API`
    // to upload this file to S3 at `play.min.io:9000` using the URL:
    function uploadFile(file, url) {
        if (document.querySelector('#status').innerText === 'No uploads') {
            document.querySelector('#status').innerHTML = '';
        }
        fetch(url, {
            method: 'PUT',
            body: file
        }).then(() => {
            // If multiple files are uploaded, append upload status on the next line.
            document.querySelector('#status').innerHTML += `<br>Uploaded ${file.name}.`;
        }).catch((e) => {
            console.error(e);
        });
    }
</script>

注意: 本示例使用了 File APIQuerySelector APIfetch APIPromise API

6 - 使用 Certbot 为 Silo 生成 Let’s Encrypt 证书

Slack

Let’s Encrypt 是一个新的免费、自动化且开源的证书颁发机构(Certificate Authority)。

Certbot 是一个基于控制台的 Let’s Encrypt 证书生成工具。

在本教程中,我们将使用 Certbot 生成 Let’s Encypt 证书。随后将把该证书部署到 MinIO Server 中使用。

1. 前置条件

2. 依赖要求

  • 在执行 certbot 时,https 使用的 443 端口需要处于开放且可用状态。
  • Certbot 执行时需要 root 访问权限,因为只有 root 可以绑定 1024 以下的端口。
  • 本教程将使用我们自己的域名 myminio.com 作为示例。请在你的环境中替换为你自己的域名。

3. 操作步骤

第 1 步:安装 Certbot

请按照 https://certbot.eff.org/ 上的文档安装 Certbot。

第 2 步:生成 Let’s Encrypt 证书

# certbot certonly --standalone -d myminio.com --staple-ocsp -m [email protected] --agree-tos

第 3 步:验证证书

列出保存在 /etc/letsencrypt/live/myminio.com 目录中的证书。

$ ls -l /etc/letsencrypt/live/myminio.com
total 4
lrwxrwxrwx 1 root root  37 Aug  2 09:58 cert.pem -> ../../archive/myminio.com/cert4.pem
lrwxrwxrwx 1 root root  38 Aug  2 09:58 chain.pem -> ../../archive/myminio.com/chain4.pem
lrwxrwxrwx 1 root root  42 Aug  2 09:58 fullchain.pem -> ../../archive/myminio.com/fullchain4.pem
lrwxrwxrwx 1 root root  40 Aug  2 09:58 privkey.pem -> ../../archive/myminio.com/privkey4.pem
-rw-r--r-- 1 root root 543 May 10 22:07 README

第 4 步:使用证书在 MinIO Server 上配置 SSL。

通过 Certbot 生成的证书和密钥需要放置在用户的主目录中。

$ cp /etc/letsencrypt/live/myminio.com/fullchain.pem /home/user/.minio/certs/public.crt
$ cp /etc/letsencrypt/live/myminio.com/privkey.pem /home/user/.minio/certs/private.key

第 5 步:更改证书的所有权。

$ sudo chown user:user /home/user/.minio/certs/private.key
$ sudo chown user:user /home/user/.minio/certs/public.crt

第 6 步:使用 HTTPS 启动 MinIO Server。

如果你不打算以 root 权限运行 MinIO,则需要通过以下命令为 MinIO 赋予监听小于 1024 端口的能力:

sudo setcap 'cap_net_bind_service=+ep' ./minio

现在,你可以在 “443” 端口上启动 MinIO Server。

$ ./minio server --address ":443" /mnt/data

如果你使用的是 MinIO 的 dockerized 版本,那么你需要

$ sudo docker run -p 443:443 -v /home/user/.minio:/root/.minio/ -v /home/user/data:/data minio/minio server --address ":443" /data

第 7 步:在浏览器中访问 https://myminio.com

Letsencrypt