(2021/5/18 追記) Operator のインストールしかしてないじゃん、ってことでタイトル変更しました。 実際に Operator で構築した Minio を試して、続編として投稿したいと思います。

前回の投稿から 3 ヶ月ほど空いてしまいました。

その間に、誕生日に Japan Rook Meetup で登壇したり…

CKA (Certified Kubernetes Administrator) の資格を取ったり…

したのですが、まったくブログにアウトプットできてませんでした。

現在は CKAD (Certified Kubernetes Application Developer) に向けて勉強中なのですが、裏で MinIO Operator を触ってみたので気晴らしに久しぶりの投稿をします。

MinIO とは

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

MinIO | Enterprise Grade, High Performance Object Storage

プライベート/ハイブリッドクラウドの標準オブジェクトストレージとなることを前提とした設計のようです。

そのためか、公式サイトではファイルシステムやブロックストレージには結構キツい物言いをしている感じがします(個人の感想です)。

ハイブリッドクラウドストレージは、パブリッククラウドで確立されたモデルに従い、パブリッククラウドプロバイダーは全会一致でクラウドネイティブオブジェクトストレージを採用しています。

パブリッククラウドの成功により、ファイルとブロックストレージは事実上時代遅れになりました。

すべての新しいアプリケーションは、POSIXではなくAWS S3API用に作成されています。

クラウドネイティブテクノロジーのようにスケーリングして実行するには、古いアプリケーションをS3 API用に書き直し、コンテナ互換になるようにマイクロサービスにリファクタリングする必要があります。

また、かつて Rook (v1.2)でもストレージプロバイダとして MinIO が対象となっていたのですが、残念ながら現在は対象外となってしまったようです。

minio: remove from rook · rook/rook@9a078bf

ちなみに、MinIO の読み方は「ミン・アイオー」のようです(ミニオって言ってしまってました…)。

MinIO(1) 概要とRookを使ったデプロイ方法 - Qiita

MinIO Operator

そんな MinIO を Kubernetes にデプロイして運用までしてくれる MinIO Operator がリリースされたようです。

MinIO adds mainstream object storage management features – Blocks and Files

今回は公式リポジトリの手順に沿って MinIO Operator をインストールして、オブジェクトを格納するためのテナントを作成するところまで試してみます。

minio/operator: MinIO Operator creates/configures/manages MinIO clusters on Kubernetes

前提条件

MinIO Operator のインストール、およびテナント作成の前提条件は以下の 4 つです。

  • Kubernetes クラスタのバージョンが 1.17.0 以上であること

    1.17.0 未満だったら Kubernetes 公式を参照してアップグレードします。

    今回使用したクラスタは v1.21.0 のため、そのまま使用します。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:25:06Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"linux/amd64"}
  • Kubernetes クラスタに MinIO テナント用の namespace があること

    MinIO Operator はテナント毎に namespace を使用します。

    今回は検証用の minio-tenant-1 namespace を作成します。

$ kubectl create namespace minio-tenant-1
namespace/minio-tenant-1 created
  • Kubernetes クラスタに volumeBindingMode: WaitForFirstConsumer の StorageClass があること

    MinIO Operator は volumeBindingMode: WaitForFirstConsumer の StorageClass にデータを格納します。 今回使用する Kubernetes クラスタには Rook/Ceph が導入済みのため、Rook/Ceph を使って MinIO Operator 用の StorageClass を作成します。

apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
  name: minio-pool
  namespace: rook-ceph
spec:
  failureDomain: host
  replicated:
    size: 3
    requireSafeReplicaSize: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: minio-rook-ceph-block
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
    clusterID: rook-ceph
    pool: replicapool
    imageFormat: "2"
    imageFeatures: layering
    csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
    csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
    csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
    csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
    csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
    csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
    csi.storage.k8s.io/fstype: ext4
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
  • Krew がインストールされていること

    MinIO Operator は kubectl コマンドラインツールの Krew を使用してインストールします。

    以下のサイトを参照して Krew をインストールします。

    Installing · Krew

インストール

Krew を使って MinIO Operator をインストールしていきます。

