Automatic Virtual Host Setup Using Nginx Ingress Controller On Kubernetes

A

A common scenario that you may face in your compute environment is the need to deploy various web applications, websites, APIs, and other such services that you will likely want to associate domain names to instead of just using IP addresses for everything. There are a plethora of different ways to achieve these types of deployments in Kubernetes, but for the sake of simplicity and automation, I will present one route that takes a lot of the complexity out of achieving these goals.

Enter the Nginx Ingress Controller for Kubernetes. This is not to be confused for the Kubernetes Ingress Controller that also uses Nginx. The outcomes provided by the two are very similar but project goals different. For this tutorial and many others on this blog, I will focus on the former of the two as that is what I run in my production environments. It is also worth mentioning that this option paves the road for a very useful integration that solves another need that is just as common as the need for simple virtual hosts. That integration would be automatic SSL certificate registration and deployment using ACME providers like LetsEncrypt. I have also provided a tutorial on this blog to cover the implementation of that solution as well.

This tutorial is pretty simple so let’s jump right into it. Working from a kubectl enabled environment for your Kubernetes cluster, execute the following commands:

git clone -b v2.1.1 https://github.com/nginxinc/kubernetes-ingress/
cd kubernetes-ingress/deployments

The first change you should make is to apply the role based access control (RBAC) configurations to the Kubernetes environment by executing the following command:

kubectl apply -f common/ns-and-sa.yaml -f rbac/rbac.yaml

Now you can setup all of the definitions and dependencies required to run the Nginx Ingress Controller by executing the following commands:

kubectl apply -f common/default-server-secret.yaml
kubectl apply -f common/nginx-config.yaml
kubectl apply -f common/ingress-class.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_virtualserverroutes.yaml
kubectl apply -f common/crds/k8s.nginx.org_transportservers.yaml
kubectl apply -f common/crds/k8s.nginx.org_policies.yaml
kubectl apply -f common/crds/k8s.nginx.org_globalconfigurations.yaml

Now you’re ready to deploy the actual ingress controller. There are two general approaches for deployment which are DaemonSets and Deployments. In this tutorial, the latter will be used as it is likely most sufficient for your environment. Execute the following command:L

kubectl apply -f deployment/nginx-ingress.yaml

Now for the final step which is to expose access to the ingress controller via a Kubernetes service. Let’s take a look at the default service configuration which can be found in the service/loadbalancer.yaml file:

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress
  namespace: nginx-ingress
spec:
  externalTrafficPolicy: Local
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  - port: 443
    targetPort: 443
    protocol: TCP
    name: https
  selector:
    app: nginx-ingress

This file will work as is to get you started but I will assume you probably want to expose some of the services connected to the ingress controller via a public IP address in your network. If you do not need to expose the ingress controller via a public IP address then you may skip the next section and jump to the last part of this step.

This approach assumes that you have connected your Kubernetes environment into your network via BGP with Calico CNI. Take a look at the modified service/loadbalancer.yaml file below to see how easy it is to add one or more additional IP addresses to the controller which will be automatically announced as a /32 route via BGP. Keep in mind, the IP addresses used here must be defined in your Calico CNI BGP configuration under the “serviceExternalIPs” section or the address assignments will not be announced via BGP.

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress
  namespace: nginx-ingress
spec:
  externalTrafficPolicy: Local
  type: LoadBalancer
  externalIPs:
  - 123.45.54.321
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  - port: 443
    targetPort: 443
    protocol: TCP
    name: https
  selector:
    app: nginx-ingress

Once you have the service/loadbalancer.yaml file modified to your requirements, execute the following command to create the service:

kubectl apply -f service/loadbalancer.yaml

Now that this has been setup, you can easily connect the Kubernetes services you deploy to the ingress controller by defining a configuration object in your application namespace similar to the following:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: http-lb
  namespace: website-namespace
spec:
  rules:
  - host: your.website.domain
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: http-svc
            port:
              number: 80

That’s it! Hopefully that was as simple as I made it out to be!

I recommend you check out this post next to take your Kubernetes deployment to the next level.

About the author

Add Comment

By Matt

Matt

Get in touch

If you would like to contact me, head over to my company website at https://azorian.solutions.