Recently, I tried to setup letsencrypt using microk8s and the default ingress controller on a bare-metal server.
I found a few guides online that were very useful but it seems as if there must have been a recent update to microk8s that changed the way the ingress controller is configured.
To save you guys time, I wrote out exactly what I did.
Here are some useful resources if you get stuck or to get a better understanding.
https://cert-manager.io/docs/installation/kubernetes/
https://cert-manager.io/docs/tutorials/acme/ingress/
This link was really useful for troubleshooting
https://cert-manager.io/docs/faq/acme/
By default, Let's Encrypt certificates expire every 90 days. Let's Encrypt usually sends an e-mail (like the one above) to the address associated with the Certificate resource created in Kubernetes to remind the cluster admin to renew it. As a best practice, certificates should be renewed about 30 days before expiry.
cert-manager adds certificates and certificate issuers as resource types in Kubernetes clusters, and simplifies the process of obtaining, renewing and using those certificates. It can issue certificates from a variety of supported sources, including Let's Encrypt, HashiCorp Vault, and Venafi as well as private PKI.
This guide is to set up Letsencrypt with Kubernetes using Microk8s and the default Ingress controller.
Versions used:
microk8s version 1.21/stable
cert-manager v1.3.1
Pre-requisite: Forward ports 80 & 443 to your server. Set up a domain name that points to your server.
Install microk8s
snap install microk8s --classic --channel=1.21/stable
Enable dns and ingress
sudo microk8s enable dns ingress
We'll create a test webserver deployment/service using the nginx webserver image to test web traffic
webserver-depl-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webserver-depl
spec:
selector:
matchLabels:
app: webserver-app
template:
metadata:
labels:
app: webserver-app
spec:
containers:
- name: webserver-app
image: nginx:1.8
---
apiVersion: v1
kind: Service
metadata:
name: webserver-svc
spec:
selector:
app: webserver-app
ports:
- name: webserver-app
protocol: TCP
port: 80
targetPort: 80
apply the config file
sudo microk8s kubectl apply -f webserver-depl-svc.yaml
now to configure the default ingress to serve the test webserver
ingress-routes.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-routes
spec:
rules:
#change yourdomain.com to your domain
- host: yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webserver-svc
port:
number: 80
Apply the ingress routes
sudo microk8s kubectl apply -f ingress-routes.yaml
When you visit yourdomain.com, you should see the default "welcome to nginx!" splash screen.
Now to install cert-manager https://cert-manager.io/docs/installation/kubernetes/
sudo microk8s kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
The next command should show 3 pods to confirm cert-manager is installed and running
sudo microk8s kubectl get pods --n=cert-manager
Now to create the certificate issuer config. A detail to notice is that the class used in this config is public as opposed to nginx. This may be microk8s specific. https://cert-manager.io/docs/tutorials/acme/ingress/
letsencrypt-staging.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
#change to your email
email: [email protected]
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
class: public
letsencrypt-prod.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
#change to your email
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: public
Apply both issuer configs
sudo microk8s kubectl apply -f letsencrypt-staging.yaml
sudo microk8s kubectl apply -f letsencrypt-prod.yaml
now to update ingress-routes.yaml to use the staging certificate.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-routes
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-staging"
spec:
tls:
- hosts:
#change to your domain
- yourdomain.com
secretName: tls-secret
rules:
#change to your domain
- host: yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webserver-svc
port:
number: 80
Apply the update
sudo microk8s kubectl apply -f ingress-routes.yaml
Run the next command to confirm Ready=True
sudo microk8s kubectl get certificate
If it returned true, that means HTTP-01 challenge was successful. You can see more detail at the end of output running the next command
sudo microk8s kubectl describe certificate tls-secret
Now to change ingress-routes.yaml to use the production certificate.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-routes
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
#change to your domain
- yourdomain.com
secretName: tls-secret
rules:
#change to your domain
- host: yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webserver-svc
port:
number: 80
Apply the update
sudo microk8s kubectl apply -f ingress-routes.yaml
Now the moment of truth. Run the next command to confirm a certificate was generated. Ready=True
sudo microk8s kubectl get certificate
Run the next command and look at the final output to verify the certificate was issued.
sudo microk8s kubectl describe certificate tls-secret
Now if you visit your domain. You should see the little lock of success! :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With