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@pet2cattle.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: jprats@systemadmin.es
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