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
kubectl
access to yourk8s
cluster
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.yaml
For 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.yaml
MinIO 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-operator
Request 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.io
kubectl apply -f operator-ca-tls-secret.yaml
A 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-tls
kubectl apply -f operator-ca-issuer.yaml
Request 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-issuer
kubectl apply -f sts-tls-certificate.yaml
This 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-operator
To create the Certificate Authority (CA) certificate in the namespace tenant-1
, first create the namespace
kubectl create ns tenant-1
Next, 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.io
kubectl apply -f tenant-1-ca-certificate.yaml
Then 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-tls
kubectl apply -f tenant-1-ca-issuer.yaml
Request 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-name
is the name provided to your tenant in themetadata.name
of the Tenant YAML. For this example it ismyminio
.namespace
is the namespace where the tenant is created, themetadata.namespace
notes 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-issuer
Tip
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.yaml
In 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.crt
Create the secret:
kubectl create secret generic operator-ca-tls-tenant-1 --from-file=ca.crt -n minio-operator
Tip
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.