在雲端環境中,使用 CloudFormation 進行基礎設施即程式碼(IaC)的管理至關重要。為了確保 CloudFormation 範本的品質和可靠性,驗證和檢查範本是不可或缺的步驟。cfn-lint 提供了預設規則檢查,而 cloudformation-guard 則允許自定義規則,更靈活地符合特定需求。選擇合適的工具取決於專案規模和規範複雜度。佈署堆積疊時,除了基本的 create-stackupdate-stack 指令外,deploy 子命令提供更簡潔的佈署流程,並透過變更集預覽變更,提升安全性。然而,佈署過程中仍需注意資源的刪除保護設定,避免回復失敗導致資源殘留。妥善運用這些工具和技巧,能有效提升 CloudFormation 的使用效率,降低佈署風險。

驗證、程式碼檢查及佈署堆積疊

在前面的章節中,我們已經討論瞭如何撰寫CloudFormation範本,接下來我們將探討如何驗證和檢查這些範本,以確保它們符合最佳實踐和內部規範。我們將介紹兩個重要的工具:cfn-lintcloudformation-guard

使用cloudformation-guard進行自定義規則檢查

cloudformation-guard使用一種專門的領域特定語言(DSL)來撰寫規則。首先,我們需要在系統上安裝cloudformation-guard

安裝cloudformation-guard

在macOS上安裝非常簡單:

$ brew install cloudformation-guard

對於其他作業系統,如Ubuntu,我們需要使用curl指令:

$ curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/aws-cloudformation/cloudformation-guard/main/install-guard.sh | sh

對於Windows安裝,請參考官方:https://github.com/aws-cloudformation/cloudformation-guard#windows-10-install-rust-and-cargo。

編寫自定義規則

cloudformation-guard沒有像cfn-lint那樣預設的檢查規則,因此我們需要自行撰寫規則。下面是一個範例規則,用於檢查所有VPC子網路資源型別是否具有必要的標籤鍵:

let subnets = Resources.*[ Type == 'AWS::EC2::Subnet' ]
rule no_tags_assigned when %subnets !empty {
  %subnets.Properties.Tags[*] {
    Key in ["Env", "Name"]
    <<
      The subnet is missing Env or Name tag key
    >>
  }
}

執行規則檢查

執行以下指令來檢查範本:

$ cfn-guard validate \
  -d core_full.yaml \
  -r cfn_guard_rules/subnets_have_tags.guard

如果範本符合規則,則不會有任何輸出。讓我們針對一個故意缺少標籤的範本進行檢查:

$ cfn-guard validate \
  -d core_missing_tag.yaml \
  -r cfn_guard_rules/subnets_have_tags.guard

輸出將顯示不符合規範的資源和相關的錯誤訊息。

選擇適合的檢查工具

cfn-lintcloudformation-guard都是非常強大的工具,但它們有不同的優缺點。cfn-lint具有預設的檢查規則,而cloudformation-guard需要自行撰寫規則,但其DSL更簡單易用。

我們的建議

根據實際需求選擇合適的工具。如果您執行的是小型基礎設施並希望進行基本的檢查,cfn-lint是一個不錯的選擇。如果您有一套強大的內部規範並希望更容易地撰寫自定義規則,那麼cloudformation-guard是更好的選擇。

佈署堆積疊

在第1章中,我們使用簡單的指令建立了堆積疊:

$ aws cloudformation create-stack --stack-name ... --template-body file://...

這個指令呼叫了CloudFormation的CreateStack API。當我們需要更新堆積疊時,我們會呼叫UpdateStack API:

$ aws cloudformation update-stack --stack-name ... --template-body file://...

在這兩種情況下,AWS CLI都會呼叫ListStacks API方法來檢查堆積疊是否存在。

重要考量

在佈署堆積疊之前,請確保範本已經透過驗證和檢查,以避免錯誤和不符合規範的資源被建立。

佈署前的檢查清單

  1. 範本驗證:使用cfn-lintcloudformation-guard進行範本驗證。
  2. 資源檢查:檢查範本中的資源是否符合內部規範和最佳實踐。
  3. 引數檢查:檢查範本中的引數是否正確和完整。

