Moving from kube-lego to cert-manager for automatic TLS certificates

We’re moving the Letsencrypt service on our Kubernetes from the deprecated kube-lego to cert-manager.

Cert-manager comes with a whole set of new features, mainly the ability to use the dns01 ACME challenge for certificate validation. This means you could also use cert-manager to request internal-only certificates. It is now also possible to request wildcard certificates.

Other, currently unexplored, features include the possiblity to use other certificate providers like an internal CA, self-signed certs and Vault.

Migration process

In the coming days we will be transparently replacing kube-lego with cert-manager on our staging clusters and thus existing certificates will not be re-issued if they are still valid. Once everything has been confirmed as working and no issues pop up, we’ll do the same for the production cluster.

You can check whether cert-manager is available on your cluster(s) by listing the certificates via the new CRD:

$ kubectl get certificates --all-namespaces
NAMESPACE        NAME                                 CREATED AT
infrastructure   cert-manager-webhook-ca              9m
infrastructure   cert-manager-webhook-webhook-tls     9m
infrastructure   foo-staging-cert                     2m
infrastructure   kubesignin-alertmanager-lego-tls     5m
infrastructure   kubesignin-dashboard-lego-tls        5m
infrastructure   kubesignin-grafana-lego-tls          5m
infrastructure   kubesignin-kibana-lego-tls           5m
infrastructure   kubesignin-kubesignin-app-lego-tls   5m
infrastructure   kubesignin-prometheus-lego-tls       5m
infrastructure   wild-staging-cert                    37s

Actions to take

We deploy a letsencrypt-prod ClusterIssuer by default, which uses dns01 validation via Route 53. This ClusterIssuer will be used as the default when you specify the kubernetes.io/tls-acme: "true" annotation on your Ingress, just like before.

Of coure you can also define your own Issuers and/or ClusterIssuers.

Examples

Below are some simple examples on how to issue certicicates as usually done on the Ingress. Of course there are way more possibilities, which you can find in the official documentation.

Get a LetsEncrypt certificate using defaults (dns01)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/tls-acme: "true"
  name: foo
  namespace: default
spec:
  rules:
  - host: foo.staging.skyscrape.rs
    http:
      paths:
      - backend:
          serviceName: kubesignin-dashboard
          servicePort: 3000
        path: /
  tls:
  - hosts:
    - foo.staging.skyscrape.rs
    secretName: foo-staging-tls

Get a LetsEncrypt certificate using the http01 challenge

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/tls-acme: "true"
    certmanager.k8s.io/acme-challenge-type: "http01"
  name: bar
  namespace: default
spec:
  rules:
  - host: bar.staging.skyscrape.rs
    http:
      paths:
      - backend:
          serviceName: kubesignin-dashboard
          servicePort: 3000
        path: /
  tls:
  - hosts:
    - bar.staging.skyscrape.rs
    secretName: bar-staging-tls

Get a LetsEncrypt wildcard certificate using defaults (dns01)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/tls-acme: "true"
  name: wild
  namespace: default
spec:
  rules:
  - host: wild.staging.skyscrape.rs
    http:
      paths:
      - backend:
          serviceName: kubesignin-dashboard
          servicePort: 3000
        path: /
  tls:
  - hosts:
    - "*.staging.skyscrape.rs"
    secretName: wild-staging-tls

Upstream resources