This document explains how to deploy MinIO Operator and a MinIO Tenant using certificates generated by cert-manager.
On a Kubernetes cluster, Certificate Manager requires a global level Cluster Issuer to generate intermediary Issuers and certificates.
At the namespace level, Cert Manager issues certificates derived from an Issuer.
The main difference between a Cluster Issuer and an Issuer is that Cluster Issuer can issue certificates for several
namespaces and an Issuer can only issue them in a single namespace.
To learn more about Cert Manager Issuers refer to their documentation https://cert-manager.io/docs/concepts/issuer/.
Below is a logical view of a Kubernetes cluster:
This cluster contains 4 namespaces:
- minio-operator
- tenant-1
- tenant-2
- other-namespace
This guide shows you how to set up different Certificate Authorities (CA) in each namespace, all of them referencing a global Cluster Issuer.
Cert Manager is installed in the cert-manager namespace.
The global Cluster Issuer is created in the default namespace.
A local Issuer is created in each tenant namespace.
An Issuer is also created in the minio-operator namespace. More about services that require TLS certificates
in the minio-operator namespace are covered below in MinIO Operator services with cert-manager..
Note
This guide uses a self-signed Cluster Issuer. You can also use other Issuers supported by Cert Manager.
The main difference is that you must provide the Issuer CA certificate to minio, instead of the CA's mentioned in this guide.
- Kubernetes version
+v1.21. While cert-manager supports earlier K8s versions, MinIO Operator requires 1.21 or later. - kustomize installed
kubectlaccess to yourk8scluster
Install cert-manager 1.12.X LTS is preferred, or install latest, for example using kubectl.
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.9/cert-manager.yamlFor more details on the Cert Manager refer to https://cert-manager.io/docs/installation/.
The Cluster Issuer is the cluster level Issuer all other certificates are derived from. Request Cert Manager to
generate this by creating a ClusterIssuer resource:
# selfsigned-root-clusterissuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-root
spec:
selfSigned: {}kubectl apply -f selfsigned-root-clusterissuer.yamlMinIO Operator manages the TLS certificate issuing for the services hosted in the minio-operator namespace. That is the Secure Token Service sts.
This section describes how to generate the sts TLS certificate with Cert Manager.
These certificates must be issued before installing Operator.
Be sure to follow step Create Cluster Self-signed root Issuer mentioned above.
MinIO STS is a service included with MinIO Operator that provides Native IAM Authentication for Kubernetes. In essence this service allows you to control access to your MinIO tenant from your kubernetes applications without having to explicitly create credentials for each application. For more information on the Service see the MinIO docs at https://min.io/docs/minio/kubernetes/upstream/developers/sts-for-operator.html. There is also an STS guide in the docs and example client code in https://github.com/minio/operator/tree/master/examples/kustomization/sts-example.
For the purpose of this guide, STS Service can be considered a webserver presented with a TLS certificate for https traffic. This guide covers how to disable the automatic generation of the certificate in MinIO Operator and issue the certificate using Cert Manager instead.
To create the Certificate Authority (CA) certificate used to issue certificates for services in the minio-operator
namespace, first create the minio-operator namespace
kubectl create ns minio-operatorRequest a Certificate with spec.isCA: true specified. This is our CA for the minio-operator namespace.
# operator-ca-tls-secret.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: minio-operator-ca-certificate
namespace: minio-operator
spec:
isCA: true
commonName: operator
secretName: operator-ca-tls
duration: 70128h # 8y
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: selfsigned-root
kind: ClusterIssuer
group: cert-manager.iokubectl apply -f operator-ca-tls-secret.yamlA new secret with the name operator-ca-tls is created in the minio-operator namespace, this is the CA issuing TLS certificates for the services in the minio-operator namespace.
Important
Make sure to trust this certificate in your applications that need to interact with the sts service.
Now create the Issuer:
# operator-ca-issuer.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: minio-operator-ca-issuer
namespace: minio-operator
spec:
ca:
secretName: operator-ca-tlskubectl apply -f operator-ca-issuer.yamlRequest Cert Manager to issue a new certificate containing following DNS domains:
sts
sts.minio-operator.svc.
sts.minio-operator.svc.<cluster domain>Important
Replace <cluster domain> with the actual values for your MinIO tenant.
cluster domain is the internal root DNS domain assigned in your Kubernetes cluster. Typically this is cluster.local, check on your coredns
configuration for the correct value for your Kubernetes cluster. For example, using kubectl get configmap coredns -n kube-system -o jsonpath="{.data}".
The way the root DNS domain is managed can vary depending on the Kubernetes distribution (Openshift, Rancher, EKS, etc.)
Create a Certificate for the domains mentioned above:
# sts-tls-certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: sts-certmanager-cert
namespace: minio-operator
spec:
dnsNames:
- sts
- sts.minio-operator.svc
- sts.minio-operator.svc.cluster.local
secretName: sts-tls
issuerRef:
name: minio-operator-ca-issuerkubectl apply -f sts-tls-certificate.yamlThis creates a secret called sts-tls in the minio-operator namespace.
Important
The secret name is not optional. Make sure the secret name is sts-tls by setting spec.secretName: sts-tls as in the example above.
When installing the Operator deployment, make sure to set OPERATOR_STS_AUTO_TLS_ENABLED: off env variable in the minio-operator container. This prevents
MinIO Operator from issuing the certificate for STS and instead wait for you to provide the TLS certificate issued by Cert Manager.
Warning
Missing to provide the secret sts-tls containing the TLS certificate or providing an invalid key-pair in the secret will
prevent the STS service from start.
A way to make sure that the env variables are properly set is using kustomization to patch the minio-operator deployment:
# minio-operator/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- github.com/minio/operator/resources
patches:
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio-operator
namespace: minio-operator
spec:
template:
spec:
containers:
- name: minio-operator
env:
- name: OPERATOR_STS_AUTO_TLS_ENABLED
value: "off"
- name: OPERATOR_STS_ENABLED
value: "on"kubectl apply -k minio-operatorTo create the Certificate Authority (CA) certificate in the namespace tenant-1, first create the namespace
kubectl create ns tenant-1Next, request a Certificate with spec.isCA: true specified:
# tenant-1-ca-certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: tenant-1-ca-certificate
namespace: tenant-1
spec:
isCA: true
commonName: tenant-1-ca
secretName: tenant-1-ca-tls
duration: 70128h # 8y
privateKey:
algorithm: ECDSA
size: 256
issuerRef:
name: selfsigned-root
kind: ClusterIssuer
group: cert-manager.iokubectl apply -f tenant-1-ca-certificate.yamlThen create the Issuer:
# tenant-1-ca-issuer.yaml
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: tenant-1-ca-issuer
namespace: tenant-1
spec:
ca:
secretName: tenant-1-ca-tlskubectl apply -f tenant-1-ca-issuer.yamlRequest Cert Manager issue a new TLS server certificate for MinIO that includes the following DNS domains:
minio.<namespace>
minio.<namespace>.svc
minio.<namespace>.svc.<cluster domain>
*.<tenant-name>-hl.<namespace>.svc.<cluster domain>
*.minio.<namespace>.svc.<cluster domain>
*.<tenant-name>.minio.<namespace>.svc.<cluster domain>'Important
Replace <cluster domain> with the actual values for your MinIO tenant.
<cluster domain>is the internal root DNS domain assigned in your Kubernetes cluster. Typically this iscluster.local, check on your coredns configuration for the correct value for your Kubernetes cluster. For example, usingkubectl get configmap coredns -n kube-system -o jsonpath="{.data}". The way the root DNS domain is managed can vary depending on the Kubernetes distribution (Openshift, Rancher, EKS, etc.)tenant-nameis the name provided to your tenant in themetadata.nameof the Tenant YAML. For this example it ismyminio.namespaceis the namespace where the tenant is created, themetadata.namespacenotes that in the Tenant YAML. For this example it istenant-1.
Create a Certificate for the domains mentioned above:
# tenant-1-minio-certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: tenant-certmanager-cert
namespace: tenant-1
spec:
dnsNames:
- "minio.tenant-1"
- "minio.tenant-1.svc"
- 'minio.tenant-1.svc.cluster.local'
- '*.minio.tenant-1.svc.cluster.local'
- '*.myminio-hl.tenant-1.svc.cluster.local'
- '*.myminio.minio.tenant-1.svc.cluster.local'
secretName: myminio-tls
issuerRef:
name: tenant-1-ca-issuerTip
For this example, the Tenant name is myminio. We recommend naming the secret in the field spec.secretName as <tenant name>-tls, following the naming
convention MinIO Operator uses when creates certificates with Autocert enabled (spec.requestAutoCert: true).
kubectl apply -f tenant-1-minio-certificate.yamlIn the tenant spec, do the following:
- Disable Autocert
spec.requestAutoCert: false. This instructs Operator to not attempt to issue certificates and instead rely on Cert Manager to provide them in a secret. - Reference the Secret containing the TLS certificate from the previous step in
spec.externalCertSecret.
apiVersion: minio.min.io/v2
kind: Tenant
metadata:
name: myminio
namespace: tenant-1
spec:
...
## Disable default tls certificates.
requestAutoCert: false
## Use certificates generated by cert-manager.
externalCertSecret:
- name: myminio-tls
type: cert-manager.io/v1
...MinIO Operator can trust as many CA certificates as provided. To do this, create a secret with the prefix operator-ca-tls-
followed by a unique identifier in the minio-operator namespace.
MinIO Operator mounts and trusts all certificates issued by the provided CA's. This is required because MinIO Operator performs health checks using the /minio/health/cluster endpoint.
If Operator is not correctly configured to trust the MinIO Certificate (or its CA), you will see an error message like the following in the Operator Pod logs:
Failed to get cluster health: Get "https://minio.tenant-1.svc.cluster.local/minio/health/cluster":
x509: certificate signed by unknown authority
For more details about health checks, see https://min.io/docs/minio/Kubernetes/upstream/operations/monitoring/healthcheck-probe.html#cluster-write-quorum.
Copy the Cert Manager generated CA public key (ca.crt) into the minio-operator namespace. This allows Operator to trust
the cert-manager issued CA and the derived certificates.
Create a ca.crt file containing the CA:
kubectl get secrets -n tenant-1 tenant-1-ca-tls -o=jsonpath='{.data.ca\.crt}' | base64 -d > ca.crtCreate the secret:
kubectl create secret generic operator-ca-tls-tenant-1 --from-file=ca.crt -n minio-operatorTip
In this example we choose a secret name of operator-ca-tls-tenant-1. Note the tenant namespace
tenant-1 is used as suffix for easy identification of which namespace the CA is coming from.

