Managing ssl for ingress certificates with cert-manager

Cloud Platform (intermediate level) posted on 4th Sep 2018


This is a part of the series of posts on Getting an API running in Kubernetes. For this to make sense you should have worked through a few of the earlier examples
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 dont - this'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 notices "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 clusterissuer (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 clusterissuer 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 clusterissuer, 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
    




Why not join our forum, follow the blog or follow me on twitter to ensure you get updates when they are available.
Comments