APIG Ingress is a Kubernetes API object that provides Layer 7 load balancing for managing external access to services in your cluster. Configure its advanced features by adding annotations to your Ingress resources — no custom code required.
Examples in this topic use bothnginx.ingress.kubernetes.ioandhigress.ingress.kubernetes.ioannotation prefixes. Each annotation's applicable prefix is shown in the annotation index below.
Annotation index
The following table lists all annotations covered in this topic. Click an annotation name to jump to the section where it is described.
| Annotation | Type | Scope | Feature |
|---|---|---|---|
nginx.ingress.kubernetes.io/canary |
string ("true") |
Route | Canary release |
nginx.ingress.kubernetes.io/canary-by-header |
string | Route | Header-based canary release |
nginx.ingress.kubernetes.io/canary-by-header-value |
string | Route | Header-based canary release |
higress.ingress.kubernetes.io/canary-by-query |
string | Route | Query parameter-based canary release |
higress.ingress.kubernetes.io/canary-by-query-value |
string | Route | Query parameter-based canary release |
nginx.ingress.kubernetes.io/canary-by-cookie |
string | Route | Cookie-based canary release |
nginx.ingress.kubernetes.io/canary-weight |
integer (0–100) | Route | Weight-based canary release |
nginx.ingress.kubernetes.io/canary-weight-total |
integer | Route | Weight-based canary release |
higress.ingress.kubernetes.io/service-subset |
string | Route | Service subset |
higress.ingress.kubernetes.io/subset-labels |
string | Route | Service subset with custom labels |
nginx.ingress.kubernetes.io/enable-cors |
boolean | Route | CORS |
nginx.ingress.kubernetes.io/cors-allow-origin |
string | Route | CORS |
nginx.ingress.kubernetes.io/cors-allow-methods |
string | Route | CORS |
nginx.ingress.kubernetes.io/cors-allow-headers |
string | Route | CORS |
nginx.ingress.kubernetes.io/cors-expose-headers |
string | Route | CORS |
nginx.ingress.kubernetes.io/cors-allow-credentials |
boolean | Route | CORS |
nginx.ingress.kubernetes.io/cors-max-age |
integer (seconds) | Route | CORS |
nginx.ingress.kubernetes.io/use-regex |
boolean | Route | Regular expression match |
nginx.ingress.kubernetes.io/rewrite-target |
string | Route | Path rewrite |
nginx.ingress.kubernetes.io/upstream-vhost |
string | Domain | Host rewrite |
nginx.ingress.kubernetes.io/ssl-redirect |
boolean | Route | HTTP-to-HTTPS redirect |
nginx.ingress.kubernetes.io/force-ssl-redirect |
boolean | Route | HTTP-to-HTTPS redirect |
nginx.ingress.kubernetes.io/permanent-redirect |
URL | Route | Permanent redirect |
nginx.ingress.kubernetes.io/permanent-redirect-code |
integer | Route | Permanent redirect |
nginx.ingress.kubernetes.io/temporal-redirect |
URL | Route | Temporary redirect |
higress.ingress.kubernetes.io/request-header-control-add |
string | Route | Request header control |
higress.ingress.kubernetes.io/request-header-control-update |
string | Route | Request header control |
higress.ingress.kubernetes.io/request-header-control-remove |
string | Route | Request header control |
higress.ingress.kubernetes.io/response-header-control-add |
string | Route | Response header control |
higress.ingress.kubernetes.io/response-header-control-update |
string | Route | Response header control |
higress.ingress.kubernetes.io/response-header-control-remove |
string | Route | Response header control |
nginx.ingress.kubernetes.io/proxy-next-upstream-tries |
integer | Route | Retry |
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout |
integer (seconds) | Route | Retry |
nginx.ingress.kubernetes.io/proxy-next-upstream |
string | Route | Retry |
nginx.ingress.kubernetes.io/whitelist-source-range |
CIDR/IP | Route | IP access control |
higress.ingress.kubernetes.io/blacklist-source-range |
CIDR/IP | Route | IP access control |
higress.ingress.kubernetes.io/domain-whitelist-source-range |
CIDR/IP | Domain | IP access control |
higress.ingress.kubernetes.io/domain-blacklist-source-range |
CIDR/IP | Domain | IP access control |
higress.ingress.kubernetes.io/route-limit-rpm |
integer | Route | Single-gateway throttling |
higress.ingress.kubernetes.io/route-limit-rps |
integer | Route | Single-gateway throttling |
higress.ingress.kubernetes.io/route-limit-burst-multiplier |
integer | Route | Single-gateway throttling |
higress.ingress.kubernetes.io/rate-limit |
integer (RPS) | Route | Global throttling control |
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-code |
integer | Route | Global throttling control |
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-body-type |
string | Route | Global throttling control |
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-body |
string | Route | Global throttling control |
higress.ingress.kubernetes.io/rate-limit-fallback-redirect-url |
URL | Route | Global throttling control |
higress.ingress.kubernetes.io/concurrency-limit |
integer | Route | Global concurrency control |
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-code |
integer | Route | Global concurrency control |
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body-type |
string | Route | Global concurrency control |
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body |
string | Route | Global concurrency control |
higress.ingress.kubernetes.io/concurrency-limit-fallback-redirect-url |
URL | Route | Global concurrency control |
higress.ingress.kubernetes.io/mirror-target-service |
string (namespace/name:port) |
Route | Traffic mirroring |
higress.ingress.kubernetes.io/mirror-percentage |
integer (0–100) | Route | Traffic mirroring |
nginx.ingress.kubernetes.io/backend-protocol |
string (HTTPS, GRPC) |
Route | Backend service protocols |
nginx.ingress.kubernetes.io/load-balance |
string | Route | Load balancing algorithms |
nginx.ingress.kubernetes.io/upstream-hash-by |
string | Route | Consistent hashing |
higress.ingress.kubernetes.io/warmup |
integer (seconds) | Route | Warmup (graceful start) |
nginx.ingress.kubernetes.io/affinity |
string ("cookie") |
Route | Cookie affinity |
nginx.ingress.kubernetes.io/affinity-mode |
string ("balanced" or "persistent") |
Route | Cookie affinity |
nginx.ingress.kubernetes.io/session-cookie-name |
string | Route | Cookie affinity |
nginx.ingress.kubernetes.io/session-cookie-path |
string | Route | Cookie affinity |
nginx.ingress.kubernetes.io/session-cookie-max-age |
integer (seconds) | Route | Cookie affinity |
nginx.ingress.kubernetes.io/session-cookie-expires |
integer (seconds) | Route | Cookie affinity |
higress.ingress.kubernetes.io/connection-policy-tcp-max-connection |
integer | Route | Connection pool |
higress.ingress.kubernetes.io/connection-policy-tcp-max-connection-per-endpoint |
integer | Route | Connection pool |
higress.ingress.kubernetes.io/connection-policy-http-max-request-per-connection |
integer | Route | Connection pool |
higress.ingress.kubernetes.io/tls-min-protocol-version |
string | Domain | TLS versions and cipher suites |
higress.ingress.kubernetes.io/tls-max-protocol-version |
string | Domain | TLS versions and cipher suites |
nginx.ingress.kubernetes.io/ssl-cipher |
string | Domain | TLS versions and cipher suites |
nginx.ingress.kubernetes.io/proxy-ssl-secret |
string (namespace/name) |
Route | mTLS with backend services |
nginx.ingress.kubernetes.io/proxy-ssl-name |
string | Route | mTLS with backend services |
nginx.ingress.kubernetes.io/proxy-ssl-server-name |
boolean | Route | mTLS with backend services |
Canary release
Canary releases let you shift traffic to a new service version without taking down the current production version. Enable the feature with nginx.ingress.kubernetes.io/canary: "true", then add one or more targeting annotations to control how traffic is distributed.
When multiple targeting methods are configured on the same Ingress, rules are evaluated in this priority order:
Cookie > Header > Query parameter > Weight
Header-based canary release
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/canary-by-header |
Routes traffic based on a request header name. Set the header value to always to always route to the canary. Any other value routes to production unless canary-by-header-value also matches. |
nginx.ingress.kubernetes.io/canary-by-header-value |
When combined with canary-by-header, routes to the canary service only if both the header name and value match. |
Example 1: Route requests with header `apig: always` to the canary service
Clusters with version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "apig"
name: demo-canary
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: Exact
Clusters with version earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "apig"
name: demo-canary
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80
Example 2: Route to multiple canary versions by header value (`apig: v1` → v1, `apig: v2` → v2)
Clusters with version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "apig"
nginx.ingress.kubernetes.io/canary-by-header-value: "v1"
name: demo-canary-v1
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary-v1
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "apig"
nginx.ingress.kubernetes.io/canary-by-header-value: "v2"
name: demo-canary-v2
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary-v2
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: Exact
Clusters with version earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "apig"
nginx.ingress.kubernetes.io/canary-by-header-value: "v1"
name: demo-canary-v1
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary-v1
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "apig"
nginx.ingress.kubernetes.io/canary-by-header-value: "v2"
name: demo-canary-v2
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary-v2
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80
Query parameter-based canary release
| Annotation | Description |
|---|---|
higress.ingress.kubernetes.io/canary-by-query |
Routes traffic based on a URL query parameter name. Set the parameter value to always to route to the canary service. |
higress.ingress.kubernetes.io/canary-by-query-value |
When combined with canary-by-query, routes to the canary service only if both the query parameter name and value match. |
Header-based and query parameter-based rules can be combined. When both are configured, a request is routed to the canary service only if both conditions are met simultaneously.
Example 1: Route requests with URL query parameter `canary=gray` to the canary service
Clusters with version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
higress.ingress.kubernetes.io/canary-by-query: "canary"
higress.ingress.kubernetes.io/canary-by-query-value: "gray"
name: demo-canary
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: Exact
Clusters with version earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
higress.ingress.kubernetes.io/canary-by-query: "canary"
higress.ingress.kubernetes.io/canary-by-query-value: "gray"
name: demo-canary
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80
Example 2: Route to canary only when both `canary=gray` in URL and `x-user-id: test` in header are present
Clusters with version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
higress.ingress.kubernetes.io/canary-by-query: "canary"
higress.ingress.kubernetes.io/canary-by-query-value: "gray"
nginx.ingress.kubernetes.io/canary-by-header: "x-user-id"
nginx.ingress.kubernetes.io/canary-by-header-value: "test"
name: demo-canary
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: Exact
Clusters with version earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
higress.ingress.kubernetes.io/canary-by-query: "canary"
higress.ingress.kubernetes.io/canary-by-query-value: "gray"
nginx.ingress.kubernetes.io/canary-by-header: "x-user-id"
nginx.ingress.kubernetes.io/canary-by-header-value: "test"
name: demo-canary
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80
Cookie-based canary release
Use nginx.ingress.kubernetes.io/canary-by-cookie to split traffic based on a cookie. Set the cookie value to always to route requests to the canary service; all other requests go to the production service.
Cookie-based canary release does not support custom values. The cookie value must be always.
Example: Route requests with cookie `demo=always` to the canary service
Clusters with version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "demo"
name: demo-canary
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: Exact
Clusters with version earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "demo"
name: demo-canary
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80
Weight-based canary release
| Annotation | Description | Default |
|---|---|---|
nginx.ingress.kubernetes.io/canary-weight |
Percentage of requests routed to the canary version. Integer from 0 to 100. | — |
nginx.ingress.kubernetes.io/canary-weight-total |
Total weight across all versions. | 100 |
Example: Split traffic across three versions — canary v1 at 30%, canary v2 at 20%, production at 50%
Clusters with version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "30"
name: demo-canary-v1
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary-v1
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
name: demo-canary-v2
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary-v2
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: Exact
Clusters with version earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "30"
name: demo-canary-v1
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary-v1
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
name: demo-canary-v2
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary-v2
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80
Service subset
Service subsets let you route traffic to specific Pods within a Service — useful when one Service is backed by multiple Deployments running different code versions.
Use the pod label convention for APIG Ingress
Set higress.ingress.kubernetes.io/service-subset to specify which Pod group receives requests. By default, APIG Ingress maps the subset value to Pod labels prefixed with opensergo.io/canary:
-
Value
""orbase: routes to Pods with labelopensergo.io/canary: ""or Pods that have noopensergo.io/canary-prefixed label. -
Any other string (e.g.,
gray): routes to Pods with labelopensergo.io/canary-gray: gray.
Example: Route `x-user-id: test` requests to the gray Deployment of go-httpbin
First, apply the Service and Deployments:
# Kubernetes Service
apiVersion: v1
kind: Service
metadata:
name: go-httpbin
namespace: default
spec:
ports:
- port: 8080
protocol: TCP
selector:
app: go-httpbin
---
# Base Deployment — no opensergo.io/canary label
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-httpbin-base
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: go-httpbin
template:
metadata:
labels:
app: go-httpbin
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/apig/go-httpbin
args:
- "--version=base"
imagePullPolicy: Always
name: go-httpbin
---
# Gray Deployment — has label opensergo.io/canary-gray: gray
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-httpbin-gray
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: go-httpbin
template:
metadata:
labels:
app: go-httpbin
opensergo.io/canary-gray: gray
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/apig/go-httpbin
args:
- "--version=gray"
imagePullPolicy: Always
name: go-httpbin
Then configure the Ingress resources:
Clusters with version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "x-user-id"
nginx.ingress.kubernetes.io/canary-by-header-value: "test"
# Forward to Pods with label opensergo.io/canary-gray: gray
higress.ingress.kubernetes.io/service-subset: gray
name: demo-canary
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: go-httpbin
port:
number: 8080
path: /test
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
# Forward to Pods with no opensergo.io/canary-prefixed label
higress.ingress.kubernetes.io/service-subset: ""
name: demo
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: go-httpbin
port:
number: 8080
path: /test
pathType: Exact
Clusters with version earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "x-user-id"
nginx.ingress.kubernetes.io/canary-by-header-value: "test"
# Forward to Pods with label opensergo.io/canary-gray: gray
higress.ingress.kubernetes.io/service-subset: gray
name: demo-canary
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /test
backend:
serviceName: go-httpbin
servicePort: 8080
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
# Forward to Pods with no opensergo.io/canary-prefixed label
higress.ingress.kubernetes.io/service-subset: ""
name: demo
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /test
backend:
serviceName: go-httpbin
servicePort: 8080
Use custom labels
To target Pods by any arbitrary label — not the opensergo.io/canary convention — set both higress.ingress.kubernetes.io/service-subset and higress.ingress.kubernetes.io/subset-labels.
Whensubset-labelsis configured, the subset is no longer mapped toopensergo.io/canary-prefixed labels.
Example: Route `x-user-id: test` requests to Pods with label `version: gray`
First, apply the Deployments (the version: gray label is added to the gray Deployment's Pod template):
# go-httpbin Kubernetes Service
apiVersion: v1
kind: Service
metadata:
name: go-httpbin
namespace: default
spec:
ports:
- port: 8080
protocol: TCP
selector:
app: go-httpbin
---
# Base Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-httpbin-base
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: go-httpbin
template:
metadata:
labels:
app: go-httpbin
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/apig/go-httpbin
args:
- "--version=base"
imagePullPolicy: Always
name: go-httpbin
---
# Gray Deployment — uses the custom label version: gray
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-httpbin-gray
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: go-httpbin
template:
metadata:
labels:
app: go-httpbin
version: gray
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/apig/go-httpbin
args:
- "--version=gray"
imagePullPolicy: Always
name: go-httpbin
Then configure the Ingress resources:
Clusters with version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "x-user-id"
nginx.ingress.kubernetes.io/canary-by-header-value: "test"
# Forward to Pods with label version: gray
higress.ingress.kubernetes.io/service-subset: gray
higress.ingress.kubernetes.io/subset-labels: version gray
name: demo-canary
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: go-httpbin
port:
number: 8080
path: /test
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/service-subset: ""
name: demo
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: go-httpbin
port:
number: 8080
path: /test
pathType: Exact
Clusters with version earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "x-user-id"
nginx.ingress.kubernetes.io/canary-by-header-value: "test"
# Forward to Pods with label version: gray
higress.ingress.kubernetes.io/service-subset: gray
higress.ingress.kubernetes.io/subset-labels: version gray
name: demo-canary
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /test
backend:
serviceName: go-httpbin
servicePort: 8080
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/service-subset: ""
name: demo
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /test
backend:
serviceName: go-httpbin
servicePort: 8080
CORS
Cross-origin resource sharing (CORS) controls which external domains can make requests to your service.
| Annotation | Description | Default |
|---|---|---|
nginx.ingress.kubernetes.io/enable-cors |
Enable or disable CORS. | — |
nginx.ingress.kubernetes.io/cors-allow-origin |
Allowed third-party origins. Comma-separated; supports * wildcard. |
* (all origins) |
nginx.ingress.kubernetes.io/cors-allow-methods |
Allowed HTTP methods. Comma-separated; supports * wildcard. |
GET,PUT,POST,DELETE,PATCH,OPTIONS |
nginx.ingress.kubernetes.io/cors-allow-headers |
Allowed request headers. Comma-separated; supports * wildcard. |
DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization |
nginx.ingress.kubernetes.io/cors-expose-headers |
Response headers the browser is allowed to access. Comma-separated. | — |
nginx.ingress.kubernetes.io/cors-allow-credentials |
Whether to allow credentials in CORS requests. | true |
nginx.ingress.kubernetes.io/cors-max-age |
How long preflight responses can be cached, in seconds. | 1728000 |
Example: Allow `example.com`, permit only `GET` and `POST`, restrict to header `X-Foo-Bar`, and disallow credentials
Clusters of version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "example.com"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET,POST"
nginx.ingress.kubernetes.io/cors-allow-headers: "X-Foo-Bar"
nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "example.com"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET,POST"
nginx.ingress.kubernetes.io/cors-allow-headers: "X-Foo-Bar"
nginx.ingress.kubernetes.io/cors-allow-credentials: "false"
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80
Regular expression match
Standard Kubernetes Ingresses support only Exact and Prefix path matching. APIG Ingress also supports regular expression matching. Enable it with nginx.ingress.kubernetes.io/use-regex: "true", then use a regex pattern as the path value.
Example: Forward any request matching `/app/...` or `/test/...` to the demo service
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
name: regex-match
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo
port:
number: 8080
path: /(app|test)/(.*)
pathType: Prefix
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
name: regex-match
namespace: default
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /(app|test)/(.*)
backend:
serviceName: demo
servicePort: 8080
Path and host rewrite
Rewriting modifies the path or host in a request before APIG Ingress forwards it to the backend service.
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/rewrite-target |
Target path after rewriting. Supports capture groups. |
nginx.ingress.kubernetes.io/upstream-vhost |
Host header value sent to the backend service. |
Path rewrite
All examples below use nginx.ingress.kubernetes.io/rewrite-target to modify the request path.
Example 1: Rewrite `example.com/test` to `example.com/dev` before forwarding
Clusters on Kubernetes 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/dev"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters Before Kubernetes 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/dev"
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /test
pathType: Exact
backend:
serviceName: demo-service
servicePort: 80
Example 2: Strip the `/v1` prefix — rewrite `example.com/v1/xxx` to `example.com/xxx`
Clusters on Kubernetes 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/$1"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /v1/(.*)
pathType: Prefix
Clusters Before Kubernetes 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/$1"
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /v1/(.*)
pathType: Prefix
backend:
serviceName: demo-service
servicePort: 80
Example 3: Replace the `/v1` prefix with `/v2` — rewrite `example.com/v1/xxx` to `example.com/v2/xxx`
Clusters on Kubernetes 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/v2/$1"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /v1/(.*)
pathType: Prefix
Clusters Before Kubernetes 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/v2/$1"
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /v1/(.*)
pathType: Prefix
backend:
serviceName: demo-service
servicePort: 80
Host rewrite
Example: Rewrite the host from `example.com` to `test.com` before forwarding
Clusters on Kubernetes 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: "test.com"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters Before Kubernetes 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: "test.com"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Redirect
HTTP-to-HTTPS redirect
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/ssl-redirect |
Redirect HTTP requests to HTTPS. |
nginx.ingress.kubernetes.io/force-ssl-redirect |
Redirect HTTP requests to HTTPS. |
APIG Ingress treats ssl-redirect and force-ssl-redirect identically — both force an HTTP-to-HTTPS redirect.
Example: Redirect `http://example.com/test` to `https://example.com/test`
Clusters on Version 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters Before Version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Permanent redirect
| Annotation | Description | Default |
|---|---|---|
nginx.ingress.kubernetes.io/permanent-redirect |
Destination URL for a permanent redirect. Must include the scheme (http:// or https://). |
— |
nginx.ingress.kubernetes.io/permanent-redirect-code |
HTTP status code for the redirect. | 301 |
Example: Permanently redirect `http://example.com/test` to `http://example.com/app`
Clusters on Version 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: "http://example.com/app"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters Before Version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: "http://example.com/app"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Temporary redirect
Use nginx.ingress.kubernetes.io/temporal-redirect to specify the destination URL for a temporary redirect. The URL must include the scheme (http:// or https://).
Example: Temporarily redirect `http://example.com/test` to `http://example.com/app`
Clusters on Version 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/temporal-redirect: "http://example.com/app"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters Before Version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/temporal-redirect: "http://example.com/app"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Header control
Header control lets you add, update, or remove HTTP headers as APIG Ingress forwards requests to backend services and responses back to clients.
Request header control
All three annotations share the same multi-header syntax: a single header uses a key-value pair; multiple headers use the YAML | block scalar with one key-value pair per line.
| Annotation | Description |
|---|---|
higress.ingress.kubernetes.io/request-header-control-add |
Adds a header to the forwarded request. If the header already exists, the value is appended. |
higress.ingress.kubernetes.io/request-header-control-update |
Updates a header in the forwarded request. If the header already exists, the value is overwritten. |
higress.ingress.kubernetes.io/request-header-control-remove |
Removes a header from the forwarded request. Separate multiple header names with commas. |
Example 1: Add headers `foo: bar` and `test: true` to all requests to `example.com/test`
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/request-header-control-add: |
foo bar
test true
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/request-header-control-add: |
foo bar
test true
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Use header control together with canary releases to tag traffic by deployment stage
When apig: v1 is present in the request header, APIG Ingress routes to the canary and adds stage: gray. All other requests go to the base version and receive stage: production.
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "apig"
nginx.ingress.kubernetes.io/canary-by-header-value: "v1"
higress.ingress.kubernetes.io/request-header-control-add: "stage gray"
name: demo-canary-v1
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service-canary-v1
port:
number: 80
path: /hello
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/request-header-control-add: "stage production"
name: demo
spec:
ingressClassName: apig
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "apig"
nginx.ingress.kubernetes.io/canary-by-header-value: "v1"
higress.ingress.kubernetes.io/request-header-control-add: "stage gray"
name: demo-canary-v1
spec:
ingressClassName: apig
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary-v1
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/request-header-control-add: "stage production"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80
Response header control
| Annotation | Description |
|---|---|
higress.ingress.kubernetes.io/response-header-control-add |
Adds a header to the response before it is forwarded to the client. If the header already exists, the value is appended. |
higress.ingress.kubernetes.io/response-header-control-update |
Updates a header in the response before it is forwarded to the client. If the header already exists, the value is overwritten. |
higress.ingress.kubernetes.io/response-header-control-remove |
Removes a header from the response before it is forwarded to the client. Separate multiple header names with commas. |
Example: Remove the `req-cost-time` header from responses to `example.com/test`
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/response-header-control-remove: "req-cost-time"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/response-header-control-remove: "req-cost-time"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Retry
APIG Ingress automatically retries failed requests at the route level. Configure the maximum number of retries, the timeout, and the conditions that trigger a retry.
| Annotation | Description | Default |
|---|---|---|
nginx.ingress.kubernetes.io/proxy-next-upstream-tries |
Maximum number of retry attempts. | 3 |
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout |
Timeout for retries, in seconds. | No timeout |
nginx.ingress.kubernetes.io/proxy-next-upstream |
Comma-separated list of retry conditions. | error,timeout |
Valid retry conditions:
| Condition | Description |
|---|---|
error |
Connection establishment fails or a 5xx status code is returned. |
timeout |
Connection establishment times out or a 5xx status code is returned. |
invalid_header |
A request error occurs or a 5xx status code is returned. |
http_xxx |
Retry on a specific HTTP status code (e.g., http_502, http_403). |
non_idempotent |
Enable retries for non-idempotent requests (POST, PATCH). By default, these are not retried. |
off |
Disable retries entirely. |
Example: Retry up to 2 times within 5 seconds, only on HTTP 502, and also retry non-idempotent requests
Clusters for Kubernetes 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-next-upstream-tries: "2"
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "5"
nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502,non_idempotent"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters for Kubernetes Earlier Than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-next-upstream-tries: "2"
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "5"
nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502,non_idempotent"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
IP access control
APIG Ingress supports IP address allowlists and denylists at both the route level and the domain level. Route-level rules take precedence over domain-level rules.
Route-level IP access control
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/whitelist-source-range |
Allowlist for a specific route. Accepts IP addresses and CIDR blocks, comma-separated. |
higress.ingress.kubernetes.io/blacklist-source-range |
Denylist for a specific route. Accepts IP addresses and CIDR blocks, comma-separated. |
Example 1: Allow access to `example.com/test` only from `1.1.X.X`
Clusters of version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: 1.1.X.X
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: 1.1.X.X
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Block access to `example.com/test` from `2.2.2.2`
Clusters of version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/blacklist-source-range: 2.2.2.2
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/blacklist-source-range: 2.2.2.2
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Domain-level IP access control
| Annotation | Description |
|---|---|
higress.ingress.kubernetes.io/domain-whitelist-source-range |
Allowlist applied to all routes under a domain. Route-level allowlists take precedence. Accepts IP addresses and CIDR blocks, comma-separated. |
higress.ingress.kubernetes.io/domain-blacklist-source-range |
Denylist applied to all routes under a domain. Route-level denylists take precedence. Accepts IP addresses and CIDR blocks, comma-separated. |
Example 1: Allow access to all routes under `example.com` from `1.1.X.X` and `2.2.2.2`
Clusters of version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/domain-whitelist-source-range: 1.1.X.X,2.2.2.2
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
- backend:
service:
name: app-service
port:
number: 80
path: /app
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/domain-whitelist-source-range: 1.1.X.X,2.2.2.2
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
- path: /app
backend:
serviceName: app-service
servicePort: 80
Example 2: Combine domain-level and route-level allowlists — restrict `/order` to `3.3.X.X` while allowing `1.1.X.X` and `2.2.2.2` on all other routes
Clusters of version 1.19 and later
# Domain-level allowlist for /test and /app
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/domain-whitelist-source-range: 1.1.X.X,2.2.2.2
name: demo-domain
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
- backend:
service:
name: app-service
port:
number: 80
path: /app
pathType: Exact
---
# Route-level allowlist overrides domain-level for /order
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: 3.3.X.X
name: demo-route
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /order
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/domain-whitelist-source-range: 1.1.X.X,2.2.2.2
name: demo-domain
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
- path: /app
backend:
serviceName: app-service
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: 3.3.X.X
name: demo-route
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /order
backend:
serviceName: demo-service
servicePort: 80
Single-gateway throttling
Single-gateway throttling limits the request rate for a specific route on each Cloud-native API Gateway instance. The limit applies per gateway replica, not across the entire cluster.
Rate limits apply per gateway replica. If you run multiple replicas or use a Horizontal Pod Autoscaler (HPA), the effective cluster-wide limit is the configured value multiplied by the number of replicas. For a cluster-wide limit that is not affected by replica count, use global throttling control instead.
| Annotation | Description | Default |
|---|---|---|
higress.ingress.kubernetes.io/route-limit-rpm |
Maximum requests per minute (RPM) per gateway instance. When the limit is exceeded, the response body is local_rate_limited. |
— |
higress.ingress.kubernetes.io/route-limit-rps |
Maximum requests per second (RPS) per gateway instance. When the limit is exceeded, the response body is local_rate_limited. |
— |
higress.ingress.kubernetes.io/route-limit-burst-multiplier |
Burst limit multiplier. The burst limit equals the RPM or RPS value multiplied by this number. | 5 |
The response status code when throttling is triggered depends on your gateway version:
-
Gateway version earlier than 1.2.23: HTTP 503
-
Gateway version 1.2.23 or later: HTTP 429
Example 1: Limit `example.com/test` to 100 RPM with a burst limit of 200 (multiplier 2)
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/route-limit-rpm: "100"
higress.ingress.kubernetes.io/route-limit-burst-multiplier: "2"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/route-limit-rpm: "100"
higress.ingress.kubernetes.io/route-limit-burst-multiplier: "2"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Limit `example.com/test` to 10 RPS with the default burst limit (multiplier 5, burst = 50)
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/route-limit-rps: "10"
# Default burst multiplier is 5; burst limit = 50
# higress.ingress.kubernetes.io/route-limit-burst-multiplier: "5"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/route-limit-rps: "10"
# Default burst multiplier is 5; burst limit = 50
# higress.ingress.kubernetes.io/route-limit-burst-multiplier: "5"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Global throttling control
This feature requires APIG Ingress gateway version 1.2.25 or later.
Global throttling control integrates with Sentinel to enforce a cluster-wide RPS limit on a specific route. When the limit is exceeded, the default response is HTTP 429 with body sentinel rate limited. Override this behavior with a custom response or a redirect — but not both.
Custom response
| Annotation | Description | Default |
|---|---|---|
higress.ingress.kubernetes.io/rate-limit |
Maximum RPS for the route across the gateway cluster. | — |
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-code |
HTTP status code when throttling is triggered. | 429 |
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-body-type |
Response body format: text (text/plain; charset=UTF-8) or json (application/json; charset=UTF-8). |
text |
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-body |
Response body content when throttling is triggered. | sentinel rate limited |
Example 1: Limit `example.com/test` to 100 RPS with the default throttling response
Clusters of version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/rate-limit: "100"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/rate-limit: "100"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Limit `example.com/test` to 100 RPS; return HTTP 503 with body `server is overload` when throttled
Clusters of version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/rate-limit: "100"
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-code: "503"
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-body: "server is overload"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/rate-limit: "100"
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-code: "503"
higress.ingress.kubernetes.io/rate-limit-fallback-custom-response-body: "server is overload"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Redirection
Use higress.ingress.kubernetes.io/rate-limit-fallback-redirect-url to redirect clients to a fallback URL when throttling is triggered.
Example: Limit `example.com/test` to 100 RPS; redirect to `example.com/fallback` when throttled
Clusters of version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/rate-limit: "100"
higress.ingress.kubernetes.io/rate-limit-fallback-redirect-url: "example.com/fallback"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/rate-limit: "100"
higress.ingress.kubernetes.io/rate-limit-fallback-redirect-url: "example.com/fallback"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Global concurrency control
This feature requires APIG Ingress gateway version 1.2.25 or later.
Global concurrency control integrates with Sentinel to enforce a cluster-wide limit on the number of concurrent requests being processed for a specific route. When the limit is exceeded, the default response is HTTP 429 with body sentinel rate limited. Override this with a custom response or a redirect — but not both.
Custom response
| Annotation | Description | Default |
|---|---|---|
higress.ingress.kubernetes.io/concurrency-limit |
Maximum concurrent requests for the route across the gateway cluster. | — |
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-code |
HTTP status code when concurrency control is triggered. | 429 |
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body-type |
Response body format: text (text/plain; charset=UTF-8) or json (application/json; charset=UTF-8). |
text |
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body |
Response body content when concurrency control is triggered. | sentinel rate limited |
Example 1: Limit concurrent requests to `example.com/test` to 1,000 with the default response
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/concurrency-limit: "1000"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/concurrency-limit: "1000"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Limit concurrent requests to 1,000; return HTTP 503 with body `server is overloaded` when the limit is reached
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/concurrency-limit: "1000"
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-code: "503"
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body: "server is overload"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/concurrency-limit: "1000"
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-code: "503"
higress.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body: "server is overload"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Redirection
Use higress.ingress.kubernetes.io/concurrency-limit-fallback-redirect-url to redirect clients to a fallback URL when concurrency control is triggered.
Example: Limit concurrent requests to 1,000; redirect to `example.com/fallback` when the limit is reached
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/concurrency-limit: "1000"
higress.ingress.kubernetes.io/concurrency-limit-fallback-redirect-url: "example.com/fallback"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/concurrency-limit: "1000"
higress.ingress.kubernetes.io/concurrency-limit-fallback-redirect-url: "example.com/fallback"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Traffic mirroring
Traffic mirroring copies live request traffic to a shadow service without affecting the original request flow. Use it for operational auditing, traffic testing, or shadow mode validation of new service versions.
| Annotation | Description | Default |
|---|---|---|
higress.ingress.kubernetes.io/mirror-target-service |
Destination service for mirrored traffic. Format: namespace/name:port. The namespace and port fields are optional — namespace defaults to the Ingress gateway's namespace, and port defaults to the service's first port. |
— |
higress.ingress.kubernetes.io/mirror-percentage |
Percentage of traffic to mirror. Valid values: 0–100. | 100 |
When mirrored traffic is forwarded to the destination service, APIG Ingress automatically appends -shadow to the Host header. For example, example.com becomes example.com-shadow. If the destination service uses the Host header for routing or logging, account for this rewrite in your service configuration.
Example 1: Mirror all traffic from `example.com/test` to `test/app:8080`
Clusters Running Version 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/mirror-target-service: test/app:8080
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters Running Versions Earlier Than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/mirror-target-service: test/app:8080
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Mirror 10% of traffic from `example.com/test` to `test/app:8080`
Clusters Running Version 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/mirror-target-service: test/app:8080
higress.ingress.kubernetes.io/mirror-percentage: "10"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters Running Versions Earlier Than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/mirror-target-service: test/app:8080
higress.ingress.kubernetes.io/mirror-percentage: "10"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Backend service protocols
By default, APIG Ingress forwards requests to backend containers over HTTP. Use the nginx.ingress.kubernetes.io/backend-protocol annotation to switch to HTTPS or gRPC.
If the port name in a Kubernetes Service resource is set togrpcorhttp2, APIG Ingress automatically uses gRPC or HTTP/2 for that backend — without the annotation. This differs from NGINX Ingress, which requires the annotation in all cases.
Example 1: Forward requests to an HTTPS backend
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /
pathType: Exact
Clusters running Kubernetes versions earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Forward requests to a gRPC backend
Two methods are available: use the annotation for explicit control, or set the Service port name when you prefer convention over configuration.
Method 1 — annotation:
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes versions earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Method 2 — Service port name (grpc):
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /order
pathType: Exact
---
apiVersion: v1
kind: Service
metadata:
name: demo-service
spec:
ports:
- name: grpc # APIG Ingress detects this and automatically uses gRPC
port: 80
protocol: TCP
selector:
app: demo-service
Clusters running Kubernetes versions earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
name: demo-service
spec:
ports:
- name: grpc
port: 80
protocol: TCP
selector:
app: demo-service
Load balancing algorithms for backend services
Load balancing algorithms control how Cloud-native API Gateway selects backend nodes when forwarding requests.
Common load balancing algorithms
Use nginx.ingress.kubernetes.io/load-balance to set the algorithm.
| Value | Description |
|---|---|
round_robin |
Distribute requests across backend nodes in rotation. This is the default. |
least_conn |
Route each request to the node with the fewest active connections. |
random |
Select a backend node at random. |
APIG Ingress does not support the exponentially weighted moving average (EWMA) algorithm. If EWMA is configured, it falls back to round_robin.
Example: Use least connections for the demo-service backend
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/load-balance: "least_conn"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /order
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/load-balance: "least_conn"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Load balancing algorithms based on consistent hashing
Consistent hashing ensures that requests with the same key are always routed to the same backend node — useful for session-aware applications or cache locality. Set the hash key using nginx.ingress.kubernetes.io/upstream-hash-by.
Supported hash key types:
| Hash key | Configuration | Description |
|---|---|---|
| Request URI | $request_uri |
Includes path parameters. |
| Host | $host |
The request host header. |
| Client IP | $remote_addr |
The client IP address. |
| Request header | $http_<header-name> |
The value of a specific request header. |
| Query parameter | $arg_<param-name> |
The value of a specific URL query parameter. |
Example 1: Route all requests from the same client IP to the same backend node
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Route requests with the same `X-Stage` header value to the same backend node
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$http_x-stage"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$http_x-stage"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 3: Route requests with the same `X-Stage` query parameter value to the same backend node
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$arg_x-stage"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$arg_x-stage"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Warmup (graceful start)
The warmup feature gradually increases traffic to a newly started backend node over a specified time window, instead of immediately sending it full load. This gives the node time to initialize caches and JIT-compile code before handling peak traffic.
Use higress.ingress.kubernetes.io/warmup to set the warmup window in seconds. Warmup is disabled by default.
Warmup is only supported withround_robinandleast_connload balancing algorithms.
Example: Warm up demo-service over a 30-second window
Clusters running Kubernetes 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/warmup: "30"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/warmup: "30"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Cookie affinity (session persistence)
Cookie affinity ensures that all requests from the same client are routed to the same backend node. On the first request, if the client does not have the affinity cookie, APIG Ingress generates one and includes it in the response. Subsequent requests from that client carry the cookie and are always routed to the same node.
| Annotation | Description | Default |
|---|---|---|
nginx.ingress.kubernetes.io/affinity |
Affinity type. The only valid value is cookie. |
— |
nginx.ingress.kubernetes.io/affinity-mode |
Affinity mode: balanced distributes new sessions evenly across backends; persistent always routes to the same backend for the lifetime of the cookie. |
balanced |
nginx.ingress.kubernetes.io/session-cookie-name |
Name of the cookie used as the hash key. | INGRESSCOOKIE |
nginx.ingress.kubernetes.io/session-cookie-path |
Path of the generated cookie. Must match the Ingress path. | / |
nginx.ingress.kubernetes.io/session-cookie-max-age |
Expiration time of the generated cookie, in seconds. Takes precedence over session-cookie-expires. |
Session-level |
nginx.ingress.kubernetes.io/session-cookie-expires |
Expiration time of the generated cookie, in seconds. | Session-level |
Example 1: Enable cookie affinity with default settings (cookie name `INGRESSCOOKIE`, path `/`, session-level lifetime)
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Example 2: Enable cookie affinity with a custom cookie name `test`, path `/`, and 10-second expiration
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "test"
nginx.ingress.kubernetes.io/session-cookie-max-age: "10"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "test"
nginx.ingress.kubernetes.io/session-cookie-max-age: "10"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
Connection pool
Configure a connection pool between a Cloud-native API Gateway instance and a backend service to control how many connections the gateway opens to that service. This prevents the backend from being overwhelmed and helps maintain stability under load.
| Annotation | Description |
|---|---|
higress.ingress.kubernetes.io/connection-policy-tcp-max-connection |
Maximum total TCP connections between the gateway instance and the backend service. |
higress.ingress.kubernetes.io/connection-policy-tcp-max-connection-per-endpoint |
Maximum TCP connections between the gateway instance and a single backend Pod. |
higress.ingress.kubernetes.io/connection-policy-http-max-request-per-connection |
Maximum HTTP requests per TCP connection between the gateway instance and the backend service. |
Example: Limit the gateway to 10 total connections and 2 connections per Pod for demo-service
Clusters of Version 1.19 and Later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/connection-policy-tcp-max-connection: "10"
higress.ingress.kubernetes.io/connection-policy-tcp-max-connection-per-endpoint: "2"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters Before Version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/connection-policy-tcp-max-connection: "10"
higress.ingress.kubernetes.io/connection-policy-tcp-max-connection-per-endpoint: "2"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
TLS versions and cipher suites
By default, APIG Ingress accepts TLS connections from TLS 1.0 through TLS 1.3, using the following cipher suites:
-
ECDHE-ECDSA-AES128-GCM-SHA256 -
ECDHE-RSA-AES128-GCM-SHA256 -
ECDHE-ECDSA-AES128-SHA -
ECDHE-RSA-AES128-SHA -
AES128-GCM-SHA256 -
AES128-SHA -
ECDHE-ECDSA-AES256-GCM-SHA384 -
ECDHE-RSA-AES256-GCM-SHA384 -
ECDHE-ECDSA-AES256-SHA -
ECDHE-RSA-AES256-SHA -
AES256-GCM-SHA384 -
AES256-SHA
Use the following annotations to restrict the TLS version range or cipher suites for a specific domain:
| Annotation | Description | Default |
|---|---|---|
higress.ingress.kubernetes.io/tls-min-protocol-version |
Minimum TLS version. Valid values: TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3. |
TLSv1.0 |
higress.ingress.kubernetes.io/tls-max-protocol-version |
Maximum TLS version. Valid values: TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3. |
TLSv1.3 |
nginx.ingress.kubernetes.io/ssl-cipher |
Allowed cipher suites, comma-separated. Applies only to TLS 1.0–1.2 handshakes. | — |
Example: Restrict `example.com` to TLS 1.2 only
Clusters of version 1.19 and later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/tls-min-protocol-version: "TLSv1.2"
higress.ingress.kubernetes.io/tls-max-protocol-version: "TLSv1.2"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters earlier than version 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
higress.ingress.kubernetes.io/tls-min-protocol-version: "TLSv1.2"
higress.ingress.kubernetes.io/tls-max-protocol-version: "TLSv1.2"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
mTLS authentication with backend services
By default, APIG Ingress uses HTTP to connect to backend services. Using nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" (described in Backend service protocols) enables one-way TLS — the gateway verifies the backend's certificate, but the backend does not verify the gateway's.
For a zero-trust model where both sides verify each other, configure mutual TLS (mTLS). With mTLS, the backend service also verifies a client certificate presented by the gateway.
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/proxy-ssl-secret |
Client certificate used by the gateway to authenticate itself to the backend service. Format: secretNamespace/secretName. |
nginx.ingress.kubernetes.io/proxy-ssl-name |
Server Name Indication (SNI) value used during the TLS handshake. |
nginx.ingress.kubernetes.io/proxy-ssl-server-name |
Enable or disable SNI during the TLS handshake. |
Example: Configure mTLS between the gateway and demo-service using the certificate `default/gateway-cert`
Clusters running Kubernetes 1.19 or later
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/proxy-ssl-secret: "default/gateway-cert"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: Exact
Clusters running Kubernetes earlier than 1.19
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/proxy-ssl-secret: "default/gateway-cert"
name: demo
spec:
ingressClassName: apig
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80