How To Configure Ingress TLS/SSL Certificates in Kubernetes

In this guide we will learn how to configure TLS/SSL in kubernetes using ingress for already existing ssl certificates (either Self-Signed) or purchased ones.

For this to work, you should also have a working ingress set up. We will use Nginx Ingress. You should also have the domain used already configured with the Nginx ingress endpoint record.

Checkout related content:

# Obtaining a TLS Certificate

The basic requirement for ingress TLS is a TLS/SSL certificate. You can obtain these certificates in the following ways.

  1. Self-Signed Certificates: TLS certificate created and signed by our own Certificate Authority. It is great option for development environments where you can share the root CA with the team so that browsers can trust the certificate.
  2. Purchase an SSL Certificate: You can buy an SSL Certificate from one of the many well-known certificate authority trusted by browsers & operating systems for production use cases.
  3. Use Letsencrpt Certificate: Letsencrypt is a non-profit trusted certificate authority that provides free TLS certificates.

Every SSL certificate comes with an expiry date. So you need to rotate the certificate before it expires. For example, Letsecrypt certificates expire every three months.

In this guide we will need a certificate from one of the first two options. If you do not have a certificate already, create a Self-Signed certificate. Use this command:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout citizix-k8s.key -out citizix-k8s.crt

This will prompt you to fill. This command produces two files: citizix-k8s.key and citizix-k8s.crt. In production, you’d generate a key file and use it to obtain a certificate from a certificate authority.

This is the output from my machine:

➜ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout citizix-k8s.key -out citizix-k8s.crt
Generating a 2048 bit RSA private key
......................................................................+++
.......+++
writing new private key to 'citizix-k8s.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:KE
State or Province Name (full name) []:Nairobi
Locality Name (eg, city) []:Nairobi
Organization Name (eg, company) []:Citizix
Organizational Unit Name (eg, section) []:Devops
Common Name (eg, fully qualified host name) []:citizix-k8s.citizix.com
Email Address []:admin@citizix.com

# TLS/SSL with Ingress in kubernetes

SSL is** handled by the ingress controller, not the ingress resource**. Meaning, when you add TLS certificates to the ingress resource as a kubernetes secret, the ingress controller access it and makes it part of its configuration.

For example, in the Nginx controller, the SSL certificates are dynamically handled by the following block in nginx.conf

ssl_certificate_by_lua_block {
    certificate.call()
}

# Deploy a Test Application

In this section, we will create a simple application in kubernetes that we can use to test out certificate. We will create a deployment, service and an ingress.

Make sure you also have access to a kubernetes cluster and are in the right kubernetes cluster. Confirm with this command:

kubectl cluster-info

Then create a namespace where all our resources will reside:

 kubectl create ns apps

Now create a deployment in the namespace:

kubectl create deploy -n apps nginx --image nginx:latest

Use this command to confirm that the deployment was created as expected:

➜ k get deploy -n apps
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   1/1     1            1           13s

Confirm that the pods are running:

➜ k get pods -n apps
NAME                     READY   STATUS    RESTARTS   AGE
nginx-55649fd747-mnrvv   1/1     Running   0          36s

Then expose our deployment as a service:

kubectl expose deployment nginx -n apps --type=ClusterIP --name=nginx --port 80

Confirm:

➜ k get svc -n apps
NAME    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   172.20.250.180   <none>        80/TCP    11s

# Create a kubernetes TLS

We can issue the kubectl create command to create a secret from the command line.

When creating a TLS Secret using kubectl, you can use the tls subcommand as shown in the following example:

kubectl create secret tls citizix-k8s-tls \
    -n apps \
    --key=citizix-k8s.key \
    --cert=citizix-k8s.crt

Following is the equivalent YAML file where you have to add the crt and key file contents.

apiVersion: v1
kind: Secret
metadata:
  name: citizix-k8s-tls
  namespace: apps
type: kubernetes.io/tls
data:
  server.crt: |
       <crt contents here>
  server.key: |
       <private key contents here>

The public/private key pair must exist before hand. Verify that the secret was added using this command:

➜ kubectl get secret -n apps citizix-k8s-tls

NAME              TYPE                DATA   AGE
citizix-k8s-tls   kubernetes.io/tls   2      21s

To view the YAML source of the secret:

kubectl get secret -n apps citizix-k8s-tls -o yaml

# Create an ingress and add the tls block

We have to create an ingress in the same namespace where the resources have been created.

Save the following YAML as ingress.yaml. Replace citizix-k8s.citizix.comwith your hostname.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: citizix-k8s-ingress
  namespace: apps
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - citizix-k8s.citizix.com
    secretName: citizix-k8s-tls
  rules:
  - host: citizix-k8s.citizix.com
    http:
      paths:
        - pathType: Prefix
          path: "/"
          backend:
            service:
              name: nginx
              port:
                number: 80

Please note the TLS block with the domain name and the TLS secret created earlier. The host in the TLS block and rules block should match.

Create the ingress resources with this command:

➜ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/citizix-k8s-ingress created

# Validating ingress TLS

You can validate the ingress by visiting the site in your browser. If it is a self signed certificate you will receive the ‚ÄúYour connection is not private‚ÄĚ warning and if you check the certificate details, you will see the certificate information you added when generating.

If you are using curl:

curl https://citizix-k8s.citizix.com -kv

Check these information, it should have information about the certificate being used.

➜ curl https://citizix-k8s.citizix.com -kv
...
* SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=KE; ST=Nairobi; L=Nairobi; O=Citizix; OU=Devops; CN=citizix-k8s.citizix.com; emailAddress=admin@citizix.com
*  start date: Jul  6 11:00:59 2022 GMT
*  expire date: Jul  6 11:00:59 2023 GMT
*  issuer: C=KE; ST=Nairobi; L=Nairobi; O=Citizix; OU=Devops; CN=citizix-k8s.citizix.com; emailAddress=admin@citizix.com
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
...

# Ingress SSL Termination

By default, SSL gets terminated in ingress the controller. so all the traffic from the controller to the pod will be without TLS (decrypted traffic).

If you want full SSL, you can add the supported annotation by the ingress controller you are using. For example, In the Nginx ingress controller, to allow SSL traffic till the application, you can use the annotation. For this, your application should have SSL configured.

nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

# Conclusion

In this guide, we learnt how to configure Ingress TLS certificates with Kubernetes.

To clean up the resources we created, use these commands:

# Delete the deployment
kubectl delete deploy nginx -n apps

# Delete the service
kubectl delete service nginx -n apps

# Delete the ingress
kubectl delete ingress citizix-k8s-ingress -n apps

# Delete the secret
kubectl delete secret citizix-k8s-tls -n apps
comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy