IBM Cloudの既存リソースをTerraform管理下に置く
AWSの既存リソースをTerraformの管理下に入れる記事を見たので、IBM Cloudでも同じことできるだろうと手を動かした時のメモです。
偉大なる元記事
dev.classmethod.jp
TL;DR
- terraform importコマンドを使えば、IBM Cloud上のリソース作成状況を
terraform.tfstate
ファイルに落とせる。
- tfstateをもとにリソース定義のtfファイルを書けばOK。
検証環境
- macOS Catalina : 10.15.5
- Terraform : v0.12.26
- IBM Cloud CLI : 1.1.0+cc908fe-2020-04-29T09:33:25+00:00
- IBM Cloud Provider plug-in : 1.17.1
※ Terraform as a ServiceのIBM Cloud Schematicsでは未検証です。
※ IBM Cloud Schematicsを使う例はQiitaの記事が詳しい。
やること
シンプルな例として、作成済のNoSQL DBであるCloudantをTerraformの管理下に置きたい場合を考えます。
(1) ダミーのtfファイルを作成する
最初に中身が空のリソース定義を作成します。
# Provider定義
variable "ibmcloud_api_key" {}
variable "region" {}
provider ibm {
ibmcloud_api_key = var.ibmcloud_api_key
region = var.region
}
# Cloudantのインスタンスを作成するリソース定義 (中身空のダミー)
resource "ibm_resource_instance" "db_cloudant" {
}
(2) terraform importでCloud上のリソースの状態をterraform.tfstateに取り込む
ドキュメントのimport コマンドの説明に沿ってIBM Cloud上のリソースの作成状態をローカルファイル (terraform.tfstateファイル) に取り込みます。
インポートする対象リソースのID(CRNも可)をする必要があるので、事前にIBM Cloud CLIでIDを取得しておきましょう。
$ terraform init
$ ibmcloud resource service-instance ponz-cloudant --output json | jq -r '.[] | .id'
crn:v1:bluemix:public:cloudantnosqldb:jp-tok:a/123abc:7890abc::
$ terraform import ibm_resource_instance.db_cloudant crn:v1:bluemix:public:cloudantnosqldb:jp-tok:a/123abc:7890abc::
(3) terraform planで必要パラメータと差分を出力
(2)でIBM Cloud上のCloudantの状態を取り込むと、terraform.tfstateファイルの中に以下のようなJSONが出力されます。
{
"mode": "managed",
"type": "ibm_resource_instance",
"name": "db_cloudant",
"provider": "provider.ibm",
"instances": [
{
"schema_version": 0,
"attributes": {
"crn": "crn:v1:bluemix:public:cloudantnosqldb:jp-tok:a/123abc:7890abc::",
"id": "crn:v1:bluemix:public:cloudantnosqldb:jp-tok:a/123abc:7890abc::",
"location": "jp-tok",
"name": "demo-cloudant",
"parameters": null,
"plan": "lite",
"resource_controller_url": "https://cloud.ibm.com/services/",
"resource_crn": "crn:v1:bluemix:public:cloudantnosqldb:jp-tok:a/123abc:7890abc::",
"resource_group_id": "abc...",
"resource_group_name": "",
"resource_name": "demo-cloudant",
"resource_status": "active",
"service": "cloudantnosqldb",
"service_endpoints": null,
"status": "active",
"tags": [
"env:demo"
],
"timeouts": null
}
}
]
}
この状態でまずは terraform plan
を打ちます。
Error: Missing required argument
と必須項目チェックエラーが出力されます。
チェックエラーとなったすべての値を tfstate を参考にしながら埋めていきます。
terraform plan
で必須チェックエラーが出なくなるまで定義を埋めると以下のようなtfファイルになるはず。
resource "ibm_resource_instance" "db_cloudant" {
name = "ponz-cloudant"
service = "cloudantnosqldb"
location = var.region
plan = "lite"
}
これで完成です。まだ差分が出る場合はresourceブロック内をtfstateを参考にさらに埋めればOKです。
IBM Cloud Provider plug-inで作成できるリソース
IBM Cloudのリソースを管理するときに作成できるリソースは2種類に大別されます。
個別設定可能なリソースと、Resource Management resourceという区分で作成できるリソースの2種類です。
前者はAPI GatewayやCloudFoundryアプリケーション、Classic Infrastructureが該当します。これらは専用のリソース定義が用意されているのでこれらを使用すればリソースを簡単に作成できます。
後者は個別定義されていない(ほぼ)すべてのリソースを作成するためのリソース定義です。
NoSQLのCloudantや認証・認可のSaasのAppIDなどは、こちらに分類されます。 ドキュメント上の ibm_resource_instance
で作成できないか確認してみましょう。細かい設定は parameters
パラメータで指定します。
1点注意すべき点として、Terraform未対応のリソースがあります。
たとえば、IBM Cloud FunctionsはIAMベースの名前空間に存在する関数やトリガを管理できません。(ただし、CloudFoundryベースはサポートされている)
Terraform採用前にどのリソースが管理可能なのかドキュメントの確認をお勧めします。
--> Index of Terraform resources and data sources
terraform importでカバーできないこと
また、Terraformでリソース管理できても terraform import
だけでは完全に管理下に置けない場合があります。
最初からTerraformでIBM Cloudのリソースを作成した場合と、既存リソースを terraform import
した場合ではtfファイルが異なります。2つの場合を比較すると以下のような注意点がありました。
resource "ibm_resource_key" "key_db_cloudant_tf" {
name = "cloudant-credential-tf"
role = "Writer"
resource_instance_id = ibm_resource_instance.db_cloudant.id
}
既存リソースをすべて自動でとはいかないものの、Terraform管理下におくことができました。
ちなみにAnsibleにもIBM Cloudのリソースを管理するCollectionがあるようです。
次はAnsibleの学習がてらそちらを触ってみようかな。
以上。