CLOVER🍀

That was when it all began.

Amazon S3互換のオブジェクトストレージ、MinIOを試す

これは、なにをしたくて書いたもの?

前々から1度試しておきたかった、Amazon S3互換のオブジェクトストレージMinIOを扱ってみようかなと。

MinIOとは

MinIOは、Amazon S3互換のオブジェクトストレージです。

MinIO | High Performance, Kubernetes Native Object Storage

Goで実装されています。

GitHub - minio/minio: High Performance, Kubernetes Native Object Storage

3つのライセンス形態があるようですが、サポートに差があるみたいですね。

Pricing

ドキュメントは、ベアメタル環境向け、Kubernetes環境向け、VMware Cloud Fundation環境向けのものがありますが、
今回はベアメタル環境向けのものを参照します。

MinIO High Performance Object Storage — MinIO Baremetal Documentation

MinIO Object Storage for Hybrid Cloud — MinIO Hybrid Cloud Documentation

機能については、こちら。

MinIO Server Features — MinIO Baremetal Documentation

Notification、バージョニング、耐障害性、レプリケーションを備えます。

ちなみに、これらのドキュメントは現在作成中で、レガシー扱いとなったドキュメントもあります。現在のドキュメントに
記載がないものについては、レガシードキュメントの方を参照する必要があるようです。

MinIO | The MinIO Quickstart Guide

たとえば、AWS CLIや各種プログラミング言語向けのクライアントライブラリなどはレガシードキュメントにしか
ありません。

MinIO | AWS CLI with MinIO - Cookbook/Recipe

MinIO | Java Client Quickstart Guide

Amazon S3互換ということで、AWS CLIやAWS SDKが使えるわけですが、専用のクライアントコマンドや管理コマンド、
クライアントライブラリも備えています。

MinIO Client (mc) — MinIO Baremetal Documentation

MinIO Admin (mc admin) — MinIO Baremetal Documentation

今回は、とりあえずスタンドアロンでMinIOサーバーを立てて、クライアントコマンドやAWS CLIでアクセスして
みたいと思います。

環境

今回の環境は、こちら。Ubuntu Linux 20.04 LTSです。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:    20.04
Codename:   focal


$ uname -srvmpio
Linux 5.4.0-84-generic #94-Ubuntu SMP Thu Aug 26 20:27:37 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

AWS CLIもインストールしておきました。

$ aws --version
aws-cli/2.2.36 Python/3.8.8 Linux/5.4.0-84-generic exe/x86_64.ubuntu.20 prompt/off

MinIOサーバーをインストールする

まずは、MinIOサーバーをインストールします。

MinIO | Code and downloads to create high performance object storage

インストール方法は実行バイナリ、rpmパッケージ、debパッケージ、そしてDockerイメージがありますが、今回は
debパッケージのものを使うことにします。

debパッケージをダウンロードして

$ curl -O https://dl.min.io/server/minio/release/linux-amd64/minio_20210903035613.0.0_amd64.deb

インストール。

$ sudo dpkg -i minio_20210903035613.0.0_amd64.deb

バージョン。

$ minio --version
minio version RELEASE.2021-09-03T03-56-13Z

実行方法についてはこちらに記載がありますが、

MinIO Server — MinIO Baremetal Documentation

ヘルプも確認。

$ minio --help
NAME:
  minio - High Performance Object Storage

DESCRIPTION:
  Build high performance data infrastructure for machine learning, analytics and application data workloads with MinIO

USAGE:
  minio [FLAGS] COMMAND [ARGS...]

COMMANDS:
  server   start object storage server
  gateway  start object storage gateway
  
FLAGS:
  --certs-dir value, -S value  path to certs directory (default: "/home/vagrant/.minio/certs")
  --quiet                      disable startup information
  --anonymous                  hide sensitive information from logging
  --json                       output server logs and startup information in json format
  --help, -h                   show help
  --version, -v                print the version
  
VERSION:
  RELEASE.2021-09-03T03-56-13Z

起動方法にserverとgatewayがあるようです。

