ฉันได้เรียนรู้บทเรียน 6 บทนี้เกี่ยวกับการทำงานกับระบบคลาวด์ไปตลอดชีวิต

ฉันเริ่มทำงานด้วย เมฆ 4 ปีที่แล้ว. ตั้งแต่นั้นมา ฉันได้ทำลายโครงสร้างพื้นฐานจำนวนมาก แม้แต่โครงสร้างพื้นฐานที่ใช้งานจริงอยู่แล้วก็ตาม แต่ทุกครั้งที่ฉันทำอะไรผิดพลาด ฉันได้เรียนรู้สิ่งใหม่ ผ่านประสบการณ์นี้ ฉันจะแบ่งปันบทเรียนสำคัญที่สุดบางบทเรียนที่ฉันเรียนรู้

ฉันได้เรียนรู้บทเรียน 6 บทนี้เกี่ยวกับการทำงานกับระบบคลาวด์ไปตลอดชีวิต

บทที่ 1: ทดสอบการเปลี่ยนแปลงก่อนที่จะปรับใช้

ฉันได้เรียนรู้บทเรียนนี้หลังจากเริ่มทำงานด้วยไม่นาน เมฆ. ฉันจำไม่ได้ว่าฉันพังอะไรไปบ้างในตอนนั้น แต่ฉันจำได้แน่นอนว่าฉันใช้คำสั่ง การอัปเดตรูปแบบคลาวด์ของ aws. คำสั่งนี้เพียงเผยแพร่เทมเพลตโดยไม่มีการตรวจสอบความถูกต้องของการเปลี่ยนแปลงที่จะนำไปใช้งาน ฉันไม่คิดว่าจำเป็นต้องมีคำอธิบายว่าทำไมคุณควรทดสอบการเปลี่ยนแปลงทั้งหมดก่อนที่จะนำไปใช้งาน

หลังจากความล้มเหลวนี้ ฉันก็เปลี่ยนทันที ท่อวางระบบโดยแทนที่คำสั่ง update ด้วยคำสั่ง สร้างการเปลี่ยนแปลงชุด

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

เมื่อสร้างเซ็ตการแก้ไขแล้ว จะไม่มีผลกับสแต็กที่มีอยู่ ต่างจากคำสั่ง update ตรงที่วิธีเซ็ตการแก้ไขไม่ทริกเกอร์การปรับใช้จริง แต่จะสร้างรายการการเปลี่ยนแปลงที่คุณสามารถตรวจสอบก่อนปรับใช้แทน คุณสามารถดูการเปลี่ยนแปลงได้ในอินเทอร์เฟซคอนโซลของ aws แต่หากคุณต้องการทำให้ทุกสิ่งที่คุณทำได้เป็นอัตโนมัติ ให้ตรวจสอบสิ่งเหล่านี้ใน 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

คำสั่งนี้ควรสร้างเอาต์พุตที่คล้ายกับดังต่อไปนี้:

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

ให้ความสนใจเป็นพิเศษกับการเปลี่ยนแปลงที่การดำเนินการอยู่ แทนที่, ลบ หรือที่ไหน จำเป็นต้องเปลี่ยน - จริง. การเปลี่ยนแปลงเหล่านี้เป็นการเปลี่ยนแปลงที่อันตรายที่สุดและมักจะนำไปสู่การสูญเสียข้อมูล

เมื่อตรวจสอบการเปลี่ยนแปลงแล้ว ก็สามารถนำไปใช้งานได้

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"

บทที่ 2: ใช้นโยบายสแต็กเพื่อป้องกันไม่ให้ทรัพยากรที่มีสถานะถูกแทนที่หรือลบออก

บางครั้งการดูการเปลี่ยนแปลงเพียงอย่างเดียวอาจไม่เพียงพอ เราทุกคนเป็นมนุษย์และเราทุกคนต่างก็ทำผิดพลาด ไม่นานหลังจากที่เราเริ่มใช้เซ็ตการแก้ไข เพื่อนร่วมทีมของฉันก็ทำการปรับใช้โดยไม่รู้ตัว ซึ่งส่งผลให้มีการอัปเดตฐานข้อมูล ไม่มีอะไรเลวร้ายเกิดขึ้นเพราะเป็นสภาพแวดล้อมการทดสอบ

