Terraform踩坑記之:Azure Provider配置

Terraform踩坑記之:Azure Provider配置

好久沒用Terraform管理Azure上面的資源了,這周有時間複習了一下,卻發現在使用Azure Provider的時候又出了幺蛾子。

根據Terraform官方文檔關於Azure Provider的使用說明,首先你得先配置一下Azure相關的認證信息。其實就跟你平時使用Azure一樣,你想使用Azure,那第一步就是你必須打開Azure portal進行登錄,就是使用你的用戶名和密碼認證登錄到Azure上去,然後開始幹活。現在你要用Terraform來操作Azure資源,那你得告訴Terraform怎麼才能登錄到Azure,方便它替你幹活。

那接下來,我們就一起看一下在使用Terraform的時候,怎麼來配置Azure provider。關於Azure認證方式,Terraform官方,其實應該是微軟給出了四種認證方式,你可以在terraform中配置,見下圖:

Terraform踩坑記之:Azure Provider配置

詳細信息,請移步:

https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs#authenticating-to-azure

第一種方式:Azure Provider: Authenticating using the Azure CLI

這個比較直接,首先你需要安裝Azure CLI,然後運行:

PS C:\lab> az login

然後會跳出來一個網頁,輸入你的用戶名密碼即可,然後你就可以愉快的使用Terraform和Azure了,你登錄Azure的相關信息以及緩存到你本地電腦上了。所以這種方式最簡單,也不用在Terraform的代碼裏提及你的Azure認證信息,但是你換一臺電腦,再跑一下你的代碼,是跑不通的,你必須先安裝Azure CLI,再執行az login命令,然後跟着提示登錄Azure。

至於第二種和第三種方式這裏先不介紹了,這次踩坑是用第四種方式:

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的介紹:

Terraform踩坑記之:Azure 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海外版就不用擔心這個問題。好了,此次踩坑記就寫到這裏,希望能夠幫助大家。另外一點就是在閱讀相關技術文檔時,大家需要認真仔細一點,以防採坑。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章