4 min read | by Jordi Prats
To be able to automatically request letsencrypt certificates for the TLS-eanble Ingress objects in a kubernetes cluster with the traefik ingress controller we can use the cert-manager controller.
First we'll be installing it using helm. To do se we don't need to add any values, unless we want it to configuew the ClusterIssuer for us. First we are going to load the repository and update it:s
$ helm repo add jetstack https://charts.jetstack.io $ helm repo update
Once ready we can install it as follows:
helm install cert-manager jetstack/cert-manager --namespace cert-manager
We'll need to give it a few seconds to spin up all the containers:
$ kubectl get pods -n cert-manager NAME READY STATUS RESTARTS AGE cert-manager-6ffb79dfdb-mqkvm 1/1 Running 0 13s cert-manager-cainjector-5fcd49c96-2zfmw 1/1 Running 0 13s cert-manager-webhook-796ff7697b-9w67w 1/1 Running 0 13s
Once ready we can now create the ClusterIssuer objects, which defines how to connect to the external provider via the ingress controller. For this example we are going to use K3S's default ingress controller: traefik, requesting certificates to letsencrypt:
apiVersion: cert-manager.io/v1alpha2 kind: ClusterIssuer metadata: name: letsencrypt spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: email@example.com privateKeySecretRef: name: letsencrypt-ca solvers: - http01: ingress: ingressTemplate: metadata: annotations: "kubernetes.io/ingress.class": "traefik"
privateKeySecretRef is where the data is stored, it will be created for us.
We can use kubectl describe to check whether or now the ClusterIssuer is able to issue new certificates
$ kubectl describe clusterissuer letsencrypt Name: letsencrypt Namespace: Labels: <none> Annotations: <none> API Version: cert-manager.io/v1 Kind: ClusterIssuer Metadata: (...) Status: Acme: Last Registered Email: firstname.lastname@example.org Uri: https://acme-v02.api.letsencrypt.org/acme/acct/1112900837 Conditions: Last Transition Time: 2023-05-16T17:30:44Z Message: The ACME account was registered with the ACME server Observed Generation: 1 Reason: ACMEAccountRegistered Status: True Type: Ready Events: <none>
Once we have the ClusterIssuer we'll need to make sure we have the application exposed using an Ingress with the tls options:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: awscost spec: ingressClassName: traefik rules: - host: awscost.pet2cattle.com http: paths: - backend: service: name: awscost port: name: http path: / pathType: Prefix tls: - hosts: - awscost.pet2cattle.com secretName: awscost-pet2cattle-https-cert
The secret referenced in secretName is where the certificate is going to be stored, we don't need to populate it with anything.
The requirements, depending on the issuer, we'll be different. For letsencrypt we'll need to make this reachable for them to validate it so we'll need to make sure DNS is updated as well.
With the application reachable we can now proceed to create the Certificate with the commonName and SAN (dnsNames) we need:
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: awscost-pet2cattle-https-cert spec: commonName: awscost.pet2cattle.com dnsNames: - awscost.pet2cattle.com issuerRef: kind: ClusterIssuer name: letsencrypt secretName: awscost-pet2cattle-https-cert
Once created, the cert-manager controller will need to request the certificate and with for the CA to create it. It's going to take a few minutes. We can check it's status directly with kubectl get looking as the READY column:
$ kubectl get certificate NAME READY SECRET AGE awscost-pet2cattle-https-cert False awscost-pet2cattle-https-cert 6s (...) $ kubectl get certificate NAME READY SECRET AGE awscost-pet2cattle-https-cert True awscost-pet2cattle-https-cert 5m42s
In the status section we can see some details of the certificate itself:
$ kubectl get certificate awscost-pet2cattle-https-cert -n awscost -o yaml apiVersion: cert-manager.io/v1 kind: Certificate metadata: (...) spec: commonName: awscost.pet2cattle.com dnsNames: - awscost.pet2cattle.com issuerRef: kind: ClusterIssuer name: letsencrypt secretName: awscost-pet2cattle-https-cert status: conditions: - lastTransitionTime: "2023-05-17T18:12:20Z" message: Certificate is up to date and has not expired observedGeneration: 2 reason: Ready status: "True" type: Ready notAfter: "2023-08-15T17:12:18Z" notBefore: "2023-05-17T17:12:19Z" renewalTime: "2023-07-16T17:12:18Z" revision: 1
Posted on 23/05/2023