แม้ว่าสคริปต์ของเราจะแสดงรายการการเปลี่ยนแปลงและขอการยืนยัน แต่การเปลี่ยนแปลงแทนที่ก็ถูกข้ามไปเนื่องจากรายการการเปลี่ยนแปลงมีขนาดใหญ่มากจนไม่พอดีกับหน้าจอ และเนื่องจากนี่เป็นการอัปเดตปกติในสภาพแวดล้อมการทดสอบ จึงไม่ค่อยให้ความสนใจกับการเปลี่ยนแปลงมากนัก

มีทรัพยากรที่คุณไม่ต้องการแทนที่หรือลบออก บริการเหล่านี้เป็นบริการแบบระบุสถานะ เช่น อินสแตนซ์ฐานข้อมูล RDS หรือคลัสเตอร์ elasticsearch เป็นต้น คงจะดีไม่น้อยหาก aws ปฏิเสธการปรับใช้โดยอัตโนมัติ หากการดำเนินการที่กำลังดำเนินการอยู่จำเป็นต้องลบทรัพยากรดังกล่าว โชคดีที่รูปแบบคลาวด์มีวิธีการทำเช่นนี้ในตัว สิ่งนี้เรียกว่านโยบายสแต็ก และคุณสามารถอ่านเพิ่มเติมเกี่ยวกับนโยบายนี้ได้ใน เอกสาร:

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"

บทที่ 3: ใช้ UsePreviousValue เมื่ออัปเดตสแต็กด้วยพารามิเตอร์ลับ

เมื่อคุณสร้างเอนทิตี mysql ของ RDS AWS กำหนดให้คุณต้องระบุ MasterUsername และ MasterUserPassword เนื่องจากเป็นการดีกว่าที่จะไม่เก็บความลับไว้ในซอร์สโค้ด และฉันต้องการทำให้ทุกอย่างเป็นแบบอัตโนมัติ ฉันจึงใช้ "กลไกอันชาญฉลาด" ซึ่งก่อนที่จะปรับใช้ ข้อมูลประจำตัวจะได้รับจาก s3 และหากไม่พบข้อมูลประจำตัว ก็จะมีการสร้างข้อมูลประจำตัวใหม่ และ เก็บไว้ใน s3 .

ข้อมูลประจำตัวเหล่านี้จะถูกส่งผ่านเป็นพารามิเตอร์ไปยังคำสั่ง cloudformation create-change-set ขณะทดลองสคริปต์ บังเอิญว่าการเชื่อมต่อกับ s3 ขาดหายไป และ “กลไกอันชาญฉลาด” ของฉันถือว่ามันเป็นสัญญาณในการสร้างข้อมูลประจำตัวใหม่

ถ้าฉันเริ่มใช้สคริปต์นี้ในการใช้งานจริงและเกิดปัญหาการเชื่อมต่ออีกครั้ง สคริปต์จะอัปเดตสแต็กด้วยข้อมูลประจำตัวใหม่ ในกรณีนี้จะไม่มีอะไรเลวร้ายเกิดขึ้น อย่างไรก็ตาม ฉันละทิ้งแนวทางนี้และเริ่มใช้วิธีอื่นโดยระบุข้อมูลประจำตัวเพียงครั้งเดียว - เมื่อสร้างสแต็ก และต่อมา เมื่อสแต็กจำเป็นต้องอัปเดต แทนที่จะระบุค่าลับของพารามิเตอร์ ฉันจะใช้แทน 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"

บทที่ 4: ใช้การกำหนดค่าการย้อนกลับ

อีกทีมหนึ่งที่ฉันร่วมงานด้วยใช้ฟังก์ชันนี้ เมฆ, เรียกว่า การกำหนดค่าย้อนกลับ. ฉันไม่เคยเจอมันมาก่อนและรู้ได้อย่างรวดเร็วว่ามันจะทำให้การปรับใช้สแต็กของฉันเจ๋งยิ่งขึ้นไปอีก ตอนนี้ฉันใช้มันทุกครั้งที่ปรับใช้โค้ดกับ lambda หรือ ECS โดยใช้ cloudformation

