Terraform 学习总结—— 简单记录 Azure CN 上 Terraform Provider 配置的一个坑

Posted 科技D人生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Terraform 学习总结—— 简单记录 Azure CN 上 Terraform 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 的介绍:

 这下明白了,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 海外版就不用担心这个问题。

创作打卡挑战赛 赢取流量/现金/CSDN周边激励大奖

以上是关于Terraform 学习总结—— 简单记录 Azure CN 上 Terraform Provider 配置的一个坑的主要内容,如果未能解决你的问题,请参考以下文章

Terraform 学习总结—— Terraform 常用命令再总结

Terraform 学习总结—— Terraform 常用命令再总结

Terraform 学习总结(10)—— 阿里云平台 Terraform 代码开发技巧总结

Terraform 学习总结(10)—— 阿里云平台 Terraform 代码开发技巧总结

Terraform 学习总结(10)—— 阿里云平台 Terraform 代码开发技巧总结

Terraform 学习总结——Terraform 命令详解