למדתי את 6 השיעורים האלה של עבודה עם Cloudformation למשך שארית חיי.

התחלתי לעבוד עם תצורת ענן לפני 4 שנים. מאז שברתי הרבה תשתיות, אפילו כאלה שכבר היו בייצור. אבל בכל פעם שפישלתי משהו, למדתי משהו חדש. דרך התנסות זו, אחלוק כמה מהשיעורים החשובים ביותר שלמדתי.

למדתי את 6 השיעורים האלה של עבודה עם Cloudformation למשך שארית חיי.

שיעור 1: בדוק שינויים לפני פריסתם

למדתי את השיעור הזה זמן קצר לאחר שהתחלתי לעבוד עם תצורת ענן. אני לא זוכר מה בדיוק שברתי אז, אבל אני בהחלט זוכר שהשתמשתי בפקודה עדכון ענן aws. פקודה זו פשוט מוציאה את התבנית ללא כל אימות של השינויים שייפרסו. אני לא חושב שצריך הסבר למה אתה צריך לבדוק את כל השינויים לפני פריסתם.

אחרי הכישלון הזה, השתניתי מיד צינור פריסה, החלפת פקודת העדכון בפקודה צור-שנה-סט

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

לאחר יצירת ערכת שינויים, אין לה השפעה על המחסנית הקיימת. שלא כמו פקודת העדכון, גישת השינויים לא מפעילה את הפריסה בפועל. במקום זאת, הוא יוצר רשימה של שינויים שתוכל לבדוק לפני הפריסה. אתה יכול לראות את השינויים בממשק aws console. אבל אם אתה מעדיף להפוך את כל מה שאתה יכול לאוטומטי, בדוק אותם ב-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 או אשכול חיפוש של elastics, וכו'. זה יהיה נחמד אם 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 בעת עדכון מחסנית עם פרמטרים סודיים

כאשר אתה יוצר ישות RDS mysql, AWS דורש ממך לספק שם משתמש ובסיס משתמש ראשי. מכיוון שעדיף לא לשמור סודות בקוד המקור ורציתי להפוך את הכל לאוטומטי, הטמעתי "מנגנון חכם" שבו לפני הפריסה האישורים יתקבלו מ-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 במהלך תקופה זו.

להלן דוגמה לקטע תבנית תצורת ענןשבו אני יוצר אזעקת שעון ענן, אשר עוקב אחר מדד משתמש בענן כמספר השגיאות ביומני הענן (המדד נוצר באמצעות 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

עכשיו אזעקה יכול לשמש כ החזרה למצב קודם טריגר בעת הפעלת ארגז הכלים:

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: אל תמציא את הגלגל מחדש

זה אולי נראה כמו פריסה עם תצורת ענן - זה קל. אתה רק צריך חבורה של סקריפטים של bash המבצעים פקודות aws cli.

לפני 4 שנים התחלתי עם סקריפטים פשוטים שנקראים הפקודה aws cloudformation create-stack. עד מהרה התסריט כבר לא היה פשוט. כל שיעור שנלמד הפך את התסריט למורכב יותר ויותר. זה היה לא רק קשה, אלא גם מלא באגים.

כיום אני עובד במחלקת IT קטנה. הניסיון הראה שלכל צוות יש דרך משלו לפרוס ערימות ענן. וזה רע. עדיף שכולם ינקטו באותה גישה. למרבה המזל, ישנם כלים רבים זמינים כדי לעזור לך לפרוס ולהגדיר ערימות Cloudformation.

שיעורים אלה יעזרו לך להימנע מטעויות.

מקור: www.habr.com

קנה אירוח אמין לאתרים עם הגנת DDoS, שרתי VPS VDS 🔥 קנה אחסון אתרים אמין עם הגנת DDoS, שרתי VPS VDS | ProHoster