Cert-Manager
Let’s Encrypt certificates
SSL certificates can be automatically fetched and setup for applications deployed on the Kubernetes cluster via cert-manager. We deploy a letsencrypt-prod ClusterIssuer by default, which uses dns01 validation via Route 53.
To use this ClusterIssuer and get a certificate for your application, you simply need to add the following annotation to the Ingress object:
cert-manager.io/cluster-issuer: letsencrypt-prodYou’ll also need to add a tls section in the spec of the Ingress object, like the following:
tls:
- secretName: foo-example-com-tls
hosts:
- foo.example.comWith the hosts array of the tls section you’re telling cert-manager which domains need to be in the certificate, and in which Secret it should store the private key.
You can also define your own Issuers and/or ClusterIssuers.
You can get a list of all issued certificates:
$ 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 37scert-manager can also issue certificates for delegated domains. If the domain name you want to use for your ingress is hosted in some external DNS servers where cert-manager doesn’t have access, you can delegate the ACME validation domain to the cluster DNS zone by creating a CNAME record in the external DNS servers. You can read more about this feature in the official cert-manager documentation and in the example below.
Warning
Cert Manager has a limit of 60 parallel certificate Challenges that can be processed at the same time. If this limit has been reached, and it’s filled with unprocessable Challenges (eg. due to DNS misconfiguration / not propagated), then these will block any further certificate issuance. You can see how many Challenges are currently being processed by running kubectl get challenges -A (check / count which are pending).
Examples
Below are some simple examples on how to issue certificates as usually done on the Ingress.
There are way more possibilities than described in the examples, which you can find in the official documentation.
Get a LetsEncrypt certificate using defaults (dns01)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
name: foo
namespace: default
spec:
ingressClassName: traefik
rules:
- host: foo.staging.skyscrape.rs
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: foo
port:
name: http
tls:
- secretName: foo-staging-tls
hosts:
- foo.staging.skyscrape.rsGet a LetsEncrypt certificate using the http01 challenge
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
labels:
use-http-solver: "true"
name: bar
namespace: default
spec:
ingressClassName: traefik
rules:
- host: bar.staging.skyscrape.rs
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bar
port:
name: http
tls:
- secretName: bar-staging-tls
hosts:
- bar.staging.skyscrape.rsGet a LetsEncrypt wildcard certificate using the dns01 challenge
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
name: lorem
namespace: default
spec:
ingressClassName: traefik
rules:
- host: lorem.staging.skyscrape.rs
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: lorem
port:
name: http
tls:
- secretName: wildcard-staging-skyscrape-rs-tls
hosts:
- '*.staging.skyscrape.rs'
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
name: ipsum
namespace: default
spec:
ingressClassName: traefik
rules:
- host: ipsum.staging.skyscrape.rs
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ipsum
port:
name: http
tls:
- secretName: wildcard-staging-skyscrape-rs-tls
hosts:
- '*.staging.skyscrape.rs'You could also issue a Certificate first to re-use that later in your Ingresses:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-staging-skyscrape-rs
namespace: default
spec:
secretName: wildcard-staging-skyscrape-rs-tls
issuerRef:
kind: ClusterIssuer
name: letsencrypt-prod
dnsNames:
- 'skyscrape.rs'
- '*.skyscrape.rs'Note
While it is possible to generate multiple wildcard certificates via a different secretName, it is advised / more efficient to reuse the same Secret for all ingresses using the wildcard.
Note
A Secret is scoped within a single Namespace, which means if you want to use a wildcard certificate in another Namespace cert-manager will request and validate a new certificate from LetsEncrypt (unless you replicate the Secrets).
Get a certificate for a delegated domain name
Let’s say you want a certificate for the domain api.example.com but cert-manager doesn’t have access to the root DNS zone for example.com. In this situation you can create a CNAME record in the example.com DNS zone like this:
_acme-challenge.api.example.com IN CNAME _acme-challenge.api.production.eks.example.org.*Considering production.eks.example.org is the FQDN of your K8s cluster.
After this, you create your Ingress as described in the examples above, and cert-manager will follow the CNAME record to create the certificate validation record in the cluster DNS zone, where it does have access.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
name: api
namespace: default
spec:
ingressClassName: traefik
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
name: http
tls:
- secretName: api-example-com-tls
hosts:
- api.example.com