佈署堆積疊的最佳實踐

  1. 使用版本控制:將範本儲存在版本控制系統中,以便跟蹤變更。
  2. 自動化佈署:使用CI/CD管道自動化佈署堆積疊。
  3. 監控和日誌記錄:監控堆積疊的效能和日誌記錄,以便及時發現問題。

隨著雲端運算技術的不斷發展,基礎設施即程式碼(IaC)的實踐將變得越來越重要。未來,我們可以期待看到更多與IaC相關的工具和技術的發展。

參考資料

程式碼範例

import boto3

# 建立 CloudFormation 使用者端
cf_client = boto3.client('cloudformation')

# 建立堆積疊
def create_stack(stack_name, template_body):
    try:
        response = cf_client.create_stack(
            StackName=stack_name,
            TemplateBody=template_body
        )
        print(response)
    except Exception as e:
        print(e)

# 更新堆積疊
def update_stack(stack_name, template_body):
    try:
        response = cf_client.update_stack(
            StackName=stack_name,
            TemplateBody=template_body
        )
        print(response)
    except Exception as e:
        print(e)

# 刪除堆積疊
def delete_stack(stack_name):
    try:
        response = cf_client.delete_stack(
            StackName=stack_name
        )
        print(response)
    except Exception as e:
        print(e)

內容解密:

上述 Python 程式碼範例展示瞭如何使用 Boto3 函式庫與 AWS CloudFormation 服務進行互動。程式碼中定義了三個函式:create_stackupdate_stackdelete_stack,分別用於建立、更新和刪除 CloudFormation 堆積疊。這些函式使用了 Boto3 的 cloudformation 使用者端來呼叫相應的 CloudFormation API 操作。

  1. 匯入 Boto3 函式庫:首先,程式碼匯入了 boto3 函式庫,這是一個 AWS 的 SDK for Python,它允許 Python 開發者撰寫軟體時使用 Amazon 服務。

  2. 建立 CloudFormation 使用者端:使用 boto3.client('cloudformation') 建立了一個 CloudFormation 的使用者端物件 cf_client,這個物件將被用來呼叫 CloudFormation 的 API。

  3. 定義建立堆積疊函式create_stack 函式接受堆積疊名稱和範本內容作為引數,使用 cf_client.create_stack 方法建立一個新的 CloudFormation 堆積疊。如果操作成功,它將列印預出回應內容;如果發生錯誤,它將捕捉異常並列印錯誤訊息。

  4. 定義更新堆積疊函式update_stack 函式同樣接受堆積疊名稱和範本內容作為引數,使用 cf_client.update_stack 方法更新指定的 CloudFormation 堆積疊。處理邏輯與建立堆積疊函式類別似。

  5. 定義刪除堆積疊函式delete_stack 函式接受堆積疊名稱作為引數,使用 cf_client.delete_stack 方法刪除指定的 CloudFormation 堆積疊。同樣地,它會處理可能的異常。

這些函式為管理和維護 CloudFormation 堆積疊提供了一個基礎的 Python 介面,可以根據具體需求進行擴充套件和定製。

  graph LR
    A[開始] --> B{是否建立堆積疊?}
    B --> |是| C[呼叫 create_stack 函式]
    B --> |否| D{是否更新堆積疊?}
    D --> |是| E[呼叫 update_stack 函式]
    D --> |否| F{是否刪除堆積疊?}
    F --> |是| G[呼叫 delete_stack 函式]
    F --> |否| H[結束]
    C --> H
    E --> H
    G --> H

圖表翻譯:

此圖表展示了一個簡單的流程控制圖,用於決定是否建立、更新或刪除 CloudFormation 堆積疊。流程從「開始」開始,然後根據條件判斷進行不同的操作:

  • 如果需要建立堆積疊,則呼叫 create_stack 函式。
  • 如果需要更新堆積疊,則呼叫 update_stack 函式。
  • 如果需要刪除堆積疊,則呼叫 delete_stack 函式。 流程最終都會回到「結束」。這個流程圖幫助理解在不同操作需求下,程式應該如何執行相應的函式。

使用變更集佈署堆積疊

變更集(Change Sets)是一組將在佈署期間應用於堆積疊的變更。我們可以建立、審查、執行或甚至刪除變更集,具體取決於這些變更是否符合預期。

