Kam fillova të punoj cloudformation 4 vjet më parë. Që atëherë kam prishur shumë infrastrukturë, përfshirë ato që ishin tashmë në prodhim. Por çdo herë që prisja diçka, mësova diçka të re. Falë këtij përvoje, do të ndaj disa nga mësimet më të rëndësishme që kam mësuar.

Mësimi 1: kontrolloni ndryshimet para se t'i publikoni ato
E kam kuptuar këtë mësim shpejt sapo fillova të punoj me cloudformation. Nuk e mbaj mend se çfarë kam prishur atëherë, por e mbaj mend me siguri që kam përdorur komandën aws cloudformation update. Kjo komandë thjesht e hedh modelin pa asnjë kontroll që ndryshimet do të publikohen. Nuk mendoj se nevojiten shpjegime përse është e rëndësishme të kontrolloni të gjitha ndryshimet para publikimit të tyre.
Pas asaj dështimi, menjëherë e kam ndërruar pipeline e publikimit, duke e zëvendësuar komandën update me komandën create-change-set
# OPERATION is either "UPDATE" or "CREATE"
changeset_id=$(aws cloudformation create-change-set
--change-set-name "$CHANGE_SET_NAME"
--stack-name "$STACK_NAME"
--template-body "$TPL_PATH"
--change-set-type "$OPERATION"
--parameters "$PARAMETERS"
--output text
--query Id)
aws cloudformation wait
change-set-create-complete --change-set-name "$changeset_id" Kur është krijuar një grup ndryshimesh, ai nuk ndikon në flokun ekzistues. Ndryshe nga komandën update, qasja me grupin e ndryshimeve nuk shkakton publikimin faktik. Në vend të kësaj, krijon një listë ndryshimesh që mund t'i kontrolloni para publikimit. Mund të shihni ndryshimet në ndërfaqen e konsolës aws. Por nëse preferoni të automatizoni gjithçka që është e mundur, kontrolloni ato në CLI:
# this command is presented only for demonstrational purposes.
# the real command should take pagination into account
aws cloudformation describe-change-set
--change-set-name "$changeset_id"
--query 'Changes[*].ResourceChange.{Action:Action,Resource:ResourceType,ResourceId:LogicalResourceId,ReplacementNeeded:Replacement}'
--output tableKjo komandë duhet të japë një rezultat të ngjashëm me këtë:
--------------------------------------------------------------------
| DescribeChangeSet |
+---------+--------------------+----------------------+------------+
| Veprimi | Nevojitet Zëvendësim | Burimi | IdBurimi |
+---------+--------------------+----------------------+------------+
| Modifiko | E vërtetë | AWS::ECS::Cluster | MyCluster |
| Zëvendëso| E vërtetë | AWS::RDS::DBInstance| MyDB |
| Shto | Asnjë | AWS::SNS::Topic | MyTopic |
+---------+--------------------+----------------------+------------+Kujdesuni veçanërisht për ndryshimet ku Veprimi është Zëvendëso, Delete ose ku Nevojitet Zëvendësim — E vërtetë. Këto janë ndryshimet më të rrezikshme dhe zakonisht çojnë në humbje informacioni.
Kur ndryshimet të jenë kontrolluar, ato mund të publikohen
aws cloudformation execute-change-set --change-set-name "$changeset_id"
operation_lowercase=$(echo "$OPERATION" | tr '[:upper:]' '[:lower:]')
aws cloudformation wait "stack-${operation_lowercase}-complete"
--stack-name "$STACK_NAME"Mësimi 2: përdorni politikën e stack për të parandaluar zëvendësimin ose fshirjen e burimeve me ruajtjen e gjendjes
Ndonjëherë, thjesht shikimi i ndryshimeve nuk mjafton. Të gjithë jemi njerëz dhe të gjithë bëjmë gabime. Shumë shpejt pas fillimit të përdorimit të grupeve të ndryshimeve, shoku im i ekipit pa të vetëdijshëm realizoi një deploy, që rezultoi në përditësimin e bazës së të dhënave. Asgjë e keqe nuk ndodhi, sepse ishte një ambient testi.
Megjithatë, edhe pse skriptet tona shfaqnin një listë ndryshimesh dhe kërkonin konfirmim, ndryshimi 'Replace' u la pa u vënë re, sepse lista e ndryshimeve ishte kaq e gjatë sa nuk shkonte në ekran. Dhe sepse kjo ishte një përditësim rutinë në ambientin e testimit, ndryshimeve nuk iu kushtua shumë vëmendje.
Ka burime që nuk do të donit kurrë t'i zevëndësoni ose t'i fshini. Këto janë shërbimet 'stateful', siç janë instanca e bazës së të dhënave RDS ose klasteri Elasticsearch etj. Do të ishte mirë nëse AWS automatikisht do të refuzonte deploy-n nëse operacioni i kryer kërkonte fshirjen e tillë të burimit. Fatmirësisht, CloudFormation ka një mënyrë të ndërtuar për ta bërë këtë. Kjo quhet politika e stack-ut, dhe mund të mësoni më shumë për të tek :
STACK_NAME=$1
RESOURCE_ID=$2
POLICY_JSON=$(cat <<EOF
{
"Statement" : [{
"Effect" : "Deny",
"Action" : [
"Update:Replace",
"Update:Delete"
],
"Principal": "*",
"Resource" : "LogicalResourceId/$RESOURCE_ID"
}]
}
EOF
)
aws cloudformation set-stack-policy --stack-name "$STACK_NAME"
--stack-policy-body "$POLICY_JSON"Mësimi 3: përdorni UsePreviousValue kur përditësoni stack-un me parametra sekretë.
Kur krijoni një entitet RDS MySQL, AWS kërkon nga ju të jepni MasterUsername dhe MasterUserPassword. Përsa i përket ruajtjes së sekretëve në kodin burimor, dhe unë doja të automatizoja gjithçka, implementova një "mekanizëm inteligjent", ku para deployment-it, akreditimet do të merren nga S3, dhe nëse akreditimet nuk do të gjenden, do të gjeneroheshin të reja dhe do të ruheshin në S3.
Pastaj këto akreditime do të kalohen si parametra në komandën cloudformation create-change-set. Gjatë eksperimentimit me skriptin ndodhi që lidhja me S3 u humb, dhe "mekanizmi im inteligjent" e shqyrtoi atë si një sinjal për të gjeneruar akreditime të reja.
Nëse do të filloja ta përdorja këtë skript në një mjedis pune dhe problemi me lidhjen do të ndodhte përsëri, ai do të përditësonte grumbullin me të dhëna të reja. Në këtë rast të veçantë, nuk do të ndodhte asgjë e keqe. Megjithatë, unë kam hequr dorë nga kjo qasje dhe kam filluar të përdor një tjetër, duke ofruar të dhënat vetëm një herë — gjatë krijimit të grumbullit. Më vonë, kur grumbulli të kërkonte përditësim, unë do të përdorja UsePreviousValue=true:
aws cloudformation create-change-set
--change-set-name "$CHANGE_SET_NAME"
--stack-name "$STACK_NAME"
--template-body "$TPL_PATH"
--change-set-type "UPDATE"
--parameters "ParameterKey=MasterUserPassword,UsePreviousValue=true"Shkolla 4: përdorni konfigurimin e rikthimit
Një komandë tjetër me të cilën kam punuar përdorte funksionin cloudformation, i quajtur rollback configuration. Nuk isha takuar me të më parë dhe shpejt kuptova se kjo do ta bënte shpërndarjen e grumbujve të mi edhe më të lehtë. Tani e përdor çdo herë kur shpërndaj kodin tim në lambda ose ECS përmes cloudformation.
Si funksionon: ju specifikoni CloudWatch alarm arn në parametrin —rollback-configuration, kur krijoni një grup ndryshimesh. Më vonë, kur të ekzekutoni grupin e ndryshimeve, aws ndjek alarmi për të paktën një minutë. Ai e rikthen shpërndarjen në të kaluarën nëse gjatë kësaj kohe alarmi ndryshon gjendjen në ALARM.
Më poshtë është një shembull i një pjesë të shabllonit cloudformation, ku krijoj cloudwatch alarm, që ndjek një metrikë të përdoruesit në formën e numrit të gabimeve në regjistrat e reja të cloud (metrika krijohet përmes MetricFilter):
Resources:
# kjo metrikë ndjek numrin e gabimeve në regjistrat cloudwatch. Në këtë
# rast të veçantë supozohet se regjistrat janë në formatin json dhe regjistrat e gabimeve janë
# të identifikuar nga niveli "gabim". Shihni FilterPattern
ErrorMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: !Ref LogGroup
FilterPattern: !Sub '{$.level = "error"}'
MetricTransformations:
- MetricNamespace: !Sub "${AWS::StackName}-log-errors"
MetricName: Errors
MetricValue: 1
DefaultValue: 0
ErrorAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub "${AWS::StackName}-errors"
Namespace: !Sub "${AWS::StackName}-log-errors"
MetricName: Errors
Statistic: Maximum
ComparisonOperator: GreaterThanThreshold
Period: 1 # 1 minutë
EvaluationPeriods: 1
Threshold: 0
TreatMissingData: notBreaching
ActionsEnabled: yesTani alarm mund të përdoret si rollback trigjer gjatë ekzekutimit të grupit të ndryshimeve:
ALARM_ARN=$1
ROLLBACK_TRIGGER=$(cat <<EOF
{
"RollbackTriggers": [
{
"Arn": "$ALARM_ARN",
"Type": "AWS::CloudWatch::Alarm"
}
],
"MonitoringTimeInMinutes": 1
}
EOF
)
aws cloudformation create-change-set
--change-set-name "$CHANGE_SET_NAME"
--stack-name "$STACK_NAME"
--template-body "$TPL_PATH"
--change-set-type "UPDATE"
--rollback-configuration "$ROLLBACK_TRIGGER"Mësimi 5: sigurohuni që po zhvilloni versionin më të fundit të modelit
Është e lehtë të zhvillosh një version jo të fundit të modelit cloudformation, por kjo do të shkaktojë dëme të mëdha. Një herë ndodhi kështu: një zhvillues nuk dërgoi ndryshimet e fundit nga Git dhe pa e kuptuar zhvilloi versionin e mëparshëm të stack-ut. Kjo çoi në ndalesën e aplikacionit që përdorte këtë stack.
Diçka e thjeshtë, siç është shtimi i një kontrolli nëse dega është e përditësuar, para se të kryhet zhvillimi, do të ishte e mirë (nëse supozojmë se git është mjeti juaj i kontrollit të versioneve):
git fetch
HEADHASH=$(git rev-parse HEAD)
UPSTREAMHASH=$(git rev-parse master@{upstream})
if [[ "$HEADHASH" != "$UPSTREAMHASH" ]] ; then
echo "Dega nuk është e përditësuar me origjinën. Duke e ndaluar."
exit 1
fiMësimi 6: mos shpikni ndonjë biçikletë
Mund të duket se zhvillimi me cloudformation është i lehtë. Ju nevojiten thjesht disa skripte bash që ekzekutojnë komanda aws cli.
4 vjet më parë fillova me skripte të thjeshta që thërrisnin komandën aws cloudformation create-stack. Shpejt, skripti nuk ishte më i thjeshtë. Çdo mësim të nxjerrë e bënte skriptin gjithnjë e më të komplikuar. Kishte jo vetëm vështirësi, por edhe shumë defekte.
Tani punoj në një departament të vogël IT. Eksperienca tregon se çdo ekip ka mënyrën e vet të zhvillimit të stack-ut cloudformation. Dhe kjo është e keqe. Do të ishte më mirë nëse të gjithë do të përdornin një qasje të njëjtë. Fatmirësisht, ekzistojnë shumë mjete që ndihmojnë në zhvillimin dhe konfigurimin e stekëve cloudformation.
Këto mësime do t'ju ndihmojnë të shmangni gabimet.
Burimi: habr.com