มันทำงานอย่างไร: คุณระบุ สัญญาณเตือน CloudWatch ในพารามิเตอร์ --ย้อนกลับการกำหนดค่าเมื่อคุณสร้างเซ็ตการแก้ไข ต่อมา เมื่อคุณดำเนินการเปลี่ยนแปลงชุดหนึ่ง aws จะตรวจสอบสัญญาณเตือนเป็นเวลาอย่างน้อยหนึ่งนาที โดยจะย้อนกลับการใช้งานหากสัญญาณเตือนเปลี่ยนสถานะเป็น ALARM ในช่วงเวลานี้

ด้านล่างนี้เป็นตัวอย่างของข้อความที่ตัดตอนมาจากเทมเพลต เมฆที่ฉันสร้างขึ้น นาฬิกาปลุก cloudwatchซึ่งติดตามตัววัดผู้ใช้ระบบคลาวด์เป็นจำนวนข้อผิดพลาดในบันทึกระบบคลาวด์ (ตัววัดถูกสร้างขึ้นผ่าน ตัวกรองเมตริก):

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

ขณะนี้ ปลุก สามารถใช้เป็น ย้อนกลับ ทริกเกอร์เมื่อดำเนินการกล่องเครื่องมือ:

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"

บทที่ 5: ตรวจสอบให้แน่ใจว่าคุณปรับใช้เทมเพลตเวอร์ชันล่าสุด

เป็นเรื่องง่ายที่จะปรับใช้เทมเพลต cloudformation เวอร์ชันที่น้อยกว่าล่าสุด แต่การทำเช่นนั้นจะทำให้เกิดความเสียหายอย่างมาก สิ่งนี้เกิดขึ้นกับเราครั้งหนึ่ง: นักพัฒนาไม่ได้ส่งการเปลี่ยนแปลงล่าสุดจาก Git และปรับใช้สแต็กเวอร์ชันก่อนหน้าโดยไม่รู้ตัว ซึ่งส่งผลให้แอปพลิเคชันที่ใช้สแต็กนี้หยุดทำงาน

บางสิ่งที่เรียบง่ายอย่างการเพิ่มการตรวจสอบเพื่อดูว่าสาขานั้นทันสมัยหรือไม่ก่อนที่จะยอมรับมันคงจะไม่เป็นไร (สมมติว่า git เป็นเครื่องมือควบคุมเวอร์ชันของคุณ):

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

บทที่ 6: อย่าสร้างล้อขึ้นมาใหม่

มันอาจดูเหมือนปรับใช้กับ เมฆ - มันเป็นเรื่องง่าย. คุณเพียงแค่ต้องมีสคริปต์ทุบตีจำนวนมากที่รันคำสั่ง aws cli

4 ปีที่แล้ว ฉันเริ่มต้นด้วยสคริปต์ง่ายๆ ที่เรียกว่าคำสั่ง aws cloudformation create-stack ในไม่ช้าสคริปต์ก็ไม่ง่ายอีกต่อไป แต่ละบทเรียนที่ได้เรียนรู้ทำให้สคริปต์มีความซับซ้อนมากขึ้นเรื่อยๆ มันไม่เพียงแต่ยากเท่านั้น แต่ยังเต็มไปด้วยข้อบกพร่องอีกด้วย

ปัจจุบันฉันทำงานในแผนกไอทีเล็กๆ ประสบการณ์ได้แสดงให้เห็นว่าแต่ละทีมมีวิธีปรับใช้สแต็ก Cloudformation ของตัวเอง และนั่นก็แย่ จะดีกว่าถ้าทุกคนใช้แนวทางเดียวกัน โชคดีที่มีเครื่องมือมากมายที่จะช่วยคุณปรับใช้และกำหนดค่าสแต็กของ Cloudformation

บทเรียนเหล่านี้จะช่วยให้คุณหลีกเลี่ยงข้อผิดพลาด

ที่มา: will.com

เพิ่มความคิดเห็น