ЁЯОн рдзрдбрд╛ 05 тАФ Stages рдЖрдгрд┐ deployments: рд░рдВрдЧреАрдд рддрд╛рд▓реАрдо рдЖрдгрд┐ рдЦрд░рд╛ рдкреНрд░рдпреЛрдЧ
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 05 ┬╖ рдорд╛рдЧреЗ: lesson-04-mapping-validation ┬╖ рдкреБрдвреЗ: lesson-06-auth
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ04, рдЖрдгрд┐ stages (dev, prod), deployments (API рдЪреЗ snapshots),
stage variables (рддреЛрдЪ route marks-dev рдХрд┐рдВрд╡рд╛ marks-prod рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рддреЛ), рдЖрдгрд┐
canary releases. apigw/demo.py рдордзрд▓реЗ stages() рддреАрдЪ request рддреАрди
stages рдирд╛ рдкрд╛рдард╡рддреЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╢рд╛рд│реЗрдЪреНрдпрд╛ рдирд╛рдЯрдХрд╛рдЪреА рдПрдХ рд░рдВрдЧреАрдд рддрд╛рд▓реАрдо ЁЯОн рдЕрд╕рддреЗ рдЖрдгрд┐ рдПрдХ рдЦрд░рд╛ рдкреНрд░рдпреЛрдЧ ЁЯОЯя╕П. рддреАрдЪ рд╕рдВрд╣рд┐рддрд╛, рддреЗрдЪ рдХрд▓рд╛рдХрд╛рд░ тАФ рдкрдг рддрд╛рд▓рдореАрдд рдкреБрдареНрдареНрдпрд╛рдЪреЗ рд╕рд╛рд╣рд┐рддреНрдп рдЖрдгрд┐ рд▓рд╣рд╛рди рд╕рднрд╛рдЧреГрд╣ рд╡рд╛рдкрд░рддрд╛рдд, рдЖрдгрд┐ рдкреНрд░рдпреЛрдЧрд╛рдд рдЦрд░рд╛ рд░рдВрдЧрдордВрдЪ рдЖрдгрд┐ рдЦрд░реЗ рдкреНрд░реЗрдХреНрд╖рдХ рдЕрд╕рддрд╛рдд.
рд╢рд┐рдХреНрд╖рд┐рдХрд╛ рд╕рдВрд╣рд┐рддрд╛ рдмрджрд▓рддреЗ рддреЗрд╡реНрд╣рд╛ рддреЛ рдмрджрд▓ рдЬрд╛рджреВрдиреЗ рдЖрдЬрдЪреНрдпрд╛ рд░рд╛рддреНрд░реАрдЪреНрдпрд╛ рдкреНрд░рдпреЛрдЧрд╛рдд рдпреЗрдд рдирд╛рд╣реА. рдХреЛрдгреАрддрд░реА рдкреНрд░рдпреЛрдЧрд╛рд▓рд╛ рдирд╡реА рд╕рдВрд╣рд┐рддрд╛ рджреНрдпрд╛рд╡реА рд▓рд╛рдЧрддреЗ тАФ рддреЗрдЪ рдореНрд╣рдгрдЬреЗ deployment. рддреЛрдкрд░реНрдпрдВрдд рдкреНрд░рдпреЛрдЧ рдЬреБрдиреАрдЪ рд╕рдВрд╣рд┐рддрд╛ рдЪрд╛рд▓рд╡рдд рд░рд╛рд╣рддреЛ.
рдкреНрд░рддреНрдпреЗрдХ stage рдЪреНрдпрд╛ рднрд┐рдВрддреАрд╡рд░ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рдЪрд┐рдареНрдареНрдпрд╛ рдЕрд╕рддрд╛рдд: рддрд╛рд▓рдореАрд╕рд╛рдареА "рд╕рд╛рд╣рд┐рддреНрдп рдЦреЛрд▓реА 12 рдордзреНрдпреЗ рдЖрд╣реЗ", рдкреНрд░рдпреЛрдЧрд╛рд╕рд╛рдареА "рд╕рд╛рд╣рд┐рддреНрдп рдореБрдЦреНрдп рднрд╛рдВрдбрд╛рд░рд╛рдд рдЖрд╣реЗ". рддреНрдпрд╛ рдЪрд┐рдареНрдареНрдпрд╛ рдореНрд╣рдгрдЬреЗ stage variables.
рдЖрдгрд┐ рдХрд╛рд│рдЬреА рдШреЗрдгрд╛рд░реА рд╢рд┐рдХреНрд╖рд┐рдХрд╛ рд╕рдЧрд│реНрдпрд╛рдВрдЪреНрдпрд╛ рдЖрдзреА рдкреНрд░реЗрдХреНрд╖рдХрд╛рдВрдЪреНрдпрд╛ рдПрдХрд╛ рд░рд╛рдВрдЧреЗрд▓рд╛ рдирд╡рд╛ рдкреНрд░рд╡реЗрд╢ рджрд╛рдЦрд╡реВ рд╢рдХрддреЗ тАФ рддреЛ рдореНрд╣рдгрдЬреЗ canary.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
edit["тЬПя╕П you change routes"] --> dep["ЁЯУ╕ deployment<br/>a snapshot of the API"]
dep --> dev["ЁЯОн stage dev<br/>table = marks-dev ┬╖ rate 5 ┬╖ no cache"]
dep --> prod["ЁЯОЯя╕П stage prod<br/>table = marks-prod ┬╖ rate 10,000 ┬╖ cache 300 s"]
prod -.->|"canary 10%"| new["ЁЯРд new deployment"]
x["stage test"] -->|"no such stage"| no["ЁЯЪл 403 Forbidden"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/apigateway/lesson-diagrams.html#l05
тЭУ рдХрд╛рдп
- Deployment (REST APIs) тАФ рддреБрдордЪреЗ routes, integrations рдЖрдгрд┐ settings рдпрд╛рдВрдЪрд╛ рдЧреЛрдард╡рд▓реЗрд▓рд╛ snapshot. Console рдордзреНрдпреЗ рдХрд┐рдВрд╡рд╛ CLI рдиреЗ рдХреЗрд▓реЗрд▓реЗ рдмрджрд▓, рддреБрдореНрд╣реА рдирд╡реЗ deployment рдмрдирд╡реВрди stage рддреНрдпрд╛рдХрдбреЗ рд╡рд│рд╡реЗрдкрд░реНрдпрдВрдд live рдирд╕рддрд╛рдд.
- Stage тАФ API рдЪреА рдирд╛рд╡ рдЕрд╕рд▓реЗрд▓реА, call рдХрд░рддрд╛ рдпреЗрдгрд╛рд░реА рдЖрд╡реГрддреНрддреА, рдЬрд╕реЗ
devрдХрд┐рдВрд╡рд╛prod, рд╕реНрд╡рддрдГрдЪреНрдпрд╛ URL рд╕рд╣:https://abc123.execute-api.ap-south-1.amazonaws.com/prod/students/7. рдкреНрд░рддреНрдпреЗрдХ stage рдЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ throttling, cache, logging рдЖрдгрд┐ tracing settings рдЕрд╕рддрд╛рдд. - HTTP APIs auto-deploy рдХрд░реВ рд╢рдХрддрд╛рдд:
autoDeployрдЪрд╛рд▓реВ рдЕрд╕реЗрд▓ рддрд░ рдкреНрд░рддреНрдпреЗрдХ рдмрджрд▓ рддреНрдпрд╛ stage рд╡рд░ рд▓рдЧреЗрдЪ live рд╣реЛрддреЛ.devрд╕рд╛рдареА рд╕реЛрдпреАрдЪреЗ;prodрд╕рд╛рдареА рджреЛрдирджрд╛ рд╡рд┐рдЪрд╛рд░ рдХрд░рд╛. - Stage variables тАФ stage рд╡рд░рдЪреНрдпрд╛ key/value рдЬреЛрдбреНрдпрд╛, integrations рдордзреНрдпреЗ
${stageVariables.table}рдореНрд╣рдгреВрди рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд рдЖрдгрд┐ Lambda proxy events рдирд╛stageVariablesрдореНрд╣рдгреВрди рджрд┐рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд. рдиреЗрд╣рдореАрдЪрд╛ рд╡рд╛рдкрд░:devрд▓рд╛devLambda alias рдХрд┐рдВрд╡рд╛ table рдХрдбреЗ рд╡рд│рд╡рдгреЗ. - Canary release (REST APIs) тАФ stage рддреНрдпрд╛рдЪреНрдпрд╛ traffic рдЪрд╛ рдХрд╛рд╣реА рдЯрдХреНрдХреЗ рднрд╛рдЧ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде 10%) рдирд╡реНрдпрд╛ deployment рдХрдбреЗ, рддреНрдпрд╛рдЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ stage variables рд╕рд╣, рдкрд╛рдард╡реВ рд╢рдХрддреЗ; рдордЧ рддреБрдореНрд╣реА рддреЗ promote рдХрд░рддрд╛ рдХрд┐рдВрд╡рд╛ рдХрд╛рдвреВрди рдЯрд╛рдХрддрд╛.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг "рдореА console рдордзреНрдпреЗ рдмрджрд▓рд▓реЗ" рдореНрд╣рдгрдЬреЗ release рдирд╡реНрд╣реЗ. Snapshots рдореБрд│реЗ рдХрд╛рдп live рдЖрд╣реЗ рдпрд╛рдЪреА рдиреЛрдВрдж
рдорд┐рд│рддреЗ, рдкрд░рдд рдЬрд╛рдгреНрдпрд╛рдЪрд╛ рдорд╛рд░реНрдЧ рдорд┐рд│рддреЛ (stage рдЖрдзреАрдЪреНрдпрд╛ deployment рдХрдбреЗ рд╡рд│рд╡рд╛), рдЖрдгрд┐ рдЦрд░реЗ users
(prod) рдкрд╛рд╣рдгреНрдпрд╛рдЖрдзреА рдмрджрд▓ рдХрд░реВрди рдкрд╛рд╣рдгреНрдпрд╛рд╕рд╛рдареА рд╕реБрд░рдХреНрд╖рд┐рдд рдЬрд╛рдЧрд╛ (dev) рдорд┐рд│рддреЗ. Stage variables рдореБрд│реЗ
рдкреНрд░рддреНрдпреЗрдХ environment рд╕рд╛рдареА рдПрдХрдЪ API definition рд░рд╛рд╣рддреЗ, рд╣рд│реВрд╣рд│реВ рд╡реЗрдЧрд│реНрдпрд╛ рд╣реЛрдд рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдкреНрд░рддреА рдирд╛рд╣реАрдд.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
apigw/demo.py рдордзрд▓реЗ office() рд╣реЗ Gateway рд▓рд╛ рджреЛрди stages рджреЗрддреЗ:
dev (vars={"table": "marks-dev"}, rate 5, burst 5, cache_ttl=0) рдЖрдгрд┐ prod
(marks-prod, 10,000 / 5,000, cache_ttl=300). Gateway._handle() рдЕрд╕реНрддрд┐рддреНрд╡рд╛рдд рдирд╕рд▓реЗрд▓реНрдпрд╛
stage рд▓рд╛ 403 рдЙрддреНрддрд░ рджреЗрддреЗ, рдкреНрд░рддреНрдпреЗрдХ stage рд▓рд╛ рд╕реНрд╡рддрдГрдЪрд╛ token bucket рджреЗрддреЗ, рдЖрдгрд┐ stage рдЪреЗ vars
integration рдЪреНрдпрд╛ event["stageVariables"] рдордзреНрдпреЗ рдареЗрд╡рддреЗ; add_mark() table рдЪреЗ рдирд╛рд╡ рддрд┐рдереВрдирдЪ
рд╡рд╛рдЪрддреЗ. Lab рдордзреНрдпреЗ рд╡реЗрдЧрд│рд╛ deployment object рдирд╛рд╣реА: рдмрджрд▓рд▓реЗрд▓реНрдпрд╛ settings рд╕рд╣ рдирд╡реЗ office(...)
рдмрдирд╡рдгреЗ рд╣реЗрдЪ "рдирд╡реЗ deployment" рдЪреА рднреВрдорд┐рдХрд╛ рдмрдЬрд╛рд╡рддреЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 apigw/demo.py stages
python3 - <<'EOF'
import sys; sys.path.insert(0, "apigw"); from demo import office
gw, c = office()
for stage in ("dev", "prod"):
print(stage, gw.stages[stage]["vars"], "rate", gw.stages[stage]["rate"], "burst", gw.stages[stage]["burst"], "cache_ttl", gw.stages[stage]["cache_ttl"])
print(" ", [gw.handle("GET", "/students/7", stage=stage)[1].get("X-Cache") for _ in range(2)])
print("beta:", gw.handle("GET", "/students/7", stage="beta")[0::2])
gw2, _ = office(cache_ttl=0, vars={"table": "marks-prod-v2"})
print("prod after a new 'deployment':", gw2.stages["prod"]["vars"], [gw2.handle("GET", "/students/7")[1].get("X-Cache") for _ in range(2)])
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
stages рд╣реЗ
stage dev тЖТ 201 {'saved': {'student': '7', 'subject': 'maths', 'mark': 91}, 'table': 'marks-dev'},
'table': 'marks-prod' рд╕рд╣ prod рд╕рд╛рдареА рддрд╕реЗрдЪ, рдЖрдгрд┐ stage test тЖТ 403 {'message': 'Forbidden'} print рдХрд░рддреЗ.
рддреБрдордЪрд╛ snippet [None, None] рд╕рд╣ dev {'table': 'marks-dev'} rate 5 burst 5 cache_ttl 0
(dev рд╡рд░ cache рдирд╛рд╣реА тАФ X-Cache header рдЕрдЬрд┐рдмрд╛рдд рдирд╛рд╣реА), ['Miss', 'Hit'] рд╕рд╣
prod {'table': 'marks-prod'} rate 10000 burst 5000 cache_ttl 300,
рдордЧ beta: (403, {'message': 'Forbidden'}), рдЖрдгрд┐
prod after a new 'deployment': {'table': 'marks-prod-v2'} [None, None] print рдХрд░рддреЛ.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдПрдХ API, рдЕрдиреЗрдХ stages: рдкреНрд░рддреНрдпреЗрдХ stage рд╡рд░ рддреНрдпрд╛рдЪ route рдиреЗ рд╡реЗрдЧрд│реНрдпрд╛ table рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗ, рддреНрдпрд╛рд▓рд╛ рд╡реЗрдЧрд│реНрдпрд╛ limits рдЖрдгрд┐ рд╡реЗрдЧрд│рд╛ cache рд╣реЛрддрд╛, рдЖрдгрд┐ рдХрдзреАрдЪ deploy рди рдЭрд╛рд▓реЗрд▓реА stage рдЕрд╕реНрддрд┐рддреНрд╡рд╛рддрдЪ рдирд╕рддреЗ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- REST API рдмрджрд▓рдгреЗ рдЖрдгрд┐ deploy рдХрд░рд╛рдпрд▓рд╛ рд╡рд┐рд╕рд░рдгреЗ тАФ "рдорд╛рдЭрд╛ рдмрджрд▓ рдХрд╛рд╣реАрдЪ рдХрд░рдд рдирд╛рд╣реА"
- HTTP API рдЪреНрдпрд╛
prodstage рд╡рд░autoDeployтАФ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдпреЛрдЧ live рд╣реЛрддреЛ - stage variables рдордзреНрдпреЗ secrets тАФ рддреЗ рд╕рд╛рдзреЗ configuration рдЖрд╣реЗрдд, stage рд╡рд╛рдЪреВ рд╢рдХрдгрд╛рд▒реНрдпрд╛ рдХреЛрдгрд╛рд▓рд╛рд╣реА рджрд┐рд╕рддрд╛рдд; Secrets Manager рд╡рд╛рдкрд░рд╛
- рд╕рдЧрд│реНрдпрд╛рд╕рд╛рдареА рдПрдХрдЪ stage, рдореНрд╣рдгрдЬреЗ testing рдЦрд▒реНрдпрд╛ users рд╡рд░рдЪ рд╣реЛрддреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
On a real account тАФ REST API prod рд╡рд░ deploy рдХрд░рд╛, рдордЧ рдкреБрдврдЪреЗ deployment 10% traffic рд╡рд░
рдХрд░реВрди рдкрд╛рд╣рд╛, рдордЧ рддреЗ promote рдХрд░рд╛:
aws apigateway create-deployment --rest-api-id abc123 --stage-name prod \
--description "marks v1"
aws apigateway update-stage --rest-api-id abc123 --stage-name prod \
--patch-operations op=replace,path=/variables/table,value=marks-prod
aws apigateway create-deployment --rest-api-id abc123 --stage-name prod \
--canary-settings percentTraffic=10.0 --description "marks v2 canary"
# promote: the canary's deployment becomes the stage's deployment, canary back to 0%
aws apigateway update-stage --rest-api-id abc123 --stage-name prod --patch-operations \
'[{"op":"replace","path":"/canarySettings/percentTraffic","value":"0.0"},
{"op":"copy","from":"/canarySettings/deploymentId","path":"/deploymentId"}]'
Terraform тАФ API definition рдмрджрд▓рд▓реА рдХреА рдкреНрд░рддреНрдпреЗрдХ рд╡реЗрд│реА рдирд╡реЗ deployment:
resource "aws_api_gateway_deployment" "school" {
rest_api_id = aws_api_gateway_rest_api.school.id
triggers = { redeploy = sha1(jsonencode(aws_api_gateway_rest_api.school.body)) }
lifecycle { create_before_destroy = true }
}
resource "aws_api_gateway_stage" "prod" {
rest_api_id = aws_api_gateway_rest_api.school.id
deployment_id = aws_api_gateway_deployment.school.id
stage_name = "prod"
variables = { table = "marks-prod" }
}
ЁЯПн Production рдордзреНрдпреЗ рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: releases pipeline рдордзреВрди рдЬрд╛рддрд╛рдд тАФ
devрд╡рд░ deploy, test,prodрд╡рд░ deploy (рдмрджрд▓ рдзреЛрдХрд╛рджрд╛рдпрдХ рдЕрд╕реЗрд▓ рддрд░ canary рд╕рд╣) тАФ рдЖрдгрд┐ рдЖрдзреАрдЪрд╛ deployment id рд▓рд┐рд╣реВрди рдареЗрд╡рд▓реЗрд▓рд╛ рдЕрд╕рддреЛ, рдореНрд╣рдгрдЬреЗ rollback рдлрдХреНрдд рдПрдХрд╛ command рдЪреЗ рдХрд╛рдо рдард░рддреЗ.
тПня╕П рдкреБрдвреЗ
рдХреЛрдгреАрд╣реА рджрд╛рд░ рдареЛрдард╛рд╡реВ рд╢рдХрддреЛ. рдЖрддрд╛ badge рдЪреА рддрдкрд╛рд╕рдгреА: рдЖрдд рдХреЛрдг рдпреЗрдК рд╢рдХрддреЛ тАФ IAM, JWT рдЖрдгрд┐ Lambda authorizers.
git checkout lesson-06-auth