Author: Hitesh Jethva
Last Updated: Wed, Jan 4, 2023Deploying an Nginx website on Vultr Kubernetes Engine will help you to achieve reliability and scalability. Protecting sensitive data and securing website traffic with SSL/TLS is also necessary for all websites. However, it can be challenging to host SSL/TLS-based Nginx websites on Kubernetes.
This is the case where Traefik Proxy comes into the picture. You can use and set up Traefik Proxy as a network proxy with a cert-manager to install and manage Let's Encrypt SSL certificates. Let's Encrypt is a free certificate authority that provides a way to automate and manage SSL certificates for your website.
This guide shows you how to secure the Nginx website with cert-manager, Traefik, and Let's Encrypt SSL on Vultr Kubernetes Engine.
Deploy a Kubernetes cluster at Vultr with at least three or more nodes with 2GB RAM and 2 CPUs.
Install kubectl
on your local machine.
Install Helm client on your local machine.
Add the Helm repository for the Traefik ingress controller.
# helm repo add traefik https://helm.traefik.io/traefik
Update the Helm repository.
# helm repo update
Install Traefik on your Kubernetes cluster.
# helm install traefik traefik/traefik
Sample output.
NAME: traefik
LAST DEPLOYED: Sat Nov 26 19:56:05 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Traefik Proxy v2.9.5 has been deployed successfully on default namespace !
Verify the Traefik ingress controller service.
# kubectl get svc
Sample output.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5m16s
traefik LoadBalancer 10.96.215.40 192.0.2.100 80:31391/TCP,443:30688/TCP 3m
Now, deploy an Nginx web server using the Nginx docker image on the Kubernetes cluster.
Create an nginx-deployment.yml
configuration file.
# nano nginx-deployment.yml
Add the following configuration:
kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx-web
namespace: default
labels:
app: nginx-web
spec:
replicas: 1
selector:
matchLabels:
app: nginx-web
template:
metadata:
labels:
app: nginx-web
spec:
containers:
- name: nginx
image: "nginx"
Apply the above configuration to the Kubernetes cluster.
# kubectl create -f nginx-deployment.yml
Sample output.
deployment.apps/nginx-web created
Create an Nginx service to expose pods to the cluster on port 80
.
# nano nginx-service.yml
Add the following configuration.
apiVersion: v1
kind: Service
metadata:
name: nginx-web
namespace: default
spec:
selector:
app: nginx-web
ports:
- name: http
targetPort: 80
port: 80
Apply the configuration to the Kubernetes cluster.
# kubectl create -f nginx-service.yml
Sample output.
service/nginx-web created
Create a Traefik Ingress deployment to expose an Nginx website to the outside world.
# nano traefik-ingress.yml
Add the following configurations:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: nginxweb.example.com
http:
paths:
- backend:
service:
name: nginx-web
port:
number: 80
path: /
pathType: Prefix
Note: Replace
nginxweb.example.com
with a fully qualified domain name.
Apply the Traefik ingress resource to the cluster.
# kubectl create -f traefik-ingress.yml
Sample output.
ingress.networking.k8s.io/traefik-ingress created
Verify the running pods.
# kubectl get pods
Sample output.
NAME READY STATUS RESTARTS AGE
nginx-web-6b756d6954-mg5v4 1/1 Running 0 60s
traefik-6c95797465-7ck46 1/1 Running 0 6m9s
Verify the Kubernetes ingress resources.
# kubectl get ingress
Sample output.
NAME CLASS HOSTS ADDRESS PORTS AGE
traefik-ingress <none> nginxweb.example.com 80 119s
Verify the Kubernetes service to retrieve the Traefik external IP.
# kubectl get svc
Sample output.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9m50s
nginx-web ClusterIP 10.104.168.40 <none> 80/TCP 2m16s
traefik LoadBalancer 10.96.215.40 192.0.2.100 80:31391/TCP,443:30688/TCP 7m34s
Point Traefik LoadBalancer external IP 192.0.2.100
to your domain name nginxweb.example.com
.
cert-manager is a certificate management controller for Kubernetes that allows you to download, renew and use Let's Encrypt or other SSL certificates.
Run the kubectl
command to install cert-manager using the cert-manager's release file on the Kubernetes cluster.
# kubectl apply --validate=false -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml
Sample output.
service/cert-manager created
service/cert-manager-webhook created
deployment.apps/cert-manager-cainjector created
deployment.apps/cert-manager created
deployment.apps/cert-manager-webhook created
mutatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
validatingwebhookconfiguration.admissionregistration.k8s.io/cert-manager-webhook created
First, create the ClusterIssuer
for the Kubernetes cluster to issue certificates from Let's Encrypt.
# nano letsencrypt-issuer.yml
Add the following configurations.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: default
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: hitjethva@gmail.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: traefik
Deploy the above configuration to the Kubernetes cluster.
# kubectl apply -f letsencrypt-issuer.yml
Sample output.
clusterissuer.cert-manager.io/letsencrypt-prod created
Create the Traefik Ingress Let's Encrypt TLS certificate for your Nginx website.
# nano letsencrypt-certificate.yml
Add the following configurations.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: nginxweb.example.com
namespace: default
spec:
secretName: nginxweb.example.com-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
commonName: nginxweb.example.com
dnsNames:
- nginxweb.example.com
Apply the above configuration to the cluster.
# kubectl apply -f letsencrypt-certificate.yml
This will create a Traefik Ingress Let's Encrypt TLS certificate for the domain nginxweb.example.com
.
certificate.cert-manager.io/nginxweb.example.com created
Verify the created certificate.
# kubectl get certificates nginxweb.example.com
Sample output.
NAME READY SECRET AGE
nginxweb.example.com True nginxweb.example.com-tls 55s
After creating Traefik Ingress Let's Encrypt SSL, define the certificate in traefik-ingress.yml
.
Edit the traefik-ingress.yml
using the nano
editor.
# KUBE_EDITOR= "nano" kubectl edit ingress traefik-ingress
Change the file with the following configuration.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/ingress.class: traefik
creationTimestamp: "2022-11-26T14:32:09Z"
generation: 1
name: traefik-ingress
namespace: default
resourceVersion: "2125"
uid: 942404bd-6031-4a31-9f89-eccbc66b80f6
spec:
rules:
- host: nginxweb.example.com
http:
paths:
- backend:
service:
name: nginx-web
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- nginxweb.example.com
secretName: nginxweb.example.com-tls
status:
loadBalancer: {}
Your Nginx website is now deployed on the Kubernetes cluster with Let's Encrypt SSL. You can now verify it by visiting the URL https://nginxweb.example.com
in your web browser. You can also verify the Nginx website using curl.
# curl -L https://nginxweb.example.com
You have deployed an Nginx website with cert-manager, Traefik, and Let's Encrypt SSL on Vultr Kubernetes Engine. You can also deploy and serve many websites on the same cluster using different Ingress resources. For more information, visit the Traefik Proxy documentation page.