Am învățat aceste 6 lecții despre lucrul cu cloudformation pentru tot restul vieții.

Am început să lucrez cu cloudformare acum 4 ani. De atunci am spart o mulțime de infrastructuri, chiar și cele care erau deja în producție. Dar de fiecare dată când am greșit ceva, am învățat ceva nou. Prin această experiență, voi împărtăși unele dintre cele mai importante lecții pe care le-am învățat.

Am învățat aceste 6 lecții despre lucrul cu cloudformation pentru tot restul vieții.

Lecția 1: Testați modificările înainte de a le implementa

Am învățat această lecție la scurt timp după ce am început să lucrez cu cloudformare. Nu-mi amintesc exact ce am rupt atunci, dar îmi amintesc cu siguranță că am folosit comanda actualizare aws cloudformation. Această comandă pur și simplu lansează șablonul fără nicio validare a modificărilor care vor fi implementate. Nu cred că este necesară nicio explicație pentru ce ar trebui să testați toate modificările înainte de a le implementa.

După acest eșec, m-am schimbat imediat conducte de implementare, înlocuind comanda de actualizare cu comanda crea-schimba-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"

Odată creat un set de modificări, acesta nu are niciun efect asupra stivei existente. Spre deosebire de comanda de actualizare, abordarea setului de modificări nu declanșează implementarea efectivă. În schimb, creează o listă de modificări pe care le puteți revizui înainte de implementare. Puteți vedea modificările în interfața consolei aws. Dar dacă preferați să automatizați tot ce puteți, atunci verificați-le î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 table

Această comandă ar trebui să producă rezultate similare cu următoarea:

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

Acordați o atenție deosebită schimbărilor în care se află Acțiune Înlocui, Șterge sau unde Înlocuire necesară - Adevărat. Acestea sunt cele mai periculoase modificări și de obicei duc la pierderea de informații.

Odată ce modificările au fost revizuite, acestea pot fi implementate

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"

Lecția 2: Utilizați politica de stivă pentru a preveni înlocuirea sau eliminarea resurselor cu stare

Uneori, simpla vizualizare a modificărilor nu este suficientă. Cu toții suntem oameni și toți facem greșeli. La scurt timp după ce am început să folosim seturi de modificări, coechipierul meu a efectuat, fără să știe, o implementare care a dus la o actualizare a bazei de date. Nu s-a întâmplat nimic rău pentru că era un mediu de testare.

Chiar dacă scripturile noastre au afișat o listă de modificări și au cerut confirmare, modificarea Înlocuire a fost omisă deoarece lista modificărilor era atât de mare încât nu se potrivea pe ecran. Și deoarece aceasta a fost o actualizare normală într-un mediu de testare, nu s-a acordat prea multă atenție modificărilor.

Există resurse pe care nu doriți să le înlocuiți sau să le eliminați niciodată. Acestea sunt servicii complete, cum ar fi o instanță de bază de date RDS sau un cluster de căutare elastică etc. Ar fi bine ca aws să refuze automat implementarea dacă operațiunea efectuată ar necesita ștergerea unei astfel de resurse. Din fericire, cloudformation are o modalitate încorporată de a face acest lucru. Aceasta se numește politica de stivă și puteți citi mai multe despre aceasta în documentație:

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"

Lecția 3: Utilizați UsePreviousValue atunci când actualizați o stivă cu parametri secreti

Când creați o entitate RDS mysql, AWS vă solicită să furnizați un MasterUsername și MasterUserPassword. Deoarece este mai bine să nu păstrez secrete în codul sursă și am vrut să automatizez absolut totul, am implementat un „mecanism inteligent” în care înainte de implementare se vor obține acreditările de la s3, iar dacă nu se găsesc acreditările, se generează noi acreditări și stocat în s3 .

Aceste acreditări vor fi apoi transmise ca parametri la comanda cloudformation create-change-set. În timp ce experimentam cu scriptul, s-a întâmplat că conexiunea la s3 s-a pierdut, iar „mecanismul meu inteligent” a tratat-o ​​ca pe un semnal pentru a genera noi acreditări.

Dacă aș începe să folosesc acest script în producție și problema de conectare s-a întâmplat din nou, ar actualiza stiva cu noi acreditări. În acest caz, nu se va întâmpla nimic rău. Cu toate acestea, am abandonat această abordare și am început să folosesc alta, oferind acreditări o singură dată - la crearea stivei. Și mai târziu, când stiva are nevoie de actualizare, în loc să specific valoarea secretă a parametrului, aș folosi pur și simplu 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"

Lecția 4: Utilizați configurația rollback

O altă echipă cu care am lucrat a folosit funcția cloudformare, numit configurația de rollback. Nu l-am întâlnit până acum și mi-am dat seama rapid că va face implementarea stivelor mele și mai mișto. Acum îl folosesc de fiecare dată când îmi implementez codul în lambda sau ECS folosind cloudformation.

Cum funcționează: specificați Alarma CloudWatch arn în parametru --rollback-configurationcând creați un set de modificări. Mai târziu, când executați un set de modificări, aws monitorizează alarma timp de cel puțin un minut. Derulează înapoi dacă alarma își schimbă starea în ALARM în acest timp.

Mai jos este un exemplu de extras de șablon cloudformareîn care creez alarma cloudwatch, care urmărește o valoare a utilizatorului cloud ca număr de erori din jurnalele cloud (valoarea este generată prin 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

Acum alarmă poate fi folosit ca rollback declanșează la executarea casetei de instrumente:

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"

Lecția 5: Asigurați-vă că implementați cea mai recentă versiune a șablonului

Este ușor să implementați o versiune mai mică decât cea mai recentă a șablonului cloudformation, dar acest lucru va provoca multe daune. Acest lucru ni s-a întâmplat o dată: un dezvoltator nu a impus cele mai recente modificări de la Git și a implementat, fără să știe, o versiune anterioară a stivei. Acest lucru a dus la un timp de nefuncționare pentru aplicația care a folosit această stivă.

Ceva la fel de simplu precum adăugarea unei verificări pentru a vedea dacă ramura este actualizată înainte de a se angaja în ea ar fi bine (presupunând că git este instrumentul tău de control al versiunii):

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

Lecția 6: Nu reinventați roata

Poate părea că se desfășoară cu cloudformare - este ușor. Ai nevoie doar de o grămadă de scripturi bash care execută comenzi aws cli.

Acum 4 ani am început cu scripturi simple numite comanda aws cloudformation create-stack. Curând, scenariul nu a mai fost simplu. Fiecare lectie invatata a facut scenariul din ce in ce mai complex. A fost nu numai dificil, ci și plin de bug-uri.

În prezent lucrez într-un mic departament IT. Experiența a arătat că fiecare echipă are propriul mod de a implementa stivele de cloudformation. Și asta e rău. Ar fi mai bine dacă toți ar lua aceeași abordare. Din fericire, există multe instrumente disponibile pentru a vă ajuta să implementați și să configurați stivele de cloudformation.

Aceste lecții vă vor ajuta să evitați greșelile.

Sursa: www.habr.com

Adauga un comentariu