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
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: youremail@gmail.com
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: youremail@gmail.com
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! :-)
Update December 2021:
I had to update ingress-routes.yaml
to get this to work:
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