在 Azure 上使用 Terraform 時,如何排解常見問題

本文列出在 Azure 上使用 Terraform 時常見的問題及可能的解決方案。

如果你遇到 Terraform 特有的問題,請使用 HashiCorp 的社群支援管道。

HashiCorp Terraform 專屬支援管道

無法列出醫療提供者註冊狀態

錯誤訊息:

錯誤:無法列出提供者註冊狀態。 此錯誤可能是因為憑證無效,或是服務主體沒有使用 Resource Manager API 的權限。 Azure 錯誤:resources.ProvidersClient#List:回應要求失敗:StatusCode=403 -- 原始錯誤:autorest/azure:服務傳回錯誤。 Status=403 Code="AuthorizationFailed" 訊息="用戶端 '00000000-0000-0000-0000-000000000000' 的物件識別碼 '00000000-0000-0000-0000-000000000000' 未獲授權,無法在範圍 '/subscriptions/00000000-0000-0000-0000-000000000000' 上執行動作 'Microsoft.Resources/subscriptions/providers/read',或者該範圍無效。" 如果最近已授與存取權,請重新整理您的認證。」

背景:如果你從 Cloud Shell 執行 Terraform 指令,並定義某些 Terraform/Azure 環境變數,可能會遇到衝突。 下表列出環境變數及其代表的 Azure 值:

環境變數 Azure 值
ARM_SUBSCRIPTION_ID Azure 訂閱識別碼
ARM_TENANT_ID Microsoft 帳戶租用戶識別碼
ARM_CLIENT_ID Azure 服務主體應用程式識別碼
ARM_CLIENT_SECRET Azure 服務主體密碼

原因:截至目前,Cloud Shell 中執行的 Terraform 腳本會透過使用目前 Azure 訂閱的值覆蓋 ARM_SUBSCRIPTION_ID 和 ARM_TENANT_ID 環境變數。 因此,如果環境變數所參考的服務主體沒有對目前 Azure 訂閱的權利,Terraform 操作就會失敗。

取得狀態鎖時發生錯誤

錯誤訊息:

錯誤:取得狀態鎖時錯誤;錯誤訊息:發生了2個錯誤:
* 狀態 blob 已經鎖定
* blob metadata “terraformlockid” 是空的
Terraform 會取得狀態鎖,以防止多個使用者同時寫入狀態。 請解決上述問題後再試一次。 大多數指令可以用「-lock=false」標記來關閉鎖定,但這並不建議。

背景: 如果你是在對 Terraform 狀態檔案執行 Terraform 指令,且只有這個錯誤訊息出現,以下原因可能適用。 此錯誤適用於本地及遠端狀態檔案。

原因: 造成這個錯誤有兩個可能的原因。 第一個原因是,某個 Terraform 指令已經在對狀態檔案執行操作,並且已強制鎖定該檔案,因此不會發生任何問題。 第二個可能原因是當指令執行時,狀態檔案與 CLI 之間發生了連線中斷。 這種中斷最常發生在使用遠端狀態檔案時。

解決: 首先,確定你沒有對狀態檔案執行任何指令。 如果你在處理本地狀態檔案,請檢查終端機是否執行任何指令。 或者,檢查你的部署管線,看看是否有正在執行的程式正在使用狀態檔案。 如果這個條件還是沒解決問題,可能是第二個原因觸發了錯誤。 對於儲存在 Azure 儲存體 帳號容器中的遠端狀態檔案,你可以找到該檔案並使用解除租約按鈕。

顯示 Azure 儲存體 容器終止租約按鈕的截圖。

如果你用其他後端來儲存狀態檔案,建議請參考 HashiCorp 的文件。

VPN 錯誤

有關解決 VPN 錯誤的資訊,請參閱文章《 排除混合 VPN 連線疑難處理》。

Terraform 計劃刪除並重新建立一個儲存帳號

Terraform 可能會在 Azure 更改 Terraform 外的儲存帳號後,刪除並重新建立一個 Azure 儲存帳號。 此行為可能發生於受支援的 Azure 儲存體帳戶備援轉換期間,其中 account_replication_type 會跨越非區域備援組(LRS、GRS、RA-GRS)與區域備援組(ZRS、GZRS、RA-GZRS)之間的界限。

在套用計畫前,請檢視建議的變更,並確認 Terraform 為何認為儲存帳戶替換是必要的。 重新建立儲存帳號可能會導致應用程式停機或資料遺失。

為了降低此風險:

  • 關閉管理儲存帳號的部署自動核准,並檢視每一個 terraform plan.
  • 在儲存帳號資源的lifecycle區塊中設定prevent_destroy = true。
  • 在開始轉換之前,暫時將 account_replication_type 加入到 ignore_changes。
  • 轉換完成後,執行 terraform apply -refresh-only 更新 Terraform 狀態,然後更新你的 Terraform 設定,使其與已部署的儲存帳號相符。
  • 僅在執行 ignore_changes 並確認其未回報任何非預期的變更後,才移除 terraform plan。

如需詳細轉換指引,請參閱防止 Terraform 漂移以取得有狀態的 Azure 資源。