MinIO Gatewayは、AWSやAzureのオブジェクトストレージをバックエンドにするプロセスです。

今回は、serverの方を使います。

$ minio server --help
NAME:
  minio server - start object storage server

USAGE:
  minio server [FLAGS] DIR1 [DIR2..]
  minio server [FLAGS] DIR{1...64}
  minio server [FLAGS] DIR{1...64} DIR{65...128}

DIR:
  DIR points to a directory on a filesystem. When you want to combine
  multiple drives into a single large system, pass one directory per
  filesystem separated by space. You may also use a '...' convention
  to abbreviate the directory arguments. Remote directories in a
  distributed setup are encoded as HTTP(s) URIs.

FLAGS:
  --address value              bind to a specific ADDRESS:PORT, ADDRESS can be an IP or hostname (default: ":9000")
  --console-address value      bind to a specific ADDRESS:PORT for embedded Console UI, ADDRESS can be an IP or hostname
  --certs-dir value, -S value  path to certs directory (default: "/home/vagrant/.minio/certs")
  --quiet                      disable startup information
  --anonymous                  hide sensitive information from logging
  --json                       output server logs and startup information in json format
  --help, -h                   show help
  
EXAMPLES:
  1. Start minio server on "/home/shared" directory.
     $ minio server /home/shared

  2. Start single node server with 64 local drives "/mnt/data1" to "/mnt/data64".
     $ minio server /mnt/data{1...64}

  3. Start distributed minio server on an 32 node setup with 32 drives each, run following command on all the nodes
     $ export MINIO_ROOT_USER=minio
     $ export MINIO_ROOT_PASSWORD=miniostorage
     $ minio server http://node{1...32}.example.com/mnt/export{1...32}

  4. Start distributed minio server in an expanded setup, run the following command on all the nodes
     $ export MINIO_ROOT_USER=minio
     $ export MINIO_ROOT_PASSWORD=miniostorage
     $ minio server http://node{1...16}.example.com/mnt/export{1...32} \
            http://node{17...64}.example.com/mnt/export{1...64}

データを保存するためのディレクトリが必要なようなので、作成して

$ mkdir data

起動。

$ minio server data
API: http://192.168.121.136:9000  http://192.168.33.10:9000  http://127.0.0.1:9000     
RootUser: minioadmin 
RootPass: minioadmin 

Console: http://192.168.121.136:42799 http://192.168.33.10:42799 http://127.0.0.1:42799   
RootUser: minioadmin 
RootPass: minioadmin 

Command-line: https://docs.min.io/docs/minio-client-quickstart-guide
   $ mc alias set myminio http://192.168.121.136:9000 minioadmin minioadmin

Documentation: https://docs.min.io

WARNING: Console endpoint is listening on a dynamic port (42799), please use --console-address ":PORT" to choose a static port.
WARNING: Detected default credentials 'minioadmin:minioadmin', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables

特に指定しないと、Web Consoleのポートがランダムに決まるようなので、指定しておきます。ドキュメントに習って
9001にしておきました。

$ minio server data --console-address ":9001"
API: http://192.168.121.136:9000  http://192.168.33.10:9000  http://127.0.0.1:9000     
RootUser: minioadmin 
RootPass: minioadmin 

Console: http://192.168.121.136:9001 http://192.168.33.10:9001 http://127.0.0.1:9001   
RootUser: minioadmin 
RootPass: minioadmin 

Command-line: https://docs.min.io/docs/minio-client-quickstart-guide
   $ mc alias set myminio http://192.168.121.136:9000 minioadmin minioadmin

Documentation: https://docs.min.io
WARNING: Detected default credentials 'minioadmin:minioadmin', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables

起動時に表示されているのは、MinIOの管理ユーザーの名前とパスワードでもあり、AWS SDKのクレデンシャルでも
あります。

これは、MINIO_ROOT_USERおよびMINIO_ROOT_PASSWORD環境変数で指定することができます。

$ MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password minio server data --console-address ":9001"
API: http://192.168.121.136:9000  http://192.168.33.10:9000  http://127.0.0.1:9000     
RootUser: admin 
RootPass: password 

