์ €๋Š” ํ‰์ƒ ๋™์•ˆ Cloudformation์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ด๋Ÿฌํ•œ 6๊ฐ€์ง€ ๊ตํ›ˆ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ํ•จ๊ป˜ ์ผํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค ๊ตฌ๋ฆ„ ํ˜•์„ฑ 4 ๋…„ ์ „. ๊ทธ ์ดํ›„๋กœ ์ €๋Š” ์ด๋ฏธ ์ƒ์‚ฐ ์ค‘์ธ ์ธํ”„๋ผ๋ฅผ ํฌํ•จํ•˜์—ฌ ๋งŽ์€ ์ธํ”„๋ผ๋ฅผ ๋ง๊ฐ€๋œจ๋ ธ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ญ”๊ฐ€๋ฅผ ๋ง์น  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝํ—˜์„ ํ†ตํ•ด ์ œ๊ฐ€ ๋ฐฐ์šด ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ตํ›ˆ ์ค‘ ์ผ๋ถ€๋ฅผ ๊ณต์œ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ €๋Š” ํ‰์ƒ ๋™์•ˆ Cloudformation์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ด๋Ÿฌํ•œ 6๊ฐ€์ง€ ๊ตํ›ˆ์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

๋ ˆ์Šจ 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"

๋ณ€๊ฒฝ ์„ธํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด ๊ธฐ์กด ์Šคํƒ์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 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   |
+---------+--------------------+----------------------+------------+

Action์ด ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์— ํŠน๋ณ„ํ•œ ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์ด์„ธ์š”. ๊ต์ฒด, . ์•„๋‹ˆ๋ฉด ์–ด๋””์„œ ๊ต์ฒด ํ•„์š” - ์ฐธ. ์ด๋Š” ๊ฐ€์žฅ ์œ„ํ—˜ํ•œ ๋ณ€๊ฒฝ์ด๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์ •๋ณด ์†์‹ค๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๊ฒ€ํ† ๋˜๋ฉด ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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๊ฐ€ ์ž๋™์œผ๋กœ ๋ฐฐํฌ๋ฅผ ๊ฑฐ๋ถ€ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹คํ–‰์Šค๋Ÿฝ๊ฒŒ๋„ cloudformation์—๋Š” ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์Šคํƒ ์ •์ฑ…์ด๋ผ๊ณ  ํ•˜๋ฉฐ ์ด์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ ์  ์„œ๋ฅ˜ ๋น„์น˜:

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์—์„œ๋Š” 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: ๋กค๋ฐฑ ๊ตฌ์„ฑ ์‚ฌ์šฉ

์ œ๊ฐ€ ํ•จ๊ป˜ ์ผํ–ˆ๋˜ ๋‹ค๋ฅธ ํŒ€์ด ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ๋ฆ„ ํ˜•์„ฑ~๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ๋กค๋ฐฑ ๊ตฌ์„ฑ. ๋‚˜๋Š” ์ด์ „์— ๊ทธ๊ฒƒ์„ ๋ณธ ์ ์ด ์—†์—ˆ์œผ๋ฉฐ ๊ทธ๊ฒƒ์ด ๋‚ด ์Šคํƒ ๋ฐฐํฌ๋ฅผ ๋”์šฑ ๋ฉ‹์ง€๊ฒŒ ๋งŒ๋“ค ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์„ ๋นจ๋ฆฌ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค. ์ด์ œ๋Š” cloudformation์„ ์‚ฌ์šฉํ•˜์—ฌ ๋žŒ๋‹ค ๋˜๋Š” ECS์— ์ฝ”๋“œ๋ฅผ ๋ฐฐํฌํ•  ๋•Œ๋งˆ๋‹ค ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ž‘๋™ ๋ฐฉ์‹: ๊ท€ํ•˜๊ฐ€ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. CloudWatch ๊ฒฝ๋ณด ๋งค๊ฐœ๋ณ€์ˆ˜์—์„œ --๋กค๋ฐฑ ๊ตฌ์„ฑ๋ณ€๊ฒฝ ์„ธํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ. ๋‚˜์ค‘์— ์ผ๋ จ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์‹คํ–‰ํ•˜๋ฉด aws๋Š” ์ตœ์†Œ XNUMX๋ถ„ ๋™์•ˆ ๊ฒฝ๋ณด๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„ ๋™์•ˆ ๊ฒฝ๋ณด ์ƒํƒœ๊ฐ€ ALARM์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ฐฐํฌ๋ฅผ ๋กค๋ฐฑํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ํ…œํ”Œ๋ฆฟ ๋ฐœ์ทŒ์˜ ์˜ˆ์ž…๋‹ˆ๋‹ค. ๊ตฌ๋ฆ„ ํ˜•์„ฑ๋‚ด๊ฐ€ ๋งŒ๋“œ๋Š” ๊ณณ ํด๋ผ์šฐ๋“œ์›Œ์น˜ ์•Œ๋žŒ, ํด๋ผ์šฐ๋“œ ๋กœ๊ทธ์˜ ์˜ค๋ฅ˜ ์ˆ˜๋กœ ํด๋ผ์šฐ๋“œ ์‚ฌ์šฉ์ž ์ธก์ •ํ•ญ๋ชฉ์„ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค. ์ธก์ •ํ•ญ๋ชฉ์€ ๋‹ค์Œ์„ ํ†ตํ•ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋ฉ”ํŠธ๋ฆญ ํ•„ํ„ฐ):

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 ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” bash ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

4๋…„ ์ „ ์ €๋Š” aws cloudformation create-stack ๋ช…๋ น์ด๋ผ๋Š” ๊ฐ„๋‹จํ•œ ์Šคํฌ๋ฆฝํŠธ๋กœ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ณง ๋Œ€๋ณธ์€ ๋” ์ด์ƒ ๋‹จ์ˆœํ•˜์ง€ ์•Š๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฐฐ์šด ๊ฐ ๊ตํ›ˆ์€ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ ์  ๋” ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋ ค์šธ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฒ„๊ทธ๋„ ๋งŽ์•˜์Šต๋‹ˆ๋‹ค.

์ €๋Š” ํ˜„์žฌ ์†Œ๊ทœ๋ชจ IT ๋ถ€์„œ์—์„œ ๊ทผ๋ฌดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด ๊ฐ ํŒ€์—๋Š” Cloudformation ์Šคํƒ์„ ๋ฐฐํฌํ•˜๋Š” ๊ณ ์œ ํ•œ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ๋‚˜์˜๋‹ค. ๋ชจ๋‘๊ฐ€ ๊ฐ™์€ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ทจํ•˜๋ฉด ๋” ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ Cloudformation ์Šคํƒ์„ ๋ฐฐํฌํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ๋งŽ์€ ๋„๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ˆ˜์—…์€ ์‹ค์ˆ˜๋ฅผ ํ”ผํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€