MinIOでオブジェクトロック、バージョニング、ライフサイクルを理解するE2E検証

投稿者: | 2月 13, 2025

超大作なエントリ。超大作といえば、「全米が泣いた』なんていう映画広告があるが、20年前、ニューヨークの本社で3ヶ月ほど滞在したことがある。その時、日本にいる上司が「ガーデンシティーのマクドナルドは、全米で一番旨い」と言っていた。その話を現地の台湾人の同僚に話したところ「その人は、全米のマクドナルドを食べ歩いているのですか?」と聞いてきた。いやいや、同じチームの人間で、毎週テレカンで会話しているだろう。マクドナルドの味の報告もないだろうよ。老舗のソフトウェアメーカーにそんな役職はあるわけがないw 「言葉って難しいよね。」と言いつつ、そこに行ったことがある人曰く「外見が確かに美味しそうな建屋だが、出てくるのは普通のマクドナルドですよ」と。今のその店は、とてつもなく普通の外見なので、「全米で一番旨い」わけではない。

 

閑話休題

 

オブジェクトストレージを使っていると、たまに(いや多くが)、ブロックストレージと同じ感じでファイル構成で利用され、保存されていると思っている人がいる。オブジェクトストレージは、ファイルを置くのではなく、あくまでもオブジェクトを置くのが一般的で、必ずしもそのファイル名を見てファイルが想像できるデータを置くとは限らない。もちろん普通のファイル(.txtや.jpeg)を置くこともある。簡単に分けると

 データを置く場合:ファイル名でファイルが想像できるとは限らないデータ、全体データ

 ファイルを置く場合:Webサーバのデータ、1つのファイルとして参照されるデータ(写真共有サービスのjpegファイルなど)

という形になる。また、データをオブジェクトとして、置く場合、シャーディング、パーティショニングの機能を使って、複数のフォルダに分散させることによって、オブジェクトストレージのI/Oを加速させたりする。(この時点で、データが分散しているのでもはやデータを可視化してみることはできない。)

以下にオブジェクトロック、バージョニングを理解するE2Eデモを記載する。デモデータは普通の単一テキストデータだが実際は複数のデータがまるまる適用される。また、MinIOは、事前に構築されているのが前提で、MinIOのサーバがすでにあることを記載している。オブジェクトロックは、保持期間を待たなくても消せるGOVERNANCEモードで行う。COMPLIANCEモードの場合は、API,mcクライアントから消せなくなるので注意。

 

動作環境

Ubuntu Server 22.04 LTS以上あるいはWindows Server 2022以上

  • 2CPU 4GB 50GB HDD (メモリは少なくとも3GB以上)
  • 日付を進める検証があるので、壊してもいい環境で行う。

Windows環境の場合、一部シェルのヒアドキュメントがあるので、それを手入力する必要がある。

サーバとクライアントで環境を分けてもいいが、これらのサーバ構築スクリプトは、自己証明書なので、minioサーバの証明書を.mc/certs/CAにコピーをするか、mc –insecureで実行する必要がある。(わからない、面倒臭いのであれば、1台で行った方がいい。)

 

Linux-MinIO (systemd)での構築

Ubuntu Server 22.04 LTS以降でないと動作しない。

本来ならDockerで起動する方が楽だが、この検証では日付を進める場面があるために、systemd経由でMinIOを起動させる。このスクリプトで必要となる環境が自動的に構築され、起動する。

sudo -i
curl -OL https://gist.githubusercontent.com/masezou/89f254421838b8fece935ee0e589d7fa/raw/b097c38796cbd09cd3a32aa5c7ec493ec27d5c50/minio-linux-ubuntu-systemd-setup.sh
bash ./minio-linux-ubuntu-systemd-setup.sh
exit

# 補完を有効にする
source /etc/bash_completion.d/mc.sh

 

Windowsでの構築

以下をダウンロードして、PowerShllの管理者権限で実行する。

https://gist.githubusercontent.com/masezou/fa8ea7bdfd69b2d41600247716ee8e09/raw/8ebe4c1318796472d39c53d16db7f46cd857aae9/minio-windows-setup.ps1

その際、スクリプト実行前に、以下を実行。

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass 

