Kubernetes + Traefik + CertManager + LetsEncrypt

Why use k3s?

k3s is a lightweight Kubernetes distribution designed to be minimal and efficient, making it well-suited for resource-constrained environments and use cases where simplicity and ease of deployment are important. It was created by Rancher Labs and is intended to simplify the installation and management of Kubernetes clusters.

In this example use k3s with Traefik ingress controller so it’s a default by K3s and it’s a lightweight, easy, and fast solution, but if you prefer another one feel free to use it.

Why use cert manager?

Using cert-manager on Kubernetes simplifies SSL/TLS certificate management, automates the renewal process, integrates seamlessly with Kubernetes resources, and provides the flexibility to work with various certificate issuers. This results in enhanced security and reduced operational overhead for securing your Kubernetes applications.


1. Install k3s

1
curl -sfL https://get.k3s.io | sh -

If you want to have access to the k3s cluster outside the node, you can use the following parameter when creating the cluster --tls-san.

1
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--tls-san <public ip address or hostname>" sh -

By default, you do not have to execute permissions on k3.conf to resolve you need to move the file and give it the necessary permissions.

NOTE : It’s not recommended to give permissions to the original file.

1
2
3
4
5
mkdir $HOME/.kube
sudo cp /etc/rancher/k3s/k3s.yaml $HOME/.kube/config
sudo chmod 644 $HOME/.kube/config

export KUBECONFIG=~/.kube/config

You can add KUBECONFIG=~/.kube/config to your ~/.profile or ~/.bashrc to make it persist on reboot.


2. Install helm (optional)

This step is completely optional in order to follow the tutorial but highly recommended.

Helm is a package manager for Kubernetes that simplifies the deployment and management of applications in Kubernetes clusters.

Install Helm on K3s is really easy, just execute the script and you don’t need to modify any config !

1
2
3
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

3. Install cert manager

Mainly, we have two ways to install with helm or with kubectl. Personally I prefer to use the helm package manager with all the advantages that comes with it.

Add the oficial repository on Helm

1
helm repo add jetstack https://charts.jetstack.io

Update your local Helm chart repository

1
helm repo update

And install de cert-manager with namespace cert-manager

1
2
3
4
5
helm install \
 cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

NOTE : You can find the all config parameters on the oficial chart page: https://artifacthub.io/packages/helm/cert-manager/cert-manager

Option 2: Install by kubectl

1
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.4/cert-manager.crds.yaml

3.1 Verify the cert manager installation

1
kubectl -n cert-manager get pod

cert-manager pods


4. Create the ClusterIssuer resource

Create ClusterIssuer for staging environment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# cluster-issuer-staging.yaml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
  namespace: default
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: <YOUR_EMAIL> # replace for your valid email
    privateKeySecretRef:
      name: letsencrypt-staging
    solvers:
    - selector: {}
      http01:
        ingress:
          class: traefik
1
kubectl apply -f cluster-issuer-staging.yaml

Create ClusterIssuer for production environment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# cluster-issuer-production.yaml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-production
  namespace: default
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: <YOUR_EMAIL> # replace for your valid email
    privateKeySecretRef:
      name: letsencrypt-production
    solvers:
    - selector: {}
      http01:
        ingress:
          class: traefik
1
kubectl apply -f cluster-issuer-production.yaml

Verify that it has been properly applied

1
kubectl get ClusterIssuer -A

kubernetes ClusterIssuer

And check the status of ClusterIssuer

1
2
kubectl describe clusterissuer letsencrypt-staging
kubectl describe clusterissuer letsencrypt-production

5. Let’s play!

Finally we are going to create our certificate

5.1 Create a dummy application

In this step just create a very basic dummy nginx application, if you already have an application you can go to the next step.

Create a deployment using a default image from nginx:alpine

1
kubectl create deployment nginx --image nginx:alpine

Show the deployments status

1
kubectl get deployments

kubernetes deployments

1
kubectl describe deployment nginx

Expose the server at port 80

1
kubectl expose deployment nginx --port 80 --target-port 80

Check that the service is correct and running

1
kubectl get svc

kubernetes services

5.2 Create a ingress traefik controller

Define the trafik ingress with the cert-manager annotations and the tsl section to be able to manage our certificate.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# ingress ingress-nginx.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-production
    kubernetes.io/ingress.class: traefik
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  rules:
  - host: example.com # Change by your domain
    http:
      paths:
      - backend:
          service:
            name: nginx
            port: 
              number: 80
        path: /
        pathType: Prefix  
  tls:
  - hosts:
    - example.com # Change by your domain
    secretName: example-com-tls
1
kubectl apply -f ingress-nginx.yaml

Verify that the certificate has actually been created

1
kubectl get cert -n default

NOTE : I change the host example.com to letsencrypt-k3s.albertcolom.com and change example-com-tls to letsencryptk3s-albertcolom-com-tls .

kubernetes certificates

You can show the valid certificated by Let’s Encrypt!

valid certificate


Conclusion

Once you have installed cert manager it is really easy to manage your certificates together with traefik. You just have to set a couple of parameters in the ingress and the system takes care of everything.

No more excuses for not using a valid certificate!

You can read the article on Medium