When deploying to Kubernetes, there can be scenarios where you would want to use your own TLS certificates for ingress rather than Let's Encrypt or another external provider.

In this tutorial, I will show you how to set up your own certificates.

Step 1 - Civo Kubernetes cluster creation

You can create the cluster from the UI or from the Civo CLI. For this tutorial, let's create using the CLI.

$ civo k3s create
The cluster green-stone (14e7bb11-b41f-4e4b-a177-dd97670a0183) has been created

Above will create a 3 node cluster named green-stone. The name has been generated randomly as we did not provide a name. Once the cluster is up and running in a few minutes, we can proceed.

We will need to get the Kubeconfig for the cluster and save 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 green-stone --save --local-path /Users/saiyampathak/civo/test/tls-demo.config

Access your cluster with:
KUBECONFIG=/Users/saiyampathak/civo/test/tls-demo.config kubectl get node

Let's make sure that kubectl knows to use our cluster's configuration file:

$ export KUBECONFIG=/Users/saiyampathak/civo/test/tls-demo.config

$ kubectl get nodes
NAME                                   STATUS   ROLES    AGE   VERSION
NAME                                         STATUS   ROLES    AGE   VERSION
k3s-green-stone-4e4d-cc89a2-node-pool-860c   Ready    <none>   47h   v1.20.2+k3s1
k3s-green-stone-4e4d-cc89a2-node-pool-e1ea   Ready    <none>   47h   v1.20.2+k3s1
k3s-green-stone-4e4d-cc89a2-node-pool-caf8   Ready    <none>   47h   v1.20.2+k3s1

Step 2 - Create certificates

For this tutorial, create a self-signed certificate with OpenSSL. In a real-world scenario, you should request a signed certificate from a certificate authority.

Make sure your computer has OpenSSL installed, and run the following, making sure to replace the 14e7bb11-b41f-4e4b-a177-dd97670a0183.k8s.civo.com string in your command with the DNS A record of your cluster. You can get this record by running civo k8s show your-cluster-name and viewing the A record section.

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048     -out civo-ingress-tls.crt      -keyout civo-ingress-tls.key      -subj "/CN=14e7bb11-b41f-4e4b-a177-dd97670a0183.k8s.civo.com/O=civo-ingress-tls"

Generating a 2048 bit RSA private key
..........................................................................+++
....................................................................................................................................................+++
writing new private key to 'civo-ingress-tls.key'
-----
$ ls
civo-ingress-tls.crt civo-ingress-tls.key

Step3 - Create Kubernetes secret

Create a Kubernetes TLS secret in order to use the key generated in the previous step. This secret will be used later in the ingress.

$ kubectl create secret tls civo-ingress-tls --key civo-ingress-tls.key --cert civo-ingress-tls.crt
secret/civo-ingress-tls created

Step 4 - Create deployment, service and ingress

Let's create the deployment. For this demo we will be using a sample "hello world" application image:

$ kubectl create deployment demo --image=gcr.io/google-samples/hello-app:1.0
deployment.apps/demo created

Expose the deployment as a service:

$ kubectl expose deployment demo --port=8080
service/demo exposed

Now, we need to create the ingress with TLS. Civo Kubernetes ships with Traefik as the default ingress controller so you can directly create the ingress. Save the following yaml file as ingress.yaml in your current directory, making sure to edit where noted:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
spec:
  tls:
  - hosts:
    - 14e7bb11-b41f-4e4b-a177-dd97670a0183.k8s.civo.com # Replace with your cluster DNS name
    secretName: civo-ingress-tls
  rules:
  - host: 14e7bb11-b41f-4e4b-a177-dd97670a0183.k8s.civo.com # Replace with your cluster DNS name
    http:
      paths:
      - backend:
          service:
            name: demo
            port:
              number: 8080
        path: /demo
        pathType: Prefix

Then apply this ingress to your cluster to allow us to access the application:

$ kubectl apply -f ingress.yaml 
ingress.networking.k8s.io/demo-ingress created

Verify the ingress is correctly set up with kubectl get ing:

kubectl get ing
NAME           CLASS    HOSTS                                                    ADDRESS         PORTS     AGE
demo-ingress   <none>   demo.14e7bb11-b41f-4e4b-a177-dd97670a0183.k8s.civo.com   212.2.240.135   80, 443   6h56m

Step 5 - Check everything works

You already get a DNS with your Civo Kubernetes cluster so you can test using the curl command, replacing domain string below with your cluster's A record:

curl -v -k https://14e7bb11-b41f-4e4b-a177-dd97670a0183.k8s.civo.com/demo

There will be a complete verbose output but you can see that in the server certificate section, the issuer and the secret will be mentioned.

 Server certificate:
*  subject: CN=14e7bb11-b41f-4e4b-a177-dd97670a0183.k8s.civo.com; O=civo-ingress-tls
*  start date: Jan  4 18:44:06 2022 GMT
*  expire date: Jan  4 18:44:06 2023 GMT
*  issuer: CN=14e7bb11-b41f-4e4b-a177-dd97670a0183.k8s.civo.com; O=civo-ingress-tls
*  SSL certificate verify result: self signed certificate (18), continuing anyway.

And the request will be served completely, in the end of the output of the curl request you can see the output.

Hello, world!
Version: 1.0.0
Hostname: demo-6cfc75f989-bzlsm

Wrapping up

This is how you can use self signed certificates for ingress.

Let us know on Twitter @Civocloud and @SaiyamPathak if you try your own certificate out on Civo Kubernetes or face any issues.