Natutunan ko ang 6 na aral na ito ng pagtatrabaho sa cloudformation sa buong buhay ko.

Nagsimula akong magtrabaho kasama pagbuo ng ulap 4 na taon na ang nakalipas. Simula noon marami na akong nasira na mga imprastraktura, kahit na mga nasa produksyon na. Pero sa tuwing may magugulo ako, may natutunan akong bago. Sa pamamagitan ng karanasang ito, ibabahagi ko ang ilan sa pinakamahalagang aral na natutunan ko.

Natutunan ko ang 6 na aral na ito ng pagtatrabaho sa cloudformation sa buong buhay ko.

Aralin 1: Subukan ang mga pagbabago bago i-deploy ang mga ito

Natutunan ko ang araling ito sa lalong madaling panahon pagkatapos kong magsimulang magtrabaho kasama pagbuo ng ulap. Hindi ko matandaan kung ano ang eksaktong sinira ko noon, ngunit talagang naaalala ko na ginamit ko ang utos aws cloudformation update. Ang utos na ito ay inilalabas lamang ang template nang walang anumang pagpapatunay ng mga pagbabagong ipapatupad. Sa palagay ko ay hindi kailangan ng anumang paliwanag kung bakit dapat mong subukan ang lahat ng mga pagbabago bago i-deploy ang mga ito.

Pagkatapos ng kabiguan na ito, agad akong nagbago pag-deploy ng tubo, pinapalitan ang update command ng command lumikha-pagbabago-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"

Kapag nalikha ang isang changeset, wala itong epekto sa umiiral na stack. Hindi tulad ng update command, ang changeset approach ay hindi nagti-trigger ng aktwal na deployment. Sa halip, gumagawa ito ng listahan ng mga pagbabago na maaari mong suriin bago i-deploy. Maaari mong tingnan ang mga pagbabago sa interface ng aws console. Ngunit kung mas gusto mong i-automate ang lahat ng iyong makakaya, pagkatapos ay suriin ang mga ito sa 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

Ang utos na ito ay dapat gumawa ng output na katulad ng sumusunod:

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

Bigyang-pansin ang mga pagbabago kung nasaan ang Aksyon Palitan, alisin o kung saan Kailangan ng Kapalit - Totoo. Ito ang mga pinaka-mapanganib na pagbabago at kadalasang humahantong sa pagkawala ng impormasyon.

Kapag nasuri na ang mga pagbabago, maaari na silang i-deploy

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"

Aralin 2: Gumamit ng patakaran sa stack upang maiwasang mapalitan o maalis ang mga stateful na mapagkukunan

Minsan hindi sapat ang simpleng pagtingin sa mga pagbabago. Lahat tayo ay tao at lahat tayo ay nagkakamali. Di-nagtagal pagkatapos naming magsimulang gumamit ng mga pagbabago, hindi namamalayang nagsagawa ng deployment ang aking teammate na nagresulta sa pag-update ng database. Walang masamang nangyari dahil ito ay isang kapaligiran sa pagsubok.

Kahit na ang aming mga script ay nagpakita ng isang listahan ng mga pagbabago at humingi ng kumpirmasyon, ang Palitan na pagbabago ay nilaktawan dahil ang listahan ng mga pagbabago ay napakalaki na hindi ito magkasya sa screen. At dahil ito ay isang normal na pag-update sa isang kapaligiran ng pagsubok, hindi gaanong nabigyan ng pansin ang mga pagbabago.

May mga mapagkukunan na hindi mo gustong palitan o alisin. Ito ay mga statefull na serbisyo, tulad ng isang halimbawa ng database ng RDS o isang elasticsearch cluster, atbp. Magiging maganda kung awtomatikong tatanggihan ng aws ang pag-deploy kung ang operasyon na isinasagawa ay mangangailangan ng pagtanggal ng naturang mapagkukunan. Sa kabutihang palad, ang cloudformation ay may built-in na paraan upang gawin ito. Ito ay tinatawag na stack policy, at maaari mong basahin ang higit pa tungkol dito dokumentasyon:

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"

Aralin 3: Gamitin ang UsePreviousValue kapag nag-a-update ng stack na may mga lihim na parameter

Kapag gumawa ka ng RDS mysql entity, hinihiling sa iyo ng AWS na magbigay ng MasterUsername at MasterUserPassword. Dahil mas mainam na huwag magtago ng mga lihim sa source code at gusto kong ganap na i-automate ang lahat, nagpatupad ako ng isang "matalinong mekanismo" kung saan bago i-deploy ang mga kredensyal ay makukuha mula sa s3, at kung ang mga kredensyal ay hindi matagpuan, ang mga bagong kredensyal ay nabuo at nakaimbak sa s3 .

