Ingress rules in different Kubernetes namespaces

In this article I want to show how an ingress controller in Kubernetes can be used to route traffic to workloads deployed in multiple namespaces.

The online doc for AKS deploys everything in the same namespace. Hence this article is a thin extension to the online doc.

The basic trick is to deploy the ingress rules in the same namespace the service they point to is.

This isn’t Azure / AKS specific, although this is what I use to demonstrate it, it is generic Kubernetes.

As usual, the code is in GitHub.

Installing NGinx

Assuming we are starting from a vanilla cluster, we first need to install an Ingress Controller.

Here we are going to use NGinx, but any Ingress Controller could support the rest of the code.

Details of this installation can be found in the AKS online documentation. The basic steps are:

# Create a namespace for your ingress resources
kubectl create namespace ingress-basic

# Add the official stable repository
helm repo add stable https://kubernetes-charts.storage.googleapis.com/

# Use Helm to deploy an NGINX ingress controller
helm install nginx-ingress stable/nginx-ingress \
    --namespace ingress-basic \
    --set controller.replicaCount=2 \
    --set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \
    --set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux

This installs the Ingress Controller in the namespace ingress-basic.

We can validate the Ingress Controller is installed:

kubectl get svc -ningress-basic
NAME                            TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
nginx-ingress-controller        LoadBalancer   10.0.211.140   52.228.111.215   80:30725/TCP,443:30354/TCP   34m
nginx-ingress-default-backend   ClusterIP      10.0.82.178    <none>           80/TCP                       34m

Remember, an Ingress Controller is itself a Kubernetes service.

Installing services in different namespaces

We’re going to use one of the Azure samples charts to deploy services. Let’s add the charts to Helm Repo:

helm repo add azure-samples https://azure-samples.github.io/helm-charts/

Let’s create two namespaces:

kubectl create ns hello1
kubectl create ns hello2

Now let’s deploy the same chart twice in those two namespaces. We’ll pass different parameters in order to distinguish the deployment (the title is shown in the HTML):

helm install aks-helloworld azure-samples/aks-helloworld \
    --namespace hello1 \
    --set title="AKS Ingress Demo - 1" \
    --set serviceName="aks-helloworld-one"
helm install aks-helloworld azure-samples/aks-helloworld \
    --namespace hello2 \
    --set title="AKS Ingress Demo - 2" \
    --set serviceName="aks-helloworld-two"

We can validate services have been deployed in respective namespaces:

kubectl get svc -nhello1
kubectl get svc -nhello2

We can notice those services do not have external IPs.

Ingress Rules

We are going to expose the services through ingress rules:

kubectl apply -f ingress1.yaml
kubectl apply -f ingress2.yaml

The yaml files are on GitHub: ingress1.yaml & ingress2.yaml

A couple of things to notice about those ingress rules:

The first observation makes the ingress rule work. The second is simply incidental. We could have used different routing mechanism ; this simply was the simplest to implement.

To put the rule in a namespace, we simply specified the namespace in the metadata section. For example, in ingress1.yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-hello-world-1
  namespace: hello1

Testing the solution

We can test those rules. First, let’s find the Public IP of the Ingress Controller. We have already seen it when we validated the deployment of the ingress controller:

kubectl get svc -ningress-basic
NAME                            TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
nginx-ingress-controller        LoadBalancer   10.0.211.140   52.228.111.215   80:30725/TCP,443:30354/TCP   34m
nginx-ingress-default-backend   ClusterIP      10.0.82.178    <none>           80/TCP                       34m

In our case, the public IP is 52.228.111.215. We can find that public IP in the managed resource group (i.e. MC_… resource group).

If we browse to http://52.228.111.215 we should have a default backend - 404 message at the root. That is because there is no Ingress rule routing from the root.

If we browse at http://52.228.111.215/hello-world-1, we should see AKS Ingress Demo - 1.

If we browse to http://52.228.111.215/hello-world-2, we should see AKS Ingress Demo - 2.

There we have it. 2 services, in separate namespaces, exposed through one Ingress Controller.

Broken images

We can notice the image link are broken.

This is because both sites point to /static/... for their images.

This makes that site a very bad candidate to use URL routing as we did. But it’s simpler to demo…

Summary

Simple demo for a simple concept.

As we mentioned in the introduction, the trick simply to deploy the ingress rules in the same namespace as the services they point to.

As we explored in a past article, we could also have multiple Ingress Controller within a cluster.


Leave a comment