HTTPS is essential to secure the traffic of Kubernetes Ingresses. Discover Cert-Manager to automate the provisioning and renewal of Let's Encrypt certificates.
Kubernetes ingress exposes a web application or a REST API within a cluster to the outside. However, the application is reachable over HTTP by default which is not secure. The traffic between the application and clients is not encrypted.
The ingress can be configured to serve the application in HTTPS. It works like a reverse proxy by offloading this functionality from the application. To do this, you need to configure a certificate in the ingress specifying it in the tls
field:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: wordpress
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wordpress
port:
number: 80
tls:
- hosts:
- example.com
By doing this, the certificate will not be trusted by browsers and visitors will get a warning. This may reduce the user experience and the traffic of an application. To avoid that it will be necessary to generate valid certificates and especially from a certification authority.
The purpose here is to detail to you how to automate the lifecycle of certificates with Cert-manager and Let's Encrypt as a certification authority. Cert-manager automates the provisioning of Β HTTPS certificates within your Kubernetes cluster. It provides custom resources to simplify the obtain, renewal, and use of those certificates.
In order we will see how to :
- install cert-manager in your k8s cluster
- create certificate issuers for Let's Encrypt
- expose a WordPress blog over HTTPS using the Nginx ingress controller
Installing Cert-Manager
Cert-manager is easy to install using Helm. Helm is a Kubernetes package manager that allows you to add applications to your cluster using repositories with pre-built charts.
The first step is to add the Jetstack repository:
$ helm repo add jetstack https://charts.jetstack.io
$ helm repo update
Install Cert-Manager with CRDs into your cluster:
$ helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --set installCRDs=true
Jetstack also offers a kubectl plugin to easily manage cert-manager resources in your cluster:
$ curl -L -o kubectl-cert-manager.tar.gz https://github.com/jetstack/cert-manager/releases/download/v1.6.1/kubectl-cert_manager-darwin-amd64.tar.gz
$ tar xzf kubectl-cert-manager.tar.gz
$ sudo mv kubectl-cert_manager /usr/local/bin
I recommend you install cmctl
for a better experience via tab auto-completion:
$ curl -L -o cmctl-darwin-amd64.tar.gz https://github.com/jetstack/cert-manager/releases/download/v1.6.1/cmctl-darwin-amd64.tar.gz
$ tar xzf cmctl-darwin-amd64.tar.gz
$ sudo mv cmctl /usr/local/bin
$ kubectl cert-manager help
kubectl cert-manager is a CLI tool manage and configure cert-manager resources for Kubernetes
Usage: kubectl cert-manager [command]
Available Commands:
approve Approve a CertificateRequest
check Check cert-manager components
convert Convert cert-manager config files between different API versions
create Create cert-manager resources
deny Deny a CertificateRequest
experimental Interact with experimental features
help Help about any command
inspect Get details on certificate related resources
renew Mark a Certificate for manual renewal
status Get details on current status of cert-manager resources
version Print the cert-manager CLI version and the deployed cert-manager version
Flags:
-h, --help help for kubectl
--log-flush-frequency duration Maximum number of seconds between log flushes (default 5s)
Use "kubectl cert-manager [command] --help" for more information about a command.
For the rest of this tutorial, you will also need to install the Nginx ingress controller:
$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
$ helm update
$ helm install ingress-controller ingress-nginx/ingress-nginx
Configure The Let's Encrypt Certificate Issuer
Issuers and cluster issuers are resources supplying certificates to the cluster. The Cert-Manager installation is unable to issue certificates. You need to configure an issuer for Let's Encrypt to dynamically acquires new certificates for your services:
ClusterIssuer resources are cluster-based while Issuer are namespace-based
We are going to set up a cluster issuer for staging and production usage. It is good to prefer staging while you configure your integration. It avoids hitting the Let's Encrypt production rate limit.
In the following cluster issuer manifests you need to replace the email address with yours
Staging
Create a YAML file named letsencrypt-staging.yaml
:
$ kubectl create -f letsencrypt-issuer-staging.yaml
Production
Create a YAML file named letsencrypt-production.yaml
$ kubectl create -f letsencrypt-issuer-staging.yaml
Obtain an HTTPS Certificate
The issuer is now in place and ready to retrieve a certificate for the services exposed by an ingress resource. Cert-manager monitors ingress resources and creates certificates based on the tls
field.
The YAML file above defined a deployment creating one pod, a service, and an ingress exposing the service. The ingress uses the Nginx controller deployed previously. Β The pod runs a WordPress container that will be reachable over HTTPS.
Cert-manager detects the annotation cert-manager.io/cluster-issuer
in the ingress resource. It will use letsencrypt-staging
cluster issuer to acquire a certificate for the hostname defined in the tls hosts field.
Once the acquisition of a certificate is validated with the staging issuer you can proceed to the production issuer. Staging certificates are valid but are not trusted by browsers. You have to replace the value of the ingress resource field cert-manager.io/cluster-issuer
with letsencrypt-production
Conclusion
We have seen how to expose a web application in a secure with HTTPS and an ingress. It is possible now to set up trusted and valid certificates for the cluster endpoints on the fly. There is just needed to add a simple annotation in the ingress resources. Cert-Manager monitors the ingress resources with this annotation and automates the provisioning of a valid Let's Encrypt certificate. It also deals with certificate renewal.