Skip to main content

AGC, HTTPRoute, and RoutePolicy Explained

Introduction #

When you work with Azure Application Gateway for Containers (AGC) in AKS, it helps to separate traffic routing from route behavior.

That is where HTTPRoute and RoutePolicy come in.

This post brings the full picture together so it is easier to understand:

  • How AGC, HTTPRoute, and RoutePolicy fit together
  • What HTTPRoute is responsible for
  • What RoutePolicy is responsible for
  • How URL rewrites and backend weights behave
  • Why errors such as InvalidGroup happen

Overall Architecture #

You can picture the request flow like this:

Client -> AGC (Gateway) -> HTTPRoute -> Service -> Pod

And when needed:

RoutePolicy -> attaches behavior to the HTTPRoute

That gives you a clean mental model:

  • AGC is the traffic entry point
  • HTTPRoute defines routing rules
  • RoutePolicy adds advanced behavior

What HTTPRoute Does #

The core job of HTTPRoute is to decide where traffic goes.

This is where you define:

  • Path matching
  • Host matching
  • URL rewrites
  • Backend services

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
rules:
  - matches:
      - path:
          type: PathPrefix
          value: /sample-api
    filters:
      - type: URLRewrite
        urlRewrite:
          path:
            type: ReplacePrefixMatch
            replacePrefixMatch: /
    backendRefs:
      - name: sample-api-svc
        port: 80
        weight: 1

Path Matching #

With this route match:

1
2
3
path:
  type: PathPrefix
  value: /sample-api

AGC matches requests such as:

  • /sample-api
  • /sample-api/
  • /sample-api/health

URL Rewrite and ReplacePrefixMatch #

If you use:

1
type: ReplacePrefixMatch

you must have exactly one PathPrefix match in the route.

If not, AGC rejects the configuration with an error like:

Invalid: When using URLRewrite with replacePrefixMatch

What the rewrite does:

  • Incoming path: /sample-api/health
  • Path sent to backend: /health

This is useful when the external route includes a prefix, but the backend application expects requests without that prefix.

backendRefs and Weight #

backendRefs defines which service receives traffic.

Example:

1
2
3
4
backendRefs:
  - name: svc-1
    port: 80
    weight: 1

The weight value is relative, not absolute.

Examples:

  • svc-1 weight: 1 and svc-2 weight: 1 means about 50% / 50%
  • svc-1 weight: 3 and svc-2 weight: 1 means about 75% / 25%
  • If there is only one backend, weight: 1 means it receives all traffic

What RoutePolicy Does #

RoutePolicy does not handle routing decisions. Its job is to add behavior to a route.

This is where you configure features such as:

  • Session affinity
  • TLS-related behavior
  • Other AGC-supported route controls

One common example is sticky sessions:

1
2
3
sessionAffinity:
  affinityType: managed-cookie
  cookieDuration: 3600s

This means:

  • AGC manages the session cookie
  • The same client is sent back to the same backend pod during that cookie lifetime
  • The session is less likely to break because of pod switching

This is especially useful for:

  • Stateful applications
  • Session-based systems
  • Any app that should not bounce between pods mid-session

How They Work Together #

The combined flow looks like this:

  1. A client sends a request to AGC.
  2. AGC receives the traffic at the gateway frontend.
  3. HTTPRoute checks the path, host, and filters.
  4. RoutePolicy applies extra behavior such as session affinity.
  5. Traffic is sent to the selected service and pod.

A simple way to remember it:

  • HTTPRoute = traffic rules
  • RoutePolicy = behavior rules
  • AGC = execution engine

Understanding the InvalidGroup Error #

One of the most common configuration mistakes with RoutePolicy is a missing API group in targetRef.

You might see conditions like:

  • Status: False
  • Reason: InvalidGroup

The root cause is usually this:

1
2
targetRef:
  kind: HTTPRoute

It should be:

1
2
3
targetRef:
  group: gateway.networking.k8s.io
  kind: HTTPRoute

Kubernetes identifies resources using API group and kind, so HTTPRoute alone is not enough for the controller to resolve the reference.

Reading Status Conditions #

Two important conditions to watch are:

  • ResolvedRefs
  • Accepted

If you see:

  • ResolvedRefs: False
  • Accepted: False

that usually means:

  • ResolvedRefs could not resolve the referenced object
  • Accepted means the controller rejected the configuration

In other words, False here means the config is not working, not just that there is a warning.

Common Mistakes #

  • Missing group in targetRef
  • Using Exact instead of PathPrefix when ReplacePrefixMatch is involved
  • Defining multiple matches with replacePrefixMatch
  • Treating weight like a fixed percentage instead of a relative value

Final Mental Model #

If you want to keep the whole setup simple in your head, use this:

  • HTTPRoute defines where traffic goes
  • RoutePolicy defines how traffic should behave
  • AGC applies both and forwards traffic to the backend

That separation is what makes AGC with Gateway API easier to reason about than older, annotation-heavy ingress setups.