LinuxでもWindows、どちらの構成でも以下が表示されたらサーバの構築は完了

お手軽スクリプトのMinIOの環境は、必要な設定(ただし、Monitoringの設定は除く)証明書が入っていて登録されている環境。

 

接続情報は

    https://ホストのIPアドレス:9000

    miniologinuser / miniologinuser

GUIは、9001で動いているが今回は利用しない。(単にブラウザに切り替えるのが面倒だから)

 

デモの全体フロー

 1. 管理者 (root) で初期設定

 • バケットを作成し、バージョニングとオブジェクトロックを有効化。

 • MinIO のユーザーを作成し、バケットポリシーを適用。

 2. 作成したユーザー (test-user) で MinIO に接続

 • mc alias set でエイリアスを作成。

 • 以後の操作は新しいエイリアスで行う。

 3. ファイルアップロード & バージョン確認

 • 初回アップロードを行い、バージョン一覧を表示。

 4. ファイル変更 & バージョン確認

 • 再アップロードし、バージョン一覧を表示。

 5. バージョンをロック

 • Governance モードでロックし、ロック情報を確認。

 6. ロック期間中の削除試行

 • ロックされたバージョンを削除しようとし、エラーを確認。

 7. ロック解除後の削除試行

 • ロックを解除し、削除できることを確認。

 8. ライフサイクルポリシーの設定

 • ロック期間が終了した古いバージョンを削除するポリシーを適用。

 9. 自動削除を観察

 • ライフサイクルポリシーの動作を確認。

 10. 容量の確認

 

1. 管理者 (root) で初期設定

(1) MinIO のバケットを作成

# MinIOの管理者ユーザをminioadmin でエイリアス作成
export LOCALIPADDR=$(ip -4 addr show scope global | awk '/inet / {print $2}' | cut -d'/' -f1 | head -n1)
mc alias set minioadmin https://${LOCALIPADDR}:9000 miniologinuser miniologinuser --api s3v4
mc alias list minioadmin
mc ls minioadmin

# オブジェクトロックを有効化したバケットを作成
mc mb minioadmin/versioned-bucket --with-lock
# バージョニングを有効化を確認
mc version info minioadmin/versioned-bucket

(2) MinIO の新しいユーザーを作成

# MinIO ユーザー作成(test-user)
mc admin user add minioadmin test-user testpassword

(3) ユーザーに適用するバケットポリシーを作成

以下のポリシーを作成し、test-user に適用します。

このポリシーは、

✅ versioned-bucket の フルアクセス を test-user に付与するもの。

# ユーザポリシーの作成 (バケット:versioned-bucket)
cat > test-user-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
  {
    "Effect": "Allow",
    "Action": [
"s3:ListAllMyBuckets",
      "s3:ListBucket",
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject",
      "s3:ListBucketVersions",
      "s3:GetObjectVersion",
      "s3:GetBucketObjectLockConfiguration",
      "s3:GetObjectRetention",
      "s3:PutObjectRetention",
      "s3:BypassGovernanceRetention",
      "s3:GetLifecycleConfiguration",
      "s3:PutObjectLegalHold",
      "s3:GetObjectLegalHold"
    ],
    "Resource": [
      "arn:aws:s3:::versioned-bucket",
      "arn:aws:s3:::versioned-bucket/*"
    ],
    "Condition": {
      "IpAddress": {
        "aws:SourceIp": [
          "10.0.0.0/8",
          "172.16.0.0/12",
          "192.168.0.0/16"
        ]
      }
    }
  },
  {
    "Effect": "Allow",
    "Action": [
      "s3:ListBucket",
"s3:ListBucketVersions",
      "s3:GetBucketVersioning",
      "s3:PutBucketVersioning",
      "s3:PutLifecycleConfiguration"
    ],
    "Resource": "arn:aws:s3:::versioned-bucket",
    "Condition": {
      "IpAddress": {
        "aws:SourceIp": [
          "10.0.0.0/8",
          "172.16.0.0/12",
          "192.168.0.0/16"
        ]
      }
    }
  }
]
}
EOF

(4) バケットポリシーを登録して適用

# ユーザポリシーを登録して、test-userにポリシーを適用

mc admin policy create minioadmin test-user-policy test-user-policy.json
mc admin policy attach minioadmin test-user-policy --user test-user
mc admin user info minioadmin test-user

2. 作成したユーザー (test-user) で MinIO に接続

# test-user でmcのエイリアス作成
mc alias set testuser https://${LOCALIPADDR}:9000 test-user testpassword --api s3v4

確認

# mcのエイリアスの確認
mc alias list testuser

✅ 以後の操作は、指示がない限り testuser で実行!

この先は、IAM周りを別途行っておけば、AWS S3や他のS3互換ストレージでも可能なはず。

3. 複数のファイルをアップロード(1度目)

# サンプルファイル作成
echo "File 1 - Version 1" > file1.txt
echo "File 2 - Version 1" > file2.txt

# アップロード
mc cp file1.txt testuser/versioned-bucket/
mc cp file2.txt testuser/versioned-bucket/

mc ls testuser/versioned-bucket/

# バージョン確認
mc du --versions testuser/versioned-bucket/
mc ls --versions testuser/versioned-bucket/
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --versions testuser/versioned-bucket/file2.txt

アップロードしたファイルにそれぞれバージョンがついていることがわかる。

4. ファイル内容を変更して再アップロード(2度目)

# ファイルの内容を変更
echo "File 1 - Version 2" > file1.txt
echo "File 2 - Version 2" > file2.txt

# 再アップロード
mc cp file1.txt testuser/versioned-bucket/
mc cp file2.txt testuser/versioned-bucket/

mc ls testuser/versioned-bucket/

# バージョン確認
mc du --versions testuser/versioned-bucket/
mc ls --versions testuser/versioned-bucket/
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --versions testuser/versioned-bucket/file2.txt

それぞれのファイルに新しいバージョンのファイルができていることがわかる。2つのファイルだが、実際は2つのファイルにそれぞれ2バージョンのファイルが存在している。よって消費している容量も2倍になっている。

5. 個別のファイルに対してバージョンをロック

#file1.txtの2番目にアップロードしたファイルを個別にバージョンをロックしてみる。

VERSION_ID=$(mc ls --versions testuser/versioned-bucket/file1.txt | awk '{print $6}' | head -1)
echo ${VERSION_ID}

どのバージョンIDが指定されたかを確認しておく。

echo ${VERSION_ID}

625f7fd7-10c8-405a-86f2-e709fabac08d

# file1.txt のバージョン情報を取得
mc ls --versions testuser/versioned-bucket/file1.txt

# ロックを設定 
mc retention set governance 1d minioadmin/versioned-bucket/file1.txt

# ロックの確認
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --version-id ${VERSION_ID} testuser/versioned-bucket/file1.txt

6. ロック期間中の個別ファイルの個別バージョンへの削除試行

# バケットのデータ削除
mc rm testuser/versioned-bucket/file1.txt --version-id ${VERSION_ID}

✅ エラーになることを確認

ちなみに、再度データを更新(3回目)をしても、ロックをしているのは特定のバージョンのみだということがわかる。

# ファイルの内容を変更
echo "File 1 - Version 3" > file1.txt
echo "File 2 - Version 3" > file2.txt

# 再アップロード
mc cp file1.txt testuser/versioned-bucket/
mc cp file2.txt testuser/versioned-bucket/

mc ls testuser/versioned-bucket/

# リテンション、バージョンの確認
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --version-id ${VERSION_ID} testuser/versioned-bucket/file1.txt

今度は、ファイルを削除してみる。

# ファイルの削除
mc rm testuser/versioned-bucket/file1.txt
mc rm testuser/versioned-bucket/file2.txt

mc ls testuser/versioned-bucket/

# リテンション、バージョンの確認
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --version-id ${VERSION_ID} testuser/versioned-bucket/file1.txt

削除されてファイルが消えてしまったが、バージョンは残っている。

よく見ると、削除自体もバージョンとして扱われている。

# リテンション、バージョンの確認
mc ls --versions testuser/versioned-bucket/
mc retention info --recursive --versions testuser/versioned-bucket/

 

それぞれのファイルをv2バージョンに戻す。実際はv5バージョンになっている。

v1: 1度目のファイル作成

v2: 2度目のファイル作成

v3: 3度目のファイル作成

v4: 3度目のファイル削除(最新ファイル)

