Recipe skill for implementing canary releases using the a6 CLI. Covers gradual traffic shifting with the traffic-split plugin, header-based canary routing, weight adjustment progression, monitoring checkpoints, and full promotion or rollback workflows.
name a6-recipe-canary description Recipe skill for implementing canary releases using the a6 CLI. Covers gradual traffic shifting with the traffic-split plugin, header-based canary routing, weight adjustment progression, monitoring checkpoints, and full promotion or rollback workflows. version 1.0.0 author Apache APISIX Contributors license Apache-2.0 metadata {"category":"recipe","apisix_version":">=3.0.0","a6_commands":["a6 upstream create","a6 route create","a6 route update","a6 route get","a6 config sync"]} a6-recipe-canary 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. This recipe uses the traffic-split plugin to manage weighted traffic distribution between stable and canary upstreams. 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 Step-by-Step: Canary Release
a6 upstream create -f - << 'EOF' { "id" : "canary" , "type" : "roundrobin" , "nodes" : { "canary-v2:8080" : 1 } } EOF 2. Start canary at 5% a6 route create -f - << 'EOF' { "id" : "api" , "uri" : "/api/*" , "plugins" : { "traffic-split" : { "rules" : [ { "weighted_upstreams" : [ { "upstream_id" : "canary" , "weight" : 5 }, { "weight" : 95 } ] } ] } }, "upstream_id" : "stable" } EOF 3. Monitor and increase to 25% Check error rates, latency, and logs. If healthy: a6 route update api -f - << 'EOF' { "plugins" : { "traffic-split" : { "rules" : [ { "weighted_upstreams" : [ { "upstream_id" : "canary" , "weight" : 25 }, { "weight" : 75 } ] } ] } } } EOF 4. Increase to 50% a6 route update api -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: a6 route update api -f - << 'EOF' { "plugins" : {}, "upstream_id" : "canary" } EOF Then update the "stable" upstream nodes to the new version for next time: a6 upstream update stable -f - << 'EOF' { "nodes" : { "canary-v2:8080" : 1 } } EOF Rollback (at any stage) Remove the traffic-split plugin to send all traffic back to stable: a6 route update api -f - << 'EOF' { "plugins" : {}, "upstream_id" : "stable" } EOF Advanced: Header-Based Canary Route specific users (e.g., internal testers) to the canary version: a6 route update api -f - << 'EOF' { "plugins" : { "traffic-split" : { "rules" : [ { "match" : [ { "vars" : [[ "http_x-canary" , "==" , "true" ]] } ], "weighted_upstreams" : [ { "upstream_id" : "canary" , "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: { "plugins" : { "traffic-split" : { "rules" : [ { "match" : [ { "vars" : [ [ "cookie_beta" , "==" , "1" ] ] } ] , "weighted_upstreams" : [ { "upstream_id" : "canary" , "weight" : 1 } ] } ] } } } Canary Progression Script #!/bin/bash set -euo pipefail
ROUTE_ID= "api" CANARY_UPSTREAM= "canary" WEIGHTS=(5 25 50 75 100) HEALTH_URL= "http://gateway:9080/api/health" WAIT_SECONDS=300
for w in " ${WEIGHTS[@]} " ; do if [ " $w " -eq 100 ]; then echo "Promoting canary to 100%..." a6 route update " $ROUTE_ID " -f - << EOF {"plugins": {}, "upstream_id": "$CANARY_UPSTREAM"} EOF else stable_w=$(( 100
/dev/null; then echo "❌ Health check failed at ${w} %. Rolling back." a6 route update " $ROUTE_ID " -f - << EOF {"plugins": {}, "upstream_id": "stable"} EOF exit 1 fi echo "✅ Healthy at ${w} %" done echo "🎉 Canary release complete!" Config Sync Example version: "1" upstreams:
weight: 90 upstream_id: stable Troubleshooting Symptom Cause Fix Traffic ratio not exact Round-robin approximation Expected; ratios converge over many requests Canary not receiving traffic Match condition never true Check header/cookie name; use a6 route get to verify config Rollback not instant Plugin config cached APISIX updates propagate via etcd in milliseconds — verify with a6 route get 502 errors from canary Canary upstream not healthy Check canary service health before starting rollout Weight changes have no effect Editing wrong route Verify route ID with a6 route list