Těchto 6 lekcí práce s cloudformation jsem se naučil po zbytek svého života.

Začal jsem pracovat s vytváření mraků před 4 lety. Od té doby jsem rozbil spoustu infrastruktur, dokonce i ty, které už byly ve výrobě. Ale pokaždé, když jsem něco pokazil, naučil jsem se něco nového. Prostřednictvím této zkušenosti se podělím o některé z nejdůležitějších lekcí, které jsem se naučil.

Těchto 6 lekcí práce s cloudformation jsem se naučil po zbytek svého života.

Lekce 1: Otestujte změny před jejich nasazením

Tuto lekci jsem se naučil brzy poté, co jsem začal pracovat vytváření mraků. Nepamatuji si, co přesně jsem tehdy rozbil, ale určitě si pamatuji, že jsem ten příkaz použil aktualizace cloudformation aws. Tento příkaz jednoduše spustí šablonu bez jakéhokoli ověřování změn, které budou nasazeny. Nemyslím si, že je třeba vysvětlovat, proč byste měli testovat všechny změny před jejich nasazením.

Po tomto neúspěchu jsem se okamžitě změnil nasazení, nahrazující příkaz update příkazem vytvořit-změnit-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"

Jakmile je changeset vytvořen, nemá žádný vliv na existující zásobník. Na rozdíl od příkazu update, přístup changeset nespouští skutečné nasazení. Místo toho vytvoří seznam změn, které můžete zkontrolovat před nasazením. Změny můžete zobrazit v rozhraní konzoly aws. Pokud ale dáváte přednost automatizaci všeho, co můžete, zkontrolujte je v 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

Tento příkaz by měl vytvořit výstup podobný následujícímu:

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

Věnujte zvláštní pozornost změnám tam, kde je Action Nahradit, Vymazat nebo kde ReplacementNeeded – pravda. Toto jsou nejnebezpečnější změny a obvykle vedou ke ztrátě informací.

Jakmile budou změny zkontrolovány, mohou být nasazeny

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"

Lekce 2: Použijte zásady zásobníku, abyste zabránili nahrazení nebo odebrání stavových prostředků

Někdy pouhé prohlížení změn nestačí. Všichni jsme lidé a všichni děláme chyby. Krátce poté, co jsme začali používat changesety, můj týmový kolega nevědomky provedl nasazení, které vyústilo v aktualizaci databáze. Nic špatného se nestalo, protože to bylo testovací prostředí.

I když naše skripty zobrazily seznam změn a požádaly o potvrzení, změna Nahradit byla přeskočena, protože seznam změn byl tak velký, že se nevešel na obrazovku. A jelikož se jednalo o běžnou aktualizaci v testovacím prostředí, nebyla změnám věnována velká pozornost.

Existují prostředky, které nikdy nechcete nahradit nebo odebrat. Jedná se o stavové služby, jako je instance databáze RDS nebo cluster elasticsearch atd. Bylo by hezké, kdyby aws automaticky odmítl nasazení, pokud by prováděná operace vyžadovala odstranění takového zdroje. Naštěstí má cloudformation vestavěný způsob, jak toho dosáhnout. Říká se tomu zásada zásobníku a více si o tom můžete přečíst v dokumentace:

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"

Lekce 3: Použijte UsePreviousValue při aktualizaci zásobníku s tajnými parametry

Když vytvoříte entitu RDS mysql, AWS vyžaduje, abyste zadali MasterUsername a MasterUserPassword. Vzhledem k tomu, že je lepší nedělat tajnosti ve zdrojovém kódu a chtěl jsem zautomatizovat úplně vše, implementoval jsem „chytrý mechanismus“, kdy se před nasazením získá přihlašovací údaje z s3 a pokud se přihlašovací údaje nenajdou, vygenerují se nové a uloženy v s3.

Tyto přihlašovací údaje pak budou předány jako parametry příkazu cloudformation create-change-set. Při experimentování se skriptem se stalo, že se spojení se s3 ztratilo a můj „chytrý mechanismus“ to považoval za signál pro vygenerování nových přihlašovacích údajů.

Pokud bych začal používat tento skript v produkci a problém s připojením by se opakoval, aktualizovalo by se zásobník novými přihlašovacími údaji. V tomto konkrétním případě se nic špatného nestane. Tento přístup jsem však opustil a začal používat jiný, přičemž přihlašovací údaje jsem poskytl pouze jednou – při vytváření zásobníku. A později, když je třeba zásobník aktualizovat, místo zadání tajné hodnoty parametru bych jednoduše použil 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"

Lekce 4: Použijte konfiguraci vrácení zpět

Další tým, se kterým jsem pracoval, tuto funkci používal vytváření mrakůvolala konfiguraci vrácení zpět. Předtím jsem se s tím nesetkal a rychle jsem si uvědomil, že díky tomu bude nasazení mých stacků ještě chladnější. Nyní jej používám pokaždé, když nasadím svůj kód do lambda nebo ECS pomocí cloudformace.

Jak to funguje: určíte Alarm CloudWatch v parametru --rollback-configurationkdyž vytvoříte changeset. Později, když provedete sadu změn, aws sleduje alarm po dobu alespoň jedné minuty. Pokud během této doby alarm změní stav na ALARM, vrátí rozmístění zpět.

Níže je uveden příklad výňatku ze šablony vytváření mrakůve kterém tvořím alarm cloudových hodinek, která sleduje uživatelskou metriku cloudu jako počet chyb v protokolech cloudu (metrika je generována prostřednictvím 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

Nyní poplach lze použít jako rollback spoušť při spuštění toolboxu:

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"

Lekce 5: Ujistěte se, že používáte nejnovější verzi šablony

Je snadné nasadit méně než nejnovější verzi šablony cloudformation, ale způsobí to spoustu škod. To se nám jednou stalo: vývojář neprosadil nejnovější změny z Gitu a nevědomky nasadil předchozí verzi zásobníku. To mělo za následek výpadek aplikace, která tento zásobník používala.

Něco tak jednoduchého jako přidání kontroly, abyste zjistili, zda je větev aktuální, než se do ní zavážete, by bylo v pořádku (za předpokladu, že git je váš nástroj pro správu verzí):

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

Lekce 6: Neobjevujte znovu kolo

Může se to zdát jako nasazení s vytváření mraků - je to snadné. Potřebujete jen spoustu bash skriptů provádějících příkazy aws cli.

Před 4 lety jsem začal s jednoduchými skripty nazvanými příkaz aws cloudformation create-stack. Brzy už scénář nebyl jednoduchý. S každou získanou lekcí byl scénář stále složitější. Bylo to nejen náročné, ale také plné bugů.

V současné době pracuji v malém IT oddělení. Zkušenosti ukázaly, že každý tým má svůj vlastní způsob nasazení cloudformačních zásobníků. A to je špatně. Bylo by lepší, kdyby všichni zvolili stejný přístup. Naštěstí je k dispozici mnoho nástrojů, které vám pomohou nasadit a nakonfigurovat zásobníky cloudformation.

Tyto lekce vám pomohou vyhnout se chybám.

Zdroj: www.habr.com

Přidat komentář