Console: http://192.168.121.136:9001 http://192.168.33.10:9001 http://127.0.0.1:9001   
RootUser: admin 
RootPass: password 

Command-line: https://docs.min.io/docs/minio-client-quickstart-guide
   $ mc alias set myminio http://192.168.121.136:9000 admin password

Documentation: https://docs.min.io

今回は、デフォルトのminioadmin / minioadminをそのまま使うことにします。

$ minio server data --console-address ":9001"

MinIOクライアントをインストールする

続いては、MinIOクライアントをインストールしましょう。

こちらも、debパッケージでインストールします。ダウンロードして

$ curl -O https://dl.min.io/client/mc/release/linux-amd64/mcli_20210902092127.0.0_amd64.deb

インストール。

$ sudo dpkg -i mcli_20210902092127.0.0_amd64.deb

バージョン。

$ mcli --version
mcli version RELEASE.2021-09-02T09-21-27Z

ちなみに、実行可能ファイルでインストールするとmcコマンドとなり、rpmパッケージやdebパッケージでインストール
するとmcliコマンドになります。

MinIO | Code and downloads to create high performance object storage

どちらにせよ、インストールされるのは単一バイナリだけですが。

$ dpkg -L mcli
/usr
/usr/local
/usr/local/bin
/usr/local/bin/mcli

ダウンロードページに記載されているコマンドに従い、myminioという名前にローカルのMinIOをエイリアスとして
設定します。この時、ユーザー名とパスワードも必要です。

$ mcli alias set myminio http://localhost:9000 minioadmin minioadmin

MinIOサーバーの情報を確認。

$ mcli admin info myminio
●  localhost:9000
   Uptime: 6 minutes 
   Version: 2021-09-03T03:56:13Z
   Network: 1/1 OK 

いくつかコマンドを試してみます。

バケットの作成。

$ mcli mb myminio/my-bucket
Bucket created successfully `myminio/my-bucket`.

確認。

$ mcli ls myminio
[2021-09-10 22:58:17 JST]     0B my-bucket/

ローカルでファイルを作成して

$ echo 'Hello World' > hello.txt

アップロード。

$ mcli cp hello.txt myminio/my-bucket/hello.txt

ダウンロード。

$ mcli cp myminio/my-bucket/hello.txt hello-copy.txt


$ cat hello-copy.txt
Hello World

ファイル削除。

$ mcli rm myminio/my-bucket/hello.txt
Removing `myminio/my-bucket/hello.txt`.

バケット削除。

$ mcli rb myminio/my-bucket
Removed `myminio/my-bucket` successfully.

もう1度バケットの作成とファイルアップロード、そしてバケットをもうひとつ作成します。

$ mcli mb myminio/my-bucket
$ mcli cp hello.txt myminio/my-bucket/hello.txt


$ mcli mb myminio/my-bucket2

起動時に--console-address ":9001"を指定したので、http://[MinIOサーバーのIPアドレス]:9001でWeb Consoleに
アクセスできます。

MinIO Console — MinIO Baremetal Documentation

ログインアカウントは、起動時に表示されたユーザー名とパスワードです。

Web Consoleでは、Minioサーバーの情報を参照したり、バケットへのアクセス、ユーザー管理などができたりします。

f:id:Kazuhira:20210910230530p:plain

f:id:Kazuhira:20210910230550p:plain

AWS CLIでアクセスする

続いて、AWS CLIでアクセスしてみましょう。

クレデンシャルとリージョンは、環境変数で指定することにします。

$ export AWS_ACCESS_KEY_ID=minioadmin
$ export AWS_SECRET_ACCESS_KEY=minioadmin
$ export AWS_DEFAULT_REGION=ap-northeast-1

AWS CLIでアクセスする際は、--endpoint-url http://[MinIOサーバーのIPアドレス]:9000を指定します。

$ aws --endpoint-url http://localhost:9000 s3 ls
2021-09-10 23:03:54 my-bucket
2021-09-10 23:04:19 my-bucket2

先ほど、MinIOのクライアントツールで作成したバケットが見えています。

