Automatically provision TLS certificates in kubernetess with cert-manager
In the first part of Ingress & TLS in kubernetes series I have introduced self-signed certificates. The process was entirely controlled by manual actions and created certs were not accepted by the browser. This time the creation will be done automatically using cert-manager.
I will start from the place I ended in previous post, so if you want to follow along, take a look at part one.
Remove some resources
# hence we will use cert-manager to provision certificates, manually created secret will be no longer needed $ k delete secret ingress-local-tls
Install cert-manager using Helm
https://cert-manager.io/docs/installation/helm/#installing-with-helm $ helm repo add jetstack https://charts.jetstack.io "jetstack" has been added to your repositories $ helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "jetstack" chart repository ...Successfully got an update from the "stable" chart repository Update Complete. ⎈Happy Helming!⎈ $ helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.4.0 \ --set installCRDs=true $ k get po -n cert-manager NAME READY STATUS RESTARTS AGE cert-manager-5d7f97b46d-nmfgb 1/1 Running 0 24m cert-manager-cainjector-69d885bf55-xxpzw 1/1 Running 0 24m cert-manager-webhook-54754dcdfd-5dkgz 1/1 Running 0 24m $ k get crd -o name customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io
Error getting keypair for CA issuer
If you are getting error:
Error getting keypair for CA issuer: certificate is not a CA
Please take a look at this issue for further debugging. Solution below.
Add below lines to /etc/ssl/openssl.cnf
[ v3_ca ] basicConstraints = critical,CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always
In the following command I will use this configuration by passing -extensions v3_ca
flag to openssl
command.
Create key-pair for cert-manager’s CA
# create a new key for CA $ openssl genrsa -out ca.key 2048 Generating RSA private key, 2048 bit long modulus ..............................+++ ...+++ e is 65537 (0x10001) # create certificate $ openssl req -x509 -new -nodes -key ca.key -sha256 -subj "/CN=ingress.local" -days 365 -out ca.crt -extensions v3_ca # put newly created key-pair in kubernetes $ k create secret tls ca-key-pair \ --cert=ca.crt \ --key=ca.key secret/ca-key-pair created # create Issuer and refer to use newly created key-pair $ cat <<EOF| k apply -f- apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: ca-issuer namespace: default spec: ca: secretName: ca-key-pair EOF $ k get issuer NAME READY AGE ca-issuer True 59s # hence we now have issuer, we can generate proper certificate for my domain ingress.local $ cat <<EOF| k apply -f- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: ingress-local namespace: default spec: secretName: ingress-local-tls issuerRef: name: ca-issuer kind: Issuer commonName: ingress.local dnsNames: - www.ingress.local EOF certificate.cert-manager.io/ingress-local created
Result
From now, our example site ingress.local
will have similar cert as in the previous post. The only difference is that when certificate expires, it will be automatically renewed by cert-manager
. Hence I still used cert signed by my own CA, it is still visible to browser as untrusted:
In the third part of this series I will eventually use cert-manager
with Let's encrypt
-certificates will be still automatically renewed, but also trusted by the browser.