$ kubectl krew update
Updated the local copy of plugin index.

$ kubectl krew install minio
Updated the local copy of plugin index.
Installing plugin: minio
Installed plugin: minio
\
 | Use this plugin:
 |      kubectl minio
 | Documentation:
 |      https://github.com/minio/operator/tree/master/kubectl-minio
 | Caveats:
 | \
 |  | * For resources that are not in default namespace, currently you must
 |  |   specify -n/--namespace explicitly (the current namespace setting is not
 |  |   yet used).
 | /
/
WARNING: You installed plugin "minio" from the krew-index plugin repository.
   These plugins are not audited for security by the Krew maintainers.
   Run them at your own risk.

MinIO プラグインをインストールできたら、Operator を初期構築します。

$ kubectl minio init
namespace/minio-operator created
serviceaccount/minio-operator created
clusterrole.rbac.authorization.k8s.io/minio-operator-role created
clusterrolebinding.rbac.authorization.k8s.io/minio-operator-binding created
customresourcedefinition.apiextensions.k8s.io/tenants.minio.min.io created
service/operator created
deployment.apps/minio-operator created
serviceaccount/console-sa created
clusterrole.rbac.authorization.k8s.io/console-sa-role created
clusterrolebinding.rbac.authorization.k8s.io/console-sa-binding created
configmap/console-env created
service/console created
deployment.apps/console created
-----------------

To open Operator UI, start a port forward using this command:

kubectl minio proxy -n minio-operator 

-----------------

上記出力の通り、proxy 経由で MinIO Operator の管理画面にアクセスできるようになります。

$ kubectl minio proxy -n minio-operator
Starting port forward of the Console UI.

To connect open a browser and go to http://localhost:9090

Current JWT to login: eyJhbGciOiJSUzI1NiIsImtpZCI6Ii0zbFc4cm51LXNPTWliSUVOYXdTNmI3ejRWeWRuVEF0dU9aenpKY0xaNGMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJtaW5pby1vcGVyYXRvciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjb25zb2xlLXNhLXRva2VuLWJmNDZyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNvbnNvbGUtc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI3ZDgwZDNjOS0wMzUyLTRjNDItOWQ5Yy0xM2I3ZDg2ZjA4OWIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6bWluaW8tb3BlcmF0b3I6Y29uc29sZS1zYSJ9.F8XsI2buT71U4QUi7tfShaDYAOs0rcgjPmZO5HiJYyWYZ0ZYN5LDZbIRf4il23CGRjGVUWksKsfeUqRFD0iG2lP21WxvTgIbUov3DbZtItB3Sj1dO4xI5WH7PLjyYAyE5eYGRQwd3K0qSpaexh4cKsG8vj5pxzd8g-f6vwWjE1Co7Ax83PzP_ATmNnOWVQE-6lI287QijtH-PfdK3UEHM1d1WU67yvei0YGLTyMgC3t6F8xKwqay0B2OLEUGirDcq74xZA5qB_Ipuvys5K05nOCKbQiWujv0J_gyyaEAwszRpGc4Gy8Mrc-bhAYe7EGLh8_BoQiwJ2d4UVcBEuEmmw

Forwarding from 0.0.0.0:9090 -> 9090

ブラウザで kubectl minio proxy コマンドを実行しているサーバにアクセスするとログイン画面が表示されるので、コマンド実行時に出力された文字列を入力してログインします。

テナント作成

次に、MinIO Operator を使ってテナントを作成します。

デプロイされる Pod やストレージサイズを指定するオプションがあるのですが、クラスタと相談のうえ設定してください。

$ kubectl minio tenant create minio-tenant-1 \
    --servers 1 \
    --volumes 4 \
    --capacity 4Gi \
    --namespace minio-tenant-1 \
    --storage-class minio-rook-ceph-block

Tenant 'minio-tenant-1' created in 'minio-tenant-1' Namespace

  Username: admin 
  Password: ac8a676c-d4a3-4cb0-98b9-c432f3c9cd5c 
  Note: Copy the credentials to a secure location. MinIO will not display these again.

