Day 25-reverse terraform: terraformer,从 infrastructure 产生 .tf 内容

本篇介绍 terraformer,除了 import 既有的 remote resource 到 terraform 中以外,还会尝试从 remote resource 的状态,逆向产生 .tf resource 与对应的 arguments

课程内容与代码会放在 Github 上: https://github.com/chechiachang/terraform-30-days

赛後文章会整理放到个人的部落格上 http://chechia.net/

追踪粉专可以收到文章的主动推播

https://ithelp.ithome.com.tw/upload/images/20210901/20120327NvpHVr2QC0.jpg


Terraform import review

如同 官方文件 import 中描述

  • Terraform 目前的 import 实作,只影响 state,不会产生 .tf resource。这是什麽意思?
  • 要 import 已经存在的 infra,却还要先写 .tf resource 再 import,这样不是很麻烦
  • terraform import 本身设计目的就是在 state manipulation,而不是在处理 resource

然而,由於 import 既有的 remote reosurce,并产生 .tf resource 需求十分常见

  • 例如中途导入既有的 infrastructure 就会一直做 terraform import
  • 但实际想要的其实是 terraform import + .tf resource generation

terraformer 能符合正样的需求

terraformer

Terraformer github 专案

  • 是一个 cli-tool
  • reverse terraform (terraform: .tf -> infra, terraformer: infra -> .tf)
  • 除了如 terraform import 产生 .state 以外
  • 也会一并产生 .tf / .json

terraformer 虽然是放在 GoogleCloudPlatform organization 下,但不是一个 google 的产品,而是由社群维护的 terraform 逆向工具

terraformer

  • 支援超多 providers,不管是主流公有云,各家小云,或是 saas 服务,都有支援

terraformer install

Github Terraformer 的安装会需要稍微注意

  • 由於 terraformer 也是会依赖各家的不同 api,透过中间不同的 provider,来产生实际与 remote resource API 互动的逻辑
  • 例如: azure 的 vm 应该要如何透过 api 取得 vm 资料,取得资料後又要如何产生 .tf resource
  • terraformer 核心是维护上述逻辑的抽象层,具体互动逻辑依赖 provider

除了有 terraformer 本身,要使用 azure 就要有 azure 的 provider plugin,以此类推

如果使用 source 来 build terraformer binary

  • go build terraformer 时需要选择需要的 provider build 即可
git clone [email protected]:GoogleCloudPlatform/terraformer.git
cd terraformer

go run build/main.go {azure}

或是使用事先 build 好的 release 版本

export PROVIDER=all
curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-darwin-amd64
chmod +x terraformer-${PROVIDER}-darwin-amd64
sudo mv terraformer-${PROVIDER}-darwin-amd64 /usr/local/bin/terraformer

使用 terraformer

terraformer version
Terraformer v0.8.17

然後把 plugin binary 放到 ~/.terraform.d/plugins/{darwin,linux}_amd64/ 目录下,让 terraformer 需要时去载入

wget https://releases.hashicorp.com/terraform-provider-azurerm/2.78.0/terraform-provider-azurerm_2.78.0_darwin_amd64.zip
unzip terraform-provider-azurerm_2.78.0_darwin_amd64.zip
mkdir -p ~/.terraform.d/plugins/darwin_amd64/
mv terraform-provider-azurerm_v2.78.0_x5 ~/.terraform.d/plugins/darwin_amd64/

example

我们开一个新 root module 作为 terraformer import 的工作目录

mkdir azure/foundation/virtual_network_terraformer
cd azure/foundation/virtual_network_terraformer

然後来 Github Terraformer azure doc 来查询支援 import 的 resource

  • 有些新的功能可能还不支援 terraform,或是 terraformer 还不支援,就不会出现
  • subnet 是支援的

依照文件所述,这边使用 service principal 来 auth

  • 也就是暂时使用 terraform 的 service principal,权限与 terraform 一样
  • 使用 terraform service principal 进行 auth

参照前面 09-iam-for-terraform 为 terraform 配置专属 service principal 的步骤,取得 auth 相关变数

APP_NAME=terraform-30-days
az ad sp list --display-name ${APP_NAME}

TENANT_ID=$(az ad sp list --display-name ${APP_NAME} | jq -r '.[0].appOwnerTenantId')
SERVICE_NAME=$(az ad sp list --display-name ${APP_NAME} | jq -r '.[0].servicePrincipalNames[0]')

az login --service-principal \
  --username ${SERVICE_NAME} \
  --tenant ${TENANT_ID} \
  --password ~/.ssh/terraform-30-days.keycrt > /tmp/azure-login-profile

