Aprendí estas 6 lecciones sobre cómo trabajar con la formación de nubes por el resto de mi vida.

comencé a trabajar con formación de nubes Hace 4 años. Desde entonces he roto muchas infraestructuras, incluso algunas que ya estaban en producción. Pero cada vez que cometía un error, aprendía algo nuevo. A través de esta experiencia, compartiré algunas de las lecciones más importantes que aprendí.

Aprendí estas 6 lecciones sobre cómo trabajar con la formación de nubes por el resto de mi vida.

Lección 1: Probar los cambios antes de implementarlos

Aprendí esta lección poco después de empezar a trabajar con formación de nubes. No recuerdo exactamente qué rompí entonces, pero definitivamente recuerdo que usé el comando actualización de la formación de nubes de AWS. Este comando simplemente implementa la plantilla sin ninguna validación de los cambios que se implementarán. No creo que sea necesaria ninguna explicación de por qué debería probar todos los cambios antes de implementarlos.

Después de este fracaso, cambié inmediatamente canalización de despliegue, reemplazando el comando de actualización con el comando crear-conjunto-de-cambios

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

Una vez que se crea un conjunto de cambios, no tiene ningún efecto en la pila existente. A diferencia del comando de actualización, el enfoque del conjunto de cambios no desencadena la implementación real. En cambio, crea una lista de cambios que puede revisar antes de la implementación. Puede ver los cambios en la interfaz de la consola de AWS. Pero si prefieres automatizar todo lo que puedas, compruébalo en 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

Este comando debería producir un resultado similar al siguiente:

--------------------------------------------------------------------
|                         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 a los cambios donde está la Acción. Reemplaza, Borrar o donde Reemplazo necesario: verdadero. Estos son los cambios más peligrosos y normalmente provocan pérdida de información.

Una vez revisados ​​los cambios, se pueden 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: Utilice la política de pila para evitar que se reemplacen o eliminen recursos con estado

A veces, simplemente ver los cambios no es suficiente. Todos somos humanos y todos cometemos errores. Poco después de que comenzamos a usar conjuntos de cambios, mi compañero de equipo, sin saberlo, realizó una implementación que resultó en una actualización de la base de datos. No pasó nada malo porque era un entorno de prueba.

Aunque nuestros scripts mostraban una lista de cambios y pedían confirmación, el cambio Reemplazar se omitió porque la lista de cambios era tan grande que no cabía en la pantalla. Y como se trataba de una actualización normal en un entorno de prueba, no se prestó mucha atención a los cambios.

Hay recursos que nunca querrás reemplazar o eliminar. Estos son servicios con estado completo, como una instancia de base de datos RDS o un clúster de búsqueda elástica, etc. Sería bueno si AWS rechazara automáticamente la implementación si la operación que se realiza requiriera eliminar dicho recurso. Afortunadamente, Cloudformation tiene una forma incorporada de hacer esto. Esto se llama política de pila y puede leer más sobre ella 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: Utilice UsePreviousValue al actualizar una pila con parámetros secretos

Cuando crea una entidad RDS mysql, AWS requiere que proporcione un nombre de usuario maestro y una contraseña de usuario maestro. Como es mejor no guardar secretos en el código fuente y quería automatizar absolutamente todo, implementé un "mecanismo inteligente" donde antes de la implementación las credenciales se obtendrán de s3, y si no se encuentran las credenciales, se generan nuevas credenciales y almacenado en s3.

Luego, estas credenciales se pasarán como parámetros al comando create-change-set de cloudformation. Mientras experimentaba con el script, sucedió que se perdió la conexión con s3 y mi "mecanismo inteligente" lo trató como una señal para generar nuevas credenciales.

Si comenzara a usar este script en producción y el problema de conexión volviera a ocurrir, se actualizaría la pila con nuevas credenciales. En este caso particular, no pasará nada malo. Sin embargo, abandoné este enfoque y comencé a usar otro, proporcionando credenciales solo una vez: al crear la pila. Y más tarde, cuando la pila necesita actualizarse, en lugar de especificar el valor secreto del parámetro, simplemente usaría UsarValorAnterior=verdadero:

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 la configuración de reversión

Otro equipo con el que trabajé usó la función. formación de nubesllamado configuración de reversión. No lo había encontrado antes y rápidamente me di cuenta de que haría que implementar mis pilas fuera aún más genial. Ahora lo uso cada vez que implemento mi código en lambda o ECS usando cloudformation.

Cómo funciona: tú especificas alarma de vigilancia en la nube en parámetro --rollback-configuracióncuando creas un conjunto de cambios. Posteriormente, cuando ejecuta un conjunto de cambios, AWS monitorea la alarma durante al menos un minuto. Revierte la implementación si la alarma cambia de estado a ALARMA durante este tiempo.

A continuación se muestra un ejemplo de un extracto de plantilla. formación de nubesen el que creo alarma de vigilancia de la nube, que rastrea una métrica de usuario de la nube como la cantidad de errores en los registros de la nube (la métrica se genera a través de Filtro métrico):

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

Ahora alarma se puede utilizar como rollback disparador al ejecutar la caja de herramientas:

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úrese de implementar la última versión de la plantilla

Es fácil implementar una versión inferior a la más reciente de la plantilla de formación en la nube, pero hacerlo causará mucho daño. Esto nos pasó una vez: un desarrollador no impulsó los últimos cambios de Git y, sin saberlo, implementó una versión anterior de la pila. Esto resultó en un tiempo de inactividad para la aplicación que usaba esta pila.

Algo tan simple como agregar una verificación para ver si la rama está actualizada antes de comprometerse con ella estaría bien (suponiendo que git sea su herramienta de control de versiones):

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: No reinventes la rueda

Puede parecer que se está implementando con formación de nubes - es fácil. Solo necesita un montón de scripts bash que ejecuten comandos de AWS CLI.

Hace 4 años comencé con scripts simples llamados comando create-stack de aws cloudformation. Pronto el guión dejó de ser sencillo. Cada lección aprendida hizo que el guión fuera cada vez más complejo. No sólo fue difícil, sino que también estuvo lleno de errores.

Actualmente trabajo en un pequeño departamento de TI. La experiencia ha demostrado que cada equipo tiene su propia forma de implementar pilas de formación en la nube. Y eso es malo. Sería mejor si todos adoptaran el mismo enfoque. Afortunadamente, existen muchas herramientas disponibles para ayudarlo a implementar y configurar pilas de formación en la nube.

Estas lecciones le ayudarán a evitar errores.

Fuente: habr.com

Añadir un comentario