+-------------+------------------------+----------------+--------------+--------------+
| APPLICATION | SERVICE NAME           | NAMESPACE      | SERVICE TYPE | SERVICE PORT |
+-------------+------------------------+----------------+--------------+--------------+
| MinIO       | minio                  | minio-tenant-1 | ClusterIP    | 443          |
| Console     | minio-tenant-1-console | minio-tenant-1 | ClusterIP    | 9443         |
+-------------+------------------------+----------------+--------------+--------------+

これでオブジェクトを格納するためのテナントが完成しました。

自分の環境では、テナントを正常に作成できた状態では以下のリソースが作られていました。

$ kubectl get secret -n minio-tenant-1
NAME                            TYPE                                  DATA   AGE
default-token-ntlzm             kubernetes.io/service-account-token   3      2m24s
minio-tenant-1-console-secret   Opaque                                4      2m22s
minio-tenant-1-console-tls      Opaque                                2      62s
minio-tenant-1-creds-secret     Opaque                                2      2m22s
minio-tenant-1-tls              Opaque                                2      2m2s
operator-tls                    Opaque                                1      2m17s
operator-webhook-secret         Opaque                                3      2m17s

$ kubectl get pods -n minio-tenant-1
NAME                    READY   STATUS    RESTARTS   AGE
minio-tenant-1-console-6b7488946f-2mvkf   1/1     Running   0          2m43s
minio-tenant-1-console-6b7488946f-6djht   1/1     Running   0          2m43s
minio-tenant-1-ss-0-0                     1/1     Running   0          3m43s

$ kubectl get csr
NAME                                        AGE    SIGNERNAME                     REQUESTOR                                             CONDITION
minio-tenant-1-console-minio-tenant-1-csr   17s    kubernetes.io/legacy-unknown   system:serviceaccount:minio-operator:minio-operator   Approved,Issued
minio-tenant-1-minio-tenant-1-csr           77s    kubernetes.io/legacy-unknown   system:serviceaccount:minio-operator:minio-operator   Approved,Issued
operator-minio-operator-csr                 4m5s   kubernetes.io/legacy-unknown   system:serviceaccount:minio-operator:minio-operator   Approved,Issued

$ kubectl get tenant -n minio-tenant-1
NAME             STATE         AGE
minio-tenant-1   Initialized   4m43s

ちなみに、--volumes が 4 未満だった場合、エラーとなります。

$ kubectl minio tenant create minio-tenant-1 \
    --servers 1 \
    --volumes 3 \
    --capacity 3Gi \
    --namespace minio-tenant-1 \
    --storage-class minio-rook-ceph-block
Error: pool #0 setup must have a minimum of 4 volumes per server

サーバ 1 台につき 4 ボリュームが必要なようです。

注意点

テナント作成時にユーザ情報が表示されますが、このとき表示される Password は再度表示することができないので、必ず控えておいてください。

また、万人に該当する注意点ではないかもですが、自分の環境では Operator の処理が遅く、上記のユーザ情報が表示されたあともテナントに必要なリソースがすべてデプロイされていませんでした。 厳密に言うと、minio-tenant-1-tls Secret が作成されなかったため、Secret をマウントできずに Pod が起動してきませんでした。

原因は不要な CSR リソースが存在していたことで、テナント作成時にデプロイされるべき CSR リソースがすでに存在していたため、minio-tenant-1-tls Secret が作成されなかったのだと推測しています。 この不要な CSR リソースは、テナント作成時のオプションを失敗して何度かテナント作成をやり直していたことで残っていたと思われます。

テナントを作成する際には CSR リソースも確認しておいたほうが良さそうです。

外部公開用サービス

ここまでの手順では Kubernetes クラスタ外のアプリケーションから MinIO テナントに接続するサービスがデプロイされていません。 そのため、Ingress や Load Balancer が必要です。

今回は MinIO テナント用の Load Balancer を作成します。

クラスタには MetalLB と ExternalDNS をデプロイ済みで、LoadBalancer を作成するとクラスタ外から接続可能な IP アドレスが振られて、 クラスタ外の DNS にレコードを登録してくれます。

