TLS is a very common security mechanism on web servers through out the Internet. It creates a transport tunnel of encrypted data between the server and client. This tunnel is created with the help of the server certificate and is dependent of that the client trusts the server. We are now going to see an example of how to set this up in the Ingress component of Kubernetes
All certificates are going to be self-signed in this example, regular certificates from trusted sources like Thwate, GlobalSign and many others will also work.
For Kubernetes I will use Minikube with the Ingress addon:
minikube addons enable ingress
1. We start with creating the server certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt -subj "/CN=test.localdev.me/O=test.localdev.me"
This should give you two files, a server.key and a server.crt file with the private key and the certificate to present to clients trying to connect.
NOTE: the “domain” test.localdev.me will normally return 127.0.0.1 automatically which makes it perfect to use in cases like this
2. Lets add the certificate to the cluster via a Secret and the special type tls
kubectl create secret tls server-certificate --key server.key --cert server.crt
3. Now we need an application to call. We create one with the Deployment below:
apiVersion: apps/v1 kind: Deployment metadata: labels: app: mywebserver name: mywebserver spec: replicas: 1 selector: matchLabels: app: mywebserver template: metadata: labels: app: mywebserver spec: containers: - image: httpd name: httpd ports: - containerPort: 80
4. A Service to expose the application to the cluster
apiVersion: v1 kind: Service metadata: labels: app: my-service name: my-service spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: mywebserver
5. A Ingress to handle the authentication
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: mtls-ingress namespace: default spec: ingressClassName: nginx rules: - host: test.localdev.me http: paths: - backend: service: name: my-service port: number: 80 path: / pathType: Prefix tls: - hosts: - test.localdev.me secretName: server-certificate
6. Time to test our TLS setup
First we need to setup a port binding to port 443 on our local machine
sudo kubectl port-forward -n ingress-nginx service/ingress-nginx-controller 443:443
and now we can test with curl and the test.localdev.me domain
curl -k -v https://test.localdev.me/
If everything is working we should get “It works!” from the Web Server
Tested in Minikube 1.26.0 and with OpenSSL 1.1.1f on Ubuntu 20.08