超大作なエントリ。超大作といえば、「全米が泣いた』なんていう映画広告があるが、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の管理者権限で実行する。
その際、スクリプト実行前に、以下を実行。
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っていうと敬遠する人が多い(自分の周りだけかもしれないが)が、便利なものは便利として入れておくべきだと思う。