traffic-label
The traffic-label plugin labels traffic based on user-defined rules and takes actions based on labels and the associated weights for actions. It provides a granular approach to traffic management, making it easy to conditionally action on requests with flexibility and precision.
Examples
The examples below demonstrate how you can configure traffic-label on a route in different scenarios.
Define a Single Matching Condition
The following example demonstrates a simple rule with one matching condition and one associated action. If the URI of the request is /headers, the plugin will add the header "X-Server-Id": "100" to the request.
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "traffic-label-route",
"uri":"/headers",
"plugins":{
"traffic-label": {
"rules": [
{
"match": [
["uri", "==", "/headers"]
],
"actions": [
{
"set_headers": {
"X-Server-Id": 100
}
}
]
}
]
}
},
"upstream":{
"type":"roundrobin",
"nodes":{
"httpbin.org:80":1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /headers
name: traffic-label-route
plugins:
traffic-label:
rules:
- match:
- - uri
- "=="
- /headers
actions:
- set_headers:
X-Server-Id: 100
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: traffic-label-plugin-config
spec:
plugins:
- name: traffic-label
config:
rules:
- match:
- - uri
- "=="
- /headers
actions:
- set_headers:
X-Server-Id: 100
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: traffic-label-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /headers
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: traffic-label-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: traffic-label-route
spec:
ingressClassName: apisix
http:
- name: traffic-label-route
match:
paths:
- /headers
upstreams:
- name: httpbin-external-domain
plugins:
- name: traffic-label
config:
rules:
- match:
- - uri
- "=="
- /headers
actions:
- set_headers:
X-Server-Id: 100
Apply the configuration:
kubectl apply -f traffic-label-ic.yaml
Send a request to verify:
curl "http://127.0.0.1:9080/headers"
You should see a response similar to the following:
{
"headers": {
"Accept": "*/*",
...
"X-Server-Id": "100"
}
}
Define Multiple Matching Conditions with Logical Operators
You can build more complex matching conditions with logical operators.
The following example demonstrates a rule with two matching conditions logically grouped by OR and one associated action. If one of the conditions is met, the plugin will add the header "X-Server-Id": "100" to the request.
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "traffic-label-route",
"uri":"/headers",
"plugins":{
"traffic-label": {
"rules": [
{
"match": [
"OR",
["arg_version", "==", "v1"],
["arg_env", "==", "dev"]
],
"actions": [
{
"set_headers": {
"X-Server-Id": 100
}
}
]
}
]
}
},
"upstream":{
"type":"roundrobin",
"nodes":{
"httpbin.org:80":1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /headers
name: traffic-label-route
plugins:
traffic-label:
rules:
- match:
- OR
- - arg_version
- "=="
- v1
- - arg_env
- "=="
- dev
actions:
- set_headers:
X-Server-Id: 100
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: traffic-label-plugin-config
spec:
plugins:
- name: traffic-label
config:
rules:
- match:
- OR
- - arg_version
- "=="
- v1
- - arg_env
- "=="
- dev
actions:
- set_headers:
X-Server-Id: 100
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: traffic-label-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /headers
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: traffic-label-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: traffic-label-route
spec:
ingressClassName: apisix
http:
- name: traffic-label-route
match:
paths:
- /headers
upstreams:
- name: httpbin-external-domain
plugins:
- name: traffic-label
config:
rules:
- match:
- OR
- - arg_version
- "=="
- v1
- - arg_env
- "=="
- dev
actions:
- set_headers:
X-Server-Id: 100
Apply the configuration:
kubectl apply -f traffic-label-ic.yaml
Send a request to verify:
curl "http://127.0.0.1:9080/headers?env=dev"
You should see a response similar to the following:
{
"headers": {
"Accept": "*/*",
...
"X-Server-Id": "100"
}
}
If you send a request that does not match any of the conditions, you will not see "X-Server-Id": "100" added to the request header.
Create Weighted Actions
The following example demonstrates a rule with one matching condition and multiple weighted actions, where incoming requests are distributed proportionally based on the weights.
If a weight is not associated with any action, this portion of the requests will not have any action performed on them.
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "traffic-label-route",
"uri":"/headers",
"plugins":{
"traffic-label": {
"rules": [
{
"match": [
["uri", "==", "/headers"]
],
"actions": [
{
"set_headers": {
"X-Server-Id": 100
},
"weight": 3
},
{
"set_headers": {
"X-API-Version": "v2"
},
"weight": 2
},
{
"weight": 5
}
]
}
]
}
},
"upstream":{
"type":"roundrobin",
"nodes":{
"httpbin.org:80":1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /headers
name: traffic-label-route
plugins:
traffic-label:
rules:
- match:
- - uri
- "=="
- /headers
actions:
- set_headers:
X-Server-Id: 100
weight: 3
- set_headers:
X-API-Version: v2
weight: 2
- weight: 5
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: traffic-label-plugin-config
spec:
plugins:
- name: traffic-label
config:
rules:
- match:
- - uri
- "=="
- /headers
actions:
- set_headers:
X-Server-Id: 100
weight: 3
- set_headers:
X-API-Version: v2
weight: 2
- weight: 5
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: traffic-label-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /headers
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: traffic-label-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: traffic-label-route
spec:
ingressClassName: apisix
http:
- name: traffic-label-route
match:
paths:
- /headers
upstreams:
- name: httpbin-external-domain
plugins:
- name: traffic-label
config:
rules:
- match:
- - uri
- "=="
- /headers
actions:
- set_headers:
X-Server-Id: 100
weight: 3
- set_headers:
X-API-Version: v2
weight: 2
- weight: 5
Apply the configuration:
kubectl apply -f traffic-label-ic.yaml
The proportion of times each action is executed is determined by the weight of the action relative to the total weight of all actions listed under the actions field. Here, the total weight is calculated as the sum of all action weights: 3 + 2 + 5 = 10.
Therefore:
❶ 30% of the requests should have the X-Server-Id: 100 request header.
❷ 20% of the requests should have the X-API-Version: v2 request header.
❸ 50% of the requests should not have any action performed on them.
Generate 50 consecutive requests to verify the weighted actions:
resp=$(seq 50 | xargs -I{} curl "http://127.0.0.1:9080/headers" -sL) && \
count_w3=$(echo "$resp" | grep -i "X-Server-Id" | wc -l) && \
count_w2=$(echo "$resp" | grep -i "X-API-Version" | wc -l) && \
echo X-Server-Id: $count_w3, X-API-Version: $count_w2
The response shows that headers are added to requests in a weighted manner:
X-Server-Id: 15, X-API-Version: 10
Define Multiple Matching Rules
The following example demonstrates the use of multiple rules, each with their matching condition and action.
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "traffic-label-route",
"uri":"/headers",
"plugins":{
"traffic-label": {
"rules": [
{
"match": [
["arg_version", "==", "v1"]
],
"actions": [
{
"set_headers": {
"X-Server-Id": 100
}
}
]
},
{
"match": [
["arg_version", "==", "v2"]
],
"actions": [
{
"set_headers": {
"X-Server-Id": 200
}
}
]
}
]
}
},
"upstream":{
"type":"roundrobin",
"nodes":{
"httpbin.org:80":1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /headers
name: traffic-label-route
plugins:
traffic-label:
rules:
- match:
- - arg_version
- "=="
- v1
actions:
- set_headers:
X-Server-Id: 100
- match:
- - arg_version
- "=="
- v2
actions:
- set_headers:
X-Server-Id: 200
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: traffic-label-plugin-config
spec:
plugins:
- name: traffic-label
config:
rules:
- match:
- - arg_version
- "=="
- v1
actions:
- set_headers:
X-Server-Id: 100
- match:
- - arg_version
- "=="
- v2
actions:
- set_headers:
X-Server-Id: 200
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: traffic-label-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /headers
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: traffic-label-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: traffic-label-route
spec:
ingressClassName: apisix
http:
- name: traffic-label-route
match:
paths:
- /headers
upstreams:
- name: httpbin-external-domain
plugins:
- name: traffic-label
config:
rules:
- match:
- - arg_version
- "=="
- v1
actions:
- set_headers:
X-Server-Id: 100
- match:
- - arg_version
- "=="
- v2
actions:
- set_headers:
X-Server-Id: 200
Apply the configuration:
kubectl apply -f traffic-label-ic.yaml
Send a request to /headers?version=v1 to verify:
curl "http://127.0.0.1:9080/headers?version=v1"
You should see a response similar to the following:
{
"headers": {
"Accept": "*/*",
...
"X-Server-Id": "100"
}
}
Send a request to /headers?version=v2 to verify:
curl "http://127.0.0.1:9080/headers?version=v2"
You should see a response similar to the following:
{
"headers": {
"Accept": "*/*",
...
"X-Server-Id": "200"
}
}