Vaig aprendre aquestes 6 lliçons de treballar amb la formació de núvols durant la resta de la meva vida.

Vaig començar a treballar amb formació de núvols fa 4 anys. Des de llavors he trencat moltes infraestructures, fins i tot les que ja estaven en producció. Però cada vegada que feia malbé alguna cosa, aprenia alguna cosa nova. A través d'aquesta experiència, compartiré algunes de les lliçons més importants que vaig aprendre.

Vaig aprendre aquestes 6 lliçons de treballar amb la formació de núvols durant la resta de la meva vida.

Lliçó 1: prova els canvis abans de desplegar-los

Vaig aprendre aquesta lliçó poc després de començar a treballar formació de núvols. No recordo què vaig trencar exactament aleshores, però definitivament recordo que vaig utilitzar l'ordre actualització aws cloudformation. Aquesta ordre simplement desplega la plantilla sense cap validació dels canvis que es desplegaran. No crec que calgui cap explicació sobre per què hauríeu de provar tots els canvis abans de desplegar-los.

Després d'aquest fracàs, vaig canviar immediatament desplegament pipeline, substituint l'ordre d'actualització per l'ordre crear-canvi-conjunt

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

Un cop creat un conjunt de canvis, no té cap efecte sobre la pila existent. A diferència de l'ordre d'actualització, l'enfocament del conjunt de canvis no activa el desplegament real. En lloc d'això, crea una llista de canvis que podeu revisar abans del desplegament. Podeu veure els canvis a la interfície de la consola aws. Però si preferiu automatitzar tot el que podeu, comproveu-los a la 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

Aquesta ordre hauria de produir una sortida similar a la següent:

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

Presteu especial atenció als canvis on hi ha Acció Reemplaçar, Esborrar o on Necessitat de substitució: cert. Aquests són els canvis més perillosos i solen conduir a la pèrdua d'informació.

Un cop revisats els canvis, es poden implementar

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"

Lliçó 2: Utilitzeu la política de pila per evitar que els recursos amb estat es substitueixin o s'eliminin

De vegades, simplement veure els canvis no és suficient. Tots som humans i tots ens equivoquem. Poc després de començar a utilitzar conjunts de canvis, el meu company d'equip, sense saber-ho, va realitzar un desplegament que va donar lloc a una actualització de la base de dades. No va passar res dolent perquè era un entorn de proves.

Tot i que els nostres scripts mostraven una llista de canvis i demanaven confirmació, el canvi de substitució es va ometre perquè la llista de canvis era tan gran que no cabia a la pantalla. I com que es tractava d'una actualització normal en un entorn de proves, no es va prestar molta atenció als canvis.

Hi ha recursos que mai no voleu substituir ni eliminar. Es tracta de serveis amb estat complet, com ara una instància de base de dades RDS o un clúster d'Elasticsearch, etc. Seria bo que aws rebutgés automàticament el desplegament si l'operació que s'està realitzant requereix la supressió d'aquest recurs. Afortunadament, Cloudformation té una manera integrada de fer-ho. Això s'anomena política de pila i podeu llegir-ne més informació a documentació:

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"

Lliçó 3: Utilitzeu UsePreviousValue quan actualitzeu una pila amb paràmetres secrets

Quan creeu una entitat RDS mysql, AWS requereix que proporcioneu un MasterUsername i una MasterUserPassword. Com que és millor no guardar secrets en el codi font i volia automatitzar-ho absolutament tot, vaig implementar un "mecanisme intel·ligent" on abans del desplegament s'obtindran les credencials de s3, i si no es troben les credencials es generen noves credencials i emmagatzemat a s3.

A continuació, aquestes credencials es passaran com a paràmetres a l'ordre create-change-set de cloudformation. Mentre experimentava amb l'script, va passar que es va perdre la connexió amb s3 i el meu "mecanisme intel·ligent" ho va tractar com un senyal per generar noves credencials.

Si comencés a utilitzar aquest script en producció i el problema de connexió tornés a passar, actualitzaria la pila amb noves credencials. En aquest cas concret, no passarà res dolent. Tanmateix, vaig abandonar aquest enfocament i vaig començar a utilitzar-ne un altre, proporcionant credencials només una vegada, en crear la pila. I més tard, quan la pila necessiti actualitzar, en lloc d'especificar el valor secret del paràmetre, simplement utilitzaria 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"

Lliçó 4: Utilitzeu la configuració de retrocés

Un altre equip amb qui vaig treballar va utilitzar la funció formació de núvols, va trucar configuració de retrocés. No l'havia trobat abans i ràpidament em vaig adonar que faria que el desplegament de les meves piles fos encara més fresc. Ara l'utilitzo cada vegada que implemento el meu codi a lambda o ECS mitjançant Cloudformation.

Com funciona: ho especifiqueu Alarma de CloudWatch en el paràmetre --rollback-configuracióquan creeu un conjunt de canvis. Més tard, quan executeu un conjunt de canvis, aws supervisa l'alarma durant almenys un minut. Es revertirà el desplegament si l'alarma canvia d'estat a ALARMA durant aquest temps.

A continuació es mostra un exemple d'un extracte de plantilla formació de núvolsen el qual jo creo alarma cloudwatch, que fa un seguiment d'una mètrica d'usuari del núvol com a nombre d'errors als registres del núvol (la mètrica es genera mitjançant 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

Ara alarma es pot utilitzar com a retrocés activador quan s'executa la caixa d'eines:

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"

Lliçó 5: assegureu-vos de desplegar la darrera versió de la plantilla

És fàcil desplegar una versió inferior a la darrera de la plantilla de formació de núvols, però fer-ho causarà molts danys. Això ens va passar una vegada: un desenvolupador no va impulsar els darrers canvis de Git i, sense saber-ho, va desplegar una versió anterior de la pila. Això va provocar temps d'inactivitat per a l'aplicació que utilitzava aquesta pila.

Una cosa tan senzill com afegir una comprovació per veure si la branca està actualitzada abans de comprometre's amb ella estaria bé (suposant que git és la vostra eina de control de versions):

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

Lliçó 6: No reinventis la roda

Pot semblar que es desplega amb formació de núvols - és fàcil. Només necessiteu un munt d'scripts bash que executin ordres aws cli.

Fa 4 anys vaig començar amb scripts senzills anomenats aws cloudformation create-stack command. Aviat el guió ja no era senzill. Cada lliçó apresa feia que el guió fos cada cop més complex. No només va ser difícil, sinó que també va ser ple d'errors.

Actualment treballo en un petit departament informàtic. L'experiència ha demostrat que cada equip té la seva pròpia manera de desplegar les piles de cloudformation. I això és dolent. Seria millor que tothom prengués el mateix enfocament. Afortunadament, hi ha moltes eines disponibles per ajudar-vos a desplegar i configurar les piles de cloudformation.

Aquestes lliçons us ajudaran a evitar errors.

Font: www.habr.com

Afegeix comentari