mcコマンドを搭載したminio-toolboxメンテナンスコンテナの作成

# はじめに

オンプレなローカルのkubernetesクラスターではRook/Cephを通してBlock StorageやFilesystemを利用しています。Object Storageについては、Rook側に少し問題があった経緯もあってminioを常用しています。

久し振りに新規でk8sクラスターを構築したので、これまで利用していた Helm chart, stable/minio, は削除し、新規にMinio公式のHelm chartを利用してサーバーを構築しました。

以下の環境に合わせて、全面的に内容を見直しています。

* kubernetes v1.25.6 (by kubespray v2.21.0)
* rook v1.11.8 (ceph v17.2.6) 
* helm chart, minio/minio v5.0.11

## 利用スタイル

各利用者はOIDCからTokenを得て、個々のnamespace内で作業をします。

原則として1ユーザーが利用できるObject Storageは1つで、"<username>-bucket"という命名規則に従います。

このObject Storeへは各ユーザーだけがアクセスできるよう、個別にアクセス情報(access-key, secret-access-key)を作成し、Secretオブジェクトとして提供します。

この記事では、各ユーザー毎のBucket・接続情報の登録をバッチ的に処理できるようなスクリプトと、ユーザーが検証できるようmcコマンドやpythonスクリプトからMinioを利用する方法などを紹介しています。

# 参考資料

