?著作权归作者所有:来自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的介绍:

image.png

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

image.png