Ang mga kredensyal na ito ay ipapasa bilang mga parameter sa cloudformation create-change-set command. Habang nag-eeksperimento sa script, nangyari na nawala ang koneksyon sa s3, at itinuring ito ng aking "matalinong mekanismo" bilang isang senyales upang makabuo ng mga bagong kredensyal.

Kung sinimulan kong gamitin ang script na ito sa produksyon at nangyari muli ang problema sa koneksyon, ia-update nito ang stack ng mga bagong kredensyal. Sa partikular na kaso, walang masamang mangyayari. Gayunpaman, tinalikuran ko ang diskarteng ito at nagsimulang gumamit ng isa pa, na nagbibigay ng mga kredensyal nang isang beses lamang - kapag gumagawa ng stack. At sa paglaon, kapag ang stack ay nangangailangan ng pag-update, sa halip na tukuyin ang lihim na halaga ng parameter, gagamitin ko lang 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"

Aralin 4: Gamitin ang rollback configuration

Ang isa pang team na nakatrabaho ko ay gumamit ng function pagbuo ng ulaptinawag pagsasaayos ng rollback. Hindi ko pa ito nakita noon at mabilis kong napagtanto na gagawing mas cool ang pag-deploy ng aking mga stack. Ngayon ay ginagamit ko ito sa tuwing i-deploy ko ang aking code sa lambda o ECS gamit ang cloudformation.

Paano ito gumagana: tinukoy mo Alarm ng CloudWatch sa parameter --rollback-configurationkapag gumawa ka ng changeset. Sa ibang pagkakataon, kapag nagsagawa ka ng isang hanay ng mga pagbabago, sinusubaybayan ng aws ang alarma nang hindi bababa sa isang minuto. Ibinabalik nito ang deployment kung magbabago ang estado ng alarm sa ALARM sa panahong ito.

Nasa ibaba ang isang halimbawa ng sipi ng template pagbuo ng ulapkung saan ako lumilikha alarma ng cloudwatch, na sumusubaybay sa sukatan ng user ng cloud bilang ang bilang ng mga error sa mga cloud log (ang sukatan ay nabuo sa pamamagitan ng 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

Ngayon alarma maaaring gamitin bilang rollback trigger kapag nagsasagawa ng toolbox:

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"

Aralin 5: Tiyaking i-deploy mo ang pinakabagong bersyon ng template

Madaling mag-deploy ng hindi gaanong pinakabagong bersyon ng template ng cloudformation, ngunit ang paggawa nito ay magdudulot ng maraming pinsala. Nangyari ito sa amin minsan: hindi itinulak ng isang developer ang pinakabagong mga pagbabago mula sa Git at hindi namamalayang nag-deploy ng nakaraang bersyon ng stack. Nagresulta ito sa downtime para sa application na gumamit ng stack na ito.

Isang bagay na kasing simple ng pagdaragdag ng isang tseke upang makita kung ang sangay ay napapanahon bago gumawa nito ay magiging maayos (ipagpalagay na ang git ay ang iyong tool sa pagkontrol ng bersyon):

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

Aralin 6: Huwag muling likhain ang gulong

Maaaring mukhang nagde-deploy kasama pagbuo ng ulap - madali lang. Kailangan mo lang ng isang grupo ng mga script ng bash na nagpapatupad ng mga utos ng aws cli.

4 na taon na ang nakalipas nagsimula ako sa mga simpleng script na tinatawag na aws cloudformation create-stack command. Sa lalong madaling panahon ang script ay hindi na simple. Ang bawat aralin na natutunan ay naging mas kumplikado ang script. Ito ay hindi lamang mahirap, ngunit puno rin ng mga bug.

Kasalukuyan akong nagtatrabaho sa isang maliit na departamento ng IT. Ipinakita ng karanasan na ang bawat koponan ay may sariling paraan ng pag-deploy ng mga cloudformation stack. At masama iyon. Mas maganda kung pare-pareho ang diskarte ng lahat. Sa kabutihang-palad, mayroong maraming tool na magagamit upang matulungan kang mag-deploy at mag-configure ng mga cloudformation stack.

Tutulungan ka ng mga araling ito na maiwasan ang mga pagkakamali.

Pinagmulan: www.habr.com

Magdagdag ng komento