佈署堆積疊步驟

  1. 建立堆積疊:首先,我們需要建立一個堆積疊。

    $ aws cloudformation create-stack \
    --stack-name core \
    --template-body file://core_partial.yaml \
    --parameters file://testing.json
    
  2. 建立變更集:接下來,我們為這個堆積疊建立一個變更集,其中包含額外的資源。

    $ aws cloudformation create-change-set \
    --stack-name core \
    --change-set-name our-change-set \
    --template-body file://core_full.yaml \
    --parameters file://testing.json \
    --capabilities CAPABILITY_IAM
    

    執行上述命令後,我們將收到類別似以下的輸出:

    {
      "Id": "arn:aws:cloudformation:REGION:ACCT_ID:changeSet/our-change-set/bd04aeb3-386b-44d7-a25c-5fe626c24aed",
      "StackId": "arn:aws:cloudformation:REGION:ACCT_ID:stack/core/00697420-1123-11ea-9d40-02433c861a1c"
    }
    
  3. 審查變更集:我們可以使用 AWS CLI 或 AWS 控制檯來審查這個變更集。

    • 使用 AWS CLI
      $ aws cloudformation describe-change-set \
      --change-set-name arn:aws:cloudformation:REGION:ACCT_ID:changeSet/our-change-set/bd04aeb3-386b-44d7-a25c-5fe626c24aed
      
      輸出結果將顯示變更的詳細資訊,例如:
      {
        "Changes": [
          {
            "Type": "Resource",
            "ResourceChange": {
              "Action": "Add",
              "LogicalResourceId": "AdminRole",
              "ResourceType": "AWS::IAM::Role",
              "Scope": [],
              "Details": []
            }
          },
          {
            "Type": "Resource",
            "ResourceChange": {
              "Action": "Add",
              "LogicalResourceId": "DevRole",
              "ResourceType": "AWS::IAM::Role",
              "Scope": [],
              "Details": []
            }
          }
        ]
      }
      

      內容解密:

      • 在這個變更集中,我們可以看到兩個新的 IAM 角色(AdminRole 和 DevRole)將被新增到堆積疊中。
      • Action 欄位表示將要執行的操作(新增、修改或刪除)。
      • LogicalResourceId 是資源在範本中的邏輯 ID。
      • ResourceType 表示資源的型別,例如 AWS::IAM::Role。
  4. 執行變更集:審查完成後,我們可以執行這個變更集。

    $ aws cloudformation execute-change-set --change-set-name our-change-set --stack-name core
    

使用 deploy 子命令

另一個有用的子命令是 deploy,它簡化了堆積疊的佈署過程。

$ aws cloudformation deploy --stack-name foo --template-file bar

create-stackupdate-stack 不同,deploy 是不可變的。如果堆積疊不存在,它將建立堆積疊;如果堆積疊已存在,它將更新堆積疊。

主要差異

  • deploy 使用變更集來執行堆積疊佈署。
  • deploy 使用 --template-file 引數而不是 --template-body
  • deploy 不支援引數檔案,而是使用 --parameter-overrides 來指定引數。
  • deploy 將等待堆積疊建立完成或失敗後才傳回結果。

示例

$ aws cloudformation deploy \
--stack-name core \
--template-file core_full.yaml \
--capabilities CAPABILITY_IAM \
--parameter-overrides \
VpcCidr="10.1.0.0/16" \
Environment="test"

內容解密:

  • 在這個例子中,我們使用 deploy 命令來佈署 core 堆積疊。
  • --template-file 指定了範本檔案的路徑。
  • --capabilities CAPABILITY_IAM 表示這個堆積疊需要建立 IAM 資源。
  • --parameter-overrides 用於覆寫範本中的引數。

處理錯誤

CloudFormation 堆積疊佈署的預設行為是在發生錯誤時回復到前一個狀態。然而,這在某些情況下可能會引起問題,例如當資源啟用了終止保護而建立失敗時,CloudFormation 將無法清理這些資源。

示例:啟用刪除保護的負載平衡器

// webtier_failing.yaml
WebTierLoadBalancer:
  Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer'
  Properties:
    DeletionProtection: true

內容解密:

  • 在這個例子中,我們定義了一個負載平衡器資源,並啟用了刪除保護。
  • 如果這個資源建立失敗並且堆積疊回復,CloudFormation 將無法刪除這個資源,因為它啟用了刪除保護。