cert-manager is a powerful and extensible X.509 certificate controller for Kubernetes. It can manage certificates in the SKS environment and in combination with our cert-manager-webhook it integrates with Exoscale DNS for issuing certificates using ACME DNS01 challenge.
In this short article we will show you how to add a cert-manager to an SKS cluster and configure it to generate a Let’s Encrypt certificate for a domain managed by Exoscale DNS service.
Prerequisites:
- SKS cluster (check our SKS Quick Start Guide for instructions on how to create a new cluster using Exoscale CLI)
- kubectl
- helm
- A valid Exoscale DNS domain
- An Exoscale API access key
Installing cert-manager and cert-manager-webhook
The easiest way to add cert-manager to an SKS cluster is using static manifest as described in the official cert-manager installation page:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.0/cert-manager.yaml
By default cert-manager will be in its own namespace inside a cluster:
$ kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-646dddd544-sxz24 1/1 Running 0 22s
cert-manager-cainjector-8676c4b7-q7s9w 1/1 Running 0 22s
cert-manager-webhook-557fb758cf-989db 1/1 Running 0 22s
cert-manager-webhook is installed using Helm and a Helm Chart in the official cert-manager webhook repository:
git clone https://github.com/exoscale/cert-manager-webhook-exoscale.git
cd cert-manager-webhook-exoscale
helm install exoscale-webhook ./deploy/exoscale-webhook
Now we can see cert-manager-webhook running in the default
namespace:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
cert-manager-webhook-exoscale-d7dccb674-9czqw 1/1 Running 0 31s
Issuing a certificate for a domain
With cert-manager and cert-manager-webhook in place, we can proceed to create a new certificate for our domain. In this example we will generate a certificate for example.com
.
cert-manager-webhook requires Exoscale API credentials to manage a DNS record used in the ACME DNS01 challenge. We can generate a restricted access key using Exoscale CLI:
$ exo iam access-key create \
--operation list-dns-domains \
--operation list-dns-domain-records \
--operation get-dns-domain-record \
--operation get-operation \
--operation create-dns-domain-record \
--operation delete-dns-domain-record \
cert-manager-webhook-key
┼────────────────┼─────────────────────────────────────────────┼
│ IAM ACCESS KEY │ │
┼────────────────┼─────────────────────────────────────────────┼
│ Name │ cert-manager-webhook-key │
│ Type │ restricted │
│ API Key │ EXOabcdefghijklmnopqrstuvwx │
│ API Secret │ ABCDEFGIJKLMNOPQRSTUVWXYZabcdefgijklmnopqrs │
│ Operations │ list-dns-domain-records │
│ │ get-dns-domain-record │
│ │ get-operation │
│ │ list-dns-domains │
│ │ create-dns-domain-record │
│ │ delete-dns-domain-record │
┼────────────────┼─────────────────────────────────────────────┼
The recommended way to provide API credentials to cert-manager-webhook is using the Kubernetes secret resource. We can create a secret.yaml
file with the following content:
apiVersion: v1
stringData:
EXOSCALE_API_KEY: EXOabcdefghijklmnopqrstuvwx
EXOSCALE_API_SECRET: ABCDEFGIJKLMNOPQRSTUVWXYZabcdefgijklmnopqrs
kind: Secret
metadata:
name: exoscale-secret
type: Opaque
Adding the resource is as simple as running:
kubectl create -f secret.yaml
Now we can reference our secret when creating an Issuer
resource (issuer.yaml
):
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: exoscale-issuer
spec:
acme:
email: my-user@example.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: exoscale-private-key-secret
solvers:
- dns01:
webhook:
groupName: acme.exoscale.com
solverName: exoscale
config:
apiKeyRef:
key: EXOSCALE_API_KEY
name: exoscale-secret
apiSecretRef:
key: EXOSCALE_API_SECRET
name: exoscale-secret
Issuers
are Kubernetes resources representing certificate authorities (CAs), that are able to generate signed certificates by honoring certificate signing requests. We can add the resource as before:
kubectl create -f issuer.yaml
The final piece of the puzzle is the Certificate
resource. A Certificate
resource specifies fields that are used to generate certificate signing requests, including domain name and which issuer they want to obtain the certificate from. Our new resource (certificate.yaml
) will look like this:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
spec:
dnsNames:
- example.com
issuerRef:
name: exoscale-issuer
secretName: example-com-tls
And to add a resource:
kubectl create -f certificate.yaml
It may take a minute or two but eventually we will see our new certificate in the ready state:
$ kubectl get certificate example-com
NAME READY SECRET AGE
example-com True example-com-tls 0m52s
That’s it, now we have a valid certificate in our cluster!
Head over to cert-manager documentation for further use cases like Securing Ingress Resources.