If you have created an application, you will need to expose it to the outside world through HTTPS. If you're working working with Kubernetes to deploy your application, you have powerful tools such as cert-manager and LetsEncrypt that can help you achieve this.
Throughout this tutorial, we will be setting everything up from scratch. This means the following guide can be applied to any Kubernetes cluster, but by using Civo Kubernetes it becomes easier as you have ready-to-use marketplace applications that will make things easier.
If you would like to try this on your own cluster that's not on Civo, you will need to install Traefik and cert-manager on your own. In this tutorial, I will add the installations commands separately for both Traefik and cert-manager.
Civo Kubernetes cluster creation
The first step of this process is to have a Kubernetes cluster created. For this tutorial, I will be using Civo Kubernetes as it is super fast with a <2 minute launch time. This will also allow me to utilize the power of Civo Marketplace which means I can install my favourite Kubernetes applications in seconds.
I will be using Civo CLI to create the cluster, which can be installed from here. If you would prefer to use the Civo web interface, you can do that too.
On the CLI, let's create our cluster:
civo k3s create https-civo --remove-applications=traefik2-nodeport --applications traefik2-loadbalancer,cert-manager
The cluster https-civo (45fab9fd-daaa-41ae-a1e8-7642d97f1c6b) has been created
The above example will create a 3 node cluster named https-civo
, and install Traefik in loadbalancer mode, as well as cert-manager at the same time. Once the cluster is up and running in a couple of minutes, we can proceed.
We will then need to get the Kubeconfig for the cluster and save it to our desired location. If you do not specify a path, it will save it to the default location of ~/.kube/config
:
civo k3s config https-civo --save --local-path /Users/saiyam/Downloads/https-civo.config
Merged with main kubernetes config: /Users/saiyam/Downloads/https-civo.config
Let's make sure that kubectl knows to use our cluster's configuration file. Make sure you specify the path where you saved your configuration file:
$ export KUBECONFIG=/Users/saiyam/Downloads/https-civo.config
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s-https-civo-4ba6-29bb47-node-pool-7071-t6g2y Ready <none> 2m14s v1.22.11+k3s1
k3s-https-civo-4ba6-29bb47-node-pool-7071-fi3vh Ready <none> 94s v1.22.11+k3s1
k3s-https-civo-4ba6-29bb47-node-pool-7071-5djri Ready <none> 13s v1.22.11+k3s1
We can also check if the Traefik Loadbalancer and cert-manager components are installed:
$ kubectl get all -n kube-system | grep traefik
pod/helm-install-traefik-crd-sjmk5 0/1 Completed 0 3m4s
pod/helm-install-traefik-2f6dq 0/1 Completed 2 3m4s
pod/traefik-znjw7 1/1 Running 0 2m15s
pod/traefik-svwxg 1/1 Running 0 2m15s
pod/traefik-6nqhm 1/1 Running 0 59s
service/traefik LoadBalancer 10.43.157.236 74.220.22.175 80:32429/TCP,443:32409/TCP 2m16s
daemonset.apps/traefik 3 3 3 3 3 <none> 2m17s
$ kubectl get pods -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-848f547974-z88kf 1/1 Running 0 3m39s
cert-manager-cainjector-54f4cc6b5-n26m5 1/1 Running 0 3m39s
cert-manager-webhook-7c9588c76-xrrq9 1/1 Running 0 3m39s
If you are not using Civo Kubernetes, you need to install Traefik following the documentation and make sure you have some arguments passed such as the ones below:
- args:
- --global.checknewversion
- --global.sendanonymoususage
- --entrypoints.metrics.address=:9100/tcp
- --entrypoints.traefik.address=:9000/tcp
- --entrypoints.web.address=:8000/tcp
- --entrypoints.websecure.address=:8443/tcp
- --api.dashboard=true
- --ping=true
- --metrics.prometheus=true
- --metrics.prometheus.entrypoint=metrics
- --providers.kubernetescrd
- --providers.kubernetesingress
- --providers.kubernetesingress.ingressendpoint.publishedservice=kube-system/traefik
- --entrypoints.websecure.http.tls=true
To install cert-manager to a non-Civo Kubernetes cluster, you can run the below command:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml
Now you should have a Kubernetes cluster with Traefik and cert-manager installed automatically if using Civo Kubernetes and selecting the apps during installation or manually using the mentioned methods above.
Create a ClusterIssuer
In order to get cert-manager to issue us a valid certificate, you need to create a Cluster Issuer resource in your cluster.
Change the email address in the snippet below, save it as clusterissuer.yaml
and then apply the YAML file to the cluster with kubectl apply -f clusterissuer.yaml
:
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: saiym911@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
Once this has been applied you should see clusterissuer.cert-manager.io/letsencrypt-prod created
returned from the cluster.
Create a certificate
For this step, you need to use your Traefik DNS or website configuration to create a certificate. When using Civo and the Civo CLI, you can find this out using the civo k3s show CLUSTER_NAME
command and get the information from the Load balancers section shown in the output. It should look something like this:
Loadbalancers:
+--------------------------------+-------------+---------------+--------------+-----------+--------------------------------------+--------------------------------------------------+
| Name | Algorithm | Public IP | Private IP | State | Firewall | DNS Name |
+--------------------------------+-------------+---------------+--------------+-----------+--------------------------------------+--------------------------------------------------+
| https-civo-kube-system-traefik | round_robin | 74.220.22.175 | 192.168.1.52 | available | c9e14ae8-b8eb-4bae-a687-9da4637233da | 0d652485-6bb6-465f-b3b3-eb12485d9aee.lb.civo.com |
+--------------------------------+-------------+---------------+--------------+-----------+--------------------------------------+--------------------------------------------------+
Use the DNS name in the commonName
and dnsNames
sections of this, the Certificate resource definition:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: demo
namespace: default
spec:
secretName: demo
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
commonName: demo.0d652485-6bb6-465f-b3b3-eb12485d9aee.lb.civo.com
dnsNames:
- demo.0d652485-6bb6-465f-b3b3-eb12485d9aee.lb.civo.com
Save the file as certificate.yaml
and apply it to your cluster with kubectl apply -f certificate.yaml
.
Once this has been applied, you will get the result: certificate.cert-manager.io/demo created
Create the demo nginx app
Next, you will need to create the demo nginx application with a clusterIP service. This is the application that will be exposed on our cluster over HTTPS. Save the following as application.yaml
:
kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx-demo
namespace: default
labels:
app: nginx-demo
spec:
replicas: 1
selector:
matchLabels:
app: nginx-demo
template:
metadata:
labels:
app: nginx-demo
spec:
containers:
- name: nginx
image: "nginx"
---
apiVersion: v1
kind: Service
metadata:
name: nginx-demo
namespace: default
spec:
selector:
app: nginx-demo
ports:
- name: http
targetPort: 80
port: 80
You will need to apply this to your cluster, with kubectl apply -f application.yaml
.
Once this is applied, you should be able to check for the application pod and service coming up with the relevant commands:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-demo-7d56b74b84-h6zww 1/1 Running 0 80s
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 16m
nginx-demo ClusterIP 10.43.130.181 <none> 80/TCP 84s
Create the ingress
Now is the time to create the ingress that will allow the application to be accessed from outside the cluster. Save the following definition YAML file, making sure you edit in the host
to match your cluster's details:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/ingress.class: traefik
name: nginx-ingress
namespace: default
spec:
rules:
- host: demo.0d652485-6bb6-465f-b3b3-eb12485d9aee.lb.civo.com
http:
paths:
- backend:
service:
name: nginx-demo
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- demo.0d652485-6bb6-465f-b3b3-eb12485d9aee.lb.civo.com
secretName: demo
Once applied, you will be able to see that the ingress has been created by the following result:
$ kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
nginx-ingress <none> demo.0d652485-6bb6-465f-b3b3-eb12485d9aee.lb.civo.com 74.220.22.175 80, 443 15s
Now, it's time to hit the HTTPS endpoint and feel the joy of exposing your application to the internet over HTTPS. You'll need to run the command curl -k https://demo.your-cluster-loadbalancer-id.lb.civo.com
as follows:
$ curl -k https://demo.0d652485-6bb6-465f-b3b3-eb12485d9aee.lb.civo.com
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h2>Welcome to nginx!</h2>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Or, you could hit the URL with your web browser:
You can see that the connection has been over HTTPS and the browser recognises the certificate as valid.
Conclusion
Now that we have reached the end of this tutorial, you have learned how to expose your applications to the internet with HTTPS using Civo Kubernetes, Traefik, and cert-manager (which can be installed via Civo Marketplace.
We would love to hear what other methods you use to expose applications over HTTPS? Let us know and we would be happy to add a post about it.