How to Deploy a Secure Nginx Website on Vultr Kubernetes Engine
Deploying 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.
Prerequisites
- 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.
Install the Traefik Ingress Controller with Helm
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
Creating Nginx Deployment and Service
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
Creating Traefik Ingress and Exposing Nginx Website
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 namenginxweb.example.com
.
Configuring cert-manager for Traefik Ingress
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
Configuring and Creating Traefik Ingress Let's Encrypt TLS Certificate
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
Define Let's Encrypt Certificate in Traefik Ingress Resource
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: {}
Verify HTTPS
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
Conclusion
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.