Jeg lærte disse 6 lektioner om at arbejde med cloudformation resten af ​​mit liv.

Jeg begyndte at arbejde med skydannelse for 4 år siden. Siden da har jeg ødelagt en masse infrastrukturer, også dem der allerede var i produktion. Men hver gang jeg rodede noget ud, lærte jeg noget nyt. Gennem denne oplevelse vil jeg dele nogle af de vigtigste lektioner, jeg har lært.

Jeg lærte disse 6 lektioner om at arbejde med cloudformation resten af ​​mit liv.

Lektion 1: Test ændringer, før du implementerer dem

Jeg lærte denne lektie kort efter, jeg begyndte at arbejde med skydannelse. Jeg kan ikke huske, hvad jeg præcist brød dengang, men jeg husker bestemt, at jeg brugte kommandoen aws cloudformation opdatering. Denne kommando ruller simpelthen skabelonen ud uden nogen validering af de ændringer, der vil blive implementeret. Jeg tror ikke, der er behov for nogen forklaring på, hvorfor du bør teste alle ændringer, før du implementerer dem.

Efter denne fiasko ændrede jeg mig straks implementeringsrørledning, og erstatter opdateringskommandoen med kommandoen skabe-ændre-sæt

# 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"

Når først et ændringssæt er oprettet, har det ingen effekt på den eksisterende stak. I modsætning til opdateringskommandoen udløser changeset-tilgangen ikke den faktiske implementering. I stedet opretter den en liste over ændringer, som du kan gennemgå før implementering. Du kan se ændringerne i aws-konsolgrænsefladen. Men hvis du foretrækker at automatisere alt, hvad du kan, så tjek dem i 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 table

Denne kommando skal producere output svarende til følgende:

--------------------------------------------------------------------
|                         DescribeChangeSet                        |
+---------+--------------------+----------------------+------------+
| Action  | ReplacementNeeded  |      Resource        | ResourceId |
+---------+--------------------+----------------------+------------+
|  Modify | True               |  AWS::ECS::Cluster   |  MyCluster |
|  Replace| True               |  AWS::RDS::DBInstance|  MyDB      |
|  Add    | None               |  AWS::SNS::Topic     |  MyTopic   |
+---------+--------------------+----------------------+------------+

Vær særlig opmærksom på ændringer, hvor Action er udskifte, Slette eller hvor Udskiftning nødvendig - sandt. Disse er de farligste ændringer og fører normalt til tab af information.

Når ændringerne er blevet gennemgået, kan de implementeres

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"

Lektion 2: Brug stakpolitik til at forhindre, at stateful ressourcer udskiftes eller fjernes

Nogle gange er det ikke nok at se ændringerne. Vi er alle mennesker, og vi laver alle fejl. Kort efter vi begyndte at bruge ændringssæt, udførte min holdkammerat ubevidst en implementering, som resulterede i en databaseopdatering. Der skete ikke noget dårligt, fordi det var et testmiljø.

Selvom vores scripts viste en liste over ændringer og bad om bekræftelse, blev ændringen Erstat sprunget over, fordi listen over ændringer var så stor, at den ikke passede på skærmen. Og da dette var en normal opdatering i et testmiljø, var der ikke meget opmærksomhed på ændringerne.

Der er ressourcer, som du aldrig ønsker at erstatte eller fjerne. Disse er statefull-tjenester, såsom en RDS-databaseforekomst eller en elasticsearch-klynge osv. Det ville være rart, hvis aws automatisk ville afvise implementering, hvis den operation, der udføres, ville kræve sletning af en sådan ressource. Heldigvis har cloudformation en indbygget måde at gøre dette på. Dette kaldes stack policy, og du kan læse mere om det i dokumentation:

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"

Lektion 3: Brug UsePreviousValue, når du opdaterer en stak med hemmelige parametre

Når du opretter en RDS mysql-entitet, kræver AWS, at du angiver et MasterUsername og MasterUserPassword. Da det er bedre ikke at holde hemmeligheder i kildekoden, og jeg ønskede at automatisere absolut alt, implementerede jeg en "smart-mekanisme", hvor legitimationsoplysningerne inden implementeringen hentes fra s3, og hvis legitimationsoplysningerne ikke findes, genereres nye legitimationsoplysninger og gemt i s3.

