Configure Nginx Ingress Controller for TLS termination on Kubernetes on Azure
If we need TLS termination on Kubernetes, you can use ingress controller. On Azure, you can use Nginx Ingress controller. (Now, Microsoft working with Azrue ingress controller which uses Application gateway)
see Status of Kubernetes on Azure
I'd like to share how to configure Nginx Ingress Controller on Kubernetes on Azure.
Clone Nginx Ingress repository
You can find ingress repo in here. Please clone it.
$ git clone https://github.com/kubernetes/ingress.git
You can find a lot of instruction and YAML file to configure Nginx Ingress.
Deploying the Nginx Ingress controller
Just follow this instruction.
Deploy default-backend pod.
$ cd ingress/examples/deployment/nginx
$ kubectl apply -f default-backend.yaml
deployment "default-http-backend" created
service "default-http-backend" created
$ kubectl -n kube-system get po
NAME READY STATUS RESTARTS A GE
default-http-backend-2657704409-tztz5 1/1 Running 0 1
:
Then deploy ingress controller. It is deployed on the kube-system name space.
$ kubectl apply -f nginx-ingress-controller.yaml
deployment "nginx-ingress-controller" created
$ kubectl -n kube-system get po
NAME READY STATUS RESTARTS A GE
default-http-backend-2657704409-tztz5 1/1 Running 0 5 0s
:
nginx-ingress-controller-3752011415-x2dks 0/1 Running 0 1 5s
TLS certificates
Reading this page, create a TLS self-signed certificate for testing.
I execute openssl command via Bash on Ubuntu on Windows. When I tried on GitBash it didn't work.
$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
Generating a 2048 bit RSA private key
.............................................+++
...........+++
writing new private key to 'tls.key'
-----
then create secret on Kubernetes using the self signed certificate.
$ kubectl create secret tls tls-secret --key tls.key --cert tls.crt
secret "tls-secret" created
Deploy Test HTTP Service
Following this instruction. Let's deploy a sample web application.
$ kubectl create -f http-svc.yaml
service "http-svc" created
replicationcontroller "http-svc" created
$ kubectl get po
NAME READY STATUS RESTARTS AGE
http-svc-23pm5 1/1 Running 0 4m
http-svc-92zfc 1/1 Running 0 4m
$ kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
http-svc 10.0.70.205 <nodes> 80:30301/TCP 1h
kubernetes 10.0.0.1 <none> 443/TCP 14d
Configure TLS termination
Follow this instruction. Go ingress/examples/tls-termination/nginx/ directory.
$ kubectl create -f nginx-tls-ingress.yaml
nginx-tls-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-test
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
# This assumes tls-secret exists.
- secretName: tls-secret
rules:
- http:
paths:
- backend:
# This assumes http-svc exists and routes to healthy endpoints.
serviceName: http-svc
servicePort: 80
However it still not enough for Azure environment.
You need to expose the Ingress Replica set. You can find the ingress replica set name.
$ kubectl get rs --namespace kube-system
NAME DESIRED CURRENT READY AGE
default-http-backend-2657704409 1 1 1 29m
heapster-v1.2.0-1448994189 1 1 1 14d
kubernetes-dashboard-696481038 1 1 1 14d
nginx-ingress-controller-3752011415 1 1 1 28m
Then expose it. specify the Replica Set name and expose 443 for SSL. You need to "--type=LoadBalancer" to expose IP. Also you need to specify "--namespace kube-system'. Nginx ingress controller is deployed with kube-system namespace.
$ kubectl expose rs nginx-ingress-controller-3752011415 --port=443 --target-p ort=443 --name=nginx-ingress-ssl --type=LoadBalancer --namespace kube-system
service "nginx-ingress-ssl" exposed
$ kubectl get services --namespace kube-system -w
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default-http-backend 10.0.244.231 <none> 80/TCP 34m
heapster 10.0.111.25 <none> 80/TCP 14d
kube-dns 10.0.0.10 <none> 53/UDP,53/TCP 14d
kubernetes-dashboard 10.0.106.144 <nodes> 80:30177/TCP 14d
nginx-ingress-ssl 10.0.232.84 <pending> 443:32541/TCP 46s
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-ingress-ssl 10.0.232.84 13.71.145.137 443:32541/TCP 1m
Now, external IP has been exposed. Let's test this.
$ curl https://13.71.145.137
% Total % Received % Xferd Average Speed Time Time Time Curre nt
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
$ curl https://13.71.145.137 -k
% Total % Received % Xferd Average Speed Time Time Time Curre nt
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 100 430 0 430 0 0 1530 0 --:--:-- --:--:-- --:--:-- 162 2CLIENT VALUES:
client_address=10.244.1.25
command=GET
real path=/
query=nil
request_version=1.1
request_uri=https://13.71.145.137:8080/
SERVER VALUES:
server_version=nginx: 1.9.11 - lua: 10001
HEADERS RECEIVED:
accept=*/*
connection=close
host=13.71.145.137
user-agent=curl/7.50.3
x-forwarded-for=127.0.0.1
x-forwarded-host=13.71.145.137
x-forwarded-port=443
x-forwarded-proto=https
x-real-ip=127.0.0.1
BODY:
-no body in request-
Done! Enjoy Nginx Ingress Controller on Azure.