From c71221c4d7c031e488c544f11f82a93240a701b9 Mon Sep 17 00:00:00 2001 From: Qi Guo <979918879@qq.com> Date: Wed, 29 Apr 2026 00:42:31 +0800 Subject: [PATCH 1/3] docs: migrate traffic recipes to service model --- skills/a7-recipe-api-versioning/SKILL.md | 192 +++++++++--------- skills/a7-recipe-blue-green/SKILL.md | 207 ++++++++++--------- skills/a7-recipe-canary/SKILL.md | 248 ++++++++++------------- 3 files changed, 311 insertions(+), 336 deletions(-) diff --git a/skills/a7-recipe-api-versioning/SKILL.md b/skills/a7-recipe-api-versioning/SKILL.md index 5f0fdf9..bf21545 100644 --- a/skills/a7-recipe-api-versioning/SKILL.md +++ b/skills/a7-recipe-api-versioning/SKILL.md @@ -2,8 +2,8 @@ name: a7-recipe-api-versioning description: >- Recipe skill for implementing API versioning strategies using API7 Enterprise Edition (API7 EE) - and the a7 CLI. Covers URI path versioning, header-based versioning, traffic splitting - for gradual migration, and enterprise version lifecycle management. + and the a7 CLI. Covers URI path versioning, header-based versioning, traffic splitting + for gradual migration, and version lifecycle management. version: "1.0.0" author: API7.ai Contributors license: Apache-2.0 @@ -11,9 +11,10 @@ metadata: category: recipe apisix_version: ">=3.0.0" a7_commands: + - a7 service create - a7 route create - a7 route update - - a7 upstream create + - a7 route list - a7 config sync - a7 gateway-group get --- @@ -22,59 +23,58 @@ metadata: ## Overview -API versioning is critical for maintaining backward compatibility while evolving your services. API7 Enterprise Edition (API7 EE) provides sophisticated traffic control mechanisms to manage multiple API versions across different **Gateway Groups**. +API versioning keeps old clients working while new versions are introduced. +In the current API7 EE model, create one service per backend version and attach +routes to those services with `service_id`. -Strategies supported: -1. **URI Path Versioning**: `/v1/service`, `/v2/service` (most common) -2. **Header-Based Versioning**: `X-API-Version: 2` or `Accept` header -3. **Query Parameter Versioning**: `?v=2` -4. **Gradual Rollout (Canary/Blue-Green)**: Shift traffic between versions based on weights -5. **Version Deprecation**: Graceful retirement with redirects or custom error messages +Supported patterns: -## When to Use +1. URI path versioning: `/v1/service`, `/v2/service`. +2. Header-based versioning: `X-API-Version: 2`. +3. Gradual rollout: send a small percentage to the new version. +4. Version deprecation: redirect or return a controlled response. -- Launching a new version of an API with breaking changes. -- Managing "Legacy", "Stable", and "Beta" versions simultaneously. -- Phasing out old versions by gradually shifting traffic. -- Providing specific versions to different **Gateway Groups** or client tiers. +## Approach A: URI Path Versioning -## Approach A: URI Path Versioning (with Gateway Groups) - -Each version is routed to its respective upstream, and the version prefix is stripped before reaching the backend. - -### 1. Create Versioned Upstreams +### 1. Create versioned services ```bash -# Upstream for v1 in the "production" gateway group -a7 upstream create -g production -f - <<'EOF' +a7 service create -g production -f - <<'EOF' { - "id": "upstream-v1", + "id": "service-v1", "name": "Service V1", - "type": "roundrobin", - "nodes": { "v1-backend:8080": 1 } + "upstream": { + "type": "roundrobin", + "nodes": [ + {"host": "v1-backend", "port": 8080, "weight": 1} + ] + } } EOF -# Upstream for v2 in the "production" gateway group -a7 upstream create -g production -f - <<'EOF' +a7 service create -g production -f - <<'EOF' { - "id": "upstream-v2", + "id": "service-v2", "name": "Service V2", - "type": "roundrobin", - "nodes": { "v2-backend:8080": 1 } + "upstream": { + "type": "roundrobin", + "nodes": [ + {"host": "v2-backend", "port": 8080, "weight": 1} + ] + } } EOF ``` -### 2. Create Routes with URI Rewriting +### 2. Create routes with URI rewriting ```bash -# Route for v1: /v1/users -> /users on backend a7 route create -g production -f - <<'EOF' { "id": "route-v1", - "uri": "/v1/*", - "upstream_id": "upstream-v1", + "name": "route-v1", + "paths": ["/v1/*"], + "service_id": "service-v1", "plugins": { "proxy-rewrite": { "regex_uri": ["^/v1/(.*)", "/$1"] @@ -83,12 +83,12 @@ a7 route create -g production -f - <<'EOF' } EOF -# Route for v2: /v2/users -> /users on backend a7 route create -g production -f - <<'EOF' { "id": "route-v2", - "uri": "/v2/*", - "upstream_id": "upstream-v2", + "name": "route-v2", + "paths": ["/v2/*"], + "service_id": "service-v2", "plugins": { "proxy-rewrite": { "regex_uri": ["^/v2/(.*)", "/$1"] @@ -100,24 +100,28 @@ EOF ## Approach B: Header-Based Versioning -A single URI serves multiple versions based on the `X-API-Version` header using the `traffic-split` plugin. +The route defaults to V1 through `service_id`. Matching requests can be routed +to V2 with `traffic-split` and an inline upstream. ```bash a7 route create -g production -f - <<'EOF' { - "uri": "/api/resource", + "id": "versioned-api", + "name": "versioned-api", + "paths": ["/api/resource"], + "service_id": "service-v1", "plugins": { "traffic-split": { "rules": [ { "match": [ - { "vars": [["http_x_api_version", "==", "2"]] } + {"vars": [["http_x_api_version", "==", "2"]]} ], "weighted_upstreams": [ { "upstream": { "type": "roundrobin", - "nodes": { "v2-backend:8080": 1 } + "nodes": {"v2-backend:8080": 1} }, "weight": 1 } @@ -125,25 +129,21 @@ a7 route create -g production -f - <<'EOF' } ] } - }, - "upstream": { - "type": "roundrobin", - "nodes": { "v1-backend:8080": 1 } } } EOF ``` -- Header `X-API-Version: 2` routes to V2. -- Missing header or other values route to V1 (default upstream). +Requests with `X-API-Version: 2` go to V2. Other requests stay on V1. ## Approach C: Gradual Version Rollout -Shift 10% of traffic to V2 to monitor stability before a full rollout. +Shift a small percentage of V1 traffic to V2 before making V2 the default. ```bash a7 route update route-v1 -g production -f - <<'EOF' { + "service_id": "service-v1", "plugins": { "traffic-split": { "rules": [ @@ -152,7 +152,7 @@ a7 route update route-v1 -g production -f - <<'EOF' { "upstream": { "type": "roundrobin", - "nodes": { "v2-backend:8080": 1 } + "nodes": {"v2-backend:8080": 1} }, "weight": 1 }, @@ -167,16 +167,16 @@ a7 route update route-v1 -g production -f - <<'EOF' } EOF ``` -*Note: A `weighted_upstreams` entry without an `upstream` field refers back to the route's default upstream (V1).* -## Version Deprecation with Redirect +The entry without `upstream` falls back to the route's default service. -When V1 is deprecated, redirect clients to the V2 equivalent with a `301` status code. +## Version Deprecation with Redirect ```bash a7 route update route-v1 -g production -f - <<'EOF' { - "uri": "/v1/*", + "paths": ["/v1/*"], + "service_id": "service-v1", "plugins": { "redirect": { "regex_uri": ["^/v1/(.*)", "/v2/$1"], @@ -187,59 +187,65 @@ a7 route update route-v1 -g production -f - <<'EOF' EOF ``` -## Declarative Versioning with Config Sync - -Manage the lifecycle of versions across Gateway Groups in a single YAML file. +## Config Sync ```yaml -# versioning-config.yaml -gateway_groups: - - id: production - upstreams: - - id: v1-backend - nodes: { "v1-svc:80": 1 } - - id: v2-backend - nodes: { "v2-svc:80": 1 } - routes: - - id: service-v1 - uri: "/v1/*" - upstream_id: v1-backend - plugins: - proxy-rewrite: - regex_uri: ["^/v1/(.*)", "/$1"] - - id: service-v2 - uri: "/v2/*" - upstream_id: v2-backend - plugins: - proxy-rewrite: - regex_uri: ["^/v2/(.*)", "/$1"] +version: "1" +gateway_group: production +services: + - id: service-v1 + name: Service V1 + upstream: + type: roundrobin + nodes: + - host: v1-svc + port: 80 + weight: 1 + - id: service-v2 + name: Service V2 + upstream: + type: roundrobin + nodes: + - host: v2-svc + port: 80 + weight: 1 +routes: + - id: service-v1-route + name: service-v1-route + paths: + - /v1/* + service_id: service-v1 + plugins: + proxy-rewrite: + regex_uri: ["^/v1/(.*)", "/$1"] + - id: service-v2-route + name: service-v2-route + paths: + - /v2/* + service_id: service-v2 + plugins: + proxy-rewrite: + regex_uri: ["^/v2/(.*)", "/$1"] ``` Apply the configuration: + ```bash a7 config sync -g production -f versioning-config.yaml ``` -## Important Considerations - -- **Gateway Group Scoping**: Always ensure your versioned routes are applied to the correct `--gateway-group`. -- **Admin API Port**: Use port `7443` (HTTPS) for API7 EE communication. -- **Authentication**: Use the `--token` flag for CLI authentication. -- **Priority**: When using multiple versioning strategies on the same URI, the order of rules in `traffic-split` is critical. -- **Regex Syntax**: `regex_uri` follows PCRE-compatible Lua regex. Double-escape special characters in JSON if necessary. - ## Verification ```bash -# Verify V1 path curl -i https://gateway.prod.example.com/v1/health - -# Verify V2 path curl -i https://gateway.prod.example.com/v2/health - -# Verify Header-based versioning curl -i -H "X-API-Version: 2" https://gateway.prod.example.com/api/resource - -# Check route status in Gateway Group -a7 route list -g production +a7 route list -g production --service-id service-v1 ``` + +## Important Considerations + +- Always apply services and routes to the intended `--gateway-group`. +- Use route priorities when multiple versioning strategies overlap. +- `regex_uri` follows APISIX/Lua-compatible regex behavior. +- Prefer `service_id` for default routing and reserve inline upstreams for plugin-specific overrides. diff --git a/skills/a7-recipe-blue-green/SKILL.md b/skills/a7-recipe-blue-green/SKILL.md index 83238dc..851763f 100644 --- a/skills/a7-recipe-blue-green/SKILL.md +++ b/skills/a7-recipe-blue-green/SKILL.md @@ -2,9 +2,8 @@ name: a7-recipe-blue-green description: >- Recipe skill for implementing blue-green deployments using the a7 CLI in API7 Enterprise Edition. - Covers creating two upstream environments, switching traffic instantly - via route updates or traffic-split plugin, rollback procedures, and - config sync workflows with gateway group scoping. + Covers creating two service-backed environments, switching traffic via route service_id updates, + rollback procedures, and config sync workflows with gateway group scoping. version: "1.0.0" author: API7.ai Contributors license: Apache-2.0 @@ -12,9 +11,10 @@ metadata: category: recipe apisix_version: ">=3.0.0" a7_commands: - - a7 upstream create + - a7 service create - a7 route create - a7 route update + - a7 route get - a7 config sync - a7 config diff --- @@ -23,211 +23,217 @@ metadata: ## Overview -Blue-green deployment runs two identical production environments (blue and -green). At any time, only one serves live traffic. Deploy the new version to -the idle environment, test it, then switch traffic instantly. If anything -goes wrong, switch back. +Blue-green deployment runs two identical production environments. Only one +environment serves live traffic at a time. Deploy the new version to the idle +environment, test it, then switch the route to the new service. If anything +goes wrong, switch the route back. -This recipe implements blue-green deployment using API7 Enterprise Edition (API7 EE) routes and upstreams -managed by the a7 CLI. +This recipe uses the current API7 EE service-backed route model: -## When to Use - -- Zero-downtime deployments with instant rollback. -- You have two identical environments that can be swapped. -- You want to test the new version with internal traffic before switching. -- You need an auditable, scriptable deployment process. +1. Create one service for blue. +2. Create one service for green. +3. Point the route to the active service with `service_id`. +4. Switch or roll back by updating the route's `service_id`. ## Prerequisites - API7 EE Control Plane and at least one Gateway Group. - a7 CLI configured with a valid token and server address. +- Two deployable backend environments, such as blue and green. -## Approach A: Upstream Swap (Simplest) - -Switch traffic by updating the route's `upstream_id` to point at the other -environment. +## Approach A: Service Swap -### 1. Create both upstreams +### 1. Create both services ```bash -a7 upstream create --gateway-group default -f - <<'EOF' +a7 service create --gateway-group default -f - <<'EOF' { - "id": "blue", - "type": "roundrobin", - "nodes": { - "blue-backend-1:8080": 1, - "blue-backend-2:8080": 1 + "id": "blue-service", + "name": "blue-service", + "upstream": { + "type": "roundrobin", + "nodes": [ + {"host": "blue-backend-1", "port": 8080, "weight": 1}, + {"host": "blue-backend-2", "port": 8080, "weight": 1} + ] } } EOF -a7 upstream create --gateway-group default -f - <<'EOF' +a7 service create --gateway-group default -f - <<'EOF' { - "id": "green", - "type": "roundrobin", - "nodes": { - "green-backend-1:8080": 1, - "green-backend-2:8080": 1 + "id": "green-service", + "name": "green-service", + "upstream": { + "type": "roundrobin", + "nodes": [ + {"host": "green-backend-1", "port": 8080, "weight": 1}, + {"host": "green-backend-2", "port": 8080, "weight": 1} + ] } } EOF ``` -### 2. Create route pointing to blue +### 2. Create the route pointing to blue ```bash a7 route create --gateway-group default -f - <<'EOF' { "id": "api", - "uri": "/api/*", - "upstream_id": "blue" + "name": "api", + "paths": ["/api/*"], + "service_id": "blue-service" } EOF ``` -### 3. Deploy new version to green, test it +### 3. Deploy and test green -Deploy your new version to the green environment. Test internally using its direct IP/hostname. +Deploy the new version to the green environment, then test it directly through +its internal hostname or a temporary test route before switching production +traffic. ### 4. Switch to green ```bash a7 route update api --gateway-group default -f - <<'EOF' { - "upstream_id": "green" + "service_id": "green-service" } EOF ``` -Traffic switches instantly across all gateways in the `default` gateway group. No downtime. +Traffic switches across all gateways in the `default` gateway group after the +configuration propagates. -### 5. Rollback to blue (if needed) +### 5. Roll back to blue ```bash a7 route update api --gateway-group default -f - <<'EOF' { - "upstream_id": "blue" + "service_id": "blue-service" } EOF ``` -## Approach B: Traffic-Split Plugin (Header-Based Testing) +## Approach B: Header-Based Green Testing -Use the `traffic-split` plugin to test the green environment with specific -headers before full switch. - -### 1. Create route with traffic-split +Use `traffic-split` for targeted green testing while the route defaults to blue. +The route still uses `service_id` for the default backend; the plugin contains +an inline upstream only for matched green requests. ```bash -a7 route create --gateway-group default -f - <<'EOF' +a7 route update api --gateway-group default -f - <<'EOF' { - "id": "api", - "uri": "/api/*", + "service_id": "blue-service", "plugins": { "traffic-split": { "rules": [ { "match": [ - { - "vars": [["http_x-env", "==", "green"]] - } + {"vars": [["http_x_env", "==", "green"]]} ], "weighted_upstreams": [ { - "upstream_id": "green", + "upstream": { + "type": "roundrobin", + "nodes": {"green-backend-1:8080": 1} + }, "weight": 1 } ] } ] } - }, - "upstream_id": "blue" + } } EOF ``` -### 2. Test green internally +Test green with: ```bash curl -H "x-env: green" http://gateway:9080/api/health ``` -### 3. Full switch — remove traffic-split, swap upstream +When ready, remove the plugin and switch the route to `green-service`: ```bash a7 route update api --gateway-group default -f - <<'EOF' { "plugins": {}, - "upstream_id": "green" + "service_id": "green-service" } EOF ``` -## Approach C: Config Sync (Declarative) - -### config.yaml — Blue active +## Config Sync ```yaml version: "1" gateway_group: default -upstreams: - - id: blue - type: roundrobin - nodes: - "blue-backend-1:8080": 1 - "blue-backend-2:8080": 1 - - id: green - type: roundrobin - nodes: - "green-backend-1:8080": 1 - "green-backend-2:8080": 1 +services: + - id: blue-service + name: blue-service + upstream: + type: roundrobin + nodes: + - host: blue-backend-1 + port: 8080 + weight: 1 + - host: blue-backend-2 + port: 8080 + weight: 1 + - id: green-service + name: green-service + upstream: + type: roundrobin + nodes: + - host: green-backend-1 + port: 8080 + weight: 1 + - host: green-backend-2 + port: 8080 + weight: 1 routes: - id: api - uri: /api/* - upstream_id: blue # ← change to "green" to switch + name: api + paths: + - /api/* + service_id: blue-service # change to green-service to switch ``` -### Preview changes before switching +Preview and apply: ```bash -# Edit config.yaml: change upstream_id to "green" a7 config diff -f config.yaml -``` - -### Apply the switch - -```bash a7 config sync -f config.yaml ``` -## Deployment Script Example +## Deployment Script ```bash #!/bin/bash set -euo pipefail GROUP="default" -CURRENT=$(a7 route get api --gateway-group $GROUP -o json | jq -r '.upstream_id') -TARGET=$([ "$CURRENT" = "blue" ] && echo "green" || echo "blue") +ROUTE_ID="api" +CURRENT=$(a7 route get "$ROUTE_ID" --gateway-group "$GROUP" -o json | jq -r '.service_id') +TARGET=$([ "$CURRENT" = "blue-service" ] && echo "green-service" || echo "blue-service") -echo "Current: $CURRENT → Switching to: $TARGET in group: $GROUP" +echo "Current: $CURRENT; switching to: $TARGET" -# Switch -a7 route update api --gateway-group $GROUP -f - < /dev/null; then - echo "✅ $TARGET is healthy" + echo "$TARGET is healthy" else - echo "❌ $TARGET unhealthy, rolling back to $CURRENT" - a7 route update api --gateway-group $GROUP -f - <- Recipe skill for implementing canary releases using the a7 CLI in API7 Enterprise Edition. - Covers gradual traffic shifting with the traffic-split plugin, - header-based canary routing, weight adjustment progression, + Covers gradual traffic shifting with the traffic-split plugin, header-based canary routing, monitoring checkpoints, and full promotion or rollback workflows. version: "1.0.0" author: API7.ai Contributors @@ -12,8 +11,8 @@ metadata: category: recipe apisix_version: ">=3.0.0" a7_commands: - - a7 upstream create - - a7 upstream update + - a7 service create + - a7 service update - a7 route create - a7 route update - a7 route get @@ -24,47 +23,49 @@ metadata: ## Overview -A canary release gradually shifts traffic from the stable version to a new -version. Start with a small percentage (e.g., 5%), monitor for errors, then -increase incrementally until the new version receives 100% of traffic. If -errors spike at any stage, roll back instantly. +A canary release gradually shifts traffic from a stable version to a new +version. Start with a small percentage, monitor, then increase until the new +version receives all traffic. If errors spike, roll back to the stable service. -This recipe uses the `traffic-split` plugin in API7 Enterprise Edition (API7 EE) to manage weighted traffic -distribution between stable and canary upstreams within a gateway group. +This recipe uses: -## When to Use - -- Deploy new versions with minimal blast radius. -- Validate changes with real production traffic before full rollout. -- You need gradual rollout with monitoring checkpoints. -- You want automatic or scripted rollback on error detection. +- `service_id` for the route's default stable backend. +- `traffic-split` with an inline upstream for temporary canary traffic. +- `service update` or `route update` for promotion and rollback. ## Prerequisites - API7 EE Control Plane and at least one Gateway Group. - a7 CLI configured with a valid token and server address. +- Stable and canary backend deployments. -## Step-by-Step: Canary Release +## Step-by-Step Canary Release -### 1. Create stable and canary upstreams +### 1. Create stable and canary services ```bash -a7 upstream create --gateway-group default -f - <<'EOF' +a7 service create --gateway-group default -f - <<'EOF' { - "id": "stable", - "type": "roundrobin", - "nodes": { - "stable-v1:8080": 1 + "id": "stable-service", + "name": "stable-service", + "upstream": { + "type": "roundrobin", + "nodes": [ + {"host": "stable-v1", "port": 8080, "weight": 1} + ] } } EOF -a7 upstream create --gateway-group default -f - <<'EOF' +a7 service create --gateway-group default -f - <<'EOF' { - "id": "canary", - "type": "roundrobin", - "nodes": { - "canary-v2:8080": 1 + "id": "canary-service", + "name": "canary-service", + "upstream": { + "type": "roundrobin", + "nodes": [ + {"host": "canary-v2", "port": 8080, "weight": 1} + ] } } EOF @@ -76,14 +77,19 @@ EOF a7 route create --gateway-group default -f - <<'EOF' { "id": "api", - "uri": "/api/*", + "name": "api", + "paths": ["/api/*"], + "service_id": "stable-service", "plugins": { "traffic-split": { "rules": [ { "weighted_upstreams": [ { - "upstream_id": "canary", + "upstream": { + "type": "roundrobin", + "nodes": {"canary-v2:8080": 1} + }, "weight": 5 }, { @@ -93,26 +99,27 @@ a7 route create --gateway-group default -f - <<'EOF' } ] } - }, - "upstream_id": "stable" + } } EOF ``` -### 3. Monitor and increase to 25% - -Check error rates, latency, and logs in the API7 EE Dashboard or your observability tools. If healthy: +### 3. Increase to 25% ```bash a7 route update api --gateway-group default -f - <<'EOF' { + "service_id": "stable-service", "plugins": { "traffic-split": { "rules": [ { "weighted_upstreams": [ { - "upstream_id": "canary", + "upstream": { + "type": "roundrobin", + "nodes": {"canary-v2:8080": 1} + }, "weight": 25 }, { @@ -127,130 +134,82 @@ a7 route update api --gateway-group default -f - <<'EOF' EOF ``` -### 4. Increase to 50% +### 4. Promote to 100% -```bash -a7 route update api --gateway-group default -f - <<'EOF' -{ - "plugins": { - "traffic-split": { - "rules": [ - { - "weighted_upstreams": [ - { - "upstream_id": "canary", - "weight": 50 - }, - { - "weight": 50 - } - ] - } - ] - } - } -} -EOF -``` - -### 5. Promote to 100% (complete the rollout) - -Remove traffic-split and switch to canary as the new stable: +Remove `traffic-split` and switch the route's default service to canary. ```bash a7 route update api --gateway-group default -f - <<'EOF' { "plugins": {}, - "upstream_id": "canary" + "service_id": "canary-service" } EOF ``` -Then update the "stable" upstream nodes to the new version for next time: +Optionally update the stable service to point to the promoted backend so the +same service IDs can be reused in the next release: ```bash -a7 upstream update stable --gateway-group default -f - <<'EOF' +a7 service update stable-service --gateway-group default -f - <<'EOF' { - "nodes": { - "canary-v2:8080": 1 + "id": "stable-service", + "name": "stable-service", + "upstream": { + "type": "roundrobin", + "nodes": [ + {"host": "canary-v2", "port": 8080, "weight": 1} + ] } } EOF ``` -## Rollback (at any stage) +## Rollback -Remove the traffic-split plugin to send all traffic back to stable: +Remove the plugin and send all traffic back to the stable service: ```bash a7 route update api --gateway-group default -f - <<'EOF' { "plugins": {}, - "upstream_id": "stable" + "service_id": "stable-service" } EOF ``` -## Advanced: Header-Based Canary - -Route specific users (e.g., internal testers) to the canary version: +## Header-Based Canary ```bash a7 route update api --gateway-group default -f - <<'EOF' { + "service_id": "stable-service", "plugins": { "traffic-split": { "rules": [ { "match": [ - { - "vars": [["http_x-canary", "==", "true"]] - } + {"vars": [["http_x_canary", "==", "true"]]} ], "weighted_upstreams": [ { - "upstream_id": "canary", + "upstream": { + "type": "roundrobin", + "nodes": {"canary-v2:8080": 1} + }, "weight": 1 } ] } ] } - }, - "upstream_id": "stable" + } } EOF ``` -Only requests with header `x-canary: true` go to the canary. All others stay on stable. - -## Advanced: Cookie-Based Canary - -Route users who opted into beta: - -```json -{ - "plugins": { - "traffic-split": { - "rules": [ - { - "match": [ - { - "vars": [["cookie_beta", "==", "1"]] - } - ], - "weighted_upstreams": [ - { - "upstream_id": "canary", - "weight": 1 - } - ] - } - ] - } - } -} -``` +Only requests with `x-canary: true` go to canary. All others use the route's +default `stable-service`. ## Canary Progression Script @@ -260,27 +219,25 @@ set -euo pipefail GROUP="default" ROUTE_ID="api" -CANARY_UPSTREAM="canary" WEIGHTS=(5 25 50 75 100) HEALTH_URL="http://gateway:9080/api/health" -WAIT_SECONDS=300 # 5 minutes between stages +WAIT_SECONDS=300 for w in "${WEIGHTS[@]}"; do if [ "$w" -eq 100 ]; then - echo "Promoting canary to 100% in group: $GROUP..." a7 route update "$ROUTE_ID" --gateway-group "$GROUP" -f - < /dev/null; then - echo "❌ Health check failed at ${w}%. Rolling back." a7 route update "$ROUTE_ID" --gateway-group "$GROUP" -f - < Date: Wed, 29 Apr 2026 00:51:56 +0800 Subject: [PATCH 2/3] docs: preserve rewrite during version rollout --- skills/a7-recipe-api-versioning/SKILL.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/skills/a7-recipe-api-versioning/SKILL.md b/skills/a7-recipe-api-versioning/SKILL.md index bf21545..7802397 100644 --- a/skills/a7-recipe-api-versioning/SKILL.md +++ b/skills/a7-recipe-api-versioning/SKILL.md @@ -145,6 +145,9 @@ a7 route update route-v1 -g production -f - <<'EOF' { "service_id": "service-v1", "plugins": { + "proxy-rewrite": { + "regex_uri": ["^/v1/(.*)", "/$1"] + }, "traffic-split": { "rules": [ { From 8b508f1bd7da297be48aea81ed3a18c45ce60807 Mon Sep 17 00:00:00 2001 From: Qi Guo <979918879@qq.com> Date: Thu, 30 Apr 2026 00:42:07 +0800 Subject: [PATCH 3/3] docs: fix traffic recipe review issues --- skills/a7-recipe-api-versioning/SKILL.md | 1 - skills/a7-recipe-blue-green/SKILL.md | 3 +-- skills/a7-recipe-canary/SKILL.md | 7 +++---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/skills/a7-recipe-api-versioning/SKILL.md b/skills/a7-recipe-api-versioning/SKILL.md index 7802397..d3be4f4 100644 --- a/skills/a7-recipe-api-versioning/SKILL.md +++ b/skills/a7-recipe-api-versioning/SKILL.md @@ -194,7 +194,6 @@ EOF ```yaml version: "1" -gateway_group: production services: - id: service-v1 name: Service V1 diff --git a/skills/a7-recipe-blue-green/SKILL.md b/skills/a7-recipe-blue-green/SKILL.md index 851763f..ae2ce9b 100644 --- a/skills/a7-recipe-blue-green/SKILL.md +++ b/skills/a7-recipe-blue-green/SKILL.md @@ -172,7 +172,6 @@ EOF ```yaml version: "1" -gateway_group: default services: - id: blue-service name: blue-service @@ -244,7 +243,7 @@ fi | Symptom | Cause | Fix | |---------|-------|-----| | 502 after switch | New environment not ready | Test health endpoint before switching; roll back if needed | -| Traffic still going to old env | Route update has not propagated yet | Verify with `a7 route get api -o json` and retry after propagation | +| Traffic still going to old env | Route update has not propagated yet | Verify with `a7 route get api --gateway-group "$GROUP" -o json` and retry after propagation | | Cannot roll back | Previous service ID was not recorded | Record `service_id` before switching | | Command failed with 401 | Invalid token | Refresh your token using `a7 context create` | | Service not found | Different gateway group | Ensure `--gateway-group` matches where services and routes were created | diff --git a/skills/a7-recipe-canary/SKILL.md b/skills/a7-recipe-canary/SKILL.md index e2a5f2c..ad7a039 100644 --- a/skills/a7-recipe-canary/SKILL.md +++ b/skills/a7-recipe-canary/SKILL.md @@ -261,7 +261,6 @@ done ```yaml version: "1" -gateway_group: default services: - id: stable-service name: stable-service @@ -302,8 +301,8 @@ routes: | Symptom | Cause | Fix | |---------|-------|-----| | Traffic ratio is not exact | Weighted routing is probabilistic | Measure over enough requests | -| Canary not receiving traffic | Match condition never true | Check header/cookie name and `a7 route get` output | -| Rollback not instant | Config has not propagated yet | Verify with `a7 route get` and retry after propagation | +| Canary not receiving traffic | Match condition never true | Check header/cookie name and `a7 route get api --gateway-group default` output | +| Rollback not instant | Config has not propagated yet | Verify with `a7 route get api --gateway-group default` and retry after propagation | | 502 from canary | Canary backend is unhealthy | Check canary service health before increasing weight | -| Weight changes have no effect | Editing wrong route | Verify route ID with `a7 route list --service-id stable-service` | +| Weight changes have no effect | Editing wrong route | Verify route ID with `a7 route list --gateway-group default --service-id stable-service` | | Command failed with 403 | RBAC permission issue | Ensure your token can modify routes in the gateway group |