Exposing Container Applications in AKS: Azure Application Gateway Ingress controller (AGIC)

Sijomon ND
7 min readFeb 19, 2024

--

PART-3

Photo by Red John on Unsplash

Introduction

Exposing an application container in Kubernetes is about making your application running in a container accessible and reachable to users or other services within and beyond the Kubernetes cluster. Configuring how you expose your application requires careful consideration. Kubernetes offers mechanisms like Services, Ingress and Load Balancers to guide incoming traffic to your containerized application securely and efficiently. This series will focus on a few methods for exposing AKS clusters applications.

In Part 1 of the series, we explored connecting to an application via The Azure Load Balancer. I showed you how to up service for ALB also, we discussed some Pros and Cons of having a L4 Load-balancer.

In Part 2, I provided an overview of the ingress controllers and how it can be leveraged for possible use cases and limitations in an AKS cluster. While there are many ingress controller options I used NGINX Ingress Controller.

In this Part 3 I will provide a similar walkthrough on AGIC that helps AKS utilize Azure’s own Application Gateway Layer7 Load-balancer to expose your application to the Internet.

I have added all the artifacts that we are going to use below gist

https://gist.github.com/sijomon/bd1ae54fcc15296799e919295d96daeb

Azure Application Gateway Ingress Controller (AGIC)

The Application Gateway Ingress Controller (AGIC) is a Kubernetes application that enables Azure Kubernetes Service (AKS) customers to utilize Azure’s native Application Gateway L7 load-balancer for exposing cloud software to the Internet.

AGIC allows AKS clusters to leverage Azure Application Gateway as an ingress controller. It continuously monitors the Kubernetes cluster and dynamically updates the associated Application Gateway configuration. The Ingress Controller runs within its own pod in the AKS cluster. Application Gateway communicates directly with pods using their private IP addresses, avoiding NodePort or KubeProxy services.

How AGIC works?

AGIC acts as the bridge between Kubernetes Ingress resources and Azure Application Gateway, dynamically updating the routing configuration based on your Ingress rules. When you create a new Ingress resource in Kubernetes with the Application Gateway Ingress Controller (AGIC), the following process occurs to create routes in the Application Gateway:

  1. Ingress Resource Creation:
  • You define an Ingress resource in your Kubernetes cluster. This resource specifies the routing rules for incoming traffic to your services.
  • The Ingress resource contains information about hostnames, paths, and backend services.

2. AGIC Watches for Changes:

  • The AGIC continuously monitors the Kubernetes cluster for changes in Ingress resources.
  • When a new Ingress resource is created or updated, AGIC detects it.

3. Configuration Generation:

  • AGIC generates a configuration based on the Ingress rules.
  • It creates or updates the routing rules within the Azure Application Gateway.

4. Application Gateway Configuration Update:

  • AGIC communicates with the Azure Application Gateway.
  • It applies the changes to the Application Gateway’s routing table.
  • This includes creating or updating listeners, URL path maps, and request routing rules.

5. Redirection and TLS Termination (Optional):

  • If your Ingress resource specifies redirection from HTTP to HTTPS, AGIC configures the Application Gateway accordingly.
  • If TLS termination is configured, AGIC ensures that HTTPS traffic is handled correctly.

6. Traffic Flow:

  • Incoming traffic from the Internet hits the Application Gateway’s public IP address.
  • The Application Gateway routes the traffic based on the rules defined in the Ingress resource.
  • Finally, the traffic reaches the appropriate backend services (Pods) in your AKS cluster.

AGIC can be deployed in two ways, Helm Deployment and AKS Add-On.Creating the AKS With Application Gateway Ingress Controller(AGIC) using Azure CLI. Make sure you have Azure CLI installed on your machine.

  1. Make sure you are logged in to the portal using
az login

2. Create a resource group and AKS cluster

az group create --name RGaks --location australiacentral
az aks create -n sijoaks1 -g RGaks  --network-plugin azure --enable-managed-identity -a ingress-appgw --appgw-name myApplicationGateway --appgw-subnet-cidr "10.225.0.0/16" --generate-ssh-keys

3.

#Get application gateway id from AKS addon profile
appGatewayId=$(az aks show -n sijoaks1 -g RGaks -o tsv --query "addonProfiles.ingressApplicationGateway.config.effectiveApplicationGatewayId")
# Get application Gateway subnet id
aks-nginx % appGatewaySubnetId=$(az network application-gateway show --ids $appGatewayId -o tsv --query "gatewayIpConfigurations[0].subnet.id")
#Get AGIC addon identity
agicAddonIdentity=$(az aks show -n sijoaks1 -g RGaks -o tsv --query "addonProfiles.ingressApplicationGateway.identity.clientId")
#Assign network contributor role to AGIC addon identity to subnet that contains the Application Gateway
az role assignment create --assignee $agicAddonIdentity --scope $appGatewaySubnetId --role "Network Contributor"