ファイルのダウンロード。

$ aws --endpoint-url http://localhost:9000 s3 cp s3://my-bucket/hello.txt -
Hello World

こちらもOKそうですね。

systemdでMinIOサーバーを起動する

ところで、MinIOサーバーのパッケージを見ると、どうやらsystemdの定義ファイルが含まれているようです。

$ dpkg -L minio
/usr
/usr/local
/usr/local/bin
/usr/local/bin/minio
/etc
/etc/systemd
/etc/systemd/system
/etc/systemd/system/minio.service

systemdのユニット定義ファイルは、こんな感じでした。

/etc/systemd/system/minio.service

[Unit]
Description=MinIO
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/bin/minio

[Service]
WorkingDirectory=/usr/local

User=minio-user
Group=minio-user
ProtectProc=invisible

EnvironmentFile=-/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES

# Let systemd restart this service always
Restart=always

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536

# Specifies the maximum number of threads this process can create
TasksMax=infinity

# Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no

[Install]
WantedBy=multi-user.target

# Built for ${project.name}-${project.version} (${project.name})

有効化して

$ sudo systemctl enable minio
Created symlink /etc/systemd/system/multi-user.target.wants/minio.service → /etc/systemd/system/minio.service.

起動しようとすると、失敗します。

$ sudo systemctl start minio
Job for minio.service failed because the control process exited with error code.
See "systemctl status minio.service" and "journalctl -xe" for details.

ログを見ると、クレデンシャルに問題があるようです。

 9月 10 23:18:28 server systemd[1]: Starting MinIO...
 9月 10 23:18:28 server systemd[1989]: minio.service: Failed to determine user credentials: No such process
 9月 10 23:18:28 server systemd[1989]: minio.service: Failed at step USER spawning /bin/bash: No such process

ユニット定義のユーザーおよびグループ指定を見ると、存在しないユーザーとグループが指定されています。

User=minio-user
Group=minio-user

このままだと起動しないので、ユーザーを追加します。

$ sudo useradd minio-user

これでもまだ失敗します。

$ sudo systemctl start minio
Job for minio.service failed because the control process exited with error code.
See "systemctl status minio.service" and "journalctl -xe" for details.

エラーメッセージを確認すると、/etc/default/minioというファイルに環境変数の定義がないと言っています。

 9月 10 23:19:44 server systemd[1]: Starting MinIO...
 9月 10 23:19:44 server bash[2030]: Variable MINIO_VOLUMES not set in /etc/default/minio

これは、ExecStartPreおよびExecStartを見ると理由がわかります。

ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES

起動時の設定をしなければいけないようです。

では、データを保存するディレクトリを作成して

$ sudo mkdir -p /var/lib/minio/data
$ sudo chown -R minio-user:minio-user /var/lib/minio

/etc/default/minioファイルも作成します。ここで、起動時のオプションとデータの保存先を指定します。

/etc/default/minio

MINIO_OPTS=--console-address :9001
MINIO_VOLUMES=/var/lib/minio/data

今度は起動するようになります。

$ sudo systemctl start minio

デフォルトのクレデンシャルだと警告が出るので

 9月 10 23:26:00 server minio[2273]: WARNING: Detected default credentials 'minioadmin:minioadmin', we recommend that you change these values with 'MINIO_ROOT_USER' and 'MINIO_ROOT_PASSWORD' environment variables

好みに応じて、MINIO_ROOT_USERおよびMINIO_ROOT_PASSWORDを設定してクレデンシャルを指定すると
よいでしょう。

/etc/default/minio

MINIO_OPTS=--console-address :9001
MINIO_VOLUMES=/var/lib/minio/data
MINIO_ROOT_USER=root-user
MINIO_ROOT_PASSWORD=password

まとめ

Amazon S3互換のオブジェクトストレージ、MinIOを試してみました。

MinIOのクライアントコマンドは最初は戸惑ったりしましたが、あとはそれほど困りませんでしたね。

お手軽に使えそうなので、Amazon S3の代わりが欲しい時はLocalStackと使い分けていこうかなと思います。