Zum Inhalt springen

Application Load Balancer (ALB) Ingress

Zuletzt aktualisiert am

The STACKIT Application Load Balancer Controller Manager (ALBCM) exposes HTTP/HTTPS applications by provisioning and configuring managed STACKIT ALBs based on native Kubernetes Ingress resources.

The Application Load Balancer extension is disabled by default and can be activated for your cluster through the SKE-API by setting the enabled field to true inside the applicationLoadBalancer block under extensions:

{
"extensions": {
"applicationLoadBalancer": {
"enabled": true
}
}
}

To expose an application, you need to deploy three core resources: an IngressClass to provision the ALB, a Service to expose your pods, and an Ingress to define the routing.

Creating an IngressClass provisions the managed ALB instance. By default, the ALB is assigned a public ephemeral IP address, unless you configure it as an internal ALB or assign a pre-existing static IP using annotations (see Configuration).

If no Ingress resources are linked to this class, the ALB acts as an empty listener that returns an HTTP 404 Not Found.

You must include the alb.stackit.cloud/network-mode annotation on the IngressClass. This is mandatory because it tells the ALB how to reach your cluster, instructing the load balancer to route incoming traffic directly to the node ports on your cluster’s worker nodes. At the moment, NodePort is the only supported network mode.

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: stackit-alb
annotations:
alb.stackit.cloud/network-mode: "NodePort"
spec:
controller: stackit.cloud/alb-ingress

Expose your application pods using a Kubernetes Service. The controller currently only supports routing traffic to backend Services of type: NodePort (or LoadBalancer, which also allocates a NodePort).

apiVersion: v1
kind: Service
metadata:
name: example-alb-service
namespace: default
labels:
app: example-alb
spec:
type: NodePort
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: example-alb

Create the Ingress resource to route incoming traffic to your backend Service. Link it to your ALB by referencing the IngressClass name.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: service-ingress
namespace: default
spec:
ingressClassName: stackit-alb
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-alb-service
port:
number: 80

The path type ImplementationSpecific is currently treated as Exact. Regex matchers are not allowed.

The controller automatically merges all Ingress resources that reference the same IngressClass onto a single, shared ALB instance. To provision completely isolated ALBs (for example, to separate public and internal traffic or to assign different static IPs) you must create a distinct IngressClass for each one.

If you delete all Ingress resources associated with a specific class, the controller does not delete the underlying ALB infrastructure. Instead, it transitions the ALB into an empty state that returns HTTP 404 responses. This behavior preserves your allocated IP address and prevents unnecessary infrastructure recreation delays.

To completely delete the ALB and release its associated resources, you must delete the IngressClass.

When multiple Ingress resources share an ALB, their routing rules are evaluated chronologically by default, meaning older Ingress resources take precedence based on their CreationTimestamp. The precedence is only important if not all rules can be admitted to the load balancer.

You can override this default order by adding the alb.stackit.cloud/priority annotation to an Ingress. Higher integer values are evaluated first, and in the event of a tie, the controller falls back to the creation timestamp. Within an ingress, rules are evaluated top to bottom.

After the admission phase, rules are ordered differently to prefer more specific matchers. Using the following criteria:

  • By path type: Exact, ImplementationSpecific, Prefix.
  • By path length, longest first.
  • By path lexicographically.

Note, that an ingress with a higher priority does not match first. It only means that it is preferred if not all rules can be admitted to the load balancer.

The minimal Ingress example under Getting started shows a plain, unencrypted HTTP configuration. To expose your application securely through HTTPS, the ALB Ingress controller supports TLS offloading using standard Kubernetes TLS Secrets.

This functionality integrates seamlessly with tools like cert-manager to automate certificate provisioning and renewal. When a Secret is referenced in the Ingress tls block, the controller automatically handles the certificate deployment on the ALB. It continuously monitors the Secret for changes, such as during automated certificate rotation, and updates the ALB without manual intervention. Once a TLS Secret is no longer referenced by any Ingress on that ALB, it is automatically removed.

By default, standard unencrypted HTTP traffic will still be possible alongside HTTPS to make automated ACME certificate challenges possible. If you want to restrict traffic so the Ingress is not reachable via standard HTTP, you can add the alb.stackit.cloud/https-only: "true" annotation to your Ingress or IngressClass resource.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-ingress
namespace: default
spec:
ingressClassName: stackit-alb
tls:
- hosts:
- secure.example.com
secretName: my-tls-secret
rules:
- host: secure.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-alb-service
port:
number: 80

The following limitations are imposed directly by the STACKIT ALB API (not the controller itself):

  • Maximum targets per pool: An individual target pool can contain a maximum of 250 targets.
  • Maximum target pools per ALB: A single ALB instance supports a maximum of 20 target pools.

A target in a pool corresponds directly to a node in your Kubernetes cluster. Nodes that are marked for deletion are removed as targets. If the remaining nodes exceed 250 then the youngest 250 nodes are used as targets.

Each service reference in each ingress translates to a target pool. If two ingresses or paths within an ingress reference the same service and port the controller will create two target pools. If all ingresses of a single ingress class exceed 20 target pools then the first 20 are admitted based on their precedence.

Configure the STACKIT Application Load Balancer using the following annotations:

The controller currently only supports routing traffic to backend Services of type: NodePort (or LoadBalancer, which also allocates a NodePort). Services of type ClusterIP cannot be used as backends because the ALB needs a node-reachable port to forward traffic to.

Each Service that is referenced in an Ingress must use the default externalTrafficPolicy=Cluster. This is due to the fact that the load balancer is limited to 250 targets. However, a Kubernetes cluster can have more than 250 nodes. The Application Load Balancer controller drops nodes beyond 250. With externalTrafficPolicy=Local, this could cause zero targets to be available.

The Application Load Balancer Controller currently does not support the defaultBackend field on Ingress resources. Customers should avoid relying on this feature as that field will be ignored during ALB reconciliation. This implies that ingresses that contain rules but no paths will also be ignored.

Dummy listener for empty Application Load Balancers

Section titled “Dummy listener for empty Application Load Balancers”

Currently, Application Load Balancers require at least one listener. If the IngressClass results in zero listeners, a dummy listener on port 80 is added to be able to create the load balancer. This listener always returns the HTTP status code 404. Common scenarios where this can happen is when there are zero ingresses or an HTTPS-only load balancer does not have any certificates yet.

The observability options are not configured when the Observability Extension in the Kubernetes cluster is enabled. Currently, if observability is needed, it must be configured manually on the ALB directly.