Jeg lærte disse 6 leksjonene med å jobbe med skyformasjon resten av livet.

Jeg begynte å jobbe med skyformasjon 4 år siden. Siden den gang har jeg ødelagt mange infrastrukturer, også de som allerede var i produksjon. Men hver gang jeg rotet til noe, lærte jeg noe nytt. Gjennom denne erfaringen vil jeg dele noen av de viktigste leksjonene jeg har lært.

Jeg lærte disse 6 leksjonene med å jobbe med skyformasjon resten av livet.

Leksjon 1: Test endringer før du distribuerer dem

Jeg lærte denne leksjonen kort tid etter at jeg begynte å jobbe med skyformasjon. Jeg husker ikke nøyaktig hva jeg brøt da, men jeg husker definitivt at jeg brukte kommandoen aws cloudformation oppdatering. Denne kommandoen ruller ganske enkelt ut malen uten noen validering av endringene som vil bli distribuert. Jeg tror ikke det er nødvendig med noen forklaring på hvorfor du bør teste alle endringer før du implementerer dem.

Etter denne fiaskoen endret jeg meg umiddelbart distribusjonsrørledning, erstatter oppdateringskommandoen med kommandoen lage-endre-sett

# 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 et endringssett er opprettet, har det ingen effekt på den eksisterende stabelen. I motsetning til oppdateringskommandoen, utløser ikke changeset-tilnærmingen selve distribusjonen. I stedet oppretter den en liste over endringer som du kan gjennomgå før distribusjon. Du kan se endringene i aws-konsollens grensesnitt. Men hvis du foretrekker å automatisere alt du kan, så sjekk 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 kommandoen skal produsere utdata som ligner på 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 spesielt oppmerksom på endringer der Action er Erstatt, Delete eller hvor Nødvendig erstatning - sant. Dette er de farligste endringene og fører vanligvis til tap av informasjon.

Når endringene er gjennomgått, 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"

Leksjon 2: Bruk stackpolicy for å forhindre at stateful ressurser erstattes eller fjernes

Noen ganger er det ikke nok å bare se endringene. Vi er alle mennesker og vi gjør alle feil. Kort tid etter at vi begynte å bruke endringssett, utførte lagkameraten min ubevisst en distribusjon som resulterte i en databaseoppdatering. Ingenting vondt skjedde fordi det var et testmiljø.

Selv om skriptene våre viste en liste over endringer og ba om bekreftelse, ble Erstatt-endringen hoppet over fordi listen over endringer var så stor at den ikke fikk plass på skjermen. Og siden dette var en vanlig oppdatering i et testmiljø, ble det ikke viet mye oppmerksomhet til endringene.

Det er ressurser du aldri vil erstatte eller fjerne. Dette er statefull-tjenester, for eksempel en RDS-databaseforekomst eller en elasticsearch-klynge, osv. Det ville være fint om aws automatisk ville nekte distribusjon hvis operasjonen som utføres ville kreve sletting av en slik ressurs. Heldigvis har skyformasjon en innebygd måte å gjøre dette på. Dette kalles stackpolicy, og du kan lese mer om det i dokumentasjon:

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"

Leksjon 3: Bruk UsePreviousValue når du oppdaterer en stabel med hemmelige parametere

Når du oppretter en RDS mysql-enhet, krever AWS at du oppgir et MasterUsername og MasterUserPassword. Siden det er bedre å ikke holde på hemmeligheter i kildekoden og jeg ønsket å automatisere absolutt alt, implementerte jeg en "smart mekanisme" der før utrulling vil legitimasjonen hentes fra s3, og hvis legitimasjonen ikke blir funnet, genereres ny legitimasjon og lagret i s3.

Disse legitimasjonene vil deretter bli sendt som parametere til cloudformation create-change-set-kommandoen. Mens jeg eksperimenterte med skriptet, skjedde det at forbindelsen til s3 gikk tapt, og min "smarte mekanisme" behandlet det som et signal om å generere ny legitimasjon.

Hvis jeg begynte å bruke dette skriptet i produksjonen og tilkoblingsproblemet skjedde igjen, ville det oppdatere stabelen med ny legitimasjon. I dette spesielle tilfellet vil det ikke skje noe vondt. Jeg forlot imidlertid denne tilnærmingen og begynte å bruke en annen, og ga kun legitimasjon én gang - når jeg opprettet stabelen. Og senere, når stabelen trenger oppdatering, i stedet for å spesifisere den hemmelige verdien til parameteren, ville jeg ganske enkelt bruke 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"

Leksjon 4: Bruk tilbakestillingskonfigurasjon

Et annet team jeg jobbet med brukte funksjonen skyformasjonkalt tilbakestillingskonfigurasjon. Jeg hadde ikke kommet over det før og skjønte raskt at det ville gjøre utplasseringen av stablene mine enda kulere. Nå bruker jeg det hver gang jeg distribuerer koden min til lambda eller ECS ved hjelp av skyformasjon.

Hvordan det fungerer: du spesifiserer CloudWatch alarm i parameter --rollback-konfigurasjonnår du oppretter et endringssett. Senere, når du utfører et sett med endringer, overvåker aws alarmen i minst ett minutt. Den ruller tilbake utrullingen hvis alarmen endrer status til ALARM i løpet av denne tiden.

Nedenfor er et eksempel på et malutdrag skyformasjonder jeg skaper skyklokkealarm, som sporer en skybrukerberegning som antall feil i skyloggene (beregningen 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

alarm kan brukes som rollback trigger når du kjører verktøykasse:

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"

Leksjon 5: Sørg for at du distribuerer den nyeste versjonen av malen

Det er enkelt å distribuere en mindre enn nyeste versjon av skyformasjonsmalen, men å gjøre det vil forårsake mye skade. Dette skjedde med oss ​​en gang: en utvikler presset ikke de siste endringene fra Git og distribuerte ubevisst en tidligere versjon av stabelen. Dette resulterte i nedetid for applikasjonen som brukte denne stabelen.

Noe så enkelt som å legge til en sjekk for å se om grenen er oppdatert før du forplikter deg til den, ville være greit (forutsatt at git er ditt versjonskontrollverktøy):

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

Leksjon 6: Ikke oppfinn hjulet på nytt

Det kan virke som å distribuere med skyformasjon - det er lett. Du trenger bare en haug med bash-skript som utfører aws cli-kommandoer.

For 4 år siden begynte jeg med enkle skript kalt aws cloudformation create-stack-kommandoen. Snart var ikke manuset enkelt lenger. Hver leksjon gjorde manuset mer og mer komplekst. Det var ikke bare vanskelig, men også fullt av feil.

Jeg jobber for tiden i en liten IT-avdeling. Erfaring har vist at hvert lag har sin egen måte å distribuere skyformasjonsstabler på. Og det er ille. Det ville vært bedre om alle hadde samme tilnærming. Heldigvis er det mange verktøy tilgjengelig for å hjelpe deg med å distribuere og konfigurere skyformasjonsstabler.

Disse leksjonene vil hjelpe deg å unngå feil.

Kilde: www.habr.com

Legg til en kommentar