export ARM_CLIENT_ID=$(cat /tmp/azure-login-profile | jq -r '.[0].user.name')
export ARM_CLIENT_CERTIFICATE_PATH="/Users/che-chia/.ssh/terraform-30-days.pfx"
export ARM_CLIENT_CERTIFICATE_PASSWORD=
export ARM_SUBSCRIPTION_ID=$(az account subscription list | jq -r '.[0].subscriptionId')
export ARM_TENANT_ID=$(cat /tmp/azure-login-profile | jq -r '.[0].tenantId')

将 auth export 到环境变数後,就可以使用 terraformer

terraformer import azure -h

terraformer import azure list

analysis
app_service
container
cosmosdb
data_factory
database
databricks
disk
dns
eventhub
keyvault
load_balancer
network_interface
network_security_group
private_dns
private_endpoint
public_ip
purview
redis
resource_group
scaleset
security_center_contact
security_center_subscription_pricing
storage_account
storage_blob
storage_container
subnet
synapse
virtual_machine
virtual_network

terraformer import azure -r subnet

2021/09/25 23:00:52 Testing if Service Principal / Client Certificate is applicable for Authentication..
2021/09/25 23:00:52 Using Service Principal / Client Certificate for Authentication
2021/09/25 23:00:52 Getting OAuth config for endpoint https://login.microsoftonline.com/ with  tenant 5dc1c3ed-d350-4c3b-ba3d-db5ac4bfe072


2021/09/25 23:01:36 Testing if Service Principal / Client Certificate is applicable for Authentication..
2021/09/25 23:01:36 Using Service Principal / Client Certificate for Authentication
2021/09/25 23:01:36 Getting OAuth config for endpoint https://login.microsoftonline.com/ with  tenant 5dc1c3ed-d350-4c3b-ba3d-db5ac4bfe072
2021/09/25 23:01:41 azurerm importing... subnet
2021/09/25 23:01:48 azurerm done importing subnet
2021/09/25 23:01:48 Number of resources for service subnet: 7
2021/09/25 23:01:48 Refreshing state... azurerm_subnet.tfer--dev-002D-3
2021/09/25 23:01:48 Refreshing state... azurerm_subnet.tfer--dev-002D-2
2021/09/25 23:01:48 Refreshing state... azurerm_subnet_network_security_group_association.tfer--aks-002D-subnet_network_security_group_association
2021/09/25 23:01:48 Refreshing state... azurerm_subnet_network_security_group_association.tfer--base-002D-external_network_security_group_association
2021/09/25 23:01:48 Refreshing state... azurerm_subnet.tfer--dev-002D-1
2021/09/25 23:01:48 Refreshing state... azurerm_subnet.tfer--base-002D-external
2021/09/25 23:01:48 Refreshing state... azurerm_subnet.tfer--aks-002D-subnet
2021/09/25 23:01:53 Filtered number of resources for service subnet: 7
2021/09/25 23:01:53 azurerm Connecting....
2021/09/25 23:01:53 azurerm save subnet
2021/09/25 23:01:53 azurerm save tfstate for subnet

import results

cd azure/foundation/compute_network_terraformer
tree
.
└── generated
    └── azurerm
        └── subnet
            ├── outputs.tf
            ├── provider.tf
            ├── subnet.tf
            ├── subnet_network_security_group_association.tf
            ├── terraform.tfstate
            └── variables.tf

内容是在 terraform service principal 中可见的 subnets,已经变成 .tf,然而内容还需要整理

don't commit generated files

不要 commit 产生的 generated 资料夹到 git 上

  • state 档案不 commit,内有 sensitive data
  • .tf 档案都还蓄要整理内容

将 generated 加到 .gitignore 中


<<:  将自己的强项点好点满

>>:  Day 10 - 来谈谈在P5最常用的色彩学

Day9 - TextView(三)

如何让你的APP更独特 五颜六色的界面是一个很棒的范例 随便打开一个APP,他的字不可能都是黑色的,...

初学者跪着学JavaScript Day18 : 物件:new Map()

一日客语:中文:柚子 客语:U欸 是收集资料的类型 主要功用:可以用於快速搜索和查找资料 Map又称...

[第五只羊] 迷雾森林建筑工事 IV 专案环境设定 READY GO

天亮了 昨晚是平安夜 关於迷雾森林故事 小狼现身请睁眼 待洛神解释完了迷雾森林的由来 知悉了 ani...

Day 18 - 研习计画之工具评估与协作开发

开发框架 在昨日有提到负责後端的研习生的第一个功课是确定开发的框架,而在评估了一个月之後的考量对象包...

简单的先做 VS 技术难题先做

这个问题来自於我的专案执行的经验,也让大家一起想想看。 在收到专案後,第一个动作就是去寻找这个专案的...