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

# 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   80:30725/TCP,443:30354/TCP   34m
nginx-ingress-default-backend   ClusterIP    <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

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
  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   80:30725/TCP,443:30354/TCP   34m
nginx-ingress-default-backend   ClusterIP    <none>           80/TCP                       34m

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

If we browse to 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, we should see AKS Ingress Demo - 1.

If we browse to, 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…


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.

4 responses

  1. Kenneth 2020-08-26 at 05:56

    you have 2 different ingress in 2 different namespaces :-)

    2 different rules of the same ingress must be in the same namespace.

  2. Vincent-Philippe Lauzon 2020-08-28 at 12:27

    True but that’s not a huge constraint.

    The point of the article was to show we could have different ingress in different namespace managed in a non-central fashion (i.e. each in their own namespace).

    Did I use ingress controller / ingress / ingress rule interchangeably?

  3. inna 2021-03-16 at 07:41

    Thank you for a very good article.

  4. sai krishna 2021-04-15 at 23:24

    When we use two ingress one in each namespace with specifying annotation as alb what happens? Can we use one load balancer with two ingress ? each in different namespace

Leave a comment