v5: 1度目のファイルにリストア 

mc ls --versions testuser/versioned-bucket/file1.txt
mc cp testuser/versioned-bucket/file1.txt --version-id 625f7fd7-10c8-405a-86f2-e709fabac08d testuser/versioned-bucket/file1.txt
mc ls --versions testuser/versioned-bucket/file2.txt
mc cp testuser/versioned-bucket/file2.txt --version-id aa6e4999-244a-4d43-919b-fdfe63c3fc23 testuser/versioned-bucket/file2.txt

mc ls testuser/versioned-bucket/

# バージョン確認
mc du --versions testuser/versioned-bucket/
mc ls --versions testuser/versioned-bucket/
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --versions testuser/versioned-bucket/file2.txt

 

7. ロック解除後の個別ファイルの個別バージョンへの削除試行

mc retention clear testuser/versioned-bucket/file1.txt --version-id ${VERSION_ID}
mc rm testuser/versioned-bucket/file1.txt --version-id ${VERSION_ID}
mc retention info --recursive --versions testuser/versioned-bucket/
mc ls --versions testuser/versioned-bucket/file1.txt

✅ 削除できることを確認

file1.txtのロックされていたバージョンが消えている。

8. まとめ

MinIOのオブジェクトロックはあくまでも、バージョンのロックをしている。つまり、ストレージのバージョン単位でロック(Immutable)にしている。ある意味、ストレージのスナップショットがあって、そのスナップショットのロックができるとも言える。決して、あるファイルが単に消せなくなっているという意味ではない。また、ファイルのバージョンは、デフォルトだとどんどん残ってしまうので、手動で消し込むか、ライフサイクルで管理する必要がある。

 

以降日付を進める部分があるが、日付を進めるのに待てるのであれば、無理に日付を進める必要はない。また、その場合は、Scannerの設定変更は不要。

 

9. ライフサイクルの確認のために、一旦バケットを一から作り直す

ライフサイクルの確認をしたいので、一度、バケットを消して作り直す。

# バケットの全削除
mc rb minioadmin/versioned-bucket/ --force --dangerous
mc ls minioadmin/

再度バケットを作成する。ただし、今度は、バケット自体にGOVENANCEモードでリテンション1日をつける。

作成したファイルは、自動的にGOVENANCEモードの管理下になる。

#バケットをロック設定にして、GOVERNANCEモード1日にして作成
mc mb minioadmin/versioned-bucket --with-lock
mc retention set --default governance 1d minioadmin/versioned-bucket
mc retention info minioadmin/versioned-bucket
mc version info minioadmin/versioned-bucket

ライフサイクル管理の動作はScannerで行われる。

mc admin scanner info minioadmin

検証のためにScannerの速度を上げる

echo "MINIO_SCANNER_SPEED=fastest" | sudo tee -a /etc/default/minio
sudo systemctl restart minio.service
sudo systemctl status minio.service

常時Scannerが動き始める

mc admin scanner info minioadmin

この検証では日付を進めたいので、chronyを止める。

sudo systemctl stop chrony
sudo systemctl status chrony

10. ライフサイクルポリシーを設定

削除フラグがついてから1日経過したものを削除する。

# ライフサイクルポリシーを設定

mc ilm rule add --noncurrent-expire-days 1  testuser/versioned-bucket
mc ilm rule list testuser/versioned-bucket

11.複数のファイルをアップロード (1日目)

# サンプルファイル作成
echo "File 1 - Version 1" > file1.txt
echo "File 2 - Version 1" > file2.txt

# アップロード
mc cp file1.txt testuser/versioned-bucket/
mc cp file2.txt testuser/versioned-bucket/

mc ls testuser/versioned-bucket/

# バージョン確認
mc du --versions testuser/versioned-bucket/
mc ls --versions testuser/versioned-bucket/
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --versions testuser/versioned-bucket/file2.txt

デフォルトでGOVENANCEモードになっていることがわかる。

日付を1日進める。(2日目へ)

date
sudo date -s "+1 day"
date

12.複数のファイルをアップロード (2日目)

# サンプルファイル作成
echo "File 1 - Version 2" > file1.txt
echo "File 2 - Version 2" > file2.txt

