如何將 Terraform 狀態遷移至 GitLab CI/CD

身為處理基礎設施即代碼(IaC)的軟體專業人士,您很可能經常與Terraform打交道。在協助新客戶使用IaC時,簡化流程是常見做法,但管理Terraform狀態檔案卻是您面臨的首要挑戰。實質上,Terraform狀態包含了敏感資訊,不應存放於原始碼控制中,但若有多位使用者共用同一Terraform狀態,則此方法亦難以擴展。解決之道?後端服務。

值得注意的是,您可以將狀態檔案存於S3桶,並利用DynamoDB管理鎖定狀態。然而,此法將迫使您建立額外資源,使其成為複雜選項,尤其是當客戶使用GitLab時。GitLab近期降低了整合Terraform的門檻,提供了儲存與管理Terraform狀態的方法,以及簡便的CI設置方式。

本文將說明何謂Terraform狀態檔案、如何將其遷移至GitLab,以及如何為其建立CI管線。您可訪問我們的儲存庫這裡

目錄

  • 什麼是Terraform狀態?
  • 如何讓GitLab管理Terraform狀態
  • 如何讓GitLab透過CI管線執行您的IaC
    • 額外提示:Infracost
  • 結論

什麼是Terraform狀態?

Terraform透過狀態檔案記錄您程式碼中定義的基礎設施相關資訊。以JSON格式撰寫,主要記錄了Terraform程式碼與實際建立的資源之間的對應關係。以下是一個terraform.tfstate檔案的範例。基本上,每當您執行Terraform時,它會取得EC2實例的最新狀態,並與您的Terraform設定進行比較,以決定需要應用哪些變更:

 

{   
     "version": 4,    
     "terraform_version": "0.12.0",    
     "serial": 1,    
     "lineage": "1f2087f9-4b3c-1b66-65db-8b78faafc6fb",    
     "outputs": {},    
     "resources": [     
      {        
         "mode": "managed",        
         "type": "aws_instance",       
         "name": "example",       
         "provider": "provider.aws",       
         "instances": [         
           {           
             "schema_version": 1,           
             "attributes": {              
               "ami": "ami-0c55b159cbfafe1f0",             
               "availability_zone": "us-west-2a",             
               "id": "i-00a123a0accffffff",            
               "instance_state": "running",             
               "instance_type": "t2.micro",            
               "(...)": "(truncated)"           
            }         
          }       
        ]      
      }   
    ]  
 }

預設情況下,此terraform.tfstate檔案會儲存在您存放Terraform檔案、計劃及應用變更的本地位置。對於個人專案,僅用於進行一些測試時,這樣做尚可接受,但並非推薦方式,原因如下:

  • 儲存在共用位置: 若您將此狀態檔案託管在本地工作站,並需與其他工程師協作,情況將變得複雜。你們兩人都必須確保使用的是最新版本的狀態檔,並且如果同時執行Terraform計劃或應用,可能會遇到競爭條件。
  • 保護敏感資訊: 生成的狀態檔案可能包含加密金鑰和基礎設施密碼。然而,狀態檔案預設並未加密,將敏感資訊以明文儲存並非明智之舉。
  • 鎖定機制: 大多數版本控制系統不支援任何形式的鎖定,這阻止了兩個團隊成員同時對同一狀態檔案執行Terraform apply。這是另一個原因,為何我們不會看到由版本控制管理的狀態檔案。

如何在GitLab上管理Terraform狀態

隨著Terraform被視為雲基礎設施配置的標準,GitLab自一年前開始提供存儲和管理Terraform狀態的方法。因此,我們想與您分享遷移過程,因為我們最近開始使用GitLab來管理我們的IaC。

本文假設您正在使用本地狀態,並且您的狀態由AWS S3 Bucket或其他後端解決方案管理。

首先,您需要將backend.tf更改為使用HTTP:

 

terraform {  
    backend "http" {} 
  }

接下來,您需要在終端中設置四個變量:

1. PROJECT_ID:您可以通過導航到“項目概覽”頁面上的您的repo輕鬆找到此信息。

2. TF_USERNAME:具有訪問您正在工作的repo權限的GitLab用戶名。

3. TF_PASSWORD:從您的GitLab用戶生成的訪問令牌。

4. TF_ADDRESS:遠程狀態後端的URL。

 

PROJECT_ID="28450092"
TF_USERNAME="florianpialoux"
TF_PASSWORD="123456789"
TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/aws-buckets"

現在,您可以運行遷移命令,將您的Terraform狀態從先前的位置移動到GitLab,使用以下命令:

 

  terraform init \  
    -migrate-state \  
    -backend-config=address=${TF_ADDRESS} \  
    -backend-config=lock_address=${TF_ADDRESS}/lock \ 
    -backend-config=unlock_address=${TF_ADDRESS}/lock \  
    -backend-config=username=${TF_USERNAME} \ 
    -backend-config=password=${TF_PASSWORD} \  
    -backend-config=lock_method=POST \ 
    -backend-config=unlock_method=DELETE \ 
    -backend-config=retry_wait_min=5

您需要通過輸入“”來確認,以便GitLab可以開始管理您的狀態文件。這裡有一個從本地狀態遷移到GitLab的例子:


從S3遷移到GitLab的例子:

Now, you can navigate to Infrastructure > Terraform from the GitLab interface and see your state:

I noticed for some of the state files I had from S3 will be blank even after using the migrate-state command ran previously. In this case, you can run this:  

 
terraform state pull > aws-buckets.json

從S3狀態複製並粘貼內容,然後運行推送:

 
terraform state push -lock=true aws-buckets.json

GitLab支援對您的Terraform狀態檔案進行版本控制,但若要透過WebUI查看或恢復舊版本,則需使用GitLab Premium計劃。若非如此,您將需要透過GraphQL API 請求來操作。

如何在CI管線中讓GitLab執行您的IaC

GitLab提供一個Docker映像,內含GitLab-Terraform,這是一個圍繞官方Terraform二進制文件的薄型包裝腳本。或者,您也可以使用Hashicorp的官方Docker映像。更多關於GitLab Terraform映像的資訊可在此查閱。

一旦Terraform apply作業運行,您將能夠看到狀態被使用的時間以及使用哪個管線。

Learn more about what our gitlab-ci.yml looks like here. Below, are the variables that will need to be defined on the project level.

額外提示:Infracost

如您所見,在我們的gitlab-ci.yaml中加入了Infracost,這使我們能更有效地控制雲端計費,因為每當您在IaC中定義新資源時,它會提供成本估算。

結論

在GitLab上運行Terraform狀態和CI是遵循GitOps最佳實踐的絕佳方式。這兩者結合起來,非常適合開發和部署基礎設施即代碼(IaC)。鑒於大多數人可能已經在使用GitLab管理代碼庫,將IaC整合在同一平台下,並讓GitLab通過支持傳輸中和靜態加密、版本控制、狀態鎖定和解鎖來管理您的Terraform狀態,變得更加簡單。

Source:
https://dzone.com/articles/how-to-migrate-terraform-state-to-gitlab-cicd