It’s been a lot easier nowadays to turn on full site SSL/TLS encryption with an ACME issuer such as the popular non-profit Let’s Encrypt which I’ve started using it a few months ago.
However the free certificates from Let’s Encrypt are only valid for 90 days and I have been notified to renew them already. I could run the cert-bot again to semi-automatically renew the certificates in my Kubernetes cluster, but there’s Cert Manager which claims to be able to fully automate the whole process. I have to give it a try.
The Cert Manager essentially is a bundle of a Kubernetes Operator + CRDs(Custom Resource Definition), I followed the installation steps and installed Cert Manager easily with default settings. I chose to install with plain manifests because I tried the Helm charts first but it had some issues with my FluxCD pipeline. The plain manifests include the Cert Manager operator, CRDs and relevant Kubernetes resources such as Namespace and Service Account.
To use the same CloudFlare DNS challenge I used with cert-bot, I created a secret containing my CF API token:
$ k create secret generic cloudflare-api-token -n cert-manager --from-literal=api-key=eQ9Ls6...
Note: it will take a while for the Cert Manager to self-signed certificate for itself and get ready for requests.
Then I created a ClusterIssuer using CloudFlare DNS challenge to verify domain authority:
$ cat <<EOF |k apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer
spec:
acme:
email: <my email>
server: https://acme-v02.api.letsencrypt.org/directory
# this is the new CA chain
preferredChain: "ISRG Root X1"
# a secret name to save the private key
privateKeySecretRef:
name: letsencrypt-issuer
solvers:
- dns01:
cloudflare:
email: <my cloudflare email>
# the secret to provide CloudFlare API Token
apiTokenSecretRef:
name: cloudflare-api-token
key: api-key
EOFThen I checked if the ClusterIssuer is up:
$ k get clusterissuer NAME READY AGE letsencrypt-issuer True 1m
Almost done! The Cert Manager is now ready to manage certificates. I then created a Certificate resource to request and manage a new certificate:
$ cat <<EOF |k apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wordpress-raynix
# the cert will be in istio-system namespace to be used by istio
namespace: istio-system
spec:
# the secret to hold this cert
secretName: wordpress-raynix-cert
duration: 2160h # 90d
renewBefore: 360h # 15d
subject:
organizations:
- raynix.info
isCA: false
privateKey:
algorithm: RSA
size: 2048
usages:
- server auth
- client auth
# put all DNS names in the cert here
dnsNames:
- raynix.info
# refer to the ClusterIssuer
issuerRef:
name: letsencrypt-issuer
kind: ClusterIssuer
EOFThen it usually takes a minute or longer to actually see the secret in the newly created secret. The DNS challenge process is now run by the Cert Manager pod instead of the cert-bot.
As a last step, the new cert can be used in an Istio Gateway:
# this is the existing gateway
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: wordpress-gateway
namespace: wordpress-raynix
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- raynix.info
port:
name: https
number: 443
protocol: HTTPS
tls:
# use the new cert in the new secret!
credentialName: wordpress-raynix-cert
mode: SIMPLE
- hosts:
- raynix.info
port:
name: http
number: 80
protocol: HTTP
tls:
httpsRedirect: trueThat’s it! Cert Manager claims that it can manage that cert and renew it accordingly, let’s see if that’s true 🙂