4. Get credentials to the AKS cluster

az aks get-credentials -n sijoaks1  -g RGaks

5. Deploy a sample application by using AGIC

Create a file named demo-one.yaml

apiVersion: v1
kind: Pod
metadata:
name: demoapp
labels:
app: demoapp
spec:
containers:
- image: "mcr.microsoft.com/dotnet/samples:aspnetapp"
name: aspnetapp-image
ports:
- containerPort: 8080
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: demoapp
spec:
selector:
app: demoapp
ports:
- protocol: TCP
port: 80
targetPort: 8080
kubectl apply -f demo-one.yml 

deployment.apps/demo-one created
service/demo-one created

6. Create an Ingress Resource

Create a file named Ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demoapp
annotations:
appgw.ingress.kubernetes.io/backend-path-prefix: /
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.k8s.io/v1","kind":"Ingress","metadata":{"annotations":{},"name":"demoapp","namespace":"default"},"spec":{"ingressClassName":"azure-application-gateway","rules":[{"http":{"paths":[{"backend":{"service":{"name":"demo-one","port":{"number":80}}},"path":"/","pathType":"Exact"}]}}]}}

spec:
ingressClassName: azure-application-gateway
rules:
- http:
paths:
- backend:
service:
name: demoapp
port:
number: 80
path: /test
pathType: Exact
- backend:
service:
name: demoapp
port:
number: 80
path: /nginx
pathType: Exact

kubectl apply -f ingress.yml 
ingress.networking.k8s.io/demo-one created
kubectl get ingressNAME       CLASS                       HOSTS   ADDRESS          PORTS   AGE
demo-one azure-application-gateway * 20.213.250.140 80 93s

Use of Annotations in Azure Application Gateway

annotations:
appgw.ingress.kubernetes.io/backend-path-prefix: /

Annotations play a crucial role in configuring Azure Application Gateway when used in conjunction with the Application Gateway Ingress Controller (AGIC).

What Are Annotations?

The Kubernetes Ingress resource can be annotated with arbitrary key/value pairs. AGIC relies on these annotations to program features of the Application Gateway that cannot be configured using the standard Ingress YAML. These annotations are applied to HTTP settings, backend pools, and listeners derived from an ingress resource. For AGIC to recognize an Ingress resource, it must be annotated with:
kubernetes.io/ingress.class: azure/application-gateway.

Supported annotations are : https://azure.github.io/application-gateway-kubernetes-ingress/annotations/

Suppose you want to rewrite the backend path /hello/ to /test/.

You can achieve this by adding the following annotation to your Ingress resource.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: go-server-ingress-bkprefix
namespace: test-ag
annotations:
kubernetes.io/ingress.class: azure/application-gateway
appgw.ingress.kubernetes.io/backend-path-prefix: "/test/"
spec:
rules:
- http:
paths:
- path: /hello/
pathType: Exact
backend:
service:
name: go-server-service
port:
number: 80

In this example, the annotation ensures that the path /hello/ is overridden with /test/. AGIC can automatically redirect HTTP URLs to their HTTPS counterparts. When the appgw.ingress.kubernetes.io/ssl-redirect annotation is present and TLS is configured, AGIC creates a routing rule for redirection.

7. Browse to <External IP>test

Browse to <External IP>nginx

POD Phases & Logs

When you deploy a pod, it could typically fall under any one of the following phases.

Pending: The Pod is created but not yet running.

Running: At least one container is running, or is in the process of starting or restarting.

Succeeded: All containers have been completed successfully.

Failed: At least one container has failed.

Unknown: The Pod status couldn’t be obtained by the API server.

POD Logs

To view pod logs in an Azure Kubernetes Service (AKS) cluster, you have a few options.

Using kubectl logs Command:

The kubectl logs command is a powerful tool in Kubernetes for viewing the logs generated by a specific pod within a cluster. It allows you to retrieve logs from containers, making it useful for debugging, monitoring, and troubleshooting

For example:
kubectl logs <pod-name>

Replace <pod-name> with the actual pod name and <container-name> with the name of the container whose logs you want to view.

kubectl logs ingress-nginx-controller-7cd559d55f-mj8sm

If the pod has multiple containers, specify the container name using the -c flag:

kubectl logs <pod-name> -c <container-name>

Stream logs from all containers in pods labeled with app=nginx:
kubectl logs -f -l app=nginx — all-containers=true

In production environments, when you have a stable cluster deployed and running, it’s possible to forget the logs and assume everything is working fine easily. Also, since containers in pods are ephemeral, in situations where the pods get restarted, you lose logs for those containers, which may contain critical data to be analyzed later

--

--