Terraform踩坑记之:Azure Provider配置

©著作权归作者所有:来自51CTO博客作者臭臭粑粑的原创作品,如需转载,请注明出处,否则将追究法律责任

好久没用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配置 好久没用Terraform管理Azure上面的资源了,这周有时间复习了一下,却发现在使用Azure Provider的时候又出了幺蛾子。

根据Terraform官方文档关于Azure Provider的使用说明,首先你得先配置一下Azure相关的认证信息。其实就跟你平时使用Azure一样,你想使用Azure,那第一步就是你必须打开Azure portal进行登录,就是使用你的用户名和密码认证登录到Azure上去,然后开始干活。现在你要用Terraform来操作Azure资源,那你得告诉Terraform怎么才能登录到Azure,方便它替你干活。

那接下来,我们就一起看一下在使用Terraform的时候,怎么来配置Azure provider。关于Azure认证方式,Terraform官方,其实应该是微软给出了四种认证方式,你可以在terraform中配置,见下图:

详细信息,请移步: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海外版就不用担心这个问题。好了,此次踩坑记就写到这里,希望能够帮助大家。另外一点就是在阅读相关技术文档时,大家需要认真仔细一点,以防采坑。

Terraform踩坑记之:Azure Provider配置


上一篇:Terraform,模块基础


下一篇:Terraform,变量详解