After hosting an application on Kubernetes we need to configure TLS/SSL certificate to serve our application over HTTPS securely. Configuring certificates in Kubernetes is a little tedious task because we need to apply certificates, configure them for auto-renewal and get certificates from trusted CA automatically.
Cert-manager comes here to rescue certificate management.
What is a cert-manager?
cert-manager adds certificates and certificates issuer as resource types in Kubernetes clusters and simplifies the process of obtaining, renewing, and using those certificates. It is running by jet stack under an open-source project.
Some of the features of cert-manager are:
- cert-manager can issue certificates from a variety of supported sources, including Let’s Encrypt, HashiCorp Vault, and Venafi as well as private PKI.
- It will ensure certificates are valid and up to date, and attempt to renew certificates at a configured time before expiry.
- It is loosely based upon the work of Kube-lego and has borrowed some wisdom from other similar projects such as Kube-cert-manager.
- Kubernetes Cluster
- Ingress controller installed in the Kubernetes cluster
- A sample application running on Kubernetes cluster
- Knowledge of Helm charts
Installing Cert-Manager in Kubernetes
Firstly, we have to install a cert-manager in Kubernetes using helm charts.
Add cert-manager official repo in your helm:
$ helm repo add cert-manager https://charts.jetstack.io
Update helm repo:
$ helm repo update
Install helm Chart on Kubernetes:
$ helm install my-cert-manager cert-manager/cert-manager --version 1.7.2 --create-namespace
Now, wait for the pods to be coming up and then run the below command to check the status of your cert-manager pods:
$ kubectl get pods -n cert-manager NAME READY STATUS RESTARTS AGE cert-manager-765bfbb47b-rfrtn 1/1 Running 0 2m cert-manager-cainjector-55db655cd8-khkcs 1/1 Running 0 2m cert-manager-webhook-7d8c86cb4c-qxv7h 1/1 Running 0 2m
Issuer: Firstly, you’ll need to configure after you’ve installed cert-manager is an issuer which you can then use to issue certificates.
ClusterIssuers, are Kubernetes resources that represent certificate authorities (CAs) that are able to generate signed certificates by honoring certificate signing requests. All cert-manager certificates require a referenced issuer that is in a ready condition to attempt to honor the request.
There supported issue types in cert-manager are ACME, vault, venafi-tpp, External(AWS PCA, other external certificate providers).
Below is an example of a lets-encrypt Cluster-issuer:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: email: email@example.com server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: traefik-cert-manager
Certificate: cert-manager has the concept of
Certificates that define a desired X.509 certificate which will be renewed and kept up to date. A
Certificate is a namespaced resource that references an
ClusterIssuer that determine what will be honoring the certificate request. Below is an example:
apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: webapp namespace: demo-2 spec: secretName: webapp-secret dnsNames: - prod.himanshuchaudhary.tech issuerRef: name: letsencrypt-prod kind: ClusterIssuer
In the above certificate object, we have the following important terms:
- secretName: It is used to store the certificate and the key in the Kubernetes secret.
- dnsNames: The domain name for which you want to generate the certificate.
- issuerRef: The reference to the issuer created and the kind of the issuer, whether it is a cluster issue or issuer.
Kubernetes Secrets: Kubernetes secrets are objects that store data in base64 encoded values. Here certificate objects store the certificates and keys using these secrets.
Note: Please create a DNS entry for your domain and point the DNS to your ingress controller load balancer.
Apply the manifest file to the cluster:
$ kubectl apply -f letsencrypt-prod.yml $ kubectl apply -f certificate-webapp.yml
Note: You have to apply the certificate in the namespace where your application is running.
Now, check the status for both cluster issuer and certificate.
$ kubectl get clusterissuer NAME READY AGE letsencrypt-prod True 1m $ kubectl get certificate NAME READY SECRET AGE certificate-webapp True webapp-secret 2m
The status of the cluster issuer is True which means it is ready to be consumed. The certificate’s object is ready and also we can check the generated secret which consists of a certificate and a key.
$ kubectl get secrets
NAME TYPE DATA AGE
webapp-secret kubernetes.io/tls 2 114d
Here is the ingress object for our application to serve the external traffic to the cluster over HTTPS securely:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: webapp namespace: demo-2 annotations: kubernetes.io/ingress.class: traefik-cert-manager spec: rules: - host: prod.himanshuchaudhary.tech http: paths: - pathType: Prefix path: / backend: service: name: mywebapp port: number: 80 tls: - hosts: - prod.himanshuchaudhary.tech secretName: webapp-secret
Here, I have added the secret name to be used which contains the certificate. It can take up to 1-2 hours to apply certificates to the domain.
In this blog, we learned how can we apply certificates to our website using cert-manager to server our application over HTTPS.
For any queries and more information, you can reach out to me at firstname.lastname@example.org