Longhornのディスクを利用するMinio S3をセットアップ
MinIO is an object storage solution that provides an Amazon Web Services S3-compatible API and supports all core S3 features.
今回はオンプレミスのKubernetesクラスタ上で構築できるS3サービス、Minioをセットアップしてきます。
こちらはおうちラボ用の構築となります。複数のディスクや複数のノードで完璧なレプリケーションやバックアップを備えたS3サービスを用意するのではなく、個人利用で満足のいく、ごく簡単なものをセットアップしていきます。
これまでの流れ
- Control plane x3, worker x3のKubernetesクラスタ構築
- GitOpsのセットアップ(GitLab, fluxcd, sops)
- flux-system, infra-controllers, infra-configs, sops, appsにflux kustomizationを分けてセットアップ
- Cilium L2Announcement & Gateway + cert-managerでクラスタ外からもKubernetes上のサービスへ簡単webアクセス
- Longhornのセットアップ、storage classよりdynamic volume provisioning
今回やること
- Longhorn上でS3用に利用するディスクにタグ付け
- タグ付けされたディスクからvolume provisioningするstorage classを別途作成
- (fluxcd, HelmRepository & HelmReleaseで) minio-operatorインストール
- minio-tenantもインストール
- minio-tenantのダッシュボードおよびS3サービスへのアクセスをcilium gateway & cert-managerで用意
- できたものをお試し
ドキュメント
https://min.io/docs/minio/kubernetes/upstream/index.html
デプロイメントチェックリスト
公式ドキュメントにハードウェア、セキュリティ、ソフトウェアの観点で推奨環境を記載したチェックリストがあります。プロダクションレディなものを用意するならば、という時に参考になります。
https://min.io/docs/minio/kubernetes/upstream/operations/checklists.html
いくつか条件満たした状態で構築を進めることにはなりますが、おうちラボでの構築なので基本的に最小構成でやっていきます。
Longhornシステムに載せたディスク
先のポストでworkerノードに用意した追加ディスクを利用する形でセットアップしていきます。
- lab-worker2 with 80GB disk
- lab-worker3 with 80GB disk
Longhorn上のディスク利用に関連して
- "xfs"タグをlab-worker2, lab-worker3上の追加したディスクへセット
- 推奨に沿う形で個別のstorage classを作成
- 全ノード、全ディスクをschedule状態へ戻す (Minio S3テナントでは利用されませんが今後ほかのstorage classで利用するために)
Additionally, MinIO recommends setting a reclaim policy of Retain for the PVC StorageClass. Where possible, configure the Storage Class, CSI, or other provisioner underlying the PV to format volumes as XFS to ensure best performance.
作成するstorage classはこちらとなります。
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-xfs
parameters:
staleReplicaTimeout: "30"
diskSelector: xfs
fsType: xfs
provisioner: driver.longhorn.io
reclaimPolicy: Retain
volumeBindingMode: Immediate
allowVolumeExpansion: true
Minioのインストール
Helmチャートでminio-operatorとminio-tenantをインストールしていきます。
MinIO is a Kubernetes-native high performance object store with an S3-compatible API. The MinIO Kubernetes Operator supports deploying MinIO Tenants onto private and public cloud infrastructures (“Hybrid” Cloud).
The MinIO Operator installs a Custom Resource Definition (CRD) to support describing MinIO tenants as a Kubernetes object.
オペレータはKubernetesクラスタ上にMinioオブジェクトストレージを簡単にデプロイ、管理、運用するためのツールです。テナントが実際のS3互換オブジェクトストレージサービスを提供するインスタンスとなります。
infra-controllers flux kustomization に minio-operator をインストールし、インフラストラクチャ用に infra-configs flux kustomization に1つの minio-tenant をインストールします。後でアプリ用に別のMinioテナントを立ち上げる可能性も考慮して、このテナントを "infra-tenant" と命名します。ただおうちラボなので結局このテナント一つで全部やってしまう気はしますが!
minio-operator
Helmレポジトリを追加してその時点で最新のバージョンを確認します。
# add the repository
helm repo add minio-operator https://operator.min.io
# update helm repository whenever needed
# helm repo update
# see the latest version
helm search repo minio-operator/operator
# do not use the legacy minio-operator chart
operatorチャートのvaluesファイルをコピーし、編集します。Kubernetesクラスタのドメイン名と、イメージ取得元をおうちラボ内のHarborレジストリに変更、そしてreplica数を1にしています。
# on gitops repo
cd ./infrastructure/lab-hlv3/controllers/default-values
helm show values --version 7.0.1 minio-operator/operator > minio-operator-7.0.1-values.yaml
cp minio-operator-7.0.1-values.yaml ../values/minio-operator-values.yaml
# edit minio-operator-values.yaml file
Valuesファイルが用意出来たら、flux用のhelmrepo, helmreleaseマニフェストを生成します。バージョンの変更、valuesファイルへの更新がある度に簡単に再生成できるよう、いつもスクリプトを用意してマニフェスト生成をしています。
大雑把に、ディレクトリはこのような感じです。
-
./infrastructure/lab-hlv3/controllers/
# flux infra-controllers kustomization points here-
kustomization.yaml
# kubernetes kustomization -
minio-operator.yaml
# product flux helmrepo & helmrelease manifests file to be added to the k8s ks above -
values/minio-operator-values.yaml
# values file scripts/minio-operator.sh
-
スクリプトはこちらです。
#!/bin/bash
# add flux helmrepo to the manifest
flux create source helm minio-operator \
--url=https://operator.min.io \
--interval=1h0m0s \
--export >../minio-operator.yaml
# add flux helm release to the manifest including the customized values.yaml file
flux create helmrelease minio-operator \
--interval=10m \
--target-namespace=minio-operator \
--source=HelmRepository/minio-operator \
--chart=operator \
--chart-version=7.0.1 \
--values=../values/minio-operator-values.yaml \
--export >>../minio-operator.yaml
最後に、infra-controllers kustomizationを更新してfluxに渡す前に、minio-operator namespaceを別途作っておきます。こちらは私の場合、flux-system kustomizationの方に (./clusters/lab-hlv3/namespaces/minio-operator.yaml
に)ファイルを用意するようにしています。
flux tree ks infra-controllers
インストール後のflux tree
の出力の一部です。
# flux tree ks infra-controllers
├── HelmRelease/flux-system/minio-operator
│ ├── ServiceAccount/minio-operator/minio-operator
│ ├── CustomResourceDefinition/tenants.minio.min.io
│ ├── CustomResourceDefinition/policybindings.sts.min.io
│ ├── ClusterRole/minio-operator-role
│ ├── ClusterRoleBinding/minio-operator-binding
│ ├── Service/minio-operator/operator
│ ├── Service/minio-operator/sts
│ └── Deployment/minio-operator/minio-operator
minio-tenant
手順はオペレータと同様です。chartは先に追加したレポジトリに一緒に入っています。
# add the repository
# helm repo add minio-operator https://operator.min.io
# update helm repository whenever needed
# helm repo update
# see the latest version
helm search repo minio-operator/tenant
Valuesファイルをコピーし、編集します。
# on gitops repo
cd ./infrastructure/lab-hlv3/controllers/default-values
helm show values --version 7.0.1 minio-operator/tenant > minio-tenant-7.0.1-values.yaml
cp minio-tenant-7.0.1-values.yaml ../values/minio-tenant-values.yaml
# edit minio-tenant-values.yaml file
flux helmrepoマニフェストはオペレータ導入時に作成済みなので、テナント追加時にはflux helmreleaseマニフェストだけ生成していくことになります。
そしてテナントはinfra-configsより導入することにしています。今後テナントを追加するたびに、以下の流れで必要なファイルを増やしていくことになる予定です。
- namespace
./clusters/lab-hlv3/namespaces/minio-TENANT_NAME.yaml
- or... you could share one namespace for all tenants
- helm chart values file
./infrastructure/lab-hlv3/configs/values/minio-TENANT_NAME-values.yaml
- script to run
flux create helmrelease
to generate manifest./infrastructure/lab-hlv3/configs/scripts/minio-TENANT_NAME.sh
- generated flux helmrelease manifest file
./infrastructure/lab-hlv3/configs/minio-tenant/TENANT_NAME.yaml
#!/bin/bash
# add flux helm release to the manifest including the customized values.yaml file
flux create helmrelease minio-infra-tenant \
--interval=10m \
--target-namespace=minio-infra-tenant \
--source=HelmRepository/minio-operator \
--chart=tenant \
--chart-version=7.0.1 \
--values=../values/minio-infra-tenant-values.yaml \
--export >../minio-tenant/infra-tenant.yaml
infra-tenant用のminio-tenantチャートのvaluesファイル
Valuesファイルの変更点は次の通りです。
- tenant
- name: infra-tenant
- configuration
- name: infra-tenant-env-configuration
- configSecret:
name: infra-tenant-env-configuration
accessKey: (空白にしておく)
secretKey: (空白にしておく)
existingSecret: true - pools:
- servers: 1
- volumesPerServer: 1
- size: 60Gi
- storageClassName: longhorn-xfs
- certificate:
- requestAutoCert: false
テナントが利用するenvコンフィグファイル
config.env
ファイルで環境変数を渡すことでテナントのコンフィグができます。ここではテナントのUIにアクセスするときに使うユーザ、パスワードを用意します。
例としては以下の通りです。ユーザ名とパスワードの値は好きに指定しましょう。SOPSで暗号化したらGitOpsレポジトリへとプッシュします。
# ./sops/lab-hlv3/minio-tenant/infra-tenant-env-configuration.yaml
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: infra-tenant-env-configuration
namespace: minio-infra-tenant
stringData:
config.env: |-
export MINIO_ROOT_USER=minio
export MINIO_ROOT_PASSWORD=minio123
storage class longhorn-xfs
最初の方ですでに触れましたが、minio-tenantのvaluesファイル内でも指定しているstorage classを用意します。
# ./infrastructure/lab-hlv3/configs/longhorn/sc-longhorn-xfs.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: longhorn-xfs
parameters:
staleReplicaTimeout: "30"
diskSelector: xfs
fsType: xfs
provisioner: driver.longhorn.io
reclaimPolicy: Retain
volumeBindingMode: Immediate
allowVolumeExpansion: true
flux tree ks infra-configs
インストール後のinfra-configs ksや作成されたpod(sts)、serviceなどは以下の通りです。
$ flux tree ks infra-configs
Kustomization/flux-system/infra-configs
├── StorageClass/longhorn-xfs
└── HelmRelease/flux-system/infra-tenant
└── Tenant/minio-infra-tenant/infra-tenant
$ kubectl get all -n minio-infra-tenant
NAME READY STATUS RESTARTS AGE
pod/infra-tenant-pool-0-0 2/2 Running 2 (4h23m ago) 4h24m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/infra-tenant-console ClusterIP 10.96.6.195 <none> 9090/TCP 4h24m
service/infra-tenant-hl ClusterIP None <none> 9000/TCP 4h24m
service/minio ClusterIP 10.96.186.251 <none> 80/TCP 4h24m
NAME READY AGE
statefulset.apps/infra-tenant-pool-0 1/1 4h24m
テナントのUIへのアクセス
それでは次にUIへのアクセスを用意します。3ステップです。
- 接続先のサービスの確認
- gatewayにlistenerを追加
- 追加したlistenerとサービスを繋ぐHTTPRouteを作成
接続先サービス名はinfra-tenant-console
です。
cilium gatewayの.spec.listeners[]
に追加したlistenerはこちらです。
- name: minio-infra-tenant-https
hostname: infra-tenant.lab.blink-1x52.net
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway: cilium
tls:
mode: Terminate
certificateRefs:
- name: tls-minio-infra-tenant
kind: Secret
namespace: gateway
HTTPRouteはこのようになります。
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: minio-infra-tenant-https
namespace: minio-infra-tenant
spec:
parentRefs:
- name: cilium-gateway
sectionName: minio-infra-tenant-https
namespace: gateway
hostnames:
- "infra-tenant.lab.blink-1x52.net"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: infra-tenant-console
port: 9090
テナントのS3サービスへのアクセス
S3サービスへのアクセスもcilium gateway上に用意します。
Listenerはこちら。
- name: s3-infra-tenant-https
hostname: s3-infra-tenant.lab.blink-1x52.net
port: 443
protocol: HTTPS
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway: cilium
tls:
mode: Terminate
certificateRefs:
- name: tls-s3-infra-tenant
kind: Secret
namespace: gateway
HTTPRouteです。
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: s3-infra-tenant-https
namespace: minio-infra-tenant
spec:
parentRefs:
- name: cilium-gateway
sectionName: s3-infra-tenant-https
namespace: gateway
hostnames:
- "s3-infra-tenant.lab.blink-1x52.net"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: minio
port: 80
GitLab Runnerでお試し
GitLabのCI/CD pipelineを回してくれるGitLab Runnerはcache保存先としてS3サービスが指定可能です。Runnerのためにbucket、ポリシー、credentialsを用意します。
- "runner-cache"という名前のbucketを作成
- "rw-runner-cache"という名前でポリシーを用意、"runner-cache" bucketへのread-writeアクセスを可能とするポリシーにする
- ユーザを"giltab-runner"という名前で用意し、パスワードも設定
- "rw-runner-cache"ポリシーに"gitlab-runner"ユーザを追加
ユーザ名とそのパスワードが、S3サービスでのaccess keyおよびsecret keyとなります。
ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": ["arn:aws:s3:::runner-cache/*", "arn:aws:s3:::runner-cache"]
}
]
}
GitLab Runnerコンフィグファイル例
今おうちラボで動かしているGitLab Runnerはdockerコンテナとして稼働しているもののみですので、そのコンフィグファイル/etc/gitlab-runner/config.toml
の例を以下に紹介します。
"runners.cache"部分に"type = s3"を追加し、"runners.cache.s3"に宛先、bucket名、credentialsなどを設定しています。
参考までに、Kubernetesクラスタ上にHelmチャートでGitLab Runnerをセットアップしたときの記事、特に設定周りの記述はこちらにあります。
concurrent = 1
check_interval = 0
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "docker runner"
url = "https://GITLAB_HOST"
id = 14
token = "GITLAB_RUNNER_TOKEN"
token_obtained_at = 2025-04-04T06:04:33Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
clone_url = "https://GITLAB_HOST"
[runners.cache]
MaxUploadedArchiveSize = 0
Type = "s3"
[runners.cache.s3]
ServerAddress = "s3-infra-tenant.lab.blink-1x52.net"
BucketName = "runner-cache"
BucketLocation = "lab-hlv3"
Insecure = false
AuthenticationType = "access-key"
AccessKey = "gitlab-runner"
SecretKey = "USER_PASSWORD"
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "alpine:latest"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache"]
shm_size = 0
network_mtu = 0
ジョブのログ
Cacheを利用するジョブのログからは以下のようにcache.zipをアップロードしていることが確認できると思います。
Saving cache for successful job 00:02
Creating cache xxx-protected...
/xxx/.cache/pip: found 568 matching artifact files and directories
Uploading cache.zip to https://s3-infra-tenant.lab.blink-1x52.net/runner-cache/runner/t1_CZUpzY/project/148/xxx-protected
Created cache
Uploading artifacts for successful job 00:01
Uploading artifacts...
public/: found 333 matching artifact files and directories
Uploading artifacts as "archive" to coordinator... 201 Created id=3647 responseStatus=201 Created token=xxx
Cleaning up project directory and file based variables 00:00
Job succeeded
テナントのUIでbucketを確認すると確かにファイルができていることが確認できます。
終わりに
以上です!
minio-operatorとminio-tenantのhelmチャートを用いることでテナントを必要な数だけ、好きにインスタンスに分けて立ち上げられるのが良いですね。
今回はサーバ1台、サーバ毎のプール内のvolume数も1というstandalone構成と言われるテナントを作りましたが、S3ストレージを利用するサービスの重要性に応じて高可用性を求めた構成のテナントを立ち上げるのも簡単です。
あるいはminioテナントがstandalone構成でも、ディスクスペース提供元(今回の構成ではLonghorn)の方でレプリケーションやバックアップを充実させておき、そのディスクスペースを利用する専用のstorage classを設け、それを用いてテナントを立ち上げるというやり方もできます。
試せる構成が多くて困ってしまいますね。
今回遊んでいるKubernetesクラスタにおいて、S3を用意した主な理由の一つはロギングシステムとして導入予定のgrafana lokiです。lokiが扱うchunksやindexesの保存先としてobject storeが必要となり、その準備段階としてのS3構築でした。
Discussion