MinIO
MinIO is Lumie's shared object store for product uploads, generated artifacts, Vault backend storage, and several backup flows. It is bootstrap-owned because later GitOps applications depend on it existing first.
Source paths
lumie-infra/bootstrap/minio/argocd.yamllumie-infra/bootstrap/minio/helm-values.yamllumie-infra/bootstrap/minio/common-values.yamllumie-infra/bootstrap/minio/manifests/r2-barman-vss.yamllumie-infra/bootstrap/minio/manifests/r2-snapshot-cronjob.yamllumie-infra/bootstrap/minio/manifests/upload-proxy-ingress.yamllumie-infra/provision/ansible/roles/storage-setup/tasks/main.ymllumie-infra/security/teleport/agent/helm-values.yaml
Runtime shape
What is deployed
- Distributed MinIO with
replicas: 4anddrivesPerNode: 1 - One local PV per node, all using the
minio-localStorageClass - Separate
minio-uiconsole deployment rendered fromcharts/common - VaultStaticSecret refresh for the root credential secret
- A twice-daily snapshot CronJob that mirrors selected buckets to R2
- A Traefik
IngressRoutethat only allowsPUTandOPTIONSto presigned upload paths
Key contracts
- Local disk paths come from
common.persistentVolumesinlumie-infra/bootstrap/minio/common-values.yaml. - Bucket lifecycle is enforced with this post-install command:
customCommands:
- command: ilm rule add myminio/lumie --prefix "tmp/" --expire-days 1
Source path: lumie-infra/bootstrap/minio/helm-values.yaml
- Direct browser uploads are constrained to temporary prefixes:
- match: Host(`lumie-edu.com`) && PathPrefix(`/lumie/tmp/`) && (Method(`PUT`) || Method(`OPTIONS`))
- match: Host(`dev.lumie-infra.com`) && PathPrefix(`/lumie-dev/tmp/`) && (Method(`PUT`) || Method(`OPTIONS`))
Source path: lumie-infra/bootstrap/minio/manifests/upload-proxy-ingress.yaml
Access boundaries
- Application traffic uses the internal S3-compatible endpoint
http://minio.minio.svc:9000. - The console is exposed through the Teleport app named
minio, which proxieshttp://minio-ui.minio.svc.cluster.local:9090and rewrites the host tominio.lumie-infra.com. - Standard Kubernetes ingress is disabled for both the API and console; the upload proxy is the only public HTTP route defined in the repo.
Backup and replication flow
- CNPG-related and other object consumers write into MinIO buckets.
minio-r2-snapshotruns at0 4,16 * * *in theAsia/Seoultime zone.- The snapshot job mirrors the
lumie,lumie-dev, andvaultbuckets intor2/lumie-dr/snapshots/<bucket>/<timestamp>/.
Failure modes
- Local PV loss or a missing node breaks distributed erasure-coded capacity and may trigger long healing or reduced durability.
- If the
minio-root-passwordsecret stops refreshing, the MinIO StatefulSet and the snapshot CronJob drift from the expected credentials. - The upload proxy only allows
tmp/prefixes andPUTorOPTIONS; using permanent object keys or other HTTP verbs fails by design. - The
tmp/ILM rule automatically deletes temporary objects after one day, so workflows that expect those objects to be durable will fail later.
Verification
kubectl get applications.argoproj.io -n argocd minio
kubectl get pods -n minio
kubectl get pvc,pv -n minio
kubectl get cronjobs -n minio
kubectl get jobs -n minio | rg minio-r2-snapshot
kubectl get ingressroutes.traefik.io -n minio
Success means the minio Application is Synced/Healthy, StatefulSet pods are Ready, PVCs are Bound, the snapshot CronJob exists, recent snapshot Jobs are visible, and Traefik exposes the repo-managed upload proxy route.
Observability
- The MinIO Helm values enable a ServiceMonitor with the
release: prometheuslabel. - Grafana keeps a MinIO dashboard JSON in
lumie-infra/observability/grafana/dashboards/minio.json. - Prometheus rule files also include MinIO replication alerts in
lumie-infra/observability/prometheus/helm-values.yaml.