MSE Ingress is a Kubernetes Ingress object that manages external access to cluster services via Layer-7 load balancing. Configure advanced traffic governance features — canary releases, rate limiting, access control, header manipulation, and more — by adding annotations to your Ingress resources.
Annotation quick reference
All MSE Ingress features are controlled through Kubernetes annotations. The table below lists every supported annotation grouped by feature. Click the feature name to jump to the full configuration guide.
| Annotation | Feature | Type |
|---|---|---|
nginx.ingress.kubernetes.io/canary | Enable canary release | "true" or "false" |
nginx.ingress.kubernetes.io/canary-by-header | Header-based canary release | string |
nginx.ingress.kubernetes.io/canary-by-header-value | Header-based canary release with exact value | string |
nginx.ingress.kubernetes.io/canary-by-cookie | Cookie-based canary release | string |
nginx.ingress.kubernetes.io/canary-weight | Weight-based canary release | integer (0–100) |
nginx.ingress.kubernetes.io/canary-weight-total | Total weight denominator for weight-based canary | integer (default: 100) |
mse.ingress.kubernetes.io/canary-by-query | Query parameter-based canary release | string |
mse.ingress.kubernetes.io/canary-by-query-value | Query parameter-based canary release with exact value | string |
mse.ingress.kubernetes.io/service-subset | Service subset routing | string |
mse.ingress.kubernetes.io/subset-labels | Custom subset labels for service subset | string |
nginx.ingress.kubernetes.io/enable-cors | Enable CORS | "true" or "false" |
nginx.ingress.kubernetes.io/cors-allow-origin | Allowed CORS origins | string (default: *) |
nginx.ingress.kubernetes.io/cors-allow-methods | Allowed HTTP methods for CORS | string |
nginx.ingress.kubernetes.io/cors-allow-headers | Allowed request headers for CORS | string |
nginx.ingress.kubernetes.io/cors-allow-credentials | Allow credentials in CORS requests | "true" or "false" |
nginx.ingress.kubernetes.io/cors-max-age | Preflight cache duration for CORS (seconds) | integer (default: 1728000) |
nginx.ingress.kubernetes.io/use-regex | Enable regex path matching | "true" |
nginx.ingress.kubernetes.io/rewrite-target | Path rewrite destination | string |
nginx.ingress.kubernetes.io/upstream-vhost | Host rewrite destination | string |
nginx.ingress.kubernetes.io/ssl-redirect | Force HTTP-to-HTTPS redirect | "true" or "false" |
nginx.ingress.kubernetes.io/force-ssl-redirect | Force HTTP-to-HTTPS redirect | "true" or "false" |
nginx.ingress.kubernetes.io/permanent-redirect | Permanent redirect URL | string |
nginx.ingress.kubernetes.io/permanent-redirect-code | Permanent redirect status code | integer (default: 301) |
nginx.ingress.kubernetes.io/temporal-redirect | Temporary redirect URL | string |
mse.ingress.kubernetes.io/request-header-control-add | Add request headers | string |
mse.ingress.kubernetes.io/request-header-control-update | Update request headers | string |
mse.ingress.kubernetes.io/request-header-control-remove | Remove request headers | string |
mse.ingress.kubernetes.io/response-header-control-add | Add response headers | string |
mse.ingress.kubernetes.io/response-header-control-update | Update response headers | string |
mse.ingress.kubernetes.io/response-header-control-remove | Remove response headers | string |
nginx.ingress.kubernetes.io/proxy-next-upstream-tries | Max retry attempts | integer (default: 3) |
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout | Retry timeout (seconds) | integer |
nginx.ingress.kubernetes.io/proxy-next-upstream | Retry conditions | string (default: error,timeout) |
nginx.ingress.kubernetes.io/whitelist-source-range | IP whitelist (access control) | CIDR/IP |
mse.ingress.kubernetes.io/blacklist-source-range | IP blacklist (access control) | CIDR/IP |
mse.ingress.kubernetes.io/domain-whitelist-source-range | IP whitelist (access control) | CIDR/IP |
mse.ingress.kubernetes.io/domain-blacklist-source-range | IP blacklist (access control) | CIDR/IP |
mse.ingress.kubernetes.io/route-limit-rpm | Max requests per minute (single-gateway throttling) | integer |
mse.ingress.kubernetes.io/route-limit-rps | Max requests per second (single-gateway throttling) | integer |
mse.ingress.kubernetes.io/route-limit-burst-multiplier | Burst multiplier for single-gateway throttling | integer (default: 5) |
mse.ingress.kubernetes.io/rate-limit | Global RPS limit (global rate limiting) | integer |
mse.ingress.kubernetes.io/concurrency-limit | Global concurrency limit (global concurrency control) | integer |
mse.ingress.kubernetes.io/mirror-target-service | Traffic mirroring target | namespace/name:port |
mse.ingress.kubernetes.io/mirror-percentage | Mirrored traffic percentage (traffic mirroring) | integer (0–100, default: 100) |
nginx.ingress.kubernetes.io/backend-protocol | Backend protocol | "HTTPS" or "GRPC" |
nginx.ingress.kubernetes.io/load-balance | Load balancing algorithm | string (default: round_robin) |
nginx.ingress.kubernetes.io/upstream-hash-by | Consistent hashing key | string |
mse.ingress.kubernetes.io/warmup | Service warmup duration (seconds) | integer |
nginx.ingress.kubernetes.io/affinity | Session affinity type | "cookie" |
nginx.ingress.kubernetes.io/session-cookie-name | Session affinity cookie name | string (default: INGRESSCOOKIE) |
nginx.ingress.kubernetes.io/session-cookie-max-age | Session affinity cookie expiry (seconds) | integer |
mse.ingress.kubernetes.io/connection-policy-tcp-max-connection | Max gateway-to-backend connections (connection pool) | integer |
mse.ingress.kubernetes.io/connection-policy-tcp-max-connection-per-endpoint | Max connections per endpoint (connection pool) | integer |
mse.ingress.kubernetes.io/connection-policy-http-max-request-per-connection | Max requests per connection (connection pool) | integer |
mse.ingress.kubernetes.io/tls-min-protocol-version | Minimum TLS version | string (default: TLSv1.0) |
mse.ingress.kubernetes.io/tls-max-protocol-version | Maximum TLS version | string (default: TLSv1.3) |
nginx.ingress.kubernetes.io/ssl-cipher | TLS cipher suites | string |
nginx.ingress.kubernetes.io/proxy-ssl-secret | Gateway client certificate for mTLS | secretNamespace/secretName |
Canary release
MSE Ingress supports canary releases based on request headers, query parameters, cookies, or weights. All methods require the nginx.ingress.kubernetes.io/canary: "true" annotation on the canary Ingress resource. MSE Ingress supports an unlimited number of simultaneous canary versions, unlike NGINX Ingress and ALB Ingress, which support at most two service versions during a canary release.
Matching method precedence — when multiple methods are configured simultaneously, MSE Ingress applies them in this order:
| Priority | Method | Annotation |
|---|---|---|
| 1 (highest) | Header-based | canary-by-header |
| 1 (highest) | Query parameter-based | canary-by-query |
| 2 | Cookie-based | canary-by-cookie |
| 3 (lowest) | Weight-based | canary-weight |
Header-based canary release
Choose between two header matching modes:
| Mode | Annotations | Behavior |
|---|---|---|
| Key-only | canary-by-header only | Routes to canary when the header value is always. All other values go to the base version. |
| Key + exact value | canary-by-header + canary-by-header-value | Routes to canary only when both the header key and value match exactly. All other values go to the base version. |
Example 1: Route to canary when `mse: always`
Requests with header mse: always go to demo-service-canary. All others go to demo-service.
Kubernetes v1.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: "mse" # Route to canary when mse: always
name: demo-canary
spec:
ingressClassName: mse
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: mse
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "mse"
name: demo-canary
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80Example 2: Route to multiple canary versions by header value
Requests with mse: v1 go to demo-service-canary-v1, mse: v2 go to demo-service-canary-v2, and all others go to demo-service.
Kubernetes v1.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: "mse"
nginx.ingress.kubernetes.io/canary-by-header-value: "v1" # Exact match: routes when mse=v1
name: demo-canary-v1
spec:
ingressClassName: mse
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: "mse"
nginx.ingress.kubernetes.io/canary-by-header-value: "v2" # Exact match: routes when mse=v2
name: demo-canary-v2
spec:
ingressClassName: mse
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: mse
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "mse"
nginx.ingress.kubernetes.io/canary-by-header-value: "v1"
name: demo-canary-v1
spec:
ingressClassName: mse
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: "mse"
nginx.ingress.kubernetes.io/canary-by-header-value: "v2"
name: demo-canary-v2
spec:
ingressClassName: mse
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: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80Query parameter-based canary release
Choose between two query parameter matching modes:
| Mode | Annotations | Behavior |
|---|---|---|
| Key-only | canary-by-query only | Routes to canary when the query parameter key matches and its value is always. |
| Key + exact value | canary-by-query + canary-by-query-value | Routes to canary only when both the query parameter key and value match exactly. |
Header-based and query parameter-based canary releases can be combined. When both are configured, a request must satisfy both conditions to reach the canary version.
Example 1: Route to canary when query parameter `canary=gray`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
mse.ingress.kubernetes.io/canary-by-query: "canary" # Query param name
mse.ingress.kubernetes.io/canary-by-query-value: "gray" # Exact value to match
name: demo-canary
spec:
ingressClassName: mse
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: mse
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
mse.ingress.kubernetes.io/canary-by-query: "canary"
mse.ingress.kubernetes.io/canary-by-query-value: "gray"
name: demo-canary
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80Example 2: Combine query parameter and header conditions
Requests with query parameter canary=gray AND header x-user-id: test go to the canary version. All others go to the base version.
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
mse.ingress.kubernetes.io/canary-by-query: "canary" # Both conditions must match
mse.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: mse
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: mse
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
mse.ingress.kubernetes.io/canary-by-query: "canary"
mse.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: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80Cookie-based canary release
Use nginx.ingress.kubernetes.io/canary-by-cookie to route based on cookies. Requests go to the canary version only when the cookie value is always.
Custom cookie values are not supported. The cookie value must be always.Example: Route to canary when `demo=always`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "demo" # Routes when cookie demo=always
name: demo-canary
spec:
ingressClassName: mse
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: mse
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: ExactKubernetes earlier than v1.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: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80Weight-based canary release
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/canary-weight | Percentage of requests sent to the canary version. Integer from 0 to 100. |
nginx.ingress.kubernetes.io/canary-weight-total | Total weight denominator. Default: 100. |
Example: Split traffic across two canary versions and a base version
demo-service-canary-v1 receives 30%, demo-service-canary-v2 receives 20%, and demo-service receives the remaining 50%.
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "30" # 30% of traffic
name: demo-canary-v1
spec:
ingressClassName: mse
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" # 20% of traffic
name: demo-canary-v2
spec:
ingressClassName: mse
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: mse
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: ExactKubernetes earlier than v1.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: mse
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: mse
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: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80Service subset
A service subset routes requests to a specific subset of Pods within a single Kubernetes Service — useful when one Service spans multiple Deployments (for example, a base version and a canary version).
Use pod labels in MseIngressConfig
Use the mse.ingress.kubernetes.io/service-subset annotation. By default, MSE Ingress maps this to the Pod label prefix opensergo.io/canary:
Setting the annotation to
""orbaseroutes requests to Pods whose labels do not have theopensergo.io/canaryprefix (base Pods).Setting it to any other value (for example,
gray) routes requests to Pods with the labelopensergo.io/canary-gray: gray.
Example: Route by user ID header to different pod subsets
The go-httpbin Service is backed by two Deployments — go-httpbin-base (no canary label) and go-httpbin-gray (label opensergo.io/canary-gray: gray). Requests with header x-user-id: test go to the gray Pods; all others go to the base Pods.
Service and Deployment definitions:
# 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 (no 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/mse/go-httpbin
args:
- "--version=base"
imagePullPolicy: Always
name: go-httpbin
---
# Gray deployment (canary 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/mse/go-httpbin
args:
- "--version=gray"
imagePullPolicy: Always
name: go-httpbinIngress configurations — Kubernetes v1.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: "x-user-id"
nginx.ingress.kubernetes.io/canary-by-header-value: "test"
mse.ingress.kubernetes.io/service-subset: gray # Route to pods with label opensergo.io/canary-gray: gray
name: demo-canary
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- backend:
service:
name: go-httpbin
port:
number: 8080
path: /test
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/service-subset: "" # Route to pods without the opensergo.io/canary prefix
name: demo
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- backend:
service:
name: go-httpbin
port:
number: 8080
path: /test
pathType: ExactKubernetes earlier than v1.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"
mse.ingress.kubernetes.io/service-subset: gray # Route to pods with label opensergo.io/canary-gray: gray
name: demo-canary
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /test
backend:
serviceName: go-httpbin
servicePort: 8080
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/service-subset: "" # Route to pods without the opensergo.io/canary prefix
name: demo
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /test
backend:
serviceName: go-httpbin
servicePort: 8080Use custom labels
Combine mse.ingress.kubernetes.io/service-subset with mse.ingress.kubernetes.io/subset-labels to route based on any custom Pod label — not just the opensergo.io/canary prefix.
Whensubset-labelsis set, the subset is no longer mapped to theopensergo.io/canarylabel prefix.
Example: Route by custom `version` label
The gray Deployment has the label version: gray. Requests with header x-user-id: test go to the gray Pods; all others go to the base Pods.
Service and Deployment definitions:
# 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/mse/go-httpbin
args:
- "--version=base"
imagePullPolicy: Always
name: go-httpbin
---
# Gray deployment (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/mse/go-httpbin
args:
- "--version=gray"
imagePullPolicy: Always
name: go-httpbinIngress configurations — Kubernetes v1.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: "x-user-id"
nginx.ingress.kubernetes.io/canary-by-header-value: "test"
mse.ingress.kubernetes.io/service-subset: gray # Subset name
mse.ingress.kubernetes.io/subset-labels: version gray # Map subset name to pod label version=gray
name: demo-canary
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- backend:
service:
name: go-httpbin
port:
number: 8080
path: /test
pathType: Exact
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/service-subset: ""
name: demo
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- backend:
service:
name: go-httpbin
port:
number: 8080
path: /test
pathType: ExactKubernetes earlier than v1.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"
mse.ingress.kubernetes.io/service-subset: gray
mse.ingress.kubernetes.io/subset-labels: version gray
name: demo-canary
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /test
backend:
serviceName: go-httpbin
servicePort: 8080
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/service-subset: ""
name: demo
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /test
backend:
serviceName: go-httpbin
servicePort: 8080CORS
Cross-Origin Resource Sharing (CORS) allows web applications to access resources from a different origin. For background, see Cross-Origin Resource Sharing (CORS).
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/enable-cors | Enable CORS. |
nginx.ingress.kubernetes.io/cors-allow-origin | Allowed third-party origins, comma-separated. Wildcards (*) supported. Default: * (all origins). |
nginx.ingress.kubernetes.io/cors-allow-methods | Allowed HTTP methods, comma-separated. Wildcards supported. Default: GET,PUT,POST,DELETE,PATCH,OPTIONS. |
nginx.ingress.kubernetes.io/cors-allow-headers | Allowed request headers, comma-separated. Wildcards supported. Default: 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 exposed to the browser, comma-separated. |
nginx.ingress.kubernetes.io/cors-allow-credentials | Allow credentials in CORS requests. Default: false. |
nginx.ingress.kubernetes.io/cors-max-age | Preflight result cache duration in seconds. Default: 1728000. |
Example: Allow CORS from `example.com` with restricted methods and no credentials
Kubernetes v1.19 or 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" # Restrict to specific origin
nginx.ingress.kubernetes.io/cors-allow-methods: "GET,POST" # Only allow GET and POST
nginx.ingress.kubernetes.io/cors-allow-headers: "X-Foo-Bar"
nginx.ingress.kubernetes.io/cors-allow-credentials: "false" # No credentials
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: ExactKubernetes earlier than v1.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: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80Regular expression match
In addition to the standard Exact and Prefix path types, MSE Ingress supports regular expression matching. Set nginx.ingress.kubernetes.io/use-regex: 'true' to enable it.
Example: Route paths starting with `/app` or `/test`
Kubernetes v1.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: mse
rules:
- http:
paths:
- backend:
service:
name: demo
port:
number: 8080
path: /(app|test)/(.*)
pathType: PrefixKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/use-regex: 'true'
name: regex-match
namespace: default
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /(app|test)/(.*)
backend:
serviceName: demo
servicePort: 8080Path and host rewrite
Rewrite the path or host in a request before MSE Ingress forwards it to the backend service.
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/rewrite-target | Destination path for the rewrite. Capture groups are supported. |
nginx.ingress.kubernetes.io/upstream-vhost | Destination host for the rewrite. |
Path rewrite
Example 1: Rewrite `/test` to `/dev`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/dev" # Rewrite destination
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/dev"
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /test
pathType: Exact
backend:
serviceName: demo-service
servicePort: 80Example 2: Strip the `/v1` prefix (rewrite `/v1/xxx` to `/xxx`)
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/$1" # $1 captures the path after /v1/
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /v1/(.*)
pathType: PrefixKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/$1"
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /v1/(.*)
pathType: Prefix
backend:
serviceName: demo-service
servicePort: 80Example 3: Replace the `/v1` prefix with `/v2` (rewrite `/v1/xxx` to `/v2/xxx`)
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/v2/$1" # Prepend /v2 to the captured path
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /v1/(.*)
pathType: PrefixKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: "/v2/$1"
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /v1/(.*)
pathType: Prefix
backend:
serviceName: demo-service
servicePort: 80Host rewrite
Example: Rewrite `example.com/test` host to `test.com`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: "test.com" # Rewrite the Host header to test.com
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-vhost: "test.com"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Redirect
HTTP-to-HTTPS redirect
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/ssl-redirect | Force redirect of HTTP requests to HTTPS. |
nginx.ingress.kubernetes.io/force-ssl-redirect | Force redirect of HTTP requests to HTTPS. |
MSE Ingress treats both annotations identically — both unconditionally redirect HTTP to HTTPS.
Example: Redirect `http://example.com/test` to `https://example.com/test`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Permanent redirect
| Annotation | Description |
|---|---|
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. Default: 301. |
Example: Permanently redirect `http://example.com/test` to `http://example.com/app`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: "http://example.com/app" # Must include scheme
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/permanent-redirect: "http://example.com/app"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Temporary 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`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/temporal-redirect: "http://example.com/app" # Must include scheme
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/temporal-redirect: "http://example.com/app"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Header control
Add, update, or remove request and response headers before MSE Ingress forwards traffic.
Request header control
| Annotation | Description | |
|---|---|---|
mse.ingress.kubernetes.io/request-header-control-add | Add a header to forwarded requests. If the header already exists, the new value is appended. Single header: key-value pair. Multiple headers: use the YAML ` | ` block scalar, one key-value pair per line. |
mse.ingress.kubernetes.io/request-header-control-update | Update a header in forwarded requests. If the header already exists, the new value overwrites it. Single header: key-value pair. Multiple headers: use the YAML ` | ` block scalar, one key-value pair per line. |
mse.ingress.kubernetes.io/request-header-control-remove | Remove a header from forwarded requests. Single header: key name. Multiple headers: comma-separated key names. |
Example 1: Add `foo: bar` and `test: true` to all requests to `example.com/test`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/request-header-control-add: | # Block scalar for multiple headers
foo bar # Adds header foo: bar
test true # Adds header test: true
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/request-header-control-add: |
foo bar
test true
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Add a stage header to identify canary traffic
When the request header is mse: v1, the request goes to the canary version demo-service-canary-v1 with stage: gray added. All other requests go to demo-service with stage: production added.
Kubernetes v1.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: "mse"
nginx.ingress.kubernetes.io/canary-by-header-value: "v1"
mse.ingress.kubernetes.io/request-header-control-add: "stage gray" # Adds stage: gray
name: demo-canary-v1
spec:
ingressClassName: mse
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:
mse.ingress.kubernetes.io/request-header-control-add: "stage production" # Adds stage: production
name: demo
spec:
ingressClassName: mse
rules:
- http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /hello
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-header: "mse"
nginx.ingress.kubernetes.io/canary-by-header-value: "v1"
mse.ingress.kubernetes.io/request-header-control-add: "stage gray"
name: demo-canary-v1
spec:
ingressClassName: mse
rules:
- http:
paths:
- path: /hello
backend:
serviceName: demo-service-canary-v1
servicePort: 80
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/request-header-control-add: "stage production"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /hello
backend:
serviceName: demo-service
servicePort: 80Response header control
| Annotation | Description | |
|---|---|---|
mse.ingress.kubernetes.io/response-header-control-add | Add a header to responses before forwarding to the client. If the header already exists, the new value is appended. Single header: key-value pair. Multiple headers: use the YAML ` | ` block scalar, one key-value pair per line. |
mse.ingress.kubernetes.io/response-header-control-update | Update a header in responses before forwarding to the client. If the header already exists, the new value overwrites it. Single header: key-value pair. Multiple headers: use the YAML ` | ` block scalar, one key-value pair per line. |
mse.ingress.kubernetes.io/response-header-control-remove | Remove a header from responses before forwarding to the client. Single header: key name. Multiple headers: comma-separated key names. |
Example: Remove the `req-cost-time` header from responses to `example.com/test`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/response-header-control-remove: "req-cost-time" # Removes this response header
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/response-header-control-remove: "req-cost-time"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Retry
MSE Ingress supports route-level automatic retries. Configure retry conditions based on your backend's error patterns.
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/proxy-next-upstream-tries | Maximum number of retry attempts. Default: 3. |
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout | Retry timeout in seconds. Default: no timeout. |
nginx.ingress.kubernetes.io/proxy-next-upstream | Retry conditions, comma-separated. Default: error,timeout. Valid values: error (connection failure or 5xx), timeout (connection timeout or 5xx), invalid_header (request error or 5xx), http_xxx (specific status code, e.g., http_502, http_403), non_idempotent (retry non-idempotent requests such as POST and PATCH), off (disable retries). |
By default, MSE Ingress does not retry non-idempotent requests (POST, PATCH). Set proxy-next-upstream to non_idempotent to enable retries for these request types.
Example: Retry on 502 with a 5-second timeout, including non-idempotent requests
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-next-upstream-tries: "2" # Retry up to 2 times
nginx.ingress.kubernetes.io/proxy-next-upstream-timeout: "5" # Abort retries after 5s
nginx.ingress.kubernetes.io/proxy-next-upstream: "http_502,non_idempotent" # Retry on 502 and POST/PATCH
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.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: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Access control based on IP whitelists and blacklists
MSE Ingress supports IP-based access control at two levels:
Route level takes precedence over domain-name level.
Domain-name level applies to all routes under a domain.
Route-level IP whitelist and blacklist
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/whitelist-source-range | IP whitelist for a specific route. Accepts IP addresses and CIDR blocks, comma-separated. |
mse.ingress.kubernetes.io/blacklist-source-range | IP blacklist for a specific route. Accepts IP addresses and CIDR blocks, comma-separated. |
Example 1: Allow access to `example.com/test` only from `1.1.xx.xx`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: 1.1.X.X # Only allow this IP
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.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: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Block access to `example.com/test` from `2.2.xx.xx`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/blacklist-source-range: 2.2.2.2 # Block this IP
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/blacklist-source-range: 2.2.2.2
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Domain-level IP whitelist and blacklist
| Annotation | Description |
|---|---|
mse.ingress.kubernetes.io/domain-whitelist-source-range | IP whitelist applied to all routes under a domain. Route-level whitelists take precedence. Accepts IP addresses and CIDR blocks, comma-separated. |
mse.ingress.kubernetes.io/domain-blacklist-source-range | IP blacklist applied to all routes under a domain. Route-level blacklists take precedence. Accepts IP addresses and CIDR blocks, comma-separated. |
Example 1: Allow all routes under `example.com` from `1.1.xx.xx` and `2.2.xx.xx`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/domain-whitelist-source-range: 1.1.X.X,2.2.2.2 # Domain-level: applies to all routes
name: demo
spec:
ingressClassName: mse
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: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/domain-whitelist-source-range: 1.1.X.X,2.2.2.2
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80
- path: /app
backend:
serviceName: app-service
servicePort: 80Example 2: Combine domain-level and route-level whitelists
Allow all routes under example.com from 1.1.xx.xx and 2.2.xx.xx, but restrict the /order route to 3.3.xx.xx only.
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/domain-whitelist-source-range: 1.1.X.X,2.2.2.2 # Domain-level: /test and /app
name: demo-domain
spec:
ingressClassName: mse
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
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: 3.3.X.X # Route-level takes precedence for /order
name: demo-route
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /order
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/domain-whitelist-source-range: 1.1.X.X,2.2.2.2
name: demo-domain
spec:
ingressClassName: mse
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: mse
rules:
- host: example.com
http:
paths:
- path: /order
backend:
serviceName: demo-service
servicePort: 80Single-gateway throttling
Throttling is applied per gateway replica, not across the entire gateway cluster. To throttle traffic cluster-wide, use global rate limiting instead.
When the request rate exceeds the threshold on a single gateway instance, MSE Ingress returns local_rate_limited.
Response status codes when throttling is triggered:
Gateway version earlier than v1.2.23:
503Gateway version v1.2.23 or later:
429
The burst limit formula: burst limit = rate × `route-limit-burst-multiplier` (default multiplier: 5).
| Annotation | Description |
|---|---|
mse.ingress.kubernetes.io/route-limit-rpm | Maximum requests per minute (RPM) per gateway replica. Burst limit = value × route-limit-burst-multiplier. |
mse.ingress.kubernetes.io/route-limit-rps | Maximum requests per second (RPS) per gateway replica. Burst limit = value × route-limit-burst-multiplier. |
mse.ingress.kubernetes.io/route-limit-burst-multiplier | Burst multiplier for RPM and RPS limits. Default: 5. |
Example 1: Limit to 100 RPM with a burst of 200
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/route-limit-rpm: "100" # 100 requests per minute
mse.ingress.kubernetes.io/route-limit-burst-multiplier: "2" # Burst = 100 × 2 = 200
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/route-limit-rpm: "100"
mse.ingress.kubernetes.io/route-limit-burst-multiplier: "2"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Limit to 10 RPS with the default burst multiplier of 5 (burst: 50)
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/route-limit-rps: "10"
# Burst multiplier defaults to 5; burst limit = 10 × 5 = 50
# mse.ingress.kubernetes.io/route-limit-burst-multiplier: "5"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/route-limit-rps: "10"
# Burst multiplier defaults to 5; burst limit = 10 × 5 = 50
# mse.ingress.kubernetes.io/route-limit-burst-multiplier: "5"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Global rate limiting
MSE Ingress integrates with Sentinel to enforce cluster-wide rate limits at the route level. Use mse.ingress.kubernetes.io/rate-limit to set the maximum RPS across the entire gateway cluster.
Global rate limiting requires MSE Ingress gateway version 1.2.25 or later.
When the rate limit is triggered, the default response is:
Response code:
429Response body:
sentinel rate limited
Configure the throttling behavior using one of two methods: custom response or redirect. Only one method can be active at a time.
Custom response
| Annotation | Description |
|---|---|
mse.ingress.kubernetes.io/rate-limit-fallback-custom-response-code | Response code when rate limiting is triggered. Default: 429. |
mse.ingress.kubernetes.io/rate-limit-fallback-custom-response-body-type | Response body type. Default: text. Setting to text sets Content-Type: text/plain; charset=UTF-8. Setting to json sets Content-Type: application/json; charset=UTF-8. |
mse.ingress.kubernetes.io/rate-limit-fallback-custom-response-body | Response body when rate limiting is triggered. Default: sentinel rate limited. |
Example 1: Limit to 100 RPS with default response
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/rate-limit: "100" # Cluster-wide: max 100 RPS across all replicas
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/rate-limit: "100"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Limit to 100 RPS with custom response code and body
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/rate-limit: "100"
mse.ingress.kubernetes.io/rate-limit-fallback-custom-response-code: 503 # Return 503 instead of 429
mse.ingress.kubernetes.io/rate-limit-fallback-custom-response-body: "server is overload"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/rate-limit: "100"
mse.ingress.kubernetes.io/rate-limit-fallback-custom-response-code: 503
mse.ingress.kubernetes.io/rate-limit-fallback-custom-response-body: "server is overload"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Redirect
Use mse.ingress.kubernetes.io/rate-limit-fallback-redirect-url to specify a redirect URL when the rate limit is triggered.
Example: Limit to 100 RPS, redirect to `example.com/fallback` when triggered
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/rate-limit: "100"
mse.ingress.kubernetes.io/rate-limit-fallback-redirect-url: "example.com/fallback" # Redirect on limit
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/rate-limit: "100"
mse.ingress.kubernetes.io/rate-limit-fallback-redirect-url: "example.com/fallback"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Global concurrency control
MSE Ingress integrates with Sentinel to enforce cluster-wide concurrency limits at the route level. Use mse.ingress.kubernetes.io/concurrency-limit to set the maximum number of requests being processed simultaneously on a route across the gateway cluster.
Global concurrency control requires MSE Ingress gateway version 1.2.25 or later.
When the concurrency limit is triggered, the default response is:
Response code:
429Response body:
sentinel rate limited
Configure the behavior using one of two methods: custom response or redirect. Only one method can be active at a time.
Custom response
| Annotation | Description |
|---|---|
mse.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-code | Response code when concurrency control is triggered. Default: 429. |
mse.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body-type | Response body type. Default: text. Setting to text sets Content-Type: text/plain; charset=UTF-8. Setting to json sets Content-Type: application/json; charset=UTF-8. |
mse.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body | Response body when concurrency control is triggered. |
Example 1: Limit to 1,000 concurrent requests with default response
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/concurrency-limit: "1000" # Max 1000 in-flight requests cluster-wide
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/concurrency-limit: "1000"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Limit to 1,000 concurrent requests with custom response
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/concurrency-limit: "1000"
mse.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-code: 503
mse.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body: "server is overload"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/concurrency-limit: "1000"
mse.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-code: 503
mse.ingress.kubernetes.io/concurrency-limit-fallback-custom-response-body: "server is overload"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Redirect
Use mse.ingress.kubernetes.io/concurrency-limit-fallback-redirect-url to specify a redirect URL when concurrency control is triggered.
Example: Limit to 1,000 concurrent requests, redirect to `example.com/fallback` when triggered
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/concurrency-limit: "1000"
mse.ingress.kubernetes.io/concurrency-limit-fallback-redirect-url: "example.com/fallback"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/concurrency-limit: "1000"
mse.ingress.kubernetes.io/concurrency-limit-fallback-redirect-url: "example.com/fallback"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Traffic mirroring
Traffic mirroring copies incoming requests and forwards them to a secondary service in parallel. The original request continues to its primary backend unaffected, making traffic mirroring useful for operational auditing and shadow testing without impacting production traffic.
When mirrored traffic is forwarded, MSE Ingress automatically appends -shadow to the Host header. For example, a request originally destined for example.com reaches the mirror target with the host example.com-shadow.
| Annotation | Description |
|---|---|
mse.ingress.kubernetes.io/mirror-target-service | Destination service for mirrored traffic. Format: namespace/name:port. namespace is optional (defaults to the Ingress gateway namespace). name is required. port is optional (defaults to the first port). |
mse.ingress.kubernetes.io/mirror-percentage | Percentage of traffic to mirror. Valid values: 0–100. Default: 100. |
If mirror-percentage is omitted, 100% of traffic is mirrored. Confirm your target service can handle the full request volume before enabling mirroring in production.
Example 1: Mirror all traffic to `test/app:8080`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/mirror-target-service: test/app:8080 # namespace/name:port
# mirror-percentage defaults to 100 — mirrors all traffic
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/mirror-target-service: test/app:8080
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Mirror 10% of traffic to `test/app:8080`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/mirror-target-service: test/app:8080
mse.ingress.kubernetes.io/mirror-percentage: 10 # Mirror 10% of traffic
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/mirror-target-service: test/app:8080
mse.ingress.kubernetes.io/mirror-percentage: 10
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Backend service protocols: HTTPS and gRPC
By default, MSE 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 Kubernetes Service resource defines a port namedgrpcorhttp2, MSE Ingress automatically uses gRPC or HTTP/2 to forward requests — no annotation required. This differs from NGINX Ingress behavior.
Example 1: Forward to a backend over HTTPS
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" # Use HTTPS to reach the backend
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Forward to a backend over gRPC
Two methods are available:
Method 1 — Use an annotation:
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC" # Use gRPC to reach the backend
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Method 2 — Name the Service port grpc:
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: mse
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 # MSE Ingress auto-detects gRPC when the port is named "grpc"
port: 80
protocol: TCP
selector:
app: demo-serviceKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: demo
spec:
ingressClassName: mse
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-serviceLoad balancing algorithms
Common load balancing algorithms
Use nginx.ingress.kubernetes.io/load-balance to set the algorithm. Default: round_robin.
Valid values:
round_robin— distributes requests in rotationleast_conn— routes to the backend with the fewest active connectionsrandom— distributes requests randomly
Cloud-native gateways do not support the exponentially weighted moving average (EWMA) algorithm. If EWMA is configured, the gateway falls back to round-robin.
Example: Use least connections for `demo-service`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/load-balance: "least_conn" # Route to backend with fewest connections
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /order
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/load-balance: "least_conn"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Consistent hashing
Consistent hashing routes requests with the same hash key to the same backend node. Use nginx.ingress.kubernetes.io/upstream-hash-by to set the hash key.
Supported hash key types:
NGINX variables:
$request_uri(path + query),$host,$remote_addr(client IP)Request headers:
$http_<header-name>(for example,$http_x-stage)Query parameters:
$arg_<param-name>(for example,$arg_x-stage)
Example 1: Hash by client IP address
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr" # Hash on client IP
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Hash by the `X-Stage` request header
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$http_x-stage" # Hash on X-Stage header value
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$http_x-stage"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 3: Hash by the `X-Stage` query parameter
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$arg_x-stage" # Hash on x-stage query parameter value
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: "$arg_x-stage"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Service warmup
The service warmup feature gradually increases the traffic sent to a newly started backend node over a specified time window, reducing the risk of overloading a cold node.
Use mse.ingress.kubernetes.io/warmup to set the warmup duration in seconds. Service warmup is disabled by default.
Service warmup is supported only with the round-robin and least-connections load balancing algorithms.
Example: Enable a 30-second warmup for `demo-service`
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/warmup: "30" # Ramp up traffic to this backend over 30 seconds
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/warmup: "30"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Cookie affinity (session persistence)
Cookie affinity routes requests from the same client to the same backend node. On the first request, MSE Ingress generates a cookie and returns it to the client. Subsequent requests carrying that cookie are always routed to the same node.
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/affinity | Affinity type. The only valid value is cookie. |
nginx.ingress.kubernetes.io/affinity-mode | Affinity mode. The default and only valid value is balanced. |
nginx.ingress.kubernetes.io/session-cookie-name | Cookie name used as the hash key. Default: INGRESSCOOKIE. |
nginx.ingress.kubernetes.io/session-cookie-path | Cookie path set when the cookie does not exist. Default: /. |
nginx.ingress.kubernetes.io/session-cookie-max-age | Cookie expiry in seconds. Default: session-scoped (no explicit expiry). |
nginx.ingress.kubernetes.io/session-cookie-expires | Cookie expiry in seconds. Default: session-scoped. |
Example 1: Enable cookie affinity with default settings
Cookie name: INGRESSCOOKIE, path: /, lifecycle: session-scoped.
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie" # Only supported type
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/affinity: "cookie"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Example 2: Enable cookie affinity with a custom cookie name and 10-second expiry
Kubernetes v1.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" # Custom cookie name
nginx.ingress.kubernetes.io/session-cookie-max-age: "10" # 10-second expiry
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.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: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Connection pool between a gateway and a backend service
Configure a connection pool to cap the number of connections between the gateway and a backend service. This prevents backend overload and improves stability.
| Annotation | Description |
|---|---|
mse.ingress.kubernetes.io/connection-policy-tcp-max-connection | Maximum total connections between the gateway and the backend service. |
mse.ingress.kubernetes.io/connection-policy-tcp-max-connection-per-endpoint | Maximum connections between the gateway and a single backend endpoint (Pod). |
mse.ingress.kubernetes.io/connection-policy-http-max-request-per-connection | Maximum requests on a single connection between the gateway and the backend service. |
Example: Set max connections to 10 total, 2 per endpoint
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/connection-policy-tcp-max-connection: 10 # Total connection cap
mse.ingress.kubernetes.io/connection-policy-tcp-max-connection-per-endpoint: 2 # Per-pod connection cap
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/connection-policy-tcp-max-connection: 10
mse.ingress.kubernetes.io/connection-policy-tcp-max-connection-per-endpoint: 2
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80TLS versions and cipher suites
By default, MSE Ingress supports TLS versions from TLSv1.0 to TLSv1.3. The default cipher suites are:
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 TLS versions and cipher suites per domain:
| Annotation | Description |
|---|---|
mse.ingress.kubernetes.io/tls-min-protocol-version | Minimum TLS version. Default: TLSv1.0. Valid values: TLSv1.0, TLSv1.1, TLSv1.2, TLSv1.3. |
mse.ingress.kubernetes.io/tls-max-protocol-version | Maximum TLS version. Default: TLSv1.3. |
nginx.ingress.kubernetes.io/ssl-cipher | Comma-separated TLS cipher suites. Applies only to TLS handshakes using TLSv1.0–1.2. |
Example: Restrict `example.com` to TLSv1.2 only
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/tls-min-protocol-version: "TLSv1.2" # Set both min and max to TLSv1.2
mse.ingress.kubernetes.io/tls-max-protocol-version: "TLSv1.2" # to enforce TLSv1.2 only
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
mse.ingress.kubernetes.io/tls-min-protocol-version: "TLSv1.2"
mse.ingress.kubernetes.io/tls-max-protocol-version: "TLSv1.2"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80Mutual TLS between gateways and backend services
By default, MSE Ingress uses HTTP to forward requests to backend services. When nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" is set, MSE Ingress uses one-way TLS — the gateway validates the backend's certificate, which must be issued by a trusted certificate authority (CA).
For mutual TLS (mTLS), both parties authenticate each other: the gateway validates the backend's certificate, and the backend validates the gateway's certificate.
| Annotation | Description |
|---|---|
nginx.ingress.kubernetes.io/proxy-ssl-secret | Client certificate used by the gateway for the backend to authenticate it. Format: secretNamespace/secretName. |
nginx.ingress.kubernetes.io/proxy-ssl-name | Server Name Indication (SNI) used during the TLS handshake. |
nginx.ingress.kubernetes.io/proxy-ssl-server-name | Enable or disable SNI during the TLS handshake. |
Example: Configure mTLS with a gateway certificate from a Kubernetes secret
Kubernetes v1.19 or later:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-ssl-secret: "default/gateway-cert" # secretNamespace/secretName
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- backend:
service:
name: demo-service
port:
number: 80
path: /test
pathType: ExactKubernetes earlier than v1.19:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-ssl-secret: "default/gateway-cert"
name: demo
spec:
ingressClassName: mse
rules:
- host: example.com
http:
paths:
- path: /test
backend:
serviceName: demo-service
servicePort: 80