- Already have a cluster up and running as described in Getting cockroachDB running with Kubernetes and are using the Google Cloud console shell with the kubectl CLI. The database is of course not necessary for this example, but the cluster and CLI preparation is.
- created an app to be deployed as described in Building your App ready for Kubernetes deployment
- deployed it as described in Creating a Kubernetes deployment
- created a service as described in Creating a microservice on Kubernetes
- created an ingress controller as described in Bringing up an ingress controller
- You might also find Digging around on the Kubernetes cluster of some use to help with the familiarity of concepts.
This also replaces the info in Getting an ssl certificate for Kubernetes ingress which uses kube-lego (now being deprecated). This method uses its replacement,cert-manager.
I recommend that you save your commands in various scripts so you can repeat them or modify them later.
In this article – we’re doing this, but replacing kube-lego with cert-manager.
SSL
Before you can secure access to your service and run it over https, you’ll need to generate a certificate and certificate key. Working with certificates is horrible, and causes brain freeze in many people – including me. Luckily we have 3 things to help us.
- Letsencrypt allows you to get free certificates (normally you’d have to pay for them).
- Cert-Manager is a set of Kubernetes components that can manage the whole business of renewing and applying those certificates and is available as a helm-chart.
- Kubernetes can store secrets and they can be accessed by other cluster resources.
Cert-Manager
You should already have helm installed from Bringing up an ingress controller, but if you don’t – that’ll do it.
kubectl create serviceaccount --namespace kube-system tiller kubectl create clusterrolebinding tiller --clusterrole=cluster-admin --serviceaccount=kube-system:tiller curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash helm init kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}' helm init --service-account tiller --upgrade
Next, install cert-manager
helm install stable/cert-manager
You should see a cert manager pod
coy-dingo-cert-manager-65bf74c6b9-jl24t 1/1 Running 0 1d
What does cert-manager do
It searches for ingresses (not ingress controllers) that have a specific annotation and generates (or renews those nearing expiry) certificates in a similar way to Kube-lego. Here are some in my ingress (which I’ll cover later)
metadata: name: fidkp-ingress annotations: ingress.kubernetes.io/ssl-redirect: "true" kubernetes.io/tls-acme: "true" kubernetes.io/ingress.class: "nginx" certmanager.k8s.io/cluster-issuer: "letsencrypt-prod"
- tls-acme tells cert-manager that this is to use the acme protocol (as used by letsencrypt) to manage the certificate generation and renewal process.
- cluster-issuer tells cert-manager which certificate issuer to get certificates from.
Annotations
You may have noticed “annotations” in some of the .yaml configurations. These are markers that can be read by other Kubernetes resources. The next step is to create an ingress for our service that will contain an annotation like the one above to let cert-manager know that it needs to be processed for a certificate.
- The ingress controller checks for annotations in the configuration of ingresses to see if it should handle them
- Cert-manager checks ingresses for the tls-acme annotation to see if it needs to manage certificates
ClusterIssuer
Cert-manager has the concept of an issuer (issues certificates for a specific namespace), or a cluster issuer (issues certificates across multiple namespaces in a cluster). I’m creating a cluster issuer with this example .yaml
apiVersion: certmanager.k8s.io/v1alpha1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: # The ACME server URL server: https://acme-v02.api.letsencrypt.org/directory # Email address used for ACME registration email: bruce@mcpher.com # Name of a secret used to store the ACME account private key privateKeySecretRef: name: letsencrypt-prod # Enable the HTTP-01 challenge provider http01: {}
- letsencrypt-prod is used to match this cluster issuer to the ingress that’s going to use it
- http01 is a method of proving that you own a domain. You may have come across this before, where you place a file on your webserver to prove you actually own it. Cert-manager generates a small file and then uses your ingress controller IP address (which is pointing at by an A record in your domain DNS records) and then validates it can find it via that domain – in other words, you don’t actually have to place a file anywhere, but cert-manager uses that technique to validate domain ownership.
Certificate
A certificate is held in a secret in Kubernetes. You can create this secret with cert-manager using this YAML. This pulls together the cluster issuer, the http01 validation and creates a secret that can be used by SSL.
apiVersion: certmanager.k8s.io/v1alpha1 kind: Certificate metadata: name: api-fid-crt namespace: default spec: secretName: api-fid-crt issuerRef: name: letsencrypt-staging kind: ClusterIssuer dnsNames: - xxx.xxx.yourdomain.com acme: config: - http01: ingressClass: nginx domains: - xxx.xxx.yourdomain.com
Next step
See Kubernetes ingress with cert-manager