* [https://qiita.com/iaoiui/items/cf405099ccc483a05db4](https://qiita.com/iaoiui/items/cf405099ccc483a05db4)
* [https://helm.sh/blog/new-location-stable-incubator-charts/](https://helm.sh/blog/new-location-stable-incubator-charts/)
* [https://hub.docker.com/r/yasuhiroabe/minio-toolbox](https://hub.docker.com/r/yasuhiroabe/minio-toolbox)
* [https://github.com/YasuhiroABE/docker-minio-toolbox](https://github.com/YasuhiroABE/docker-minio-toolbox)

# 準備作業

作業手順の記録のためにMakefileを準備します。

```makefile:Makefile
NAME = minio
REL_NAME = my-minio
REPO_URL = https://charts.min.io/

CHART_PATH = minio/minio
VALUES_YAML = values.yaml

init:
  sudo kubectl create ns $(NAME)

setup-repo:
  sudo helm repo add $(NAME) $(REPO_URL)

list:
  sudo helm repo list

update:
  sudo helm repo update $(NAME)

fetch:
  sudo helm fetch $(CHART_PATH)

install:
  (cd $(NAME) ; sudo helm install $(REL_NAME) --debug --namespace $(NAME) -f $(VALUES_YAML) . )

upgrade:
  (cd $(NAME) ; sudo helm upgrade $(REL_NAME) --debug --namespace $(NAME)  -f $(VALUES_YAML) . )

delete:
  sudo helm delete --namespace $(NAME) $(REL_NAME)

delete-ns:
  sudo kubectl delete ns $(NAME)

extract-keys:
   sudo kubectl -n $(NAME) get secret $(REL_NAME) -o jsonpath='{.data.rootUser}' | base64 -d  && echo
   sudo kubectl -n $(NAME) get secret $(REL_NAME) -o jsonpath='{.data.rootPassword}' | base64 -d  && echo
```

Makefileを使って、repoの登録、tar.gzファイルの取得・展開などを進めます。

```bash:makeコマンドによる準備作業
## repoの追加
$ make setup-repo

## namespaceの作成
$ make init

## chartの入手
$ make fetch

## tar.gzファイルの展開
$ ls
Makefile  minio-5.0.11.tgz
$ tar xvzf minio-5.0.11.tgz
```

ここで、./minio/ディレクトリが出来ているはずです。

# minio/values.yamlの編集

まず minio/values.yamlを編集します。

作業前にgitで初期状態を記録しておきます。

```bash
$ cd minio
$ git init
$ git add .
$ git commit -m 'initial commit'
$ vi values.yaml
```

minio/values.yamlの編集部分は次のようになっています。

```diff:values.yamlのdiff出力結果
diff --git a/values.yaml b/values.yaml
index 6657662..5a68579 100644
--- a/values.yaml
+++ b/values.yaml
@@ -114,7 +114,7 @@ bucketRoot: ""
 # Number of drives attached to a node
 drivesPerNode: 1
 # Number of MinIO containers running
-replicas: 16
+replicas: 4
 # Number of expanded MinIO clusters
 pools: 1
 
@@ -158,7 +158,7 @@ persistence:
   ##
   ## Storage class of PV to bind. By default it looks for standard storage class.
   ## If the PV uses a different storage class, specify that here.
-  storageClass: ""
+  storageClass: "rook-ceph-block"
   VolumeName: ""
   accessMode: ReadWriteOnce
   size: 500Gi
@@ -259,7 +259,7 @@ podLabels: {}
 ##
 resources:
   requests:
-    memory: 16Gi
+    memory: 4Gi
 
 ## List of policies to be created after minio install
 ##
```

続いて導入作業を実施します。

```bash:makeコマンドによるhelmのインストール
$ make install
```

まだ確認できませんが、これでminioが動作しているはずです。

# 稼動確認

以前の記事では、mcコマンドを使ってネットワーク越しにアクセスしていました。

今回の環境はClusterIPを使っていて、LBでの接続は許可していません。

一時的であればLB用のServiceオブジェクトを定義してブラウザから作業するなどしていますが、基本的にはKubernetes内部からのアセクスしか許可したくないので稼動確認に工夫が必要です。

mcコマンドのdockerイメージは存在するもののコマンドとして利用することが前提でKubernetesのネットワークにアクセスすることはできません。これをサーバーとして稼動させるため、busybox+mcコマンドのようなコンテナがないか探したところ、[Toolbox Container Image](https://github.com/noseka1/toolbox-container) が公開されていたので、このコンセプトを参考にmcコマンドを実行するためのサーバーコンテナを作成していきます。

## mcコマンドを搭載したminio-toolboxコンテナの作成

次のようなDockerfileを現在では利用しています。

```dockerfile:Dockerfile
FROM alpine:3.18.2

ARG TARGETOS
ARG TARGETARCH

RUN apk add --no-cache tzdata bash ca-certificates busybox openssl git

WORKDIR /app
RUN wget https://dl.min.io/client/mc/release/${TARGETOS:-linux}-${TARGETARCH:-adm64}/mc
RUN chmod +x mc
COPY ./app /app
RUN chmod +x gen-template.sh

ENV DATADIR /root

CMD ["sh"]
```

最新のコンテナはDocker Hubに登録しています。

* [https://hub.docker.com/r/yasuhiroabe/minio-toolbox](https://hub.docker.com/r/yasuhiroabe/minio-toolbox)

コードはGitHubに登録しています。
GitHubにはKubernetes上で実行するYAMLファイルなども含まれています。

* [https://github.com/YasuhiroABE/docker-minio-toolbox](https://github.com/YasuhiroABE/docker-minio-toolbox)

最近はmacOSでの稼動機会も増えてきたので、arm64版も登録しています。

## namespace/minio-client で minio-toolbox を動かす

helmで構成したminioサーバーは、namespace/minioに存在しています。

NetworkPolicyによる通信制限はしていないため、別のnamespace(minio-client)に配置したminio-toolboxコンテナから接続させています。

まず作成するbucket情報などを保存するPVCを定義します。

```yaml:pvc-minio-client.yaml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-pvc
  namespace: minio-client
spec:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: rook-ceph-block
  resources:
    requests:
      storage: 1Gi
```

次にmcコマンドなどが入っている、minio-toolboxを稼動させます。

```yaml:deploy-minio-client.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: minio-toolbox
  labels:
    app: minio-toolbox
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: minio-toolbox
  template:
    metadata:
      labels:
        app: minio-toolbox
    spec:
      containers:
      - name: minio-toolbox
        image: yasuhiroabe/minio-toolbox:1.0.5
        command: ["sh","-c", "tail -f /dev/null"]
        imagePullPolicy: "Always"
        volumeMounts:
        - name: data
          mountPath: /root
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: data-pvc
```

このYAMLファイルを適用して、podを立ち上げます。

```bash:kubectlコマンドによる構成
$ sudo kubectl create ns minio-client
$ sudo kubectl -n minio-client apply -f pvc-minio-client.yaml
$ sudo kubectl -n minio-client apply -f deploy-minio-client.yaml
$ sudo kubectl -n minio-client get all

NAME                                 READY   STATUS    RESTARTS   AGE
pod/minio-toolbox-6dc6798759-r9dcn   1/1     Running   0          5h17m

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/minio-toolbox   1/1     1            1           5h17m

NAME                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/minio-toolbox-6dc6798759   1         1         1       5h17m
```

ここまでで準備作業は終わりです。

## minio-client (container-toolbox)の利用

このPodの内部に入って、mcコマンドを実行していきます。

namespaceなどの条件が同じであれば、次のようなコマンドラインをコピーして実行することで、コンテナに移動することができます。

```bash:execコマンドによる内部への移動
$ sudo kubectl -n minio-client exec -it $(sudo kubectl -n minio-client get pod -l app=minio-toolbox -o=jsonpath='{.items[0].metadata.name}') -- bash
```

内部には直下にmcコマンドなどが配置してありますので、次の要領で稼動確認ができます。

```bash:mcコマンドの稼動確認
minio-toolbox-c65b78d9b-z79d7:/app# ./mc --version
mc version RELEASE.2023-07-07T05-25-51Z (commit-id=1b992864ee0682b8be6a590ccbda080475dcadd3)
Runtime: go1.19.10 linux/amd64
Copyright (c) 2015-2023 MinIO, Inc.
License GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>
```

# mcコマンドによる初期設定

mcコマンドを利用してminioサーバーを操作する時の基本的な手順は次のとおりです。

1. ~/.mc/config.json にminioサーバーへの接続情報を登録 (初回のみ)
2. ユーザーの登録
3. ポリシーの登録
4. Bucketの作成

ここではラベル"my-minio-local"に、minioサーバーへの接続情報を登録します。

これらの情報は ~/.mc/config.json に保存されています。

* [https://min.io/docs/minio/linux/reference/minio-mc.html](https://min.io/docs/minio/linux/reference/minio-mc.html)

## 接続情報の確認

minioサーバーのFQDNはhelmでこの指示どおりに導入した場合 **my-minio-svc.minio.svc.cluster.local** で、ポート番号は **9000** 番です。

この他に必要なaccess-keyとsecret-keyは namespace/minio のSecretオブジェクトを確認します。

別の端末(shell)から、次のようなコマンドを実行し、rootUser, rootPassword の情報を確認します。

```bash:access-keyなどの確認
$ sudo kubectl -n minio get secret my-minio -o jsonpath='{.data.rootUser}' | base64 -d  && echo
$ sudo kubectl -n minio get secret my-minio -o jsonpath='{.data.rootPassword}' | base64 -d  && echo
```

このコマンドはMakefile中に"extract-keys"タスクとして登録しています。

rootUserがaccess-key、 rootPasswordがsecret-keyに対応します。

## mcコマンドによる稼動確認

再びPodに戻り、./mcコマンドを実行していきます。

```bash:k8sクラスター外にあるUbuntuから実行
minio-toolbox-c65b78d9b-z79d7:/app# ./mc config host add my-minio-local http://my-minio-svc.minio.svc.cluster.local:9000 <access-key> <secret-key> --api S3v4
Added `my-minio-local` successfully.
```

以降は~/.mc/config.jsonを参照するため、URL等の指定は不要です。
何かURLを間違ったなどの問題は、直接 ~/.mc/config.json を修正することもできます。

```bash:
minio-toolbox-c65b78d9b-z79d7:/app# ./mc ls my-minio-local
minio-toolbox-c65b78d9b-z79d7:/app# ./mc mb my-minio-local/test
Bucket created successfully `my-minio-local/test`.
minio-toolbox-c65b78d9b-z79d7:/app# ./mc cp /etc/hosts my-minoi-local/test
/etc/hosts:        340 B / 340 B ━━━━━━━━━━━━ 140.88 KiB/s 0s
minio-toolbox-c65b78d9b-z79d7:/app# ./mc ls my-minio-local/test -r
[2022-09-01 08:51:17 UTC]   227B STANDARD hosts
```

## ユーザー毎のアクセス権限の付与

利用するユーザー毎に利用できるbucketを準備するために、minio-toolboxには *gen-template.sh* を配置しています。

これは、ユーザー名をキーとして、"${username}-bucket" オブジェクトを作成し、必要な権限を一括して付与するスクリプトです。

スクリプト内部ではユーザー毎に権限を定義するjsonファイルを生成するためのテンプレートを利用しています。

```json:user-bucket-policy-_USER_ID_.json 
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "s3:*"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::_USER_ID_-bucket/*"
      ],
      "Sid": ""
    }
  ]
}
```

引数にユーザー名のリストを取り、"${username}-bucket"形式のbucketを作成し、そのbucketに接続するためのaccess-key, secret-key情報を登録します。

```bash:gen-template.sh
#!/bin/bash

## Usage: ./gen-template.sh $(cat member.list)

BASEDIR=$(dirname $(readlink -f $0))
OUTPUT_DIRNAME="$(date +%Y%m%d.%H%M%S)"
OUTPUTDIR="${DATADIR:-/root}/${OUTPUT_DIRNAME}"

MC_CMD="${BASEDIR}/mc"
MINIO_TARGET=${MINIO_TARGET:-my-minio-local}

## template filepath from ${OUTPUTDIR}
TEMPLPATH1="${BASEDIR}/user-bucket-policy-_USER_ID_.json"

## check the .mc/config file.
if test ! -f ~/.mc/config.json || test "$(grep ${MINIO_TARGET} ~/.mc/config.json >/dev/null)" == "1" ; then
  echo "Usage: Please setup the ~/.mc/config file, using the following command line."
  echo "  ./mc config host add my-minio-local http://my-minio.minio:9000 <root-access-key> <root-password> --api S3v4"
fi

## prepare outputdir and cd to it.
mkdir -p "${OUTPUTDIR}"
cd "${OUTPUTDIR}"

for username in $@
do
    ## check existing bucket
    ${MC_CMD} ls "${MINIO_TARGET}/${username}-bucket"
    test "$?" == "0" && echo "[skip] bucket, ${username}-bucket, exists" && continue

    ## prepare the template file
    OUTPUT_FILENAME=$(basename "${TEMPLPATH1}" | sed -e "s/_USER_ID_/${username}/g")
    sed -e "s/_USER_ID_/${username}/g" "${TEMPLPATH1}" > "${OUTPUT_FILENAME}"

    ## adding minio user and policy
    ACCESS_KEY="$(openssl rand -hex 8)"
    SECRET_KEY="$(openssl rand -hex 16)"
    ${MC_CMD} admin policy create "${MINIO_TARGET}" "readwrite-${username}" "${OUTPUT_FILENAME}"
    test "$?" == "0" && ${MC_CMD} admin user add "${MINIO_TARGET}" "${ACCESS_KEY}" "${SECRET_KEY}"
    test "$?" == "0" && ${MC_CMD} admin policy attach "${MINIO_TARGET}" "readwrite-${username}" --user "${ACCESS_KEY}"
    echo "${username},${ACCESS_KEY},${SECRET_KEY}" >> "../${OUTPUT_DIRNAME}.txt"

    ${MC_CMD} mb "${MINIO_TARGET}/${username}-bucket"
done
```

コマンドを実行すると、環境変数DATADIR(default: /root/)で指定したディレクトリの直下に"日付.時刻"形式のサブディレクトリが作成され、jsonファイルが保存されます。"日付.時刻".txtファイルにユーザー毎のaccess_key, secret_keyを記録したファイルが生成されます。

```bash:実行例
$ env MINIO_TARGET="my-minio-local" ./gen-template.sh user01 usre02
...

$ cat /root/20230712.050838.txt
user01,a82e1cfd6e6166f7,e53d91c7887e92174408917a553f14bd
user02,5685c31ba389058d,f9fe1aa2eba7d7a7536575e23de987f4
```

この接続情報を利用してユーザーアプリケーションからの接続確認

```bash:user01の接続情報を利用したmcコマンドの利用
$  ./mc config host add my-minio-local http://my-minio-svc.minio.svc.cluster.local:9000  a82e1cfd6e6166f7 e53d91c7887e92174408917a553f14bd --api S3v4

## user01-bucketへはアクセスできる
$ ./mc ls my-minio-local/user01-bucket

## user02-bucketへのアクセスは拒絶
$ ./mc ls my-minio-local/user02-bucket
mc: <ERROR> Unable to list folder. Access Denied.

## user01-bucketへのアクセスは問題なくできる
$ ./mc ls my-minio-local/user01-bucket
$ ./mc cp gen-template.sh my-minio-local/user01-bucket
$ ./mc ls my-minio-local/user01-bucket
[2022-09-01 15:18:53 UTC] 1.2KiB STANDARD gen-template.sh
```

実際にはユーザーはアプリケーションの中でminioクライアントや、S3互換クライアントを利用して接続すると思いますので、このaccess_key, secret_keyの利用方法が分かれば良いことになります。

## 各ユーザーにaccess_key, secret_keyを通知する

次に管理者権限でkubectlを実行できる端末に移動します。

前提としている環境では、各ユーザーは同名のnamespaceに所属していて、OIDCによって個別に認証されています。

まずnamespace毎に secret/objectstore を作成し、bucketに接続するために必要な情報を格納していきます。

先ほどのコマンドで、"日付".txt ファイルが生成されているので、その情報を使って、ユーザーの毎namespaceにSecretオブジェクトを配置します。

kubectlが実行できる環境の適当なディレクトリに、次のようなスクリプトを実行します。

```bash:store-passwd-to-namespace.sh
#!/bin/bash

## Usage: ./store-passwd-to-namespace.sh < some.keys
## Format: The input literal should be as follows:
##
##   namespace,access-key,secret-access-key
##

for line in $(cat -)
do
  ns=$(echo $line | cut -d, -f1)
  akey=$(echo $line | cut -d, -f2)
  skey=$(echo $line | cut -d, -f3)
  ip="my-minio-svc.minio.svc.cluster.local:9000"  
  host="my-minio-svc.minio.svc.cluster.local"

  sudo kubectl -n $ns create secret generic objectstore --from-literal=secret-access-key=$skey --from-literal=access-key=$akey --from-literal=aws-host="${host}" --from-literal=aws-ip="${ip}"
done
```

各ユーザーが自分の情報を知りたい場合には次のようなコマンドで各値を読み出す事が可能です。

```bash:kubectlによるsecretの読み込み($nsは自身のnamespaceを指す)
$ kubectl -n $ns get secret objectstore -o=jsonpath="{.items[0]}{.data.access-key}" | base64 --decode ; echo
$ kubectl -n $ns get secret objectstore -o=jsonpath="{.items[0]}{.data.secret-access-key}" | base64 --decode ; echo
```

これらの情報を利用してMinioにデータを保存することが可能になります。

# ユーザーによる作成したObject Storeの利用

先ほどはnamespace/minio-clusterにpod/minio-toolboxを作成しましたが、同様に自分のnamespaceで、minio-toolboxを稼動させることもできます。

この場合は先ほどと同じように操作が可能です。

もう少し現実的な、pythonのminioライブラリを使ったサンプルを載せておきます。

## Pythonの準備作業

venvを利用して適当な作業用ディレクトリで、次のようなコマンドを実行します。

```bash:pythonのvenv環境の構築
$ python3 -m venv venv/minio
$ . venv/minio/bin/activate
(minio) $ 
```

Promptが変化すれば準備は完了です。
この状態で、次のようなrequirements.txtファイルを準備します。

```python:requirements.txt
environs==9.5.0
minio==7.1.15
```

venv/minio以下にminioライブラリをダウンロードします。

```bash:
(venv) $ pip install -r requirements.txt
```

run.pyファイルに次のようなPythonコードを準備しておきます。

```python:run.py
#!/usr/bin/python

import io
from minio import Minio
from environs import Env
env = Env()
env.read_env()

MINIO_ENDPOINT_SECURITY = env.bool('MINIO_ENDPOINT_SECURITY', False)
MINIO_ENDPOINT = env.str('MINIO_ENDPOINT', '')
MINIO_ACCESS_KEY = env.str('MINIO_ACCESS_KEY', '')
MINIO_SECRET_KEY = env.str('MINIO_SECRET_KEY', '')
MINIO_BUCKET = env.str('MINIO_BUCKET', 'my-minio-local')

client = Minio(MINIO_ENDPOINT,
               access_key=MINIO_ACCESS_KEY,
               secret_key=MINIO_SECRET_KEY,
               secure=MINIO_ENDPOINT_SECURITY,)

message = "Helo world!"

client.put_object(MINIO_BUCKET, "my/message.txt",
                  io.BytesIO(message), length=len(message),)
```

## Dockerコンテナの作成と登録

これを次のようなDockerfileを利用してまとめます。

```dockerfile:Dockerfile
FROM python:3.10.12-alpine3.18

ENV PYTHONUNBUFFERED=1 \
    PIP_NO_CACHE_DIR=off \
    PORT=8000

RUN apk add --no-cache tzdata bash ca-certificates

WORKDIR /app

RUN addgroup minio
RUN adduser -S -G minio minio
RUN chown minio:minio /app
USER minio

RUN python -m venv venv
ENV PATH=/app/venv/bin/:$PATH

# Install the project requirements.
COPY requirements.txt /app
RUN pip install -r /app/requirements.txt

COPY run.py /app

ENV MINIO_ENDPOINT "minio.minio.svc.cluster.local:9000"
ENV MINIO_ENDPOINT_SECURITY "False"
ENV MINIO_ACCESS_KEY ""
ENV MINIO_SECRET_KEY ""
ENV MINIO_BUCKET ""

ENTRYPOINT ["python", "run.py"]
```

DockerHubやharborなどの適当なリポジトリに登録しておきます。

```bash:dockerHubへの登録例
$ sudo docker build . --tag minio-sample:1.0.0 --no-cache 
$ sudo docker tag minio-sample:1.0.0 docker.io/yasuhiroabe/minio-sample:1.0.0       
$ sudo docker push docker.io/yasuhiroabe/minio-sample:1.0.0
```

## 配置したサンプルの実行

ここでは、docker.io/yasuhiroabe/minio-sample:1.0.0 を使って、動作を確認していきます。
自分のリポジトリに登録した場合は、適宜読み替えてください。

Kubernetes上で、minio-sample:1.0.0を動作させるため、Deploymentオブジェクトを作成します。
この時にsecretオブジェクトから環境変数に必要な値をコピーします。

```yaml:deployment-minio-sample.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: minio-sample
  labels:
    app: minio-sample
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: minio-sample
  template:
    metadata:
      labels:
        app: minio-sample
    spec:
      containers:
      - name: minio-sample
        image: yasuhiroabe/minio-python-sample:1.0.0
        command: ["sh","-c", "tail -f /dev/null"]
        imagePullPolicy: "Always"
        env:
        - name: MINIO_BUCKET
          value: "user01-bucket"
        - name: MINIO_ACCESS_KEY
          valueFrom:
            secretKeyRef:
              name: objectstore
              key: access-key
        - name: MINIO_SECRET_KEY
          valueFrom:
            secretKeyRef:
              name: objectstore
              key: secret-access-key
        - name: MINIO_ENDPOINT
          valueFrom:
            secretKeyRef:
              name: objectstore
              key: aws-ip
```

このPodを作成し、中に入って、run.py を実行します。

## 作成したmessage.txtの確認

pod/minio-sampleからpod/minio-toolboxに移動し、Bucket上にメッセージが保存されているか確認します。

```bash:
$ sudo kubectl exec -it minio-toolbox-79d8bf654f-7hkjf -- sh

/app # ./mc ls my-minio-local/user01-bucket/
[2022-09-01 15:18:53 UTC] 1.2KiB STANDARD gen-template.sh
[2022-09-01 22:13:20 UTC]     0B my/

/app # ./mc ls my-minio-local/user01-bucket/my/message.txt
[2022-09-01 22:12:24 UTC]    11B STANDARD message.txt

/app # ./mc cp my-minio-local/user01-bucket/my/message.txt .
.../my/message.txt: 11 B / 11 B ━━━━━━━━━━━━━━━━━━━ 244 B/s 0s

/app # cat message.txt 
Hello world!
```

ここまでで、任意のBucketの作成、個別の接続情報の登録などが行えるようになりました。

# 作成した情報の削除

作成したuser, policy, bucketを削除する手順は以下のとおり

```bash:user01を削除する場合の操作例
## bucketの削除
$ ./mc rb my-minio-local/user01-bucket

## policyの削除
$ ./mc admin policy remove my-minio-local readwrite-user01

## access_keyを調べて不要なものを削除する
$ ./mc admin user list my-minio-local
$ ./mc admin user info my-minio-local 833ff7c0ac494849
$ ./mc admin user remove my-minio-local 833ff7c0ac494849
```

usre01などの情報は、bucket名とnamespaceとして参照していますが、実際に接続に使用されるID, Passwordに相当する情報は乱数なので、``./mc admin user list <bucket name>`` で接続情報のリストを確認して使われていない接続情報は削除する必要があります。

なお手元の環境では次のようになっていて、検証のために繰り返しスクリプトを実行したタイミングで重複した接続情報が登録されている様子が分かります。

```bash:
/app # ./mc admin user list my-minio-local
enabled    0443140359ee8cbb      readwrite-yasu-abe  
enabled    5685c31ba389058d      readwrite-user02    
enabled    8dca9cae82b2be30      readwrite-user01    
enabled    a82e1cfd6e6166f7      readwrite-user01    
enabled    console               consoleAdmin        
enabled    d184179c6a94a34a      readwrite-user02   
```

# さいごに

2022年頃からmcコマンドのいくつかのオプションがOBSOLETED扱いになっていて、以前のスクリプトが動作しない現象に遭遇しました。

またminioサーバーも、作成したユーザーをpolicyにattachしようとして失敗する事例にも遭遇しました。

システムを更新するタイミングで、Helmで stable/minio repo を使っていた古いクラスターは削除して、公式ドキュメントに掲載されている手順から minio/minio repo を利用して最新のバージョンに切り替えました。

まだObject Storageの利用は限定的なので、一時的にバックアップを取ったりして楽に移行できるので良いですが、長く使ったminioクラスターをメンテナンスしていくかは難しい問題になるかもしれません。

多くのユーザーが共同利用するようなクラスターで、ユーザー毎にBUCKET、ユーザー、ポリシーを個別に作成するこの実装が参考になれば幸いです。

以上