Disse legitimationsoplysninger vil derefter blive videregivet som parametre til cloudformation create-change-set-kommandoen. Mens jeg eksperimenterede med scriptet, skete det, at forbindelsen til s3 gik tabt, og min "smarte mekanisme" behandlede det som et signal om at generere nye legitimationsoplysninger.

Hvis jeg begyndte at bruge dette script i produktionen, og forbindelsesproblemet opstod igen, ville det opdatere stakken med nye legitimationsoplysninger. I dette særlige tilfælde vil der ikke ske noget dårligt. Jeg opgav dog denne tilgang og begyndte at bruge en anden, idet jeg kun gav legitimationsoplysninger én gang - da jeg oprettede stakken. Og senere, når stakken skal opdateres, i stedet for at angive den hemmelige værdi af parameteren, ville jeg simpelthen bruge UsePreviousValue=sand:

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"

Lektion 4: Brug rollback-konfiguration

Et andet team, jeg arbejdede med, brugte funktionen skydannelsehedder rollback konfiguration. Jeg var ikke stødt på det før og indså hurtigt, at det ville gøre det endnu køligere at implementere mine stakke. Nu bruger jeg det hver gang jeg implementerer min kode til lambda eller ECS ved hjælp af cloudformation.

Sådan fungerer det: du angiver CloudWatch alarm i parameteren --rollback-konfigurationnår du opretter et ændringssæt. Senere, når du udfører et sæt ændringer, overvåger aws alarmen i mindst et minut. Det ruller implementeringen tilbage, hvis alarmen skifter tilstand til ALARM i løbet af dette tidsrum.

Nedenfor er et eksempel på et skabelonuddrag skydannelsehvori jeg skaber cloudwatch alarm, som sporer en cloud-brugermetrik som antallet af fejl i skylogfilerne (metrikken genereres via MetricFilter):

Resources:
  # this metric tracks number of errors in the cloudwatch logs. In this
  # particular case it's assumed logs are in json format and the error logs are
  # identified by level "error". See 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 minute
      EvaluationPeriods: 1
      Threshold: 0
      TreatMissingData: notBreaching
      ActionsEnabled: yes

Nu alarm kan bruges som rollback trigger ved udførelse af værktøjskassen:

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"

Lektion 5: Sørg for at implementere den seneste version af skabelonen

Det er nemt at implementere en mindre end den nyeste version af cloudformationsskabelonen, men at gøre det vil forårsage en masse skade. Dette skete for os én gang: en udvikler skubbede ikke de seneste ændringer fra Git og implementerede ubevidst en tidligere version af stakken. Dette resulterede i nedetid for den applikation, der brugte denne stak.

Noget så simpelt som at tilføje et tjek for at se, om filialen er opdateret, før du forpligter dig til det, ville være fint (forudsat at git er dit versionskontrolværktøj):

git fetch
HEADHASH=$(git rev-parse HEAD)
UPSTREAMHASH=$(git rev-parse master@{upstream})

if [[ "$HEADHASH" != "$UPSTREAMHASH" ]] ; then
   echo "Branch is not up to date with origin. Aborting"
   exit 1
fi

Lektion 6: Opfind ikke hjulet igen

Det kan virke som at implementere med skydannelse - det er nemt. Du skal bare bruge en masse bash-scripts, der udfører aws cli-kommandoer.

For 4 år siden startede jeg med simple scripts kaldet aws cloudformation create-stack kommandoen. Snart var manuskriptet ikke længere enkelt. Hver lektie lærte gjorde manuskriptet mere og mere komplekst. Det var ikke kun svært, men også fyldt med fejl.

Jeg arbejder i øjeblikket i en lille IT-afdeling. Erfaring har vist, at hvert team har sin egen måde at implementere cloudformation stakke på. Og det er slemt. Det ville være bedre, hvis alle tog den samme tilgang. Heldigvis er der mange tilgængelige værktøjer til at hjælpe dig med at implementere og konfigurere cloudformation stakke.

Disse lektioner hjælper dig med at undgå fejl.

Kilde: www.habr.com

Tilføj en kommentar