In previous articles we talked about installing a k3s cluster, using Longhorn for resilient storage and using MetalLB for load-balancing. We still need to address a couple of things before deploying a simple workload.
If you plan to expose some Kubernetes workloads as a public domain or subdomain, you’ll most likely want either a mix of http and https traffic or exclusively https. In order to achieve https, your domain/subdomain will have to present a valid certificate, which a browser can then validate.
If you feel the need to find out more on the topic, you can check this video about TLS and this article about SSL/TLS termination.
I did previously touch on this topic in an article about using Nginx Proxy Manager for your Docker workloads. This is similar, but in the context of Kubernetes.
This article assumes you have a DNS provider with API access, in my case it’s Cloudflare.
Setup
First, install Cert-Manager in your cluster by running this command:
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
This will also create the cert-manager namespace, so you don’t have to do that.
Next, we’ll create a K8s secret containing the DNS provider API token. If you need some help generating a token for Cloudflare, you can check this article. The main thing is it needs to have permissions to edit the DNS of the domains (zones) you will want managed by Cert-Manager (see screenshot below).

Create a file named cloudflare-api-token-secret.yml with the following content:
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token-secret
namespace: cert-manager
type: Opaque
stringData:
api-token: YOUR_CLOUDFLARE_API_TOKEN
Replace YOUR_CLOUDFLARE_API_TOKEN with the token you previously generated.
You can create it by running:
$ kubectl apply -f cloudflare-api-token-secret.yml
Next, we’ll create a ClusterIssuer custom resource, used by Cert-Manager. Create a file named cluster-issuer.yml with this content:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-dns
spec:
acme:
email: [email protected]
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-dns-account-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
Replace [email protected] with your actual email address. You can see it references the secret you previously created for Cloudflare. Apply it by running:
$ kubectl apply -f cluster-issuer.yml
That should be it, you should now be able to use it on your ingress resources. For example, in a previous article we installed Longhorn for resilient storage. In order to expose Longhorn’s UI through an ingress, you’d define the ingress like this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: longhorn-ingress
namespace: longhorn-system
annotations:
cert-manager.io/cluster-issuer: letsencrypt-dns
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
rules:
- host: longhorn.k3s.alexmihai.rocks
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: longhorn-frontend
port:
number: 80
tls:
- hosts:
- longhorn.k3s.alexmihai.rocks
secretName: longhorn-k3s-tls
You can see it references the ClusterIssuer we have defined and in the tls section of the definition, it asks for a certificate for the longhorn.k3s.alexmihai.rocks host, which will be stored in the longhorn-k3s-tls secret.
Hope this helps, have fun clickity-clacking.
Leave a Reply