外部から接続するサービスは minioconsole の 2 種類があります。

MinIO

こちらは実際にオブジェクトストレージを操作するための API と GUI を提供するサービスです。

テナント作成時に表示された admin ユーザでログインします。

apiVersion: v1
kind: Service
metadata:
  namespace: minio-tenant-1
  name: minio-loadbalancer
  labels:
    component: minio-tenant-1
  annotations:
    external-dns.alpha.kubernetes.io/hostname: minio-tenant-1.nnstt1.work.    # ExternalDNS 用アノテーション
spec:
  type: LoadBalancer
  ports:
    - port: 9000
      targetPort: 9000
      protocol: TCP
  selector:
    v1.min.io/tenant: minio-tenant-1

Console

こちらは MinIO Operator と同時にリリースされた MinIO Console という管理ツールです。

テナントの管理や状態監視をおこなえます。 ログインは同じく admin ユーザを使用します。

ログインすると管理ポータルが表示されます。

apiVersion: v1
kind: Service
metadata:
  namespace: minio-tenant-1
  name: console-loadbalancer
  annotations:
    external-dns.alpha.kubernetes.io/hostname: minio-console.nnstt1.work.    # ExternalDNS 用アノテーション
spec:
  type: LoadBalancer
  ports:
    - name: https-console
      port: 9443
      protocol: TCP
      targetPort: 9443
  selector:
    v1.min.io/console: minio-tenant-1-console

アンインストール

作成したテナントを削除し、MinIO Operator をアンインストールしてみます。

テナント削除も MinIO Operator アンインストールも kubectl minio コマンドを使用します。

テナント

kubectl minio tenant delete で削除するテナントを指定します。 ここで指定する tenant リソースは namespace 毎に作成されるため、-n オプションで対象の namespace を指定してください。

# テナント削除
$ kubectl minio tenant delete minio-tenant-1 -n minio-tenant-1

This will delete the Tenant minio-tenant-1 and ALL its data. Do you want to proceed?: y
Deleting MinIO Tenant minio-tenant-1
Deleting MinIO Tenant Credentials Secret minio-tenant-1-creds-secret
Deleting MinIO Tenant Console Secret minio-tenant-1-console-secret

# namespace 確認
$ kubectl get pods -n minio-tenant-1
No resources found in minio-tenant-1 namespace.
$ kubectl get secret -n minio-tenant-1
NAME                  TYPE                                  DATA   AGE
default-token-swx2m   kubernetes.io/service-account-token   3      2d

MinIO Operator

kubectl minio delete で MinIO Operator がアンインストールされます。

$ kubectl minio delete

Are you sure you want to delete ALL the MinIO Tenants and MinIO Operator?: y
namespace "minio-operator" deleted
serviceaccount "minio-operator" deleted
clusterrole.rbac.authorization.k8s.io "minio-operator-role" deleted
clusterrolebinding.rbac.authorization.k8s.io "minio-operator-binding" deleted
customresourcedefinition.apiextensions.k8s.io "tenants.minio.min.io" deleted
service "operator" deleted
deployment.apps "minio-operator" deleted
serviceaccount "console-sa" deleted
clusterrole.rbac.authorization.k8s.io "console-sa-role" deleted
clusterrolebinding.rbac.authorization.k8s.io "console-sa-binding" deleted
configmap "console-env" deleted
service "console" deleted
deployment.apps "console" deleted

アンインストールはあっさりですね。

おわりに

今回は Amazon S3 互換のオブジェクトストレージ MinIO の オペレータ MinIO Operator を試してみました。

MinIO 自体、Kubernetes にとても簡単にデプロイできるため Operator が活躍する場面はまだ見えてませんが、 そもそも MinIO を使い込んでいないので、色々試してみようと思います。

本来は Operator は簡単にインストールできるのですが、注意点の節でも述べた CSR リソースの件でかなり時間を持っていかれました。 なかなか思うようにできないですね。 だけど、今回の件で CSR リソースのことを注意するようになったのでヨシ!

全然関係ないですが、MinIO のロゴってかっこいいですよね。フラミンゴかな?