Scale API gateways on Kubernetes
Use Gateway annotations to configure per-gateway scaling for the managed Consul GatewayClass on Kubernetes. You can set a fixed replica count for a gateway or let Consul manage a Kubernetes horizontal pod autoscaler (HPA) for that gateway.
Enterprise
This feature requires Consul Enterprise(opens in new tab).
Requirements
Gateway scaling is available only when all of the following are true:
- You are using the managed Consul API gateway class on Kubernetes.
- The Helm value
connectInject.apiGateway.managedGatewayClass.scaling.enabledis set totrue. - The connected Consul cluster reports a valid Consul Enterprise license.
If gateway scaling is not enabled, Consul ignores gateway scaling annotations and does not create controller-managed HPAs.
Enable gateway scaling
Set the connectInject.apiGateway.managedGatewayClass.scaling.enabled Helm value to true when you install or upgrade Consul:
values.yaml
connectInject:
enabled: true
apiGateway:
managedGatewayClass:
scaling:
enabled: true
Refer to the Helm chart reference for connectInject.apiGateway for additional context.
Configure static replicas
Add the consul.hashicorp.com/default-replicas annotation to a Gateway resource when you want Consul to keep the gateway deployment at a fixed replica count.
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: api-gateway
annotations:
consul.hashicorp.com/default-replicas: "4"
spec:
gatewayClassName: consul
listeners:
- name: http
protocol: HTTP
port: 8080
default-replicas must be a positive integer.
Configure controller-managed HPA
Add HPA annotations to a Gateway resource when you want Consul to create and reconcile an HPA for the gateway deployment.
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: api-gateway
annotations:
consul.hashicorp.com/hpa-enabled: "true"
consul.hashicorp.com/hpa-minimum-replicas: "3"
consul.hashicorp.com/hpa-maximum-replicas: "25"
consul.hashicorp.com/hpa-cpu-utilisation-target: "70"
spec:
gatewayClassName: consul
listeners:
- name: http
protocol: HTTP
port: 8080
When HPA mode is enabled, Consul creates a controller-managed HPA named <gateway-name>-hpa.
If you omit optional HPA annotations, Consul uses the following defaults:
- Minimum replicas:
1 - Maximum replicas:
10 - CPU utilization target:
80
The HPA annotations use the following validation rules:
consul.hashicorp.com/hpa-minimum-replicasmust be at least1consul.hashicorp.com/hpa-maximum-replicasmust be at least1- minimum replicas cannot be greater than maximum replicas
consul.hashicorp.com/hpa-cpu-utilisation-targetmust be between1and100
Precedence and deprecated fields
Consul resolves gateway scaling in the following order:
- A user-managed HPA that targets the gateway deployment
- Gateway scaling annotations
- Deprecated Helm chart
connectInject.apiGateway.managedGatewayClass.deploymentfields
If a user-managed HPA already targets the gateway deployment, Consul does not create or manage its own HPA for that gateway.
Precedence examples
Case 1: User-managed HPA wins over Gateway annotations
If you create your own HorizontalPodAutoscaler that targets the gateway deployment and the Gateway resource also has scaling annotations, Consul uses the user-managed HPA and ignores the annotations entirely. Consul does not create or overwrite the existing HPA.
# User-managed HPA — this takes priority
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-gateway
minReplicas: 2
maxReplicas: 8
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
Even if the following Gateway resource has hpa-enabled: "true", Consul defers to my-hpa in the previous example and does not create a second HPA.
# Gateway annotations are ignored when a user-managed HPA already exists
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: api-gateway
annotations:
consul.hashicorp.com/hpa-enabled: "true"
consul.hashicorp.com/hpa-minimum-replicas: "3"
consul.hashicorp.com/hpa-maximum-replicas: "25"
spec:
gatewayClassName: consul
listeners:
- name: http
protocol: HTTP
port: 8080
Case 2: Gateway annotations win over deprecated Helm values
If the Gateway resource has a default-replicas annotation and the Helm chart still has a deployment.defaultInstances value set, Consul uses the annotation and ignores the Helm value. Note that scaling.enabled must be true for annotations to be evaluated at all.
# values.yaml — scaling must be enabled; the deprecated defaultInstances is ignored
connectInject:
apiGateway:
managedGatewayClass:
scaling:
enabled: true # required for annotations to take effect
deployment:
defaultInstances: 2 # ignored because the annotation below is present
# gateway.yaml — annotation wins
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: api-gateway
annotations:
consul.hashicorp.com/default-replicas: "4" # this value is used
spec:
gatewayClassName: consul
listeners:
- name: http
protocol: HTTP
port: 8080
Case 3: Deprecated Helm values are the only source
If there are no Gateway annotations and no user-managed HPA, Consul falls back to the deprecated deployment.* Helm values. Consul creates the gateway deployment with defaultInstances replicas, and the controller enforces minInstances and maxInstances as bounds.
# values.yaml — used only as a fallback when no annotations exist
connectInject:
apiGateway:
managedGatewayClass:
deployment:
defaultInstances: 3
minInstances: 1
maxInstances: 5
The following Helm values under connectInject.apiGateway.managedGatewayClass.deployment are deprecated and will be removed in a future release. Migrate each one to the equivalent Gateway annotation.
Migrate deployment.defaultInstances
Before (deprecated):
values.yaml
connectInject:
apiGateway:
managedGatewayClass:
deployment:
defaultInstances: 4
After:
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: api-gateway
annotations:
consul.hashicorp.com/default-replicas: "4"
spec:
gatewayClassName: consul
listeners:
- name: http
protocol: HTTP
port: 8080
Migrate deployment.minInstances and deployment.maxInstances
Before (deprecated):
values.yaml
connectInject:
apiGateway:
managedGatewayClass:
deployment:
minInstances: 2
maxInstances: 10
After:
gateway.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: api-gateway
annotations:
consul.hashicorp.com/hpa-enabled: "true"
consul.hashicorp.com/hpa-minimum-replicas: "2"
consul.hashicorp.com/hpa-maximum-replicas: "10"
spec:
gatewayClassName: consul
listeners:
- name: http
protocol: HTTP
port: 8080
Refer to the Helm chart reference for connectInject.apiGateway for the full list of deprecated fields.
Manual scaling behavior
If a gateway is not using gateway annotations or a controller-managed HPA, Kubernetes deployment scale remains user-managed after the initial deployment is created. This lets you manually scale the gateway deployment without Consul continuously forcing it back to an earlier replica count.