title: workflow keywords:
import Tabs from ‘@theme/Tabs’; import TabItem from ‘@theme/TabItem’;
workflow 插件支持根据给定的规则集有条件地执行对客户端流量的用户定义操作,这些规则集使用 lua-resty-expr 定义。这为流量管理提供了一种细粒度的方法。
| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
|---|---|---|---|---|---|
| rules | array[object] | 是 | 一对或多对匹配条件和要执行的操作组成的数组。 | ||
| rules.case | array[array] | 否 | 一个或多个匹配条件的数组,形式为 lua-resty-expr,例如 {"arg_name", "==", "json"}。 | ||
| rules.actions | array[array] | 是 | 条件匹配成功后要执行的操作的数组。目前数组只支持一个操作,必须是 return、limit-count 或 limit-conn。当操作配置为 return 时,可以配置条件匹配成功时返回给客户端的 HTTP 状态码。当操作配置为 limit-count 时,可以配置 limit-count 插件除 group 之外的所有选项。当操作配置为 limit-conn 时,可以配置 limit-conn 插件的所有选项。 |
以下示例演示了如何在不同场景中使用 workflow 插件。
:::note
您可以这样从 config.yaml 中获取 admin_key 并存入环境变量:
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
:::
以下示例演示了一个简单的规则,其中包含一个匹配条件和一个关联操作,用于有条件地返回 HTTP 状态码。
使用 workflow 插件创建路由:
<Tabs groupId=“api” defaultValue=“admin-api” values={[ {label: ‘Admin API’, value: ‘admin-api’}, {label: ‘ADC’, value: ‘adc’}, {label: ‘Ingress Controller’, value: ‘aic’} ]}>
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "id": "workflow-route", "uri": "/anything/*", "plugins": { "workflow":{ "rules":[ { "case":[ ["uri", "==", "/anything/rejected"] ], "actions":[ [ "return", {"code": 403} ] ] } ] } }, "upstream": { "type": "roundrobin", "nodes": { "httpbin.org": 1 } } }'
services: - name: httpbin routes: - uris: - /anything/* name: workflow-route plugins: workflow: rules: - case: - ["uri", "==", "/anything/rejected"] actions: - - return - code: 403 upstream: type: roundrobin nodes: - host: httpbin.org port: 80 weight: 1
将配置同步到网关:
adc sync -f adc.yaml
<Tabs groupId=“k8s-api” defaultValue=“gateway-api” values={[ {label: ‘Gateway API’, value: ‘gateway-api’}, {label: ‘APISIX CRD’, value: ‘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: workflow-plugin-config spec: plugins: - name: workflow config: rules: - case: - ["uri", "==", "/anything/rejected"] actions: - - return - code: 403 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: namespace: aic name: workflow-route spec: parentRefs: - name: apisix rules: - matches: - path: type: PathPrefix value: /anything/ filters: - type: ExtensionRef extensionRef: group: apisix.apache.org kind: PluginConfig name: workflow-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: workflow-route spec: ingressClassName: apisix http: - name: workflow-route match: paths: - /anything/* upstreams: - name: httpbin-external-domain plugins: - name: workflow enable: true config: rules: - case: - ["uri", "==", "/anything/rejected"] actions: - - return - code: 403
将配置应用到集群:
kubectl apply -f workflow-ic.yaml
发送与任何规则都不匹配的请求:
curl -i "http://127.0.0.1:9080/anything/anything"
您应该收到 HTTP/1.1 200 OK 响应。
发送与配置的规则匹配的请求:
curl -i "http://127.0.0.1:9080/anything/rejected"
您应该收到以下 HTTP/1.1 403 Forbidden 响应:
{"error_msg":"rejected by workflow"}
以下示例演示了一条具有两个匹配条件和一个关联操作的规则,用于有条件地限制请求速率。
使用 workflow 插件创建路由:
<Tabs groupId=“api” defaultValue=“admin-api” values={[ {label: ‘Admin API’, value: ‘admin-api’}, {label: ‘ADC’, value: ‘adc’}, {label: ‘Ingress Controller’, value: ‘aic’} ]}>
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "id": "workflow-route", "uri": "/anything/*", "plugins":{ "workflow":{ "rules":[ { "case":[ ["uri", "==", "/anything/rate-limit"], ["arg_env", "==", "v1"] ], "actions":[ [ "limit-count", { "count":1, "time_window":60, "rejected_code":429 } ] ] } ] } }, "upstream": { "type": "roundrobin", "nodes": { "httpbin.org": 1 } } }'
services: - name: httpbin routes: - uris: - /anything/* name: workflow-route plugins: workflow: rules: - case: - ["uri", "==", "/anything/rate-limit"] - ["arg_env", "==", "v1"] actions: - - limit-count - count: 1 time_window: 60 rejected_code: 429 upstream: type: roundrobin nodes: - host: httpbin.org port: 80 weight: 1
将配置同步到网关:
adc sync -f adc.yaml
<Tabs groupId=“k8s-api” defaultValue=“gateway-api” values={[ {label: ‘Gateway API’, value: ‘gateway-api’}, {label: ‘APISIX CRD’, value: ‘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: workflow-plugin-config spec: plugins: - name: workflow config: rules: - case: - ["uri", "==", "/anything/rate-limit"] - ["arg_env", "==", "v1"] actions: - - limit-count - count: 1 time_window: 60 rejected_code: 429 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: namespace: aic name: workflow-route spec: parentRefs: - name: apisix rules: - matches: - path: type: PathPrefix value: /anything/ filters: - type: ExtensionRef extensionRef: group: apisix.apache.org kind: PluginConfig name: workflow-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: workflow-route spec: ingressClassName: apisix http: - name: workflow-route match: paths: - /anything/* upstreams: - name: httpbin-external-domain plugins: - name: workflow enable: true config: rules: - case: - ["uri", "==", "/anything/rate-limit"] - ["arg_env", "==", "v1"] actions: - - limit-count - count: 1 time_window: 60 rejected_code: 429
将配置应用到集群:
kubectl apply -f workflow-ic.yaml
生成两个符合规则的连续请求:
curl -i "http://127.0.0.1:9080/anything/rate-limit?env=v1"
您应该收到 HTTP/1.1 200 OK 响应和 HTTP 429 Too Many Requests 响应。
生成不符合条件的请求:
curl -i "http://127.0.0.1:9080/anything/anything?env=v1"
您应该收到所有请求的 HTTP/1.1 200 OK 响应,因为它们不受速率限制。
以下示例演示了如何配置插件以根据以下规范执行速率限制:
john 在 30 秒内应有 5 个请求的配额jane 在 30 秒内应有 3 个请求的配额虽然此示例将使用 key-auth,但您可以轻松地将其替换为其他身份验证插件。
<Tabs groupId=“api” defaultValue=“admin-api” values={[ {label: ‘Admin API’, value: ‘admin-api’}, {label: ‘ADC’, value: ‘adc’}, {label: ‘Ingress Controller’, value: ‘aic’} ]}>
创建消费者 john:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "username": "john" }'
为消费者创建 key-auth 凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/john/credentials" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "id": "cred-john-key-auth", "plugins": { "key-auth": { "key": "john-key" } } }'
创建第二个消费者 jane:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "username": "jane" }'
为消费者创建 key-auth 凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jane/credentials" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "id": "cred-jane-key-auth", "plugins": { "key-auth": { "key": "jane-key" } } }'
创建第三个消费者 jimmy:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "username": "jimmy" }'
为消费者创建 key-auth 凭证:
curl "http://127.0.0.1:9180/apisix/admin/consumers/jimmy/credentials" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "id": "cred-jimmy-key-auth", "plugins": { "key-auth": { "key": "jimmy-key" } } }'
使用 workflow 和 key-auth 插件创建路由,并设置所需的速率限制规则:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \ -H "X-API-KEY: ${admin_key}" \ -d '{ "id": "workflow-route", "uri": "/anything", "plugins":{ "key-auth": {}, "workflow":{ "rules":[ { "actions": [ [ "limit-count", { "count": 5, "key": "consumer_john", "key_type": "constant", "rejected_code": 429, "time_window": 30, "policy": "local" } ] ], "case": [ [ "consumer_name", "==", "john" ] ] }, { "actions": [ [ "limit-count", { "count": 3, "key": "consumer_jane", "key_type": "constant", "rejected_code": 429, "time_window": 30, "policy": "local" } ] ], "case": [ [ "consumer_name", "==", "jane" ] ] }, { "actions": [ [ "limit-count", { "count": 2, "key": "$consumer_name", "key_type": "var", "rejected_code": 429, "time_window": 30, "policy": "local" } ] ] } ] } }, "upstream": { "type": "roundrobin", "nodes": { "httpbin.org": 1 } } }'
创建三个消费者以及启用按消费者速率限制的路由:
consumers: - username: john credentials: - name: key-auth type: key-auth config: key: john-key - username: jane credentials: - name: key-auth type: key-auth config: key: jane-key - username: jimmy credentials: - name: key-auth type: key-auth config: key: jimmy-key services: - name: httpbin routes: - uris: - /anything name: workflow-route plugins: key-auth: {} workflow: rules: - case: - ["consumer_name", "==", "john"] actions: - - limit-count - count: 5 key: consumer_john key_type: constant rejected_code: 429 time_window: 30 policy: local - case: - ["consumer_name", "==", "jane"] actions: - - limit-count - count: 3 key: consumer_jane key_type: constant rejected_code: 429 time_window: 30 policy: local - actions: - - limit-count - count: 2 key: "$consumer_name" key_type: var rejected_code: 429 time_window: 30 policy: local upstream: type: roundrobin nodes: - host: httpbin.org port: 80 weight: 1
将配置同步到网关:
adc sync -f adc.yaml
创建三个消费者以及启用按消费者速率限制的路由。当使用 Ingress Controller 配置消费者时,消费者名称以 namespace_consumername 格式生成。因此,workflow 插件中的 consumer_name 逻辑应以此格式匹配消费者名称。
<Tabs groupId=“k8s-api” defaultValue=“gateway-api” values={[ {label: ‘Gateway API’, value: ‘gateway-api’}, {label: ‘APISIX CRD’, value: ‘apisix-crd’} ]}>
apiVersion: apisix.apache.org/v1alpha1 kind: Consumer metadata: namespace: aic name: john spec: gatewayRef: name: apisix credentials: - type: key-auth name: primary-key config: key: john-key --- apiVersion: apisix.apache.org/v1alpha1 kind: Consumer metadata: namespace: aic name: jane spec: gatewayRef: name: apisix credentials: - type: key-auth name: primary-key config: key: jane-key --- apiVersion: apisix.apache.org/v1alpha1 kind: Consumer metadata: namespace: aic name: jimmy spec: gatewayRef: name: apisix credentials: - type: key-auth name: primary-key config: key: jimmy-key --- 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: workflow-plugin-config spec: plugins: - name: key-auth config: _meta: disable: false - name: workflow config: rules: - case: - ["consumer_name", "==", "aic_john"] actions: - - limit-count - count: 5 key: consumer_john key_type: constant rejected_code: 429 time_window: 30 policy: local - case: - ["consumer_name", "==", "aic_jane"] actions: - - limit-count - count: 3 key: consumer_jane key_type: constant rejected_code: 429 time_window: 30 policy: local - actions: - - limit-count - count: 2 key: "$consumer_name" key_type: var rejected_code: 429 time_window: 30 policy: local --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: namespace: aic name: workflow-route spec: parentRefs: - name: apisix rules: - matches: - path: type: Exact value: /anything filters: - type: ExtensionRef extensionRef: group: apisix.apache.org kind: PluginConfig name: workflow-plugin-config backendRefs: - name: httpbin-external-domain port: 80
apiVersion: apisix.apache.org/v2 kind: ApisixConsumer metadata: namespace: aic name: john spec: ingressClassName: apisix authParameter: keyAuth: value: key: john-key --- apiVersion: apisix.apache.org/v2 kind: ApisixConsumer metadata: namespace: aic name: jane spec: ingressClassName: apisix authParameter: keyAuth: value: key: jane-key --- apiVersion: apisix.apache.org/v2 kind: ApisixConsumer metadata: namespace: aic name: jimmy spec: ingressClassName: apisix authParameter: keyAuth: value: key: jimmy-key --- 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: workflow-route spec: ingressClassName: apisix http: - name: workflow-route match: paths: - /anything upstreams: - name: httpbin-external-domain plugins: - name: key-auth enable: true - name: workflow enable: true config: rules: - case: - ["consumer_name", "==", "aic_john"] actions: - - limit-count - count: 5 key: consumer_john key_type: constant rejected_code: 429 time_window: 30 policy: local - case: - ["consumer_name", "==", "aic_jane"] actions: - - limit-count - count: 3 key: consumer_jane key_type: constant rejected_code: 429 time_window: 30 policy: local - actions: - - limit-count - count: 2 key: "$consumer_name" key_type: var rejected_code: 429 time_window: 30 policy: local
将配置应用到集群:
kubectl apply -f workflow-ic.yaml
为了验证,请使用 john 的密钥发送 6 个连续请求:
resp=$(seq 6 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H 'apikey: john-key' -o /dev/null -s -w "%{http_code}\n") && \ count_200=$(echo "$resp" | grep "200" | wc -l) && \ count_429=$(echo "$resp" | grep "429" | wc -l) && \ echo "200": $count_200, "429": $count_429
您应该看到以下响应,显示在 6 个请求中,5 个请求成功(状态码 200),而其他请求被拒绝(状态码 429)。
200: 5, 429: 1
使用 jane 的密钥发送 6 个连续请求:
resp=$(seq 6 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H 'apikey: jane-key' -o /dev/null -s -w "%{http_code}\n") && \ count_200=$(echo "$resp" | grep "200" | wc -l) && \ count_429=$(echo "$resp" | grep "429" | wc -l) && \ echo "200": $count_200, "429": $count_429
您应该看到以下响应,显示在 6 个请求中,3 个请求成功(状态码 200),而其他请求被拒绝(状态码 429)。
200: 3, 429: 3
使用 jimmy 的密钥发送 3 个连续请求:
resp=$(seq 3 | xargs -I{} curl "http://127.0.0.1:9080/anything" -H 'apikey: jimmy-key' -o /dev/null -s -w "%{http_code}\n") && \ count_200=$(echo "$resp" | grep "200" | wc -l) && \ count_429=$(echo "$resp" | grep "429" | wc -l) && \ echo "200": $count_200, "429": $count_429
您应该看到以下响应,显示在 3 个请求中,2 个请求成功(状态码 200),而其他请求被拒绝(状态码 429)。
200: 2, 429: 1