Aprendín estas 6 leccións de traballar coa formación de nubes durante o resto da miña vida.

Comecei a traballar con formación de nubes hai 4 anos. Dende aquela rompín moitas infraestruturas, incluso as que xa estaban en produción. Pero cada vez que estropeaba algo, aprendía algo novo. A través desta experiencia, compartirei algunhas das leccións máis importantes que aprendín.

Aprendín estas 6 leccións de traballar coa formación de nubes durante o resto da miña vida.

Lección 1: proba os cambios antes de implementalos

Aprendín esta lección pouco despois de comezar a traballar formación de nubes. Non lembro exactamente o que rompín entón, pero lembro definitivamente que usei o comando Actualización de aws cloudformation. Este comando simplemente lanza o modelo sen ningunha validación dos cambios que se implementarán. Non creo que sexa necesaria ningunha explicación sobre por que deberías probar todos os cambios antes de implementalos.

Despois deste fracaso, cambiei inmediatamente Dispositivo de implantación, substituíndo o comando de actualización polo comando crear-cambio-conxunto

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

Unha vez que se crea un conxunto de cambios, non ten ningún efecto na pila existente. A diferenza do comando de actualización, o enfoque do conxunto de cambios non desencadea a implantación real. Pola contra, crea unha lista de cambios que pode revisar antes da implantación. Podes ver os cambios na interface da consola aws. Pero se prefires automatizar todo o que poidas, comprobeo na 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

Este comando debería producir unha saída similar á seguinte:

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

Preste especial atención aos cambios onde está Acción Substituír, Borrar ou onde Reemplazo necesario - Verdadero. Estes son os cambios máis perigosos e adoitan levar á perda de información.

Unha vez revisados ​​os cambios, pódense 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"

Lección 2: Usa a política de pila para evitar que os recursos con estado sexan substituídos ou eliminados

Ás veces, simplemente ver os cambios non é suficiente. Todos somos humanos e todos cometemos erros. Pouco despois de comezar a usar conxuntos de cambios, o meu compañeiro de equipo realizou sen sabelo unha implementación que resultou nunha actualización da base de datos. Non pasou nada malo porque era un ambiente de probas.

Aínda que os nosos scripts mostraban unha lista de cambios e solicitaron confirmación, o cambio Substituír foi omitido porque a lista de cambios era tan grande que non cabía na pantalla. E como esta era unha actualización normal nun ambiente de probas, non se prestou moita atención aos cambios.

Hai recursos que nunca quere substituír ou eliminar. Estes son servizos con estado completo, como unha instancia de base de datos RDS ou un clúster de Elasticsearch, etc. Sería bo que aws rexeitase automaticamente a implantación se a operación que se está a realizar esixe eliminar ese recurso. Afortunadamente, cloudformation ten un xeito incorporado de facelo. Isto chámase política de pila e podes ler máis sobre ela en documentación:

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"

Lección 3: Use UsePreviousValue ao actualizar unha pila con parámetros secretos

Cando crea unha entidade mysql RDS, AWS esixe que proporcione un MasterUsername e un MasterUserPassword. Como é mellor non gardar segredos no código fonte e quería automatizar absolutamente todo, implementei un "mecanismo intelixente" onde antes da implantación obteranse as credenciais do s3, e se non se atopan as credenciais, xéranse novas credenciais e almacenado en s3.

Estas credenciais pasaranse entón como parámetros ao comando create-change-set de cloudformation. Mentres experimentaba co script, ocorreu que se perdeu a conexión co s3 e o meu "mecanismo intelixente" tratouno como un sinal para xerar novas credenciais.

Se comece a usar este script na produción e o problema de conexión volveu ocorrer, actualizaría a pila con novas credenciais. Neste caso concreto, non pasará nada malo. Non obstante, abandonei este enfoque e comecei a usar outro, proporcionando credenciais só unha vez, ao crear a pila. E máis tarde, cando a pila necesite actualizar, en lugar de especificar o valor secreto do parámetro, simplemente usaría 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"

Lección 4: Usar a configuración de retroceso

Outro equipo co que traballei utilizou a función formación de nubes, chamado configuración de retroceso. Non o atopara antes e axiña me decatei de que a implantación das miñas pilas sería aínda máis xenial. Agora úsoo cada vez que desprego o meu código en lambda ou ECS mediante cloudformation.

Como funciona: especificas Alarma CloudWatch en parámetro --rollback-configuracióncando crea un conxunto de cambios. Máis tarde, cando executas un conxunto de cambios, aws supervisa a alarma durante polo menos un minuto. Devolve a implementación se a alarma cambia de estado a ALARMA durante este tempo.

A continuación móstrase un exemplo dun extracto de modelo formación de nubesno que creo alarma cloudwatch, que rastrexa unha métrica de usuario na nube como o número de erros nos rexistros da nube (a métrica xérase mediante 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

Agora alarma pódese usar como retroceso disparador ao executar a caixa de ferramentas:

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"

Lección 5: asegúrate de implementar a última versión do modelo

É doado implementar unha versión inferior á última do modelo de formación de nubes, pero facelo causará moitos danos. Isto pasounos unha vez: un desenvolvedor non impulsou os últimos cambios de Git e, sen sabelo, despregou unha versión anterior da pila. Isto provocou un tempo de inactividade para a aplicación que utilizou esta pila.

Algo tan sinxelo como engadir unha comprobación para ver se a rama está actualizada antes de comprometerse con ela estaría ben (supoñendo que git é a túa ferramenta de control de versións):

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

Lección 6: Non reinventes a roda

Pode parecer que se está a implementar con formación de nubes - é doado. Só necesitas unha morea de scripts bash que executen comandos aws cli.

Hai 4 anos comecei con scripts sinxelos chamados comando aws cloudformation create-stack. Pronto o guión xa non era sinxelo. Cada lección aprendida facía que o guión fose cada vez máis complexo. Non só foi difícil, senón que tamén foi cheo de erros.

Actualmente traballo nun pequeno departamento de TI. A experiencia demostrou que cada equipo ten a súa propia forma de implantar pilas de formación na nube. E iso é malo. Sería mellor que todos adoptasen o mesmo enfoque. Afortunadamente, hai moitas ferramentas dispoñibles para axudarche a implementar e configurar pilas de cloudformation.

Estas leccións axudarán a evitar erros.

Fonte: www.habr.com

Engadir un comentario