Helm chart for deploying the RustFS Kubernetes operator.
- Kubernetes v1.30+
- Helm 3.0+
To install the chart with the release name rustfs-operator:
helm install rustfs-operator deploy/rustfs-operator/To install in a specific namespace:
helm install rustfs-operator deploy/rustfs-operator/ --namespace rustfs-system --create-namespaceTo uninstall/delete the rustfs-operator deployment:
helm uninstall rustfs-operator --namespace rustfs-systemThe following table lists the configurable parameters of the RustFS Operator chart and their default values.
| Parameter | Description | Default |
|---|---|---|
operator.replicas |
Number of operator replicas | 1 |
operator.image.repository |
Operator image repository | rustfs/operator |
operator.image.tag |
Operator image tag | latest |
operator.image.pullPolicy |
Image pull policy | IfNotPresent |
operator.imagePullSecrets |
Image pull secrets | [] |
operator.leaderElect |
Enable leader election override (null/unset for auto by replicas) |
null |
operator.resources.requests.cpu |
CPU resource requests | 100m |
operator.resources.requests.memory |
Memory resource requests | 128Mi |
operator.resources.limits.cpu |
CPU resource limits | 500m |
operator.resources.limits.memory |
Memory resource limits | 512Mi |
operator.metrics.enabled |
Enable operator /metrics, /healthz, and /readyz endpoint |
true |
operator.metrics.port |
Operator observability container port | 8080 |
operator.serviceMonitor.enabled |
Create a Prometheus Operator ServiceMonitor | false |
operator.prometheusRule.enabled |
Create Prometheus alert rules for operator and tenant storage health | false |
operator.tenantMonitor.enabled |
Poll RustFS tenant storage health and capacity metrics | true |
operator.tenantMonitor.intervalSeconds |
Tenant storage monitor interval | 300 |
operator.env |
Environment variables | [{name: RUST_LOG, value: info}] |
operator.nodeSelector |
Node selector for pod placement | {} |
operator.tolerations |
Tolerations for pod scheduling | [] |
operator.affinity |
Affinity rules for pod scheduling | {} |
| Parameter | Description | Default |
|---|---|---|
sts.enabled |
Enable the operator STS endpoint | true |
sts.audience |
Kubernetes TokenReview audience expected by the operator STS endpoint | sts.rustfs.com |
sts.port |
Operator container port for STS | 4223 |
sts.tls.enabled |
Serve the operator STS endpoint over TLS | true |
sts.tls.auto |
Create the operator STS TLS Secret when missing | true |
sts.service.type |
Kubernetes Service type for STS | ClusterIP |
sts.service.port |
Kubernetes Service port for STS | 4223 |
The RustFS operator STS endpoint intentionally uses an explicit Tenant route:
POST /sts/{tenantNamespace}/{tenantName}
This differs from MinIO Operator's namespace-only route. A PolicyBinding still lives in the Tenant namespace, but the workload must call STS with both the Tenant namespace and the Tenant name.
The STS service is HTTPS by default. When sts.tls.auto=true, the operator creates the fixed sts-tls Secret in the operator namespace with tls.crt, tls.key, and ca.crt. Workloads must trust that CA. To use an externally issued certificate, pre-create sts-tls with a certificate signed by a CA already trusted by the workload and set sts.tls.auto=false.
STS only issues credentials for TLS-enabled Tenants. For Tenant upstream calls, the operator selects the Tenant HTTPS service endpoint and trusts the CA recorded in status.certificates.tls.caSecretRef.
Operator STS does not present a client certificate when calling the Tenant. Tenants configured with spec.tls.certManager.caTrust.clientCaSecretRef continue to run with server-side mTLS enabled, but Operator STS rejects those Tenants with HTTP 400 and TenantTlsClientCertificateUnsupported.
When operator.serviceMonitor.enabled=true, the chart creates scrape targets for both the operator observability endpoint and the Console API /metrics endpoint.
Tenants can declare RustFS canned policies, regular users, and buckets directly in spec.policies, spec.users, and spec.buckets. Provisioning starts only after the Tenant workload is ready, uses spec.credsSecret as the RustFS admin credential source, and reports progress under status.provisioning.
User provisioning requires a non-empty direct policy mapping:
spec:
credsSecret:
name: rustfs-admin-creds
policies:
- name: app-readwrite
document:
configMapKeyRef:
name: app-policy
key: policy.json
users:
- name: app-user
policies:
- app-readwrite
buckets:
- name: app-data
objectLock: truePolicy ConfigMaps and user Secrets must live in the Tenant namespace. If they are created outside the Operator Console, add rustfs.tenant=<tenant-name> so changes to those resources enqueue the owning Tenant. Provisioned resources are retained when removed from the Tenant spec.
| Parameter | Description | Default |
|---|---|---|
rbac.create |
Create RBAC resources | true |
serviceAccount.create |
Create service account | true |
serviceAccount.name |
Service account name | "" (auto-generated) |
serviceAccount.annotations |
Service account annotations | {} |
| Parameter | Description | Default |
|---|---|---|
namespace |
Namespace to deploy to | "" (uses release namespace) |
commonLabels |
Labels to add to all resources | {} |
commonAnnotations |
Annotations to add to all resources | {} |
helm install rustfs-operator deploy/rustfs-operator/ \
--set operator.image.repository=myregistry/operator \
--set operator.image.tag=v0.2.0helm install rustfs-operator deploy/rustfs-operator/ \
--set operator.resources.requests.cpu=200m \
--set operator.resources.requests.memory=256Mi \
--set operator.resources.limits.cpu=1000m \
--set operator.resources.limits.memory=1GiWith the chart default behavior, leaderElect is automatically enabled when
operator.replicas > 1 and disabled when operator.replicas <= 1:
helm install rustfs-operator deploy/rustfs-operator/ \
--set operator.replicas=3Override explicitly if needed (for example, to force single-leader mode in all cases):
helm install rustfs-operator deploy/rustfs-operator/ \
--set operator.replicas=3 \
--set operator.leaderElect=falseCreate a custom values.yaml:
operator:
replicas: 2
image:
repository: myregistry/rustfs-operator
tag: v0.2.0
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 1Gi
env:
- name: RUST_LOG
value: debug
leaderElect:Install with your custom values:
helm install rustfs-operator deploy/rustfs-operator/ -f custom-values.yamlCreate a PolicyBinding in the target Tenant namespace. The binding authorizes one workload ServiceAccount to request temporary credentials for policies already defined in RustFS:
apiVersion: sts.rustfs.com/v1alpha1
kind: PolicyBinding
metadata:
name: reports-readonly
namespace: storage
spec:
application:
namespace: reports
serviceaccount: reports-api
policies:
- readonlyThe workload should mount a projected ServiceAccount token with an audience matching sts.audience:
apiVersion: v1
kind: ServiceAccount
metadata:
name: reports-api
namespace: reports
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reports-api
namespace: reports
spec:
replicas: 1
selector:
matchLabels:
app: reports-api
template:
metadata:
labels:
app: reports-api
spec:
serviceAccountName: reports-api
containers:
- name: app
image: example/reports-api:latest
volumeMounts:
- name: rustfs-sts-token
mountPath: /var/run/secrets/rustfs-sts
readOnly: true
volumes:
- name: rustfs-sts-token
projected:
sources:
- serviceAccountToken:
path: token
audience: sts.rustfs.com
expirationSeconds: 3600The workload then calls the operator STS service with the target Tenant namespace and Tenant name:
TOKEN="$(cat /var/run/secrets/rustfs-sts/token)"
curl -sS -X POST \
--cacert /var/run/secrets/rustfs-sts-ca/ca.crt \
"https://rustfs-operator-sts.rustfs-system.svc:4223/sts/storage/rustfs-a" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "Version=2011-06-15" \
--data-urlencode "Action=AssumeRoleWithWebIdentity" \
--data-urlencode "WebIdentityToken=${TOKEN}" \
--data-urlencode "DurationSeconds=3600"After installing the operator, you can create Tenant resources. See the project root examples/ directory for sample manifests:
kubectl apply -f examples/simple-tenant.yamlTo upgrade the operator:
helm upgrade rustfs-operator deploy/rustfs-operator/The published rustfs/operator image contains both the Console backend (Rust API,
/api/v1/*) and the exported console-web static frontend. By default the chart
deploys one Console service that serves both / and /api/v1 from the same pod,
so browser requests are same-origin and do not need CORS.
Serve the Console service under one HTTPS host:
-
Enable the Console and Ingress in
values.yaml:console: enabled: true ingress: enabled: true className: nginx hosts: - host: console.example.com
-
Install/upgrade the chart. The Ingress routes
/and/api/v1to the Console service. The embedded frontend is built withNEXT_PUBLIC_API_BASE_URL=/api/v1by default. If you intentionally test over plain HTTP, setCONSOLE_COOKIE_SECURE=falseinconsole.env; do not use that setting for production.
No CORS configuration is needed on the backend for this setup.
Console sessions are encrypted stateless cookies. Users paste a Kubernetes
ServiceAccount bearer token only during login; after validation, the Console
stores that token inside an encrypted session cookie for later API requests.
If you run multiple Console replicas, keep console.jwtSecret stable and shared
across all replicas. The chart reuses the existing generated Secret on upgrade
when console.jwtSecret is not set.
If the frontend is served from another host (e.g. https://ui.example.com) and the API at https://api.example.com, set allowed origins on the console backend:
console:
env:
- name: CORS_ALLOWED_ORIGINS
value: "https://ui.example.com"
# Required when the frontend and API are cross-site, so browsers send the
# encrypted session cookie on credentialed CORS requests.
- name: CONSOLE_COOKIE_SAME_SITE
value: "None"Multiple origins (e.g. dev + prod): comma-separated, e.g. "https://ui.example.com,http://localhost:3000".
console.frontend.enabled=true still deploys a separate console-web image for
installations that intentionally keep frontend and backend images separate. In
that mode the Ingress routes /api to the Console backend and / to the split
frontend service.
The Console login form expects a Kubernetes ServiceAccount bearer token. For the chart-managed Console ServiceAccount, generate a short-lived token with:
kubectl -n rustfs-system create token rustfs-operator-console --duration=24hPaste the printed token into the Console login form. Use the namespace and ServiceAccount name from your Helm release if they differ from the defaults.
Check that the operator is running:
kubectl get pods -n rustfs-system -l app.kubernetes.io/name=rustfs-operatorView operator logs:
kubectl logs -n rustfs-system -l app.kubernetes.io/name=rustfs-operator -f