# アップロード
mc cp file1.txt testuser/versioned-bucket/
mc cp file2.txt testuser/versioned-bucket/

mc ls testuser/versioned-bucket/

# バージョン確認
mc du --versions testuser/versioned-bucket/
mc ls --versions testuser/versioned-bucket/
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --versions testuser/versioned-bucket/file2.txt

前日分は期限切れになっている。

日付を1日進める。(3日目へ)

date
sudo date -s "+1 day"
date

13.複数のファイルをアップロード (3日目)

# サンプルファイル作成
echo "File 1 - Version 3" > file1.txt
echo "File 2 - Version 3" > file2.txt

# アップロード
mc cp file1.txt testuser/versioned-bucket/
mc cp file2.txt testuser/versioned-bucket/

mc ls testuser/versioned-bucket/

# バージョン確認
mc du --versions testuser/versioned-bucket/
mc ls --versions testuser/versioned-bucket/
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --versions testuser/versioned-bucket/file2.txt

日付を1日進める。(4日目へ)

date
sudo date -s "+1 day"
date

14.複数のファイルをアップロード (4日目)

# サンプルファイル作成
echo "File 1 - Version 3" > file1.txt
echo "File 2 - Version 3" > file2.txt

# アップロード
mc cp file1.txt testuser/versioned-bucket/
mc cp file2.txt testuser/versioned-bucket/

mc ls testuser/versioned-bucket/

# バージョン確認
mc du --versions testuser/versioned-bucket/
mc ls --versions testuser/versioned-bucket/
mc retention info --recursive --versions testuser/versioned-bucket/
mc stat --versions testuser/versioned-bucket/file1.txt
mc stat --versions testuser/versioned-bucket/file2.txt

1/29のバージョンが消えた。

なぜ2バージョン残るのか?

これではないかと

mc ilm rule add –noncurrent-expire-days 1 を使用していますが、

この設定は「最新バージョンではなく、過去のバージョンにのみ適用」されます。

 

🔹 MinIO の仕様

 • –noncurrent-expire-days 1 は、最新バージョンには適用されない

 • 最新バージョンは GOVERNANCE のまま残る

 • 1 つ前のバージョンが GOVERNANCE EXPIRED になる

 • 2 バージョン(最新 + 1 つ前)が残る状態が継続する

期限切れしたものが、このルール(最新+1つ前)に相当して2バージョン残る。

 

いずれにせよ、実際のMinIOにあるデータは、ライフサイクルで消すか、手動で消すかは必要。保持期限が来たからって、自動で消してくれるわけではない。

 

15.検証のクリーンナップ

 

時間を強制に進めていないのであれば。時間を進めているのであれば、環境ごと消去したほうがいい。

# バケットの削除
mc retention clear testuser/versioned-bucket/ --recursive
mc rb minioadmin testuser/versioned-bucket/ --force --dangerous
# ポリシーとユーザの削除
mc admin policy detach minioadmin test-user-policy --user test-user
mc admin policy remove minioadmin test-user-policy
mc admin user remove minioadmin test-user
# エイリアスの削除
mc alias remove testuser
mc alias remove minioadmin

Scannerの設定を変更しているのであれば、必ず元に戻して、MinIOを再起動しておく。

 

デモの観察ポイント

 1. ✅ test-user のみがバケットを操作できることを確認

 2. ✅ バージョン管理の動作

 • アップロード → バージョン生成 → ロック → ライフサイクルによる削除。

 3. ✅ ロック期間中は削除できないことを確認

 4. ✅ バージョン作成時に一覧を表示

        5. ✅ ロック解除後に削除できることを確認

 6. ✅ ライフサイクルで古いバージョンが削除されることを確認

 • ロック期間終了後、古いバージョンがポリシーによって削除される流れを確認。

 7. ✅ 容量が減少することを確認

 • 古いバージョンが削除されることで容量が減少する様子を確認。

 

ここまで理解できるとオブジェクトストレージのリテンションが使いやすくなる。あと、mcコマンドは、手元の端末に絶対入れておいた方がいいこともわかる。どういうわけだか、MinIOっていうと敬遠する人が多い(自分の周りだけかもしれないが)が、便利なものは便利として入れておくべきだと思う。

コメントを残す