很久沒用Terraform管理Azure上面的資源了,這周有時間複習了一下,卻發如今使用Azure Provider的時候又出了幺蛾子。windows
根據Terraform官方文檔關於Azure Provider的使用說明,首先你得先配置一下Azure相關的認證信息。其實就跟你平時使用Azure同樣,你想使用Azure,那第一步就是你必須打開Azure portal進行登陸,就是使用你的用戶名和密碼認證登陸到Azure上去,而後開始幹活。如今你要用Terraform來操做Azure資源,那你得告訴Terraform怎麼才能登陸到Azure,方便它替你幹活。api
那接下來,咱們就一塊兒看一下在使用Terraform的時候,怎麼來配置Azure provider。關於Azure認證方式,Terraform官方,其實應該是微軟給出了四種認證方式,你能夠在terraform中配置,見下圖:緩存
Terraform踩坑記之:Azure Provider配置 很久沒用Terraform管理Azure上面的資源了,這周有時間複習了一下,卻發如今使用Azure Provider的時候又出了幺蛾子。bash
根據Terraform官方文檔關於Azure Provider的使用說明,首先你得先配置一下Azure相關的認證信息。其實就跟你平時使用Azure同樣,你想使用Azure,那第一步就是你必須打開Azure portal進行登陸,就是使用你的用戶名和密碼認證登陸到Azure上去,而後開始幹活。如今你要用Terraform來操做Azure資源,那你得告訴Terraform怎麼才能登陸到Azure,方便它替你幹活。app
那接下來,咱們就一塊兒看一下在使用Terraform的時候,怎麼來配置Azure provider。關於Azure認證方式,Terraform官方,其實應該是微軟給出了四種認證方式,你能夠在terraform中配置,見下圖:ssh
詳細信息,請移步:https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs#authenticating-to-azureide
第一種方式:Azure Provider: Authenticating using the Azure CLIui
這個比較直接,首先你須要安裝Azure CLI,而後運行:this
PS C:\lab> az login
而後會跳出來一個網頁,輸入你的用戶名密碼便可,而後你就能夠愉快的使用Terraform和Azure了,你登陸Azure的相關信息以及緩存到你本地電腦上了。因此這種方式最簡單,也不用在Terraform的代碼裏說起你的Azure認證信息,可是你換一臺電腦,再跑一下你的代碼,是跑不通的,你必須先安裝Azure CLI,再執行az login命令,而後跟着提示登陸Azure。spa
至於第二種和第三種方式這裏先不介紹了,此次踩坑是用第四種方式:
Authenticating using a Service Principal with a Client Secret
因此這裏詳細說明一下這一種方式。
這種方式有個前提,你必須先在Azure上面建立Service Principal,具體詳細步驟請參考這個連接:
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret#creating-a-service-principal-in-the-azure-portal
Service Principal建立好以後,按照官網參考文檔,在provider.tf文件裏,就能夠配置provider azurerm的相關信息了,整個項目文件結構以下:
PS C:\lab\dev>tree ───dev │───main.tf │───provider.tf
provider.tf文件內容格式以下:
provider "azurerm" { # Whilst version is optional, we /strongly recommend/ using it to pin the version of the Provider being used version = "=2.4.0" subscription_id = "00000000-0000-0000-0000-000000000000" client_id = "00000000-0000-0000-0000-000000000000" client_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" tenant_id = "00000000-0000-0000-0000-000000000000" features {} }
說明一下:
subscription_id:你的Azure訂閱ID
client_id:建立Service Principal後的Application (client) ID
client_secret:建立Service Principal後,建立application secret
tenant_id:建立Service Principal後,application的Directory (tenant) ID
main.tf文件內容以下:
resource "azurerm_resource_group" "azure-tf-rg" { name = "terraform-eval" location = "chinaeast2" tags = { "env" = "dev" "location" = "China East2" } }
隨後terraform init走起,初始化沒問題。
PS C:\lab\dev> terraform init Initializing the backend... Initializing provider plugins... - Using previously-installed hashicorp/azurerm v2.40.0 Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to seeany changes that are required for your infrastructure. All Terraform commandsshould now work. If you ever set or change modules or backend configuration for Terraform,rerun this command to reinitialize your working directory. If you forget, othercommands will detect it and remind you to do so if necessary.
接着執行terraform plan
PS C:\lab\dev> terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not bepersisted to local or remote state storage. ------------------------------------------------------------------------ Error: Error building account: Error getting authenticated object ID: Error listing Service Principals: autorest.DetailedError{ Original:adal.tokenRefreshError{ message:"adal: Refresh request failed. Status Code = '400'. Response body: { \"error\":\"invalid_request\",\" error_description\":\"AADSTS90002: Tenant '00000000-0000-0000-0000-000000000000' not found. This may happen if there are no active subscriptions for the tenant. Check to make sure you have the correct tenant ID. Check with your subscription administrator.\\r\\n Trace ID: xxxx-1fxxx95-xxx6-xxx4-xxxxxx00\\r\\n Correlation ID: xxxxxxx-xxx-xxxxx\\r\\n Timestamp: 2020-12-11 07:02:40Z\",\" error_codes\":[90002],\" timestamp\":\"2020-12-11 07:02:40Z\",\" trace_id\":\"xxxx-1fxxx95-xxx6-xxx4-xxxxxx00\",\" correlation_id\":\"xxxx-1fxxx95-xxx6-xxx4xxxxxx00\",\" error_uri\":\"https://login.microsoftonline.com/error?code=90002\"}", resp:(*http.Response)(0xc0011c4b40)}, PackageType:"azure.BearerAuthorizer", Method:"WithAuthorization", StatusCode:400, Message:"Failed to refresh the Token for request to https://graph.windows.net/xxxx/servicePrincipals?%24filter=appId+eq+%xxxxxx00&api-version=1.6", ServiceError:[]uint8(nil), Response:(*http.Response)(0xc0011c4b40)} on provider.tf line 1, in provider "azurerm": 1: provider "azurerm" {
很差,飄紅了,認證出問題了,說Tenant id找不到,這都是copy的,不可能出錯。
接着往下看:error_uri":"https://login.microsoftonline.com
嗯,就是這裏,我是在Azure中國版上面建立的Service Principal,terraform去登陸的時候用的是Azure海外版的URI,那問題就出在這裏了。
再回去看看Terraform官網關於Azurerm Provider的介紹:
這下明白了,environment雖然是optional的,可是默認用的是public,也就是Azure海外版。問題根源找到了,改terraform代碼吧!添加environment參數,值設爲china便可。最終代碼以下:
provider "azurerm" { # Whilst version is optional, we /strongly recommend/ using it to pin the version of the Provider being used version = "=2.4.0" environment = "china" subscription_id = "00000000-0000-0000-0000-000000000000" client_id = "00000000-0000-0000-0000-000000000000" client_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" tenant_id = "00000000-0000-0000-0000-000000000000" features {} }
再來一把 terraform plan
PS C:\lab\dev> terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be ------------------------------------------------------------------------ An execution plan has been generated and is shown below.Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.azure-tf-rg will be created + resource "azurerm_resource_group" "azure-tf-rg" { + id = (known after apply) + location = "chinaeast2" + name = "terraform-eval" + tags = { + "env" = "dev" + "location" = "China East2" } } Plan: 1 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraformcan't guarantee that exactly these actions will be performed if"terraform apply" is subsequently run.
嗯,沒報錯,提示會add 1個新resource,接着走一個 terraform apply
PS C:\lab\dev> terraform apply An execution plan has been generated and is shown below.Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_resource_group.azure-tf-rg will be created + resource "azurerm_resource_group" "azure-tf-rg" { + id = (known after apply) + location = "chinaeast2" + name = "terraform-eval" + tags = { + "env" = "dev" + "location" = "China East2" } } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes azurerm_resource_group.azure-tf-rg: Creating... azurerm_resource_group.azure-tf-rg: Creation complete after 5s [id=/subscriptions/0000000-0000-0000-0000-0000000000/resourceGroups/terraform-eval] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
登陸你的Azure中國portal,去resource group裏看看,terraform-eval這個resource group被成功建立。搞定!
其實,這個坑只有你使用Azure中國版/美國政府版/德國版的時候纔會踩,使用Azure海外版就不用擔憂這個問題。好了,這次踩坑記就寫到這裏,但願可以幫助你們。另一點就是在閱讀相關技術文檔時,你們須要認真仔細一點,以防採坑。