IBM Cloud Schematics (Terraform as a Service) を使って Classic VSI を立てる


# はじめに

2019年10月に IBM Cloud Schematics (Terraform as a Service) の GA が発表されました。

>[IBM Cloud Schematics: Enabling Infrastructure as Code | IBM](https://www.ibm.com/cloud/blog/announcements/ibm-cloud-schematics-enabling-infrastructure-as-code)

IBM Cloud VPC のサービス開始もあり、Terraform を使って、マルチクラウドのリソース管理をコードベースでおこなっていくという流れがあり、その実行環境としてマネージドサービスを提供するものです。

Terraform については、こちらの記事でおさらいできます。

>[IBM Bluemix IaaS で Terraform を使ってみた - Qiita](https://qiita.com/khayama/items/e1f070ba368ab5da335a)

# IBM Cloud Schematics (Terraform as a Service) の価値
以下のようなポイントになります。

>[About IBM Cloud Schematics](https://cloud.ibm.com/docs/schematics?topic=schematics-about-schematics)

- Terraform 実行環境を用意する必要がなくマネージドで提供される
- このサービス自体は無料で使える（注文したリソースには費用発生）
- API Key などの公開したくない変数を GUI からセキュアに格納できる
- テンプレート例が豊富に公開されている
- Terraform statefile `terraform.tfstate` などをマルチリージョンで保管してくれる

>[What information is stored when I decide to create a workspace with Schematics?](https://cloud.ibm.com/docs/schematics?topic=schematics-faqs#data-residency)
>By default, all information is encrypted in transit and at rest. To make your data highly available, all data is stored in the **US South** region and replicated to the **US East** region. Make sure that your data can reside in these regions before you start using Schematics.

# まずテンプレート例をみる
IBM Cloud の Github をみましょう。

>[terraform-provider-ibm/examples at master · IBM-Cloud/terraform-provider-ibm](https://github.com/IBM-Cloud/terraform-provider-ibm/tree/master/examples)

Classic VSI だと、このようなサンプルがありますが、こちらを少しカスタマイズして試してみたいと思います。

>[ibm-vsi](https://github.com/IBM-Cloud/terraform-provider-ibm/blob/master/examples/ibm-vsi/main.tf)

```terraform:main.tf
# Create single VSI in dal09. Hourly billed with private network connection only. 

resource "ibm_compute_vm_instance" "vm1" {
  hostname             = "vm1"
  domain               = "example.com"
  os_reference_code    = "CENTOS_7_64"
  datacenter           = "dal09"
  network_speed        = 100
  hourly_billing       = true
  private_network_only = true
  cores                = 1
  memory               = 1024
  disks                = [25]
  local_disk           = false
}
```

# 次に Provider ドキュメントをみる

>[IBM Cloud Provider for Terraform(tm) Documentation](https://ibm-cloud.github.io/tf-ibm-docs/index.html)

マルチクラウドにおけるクラウドリソース管理をおこなうためには、クラウドプロバイダごとの個別の設定が必要になってきます。
例えば、以下のような API Key の登録です。
通常ローカル環境では、 `terraform.tfvars` ファイルの中で変数を格納して管理しますが、IBM Cloud Schematics では GUI から変数をセキュアに格納できます。

```terraform:provider_example.tf
# Configure the IBM Cloud Provider
provider "ibm" {
  ibmcloud_api_key    = "${var.ibm_bmx_api_key}"
  iaas_classic_username = "${var.ibm_sl_username}"
  iaas_classic_api_key  = "${var.ibm_sl_api_key}"
}
```

API key の登録は、IAM-enabled サービスの場合は不要です。
API key の登録は、Cloud Foundry / Classic Infra サービスの場合は必須です。

>https://cloud.ibm.com/docs/schematics?topic=schematics-create-tf-config#configure-provider
>In Schematics, the API key is automatically retrieved for all IAM-enabled resources, including IBM Cloud Kubernetes Service clusters, and VPC infrastructure resources. However, the API key is not retrieved for Cloud Foundry and classic infrastructure resources and must be provided in the provider block

# Github レポジトリに `tf` ファイルを準備

ファイル内には最低限、provider と resource の記述をしておきましょう。
`terraform.tfvars` は不要です。

>[terraform.tfvars file](https://cloud.ibm.com/docs/schematics?topic=schematics-schematics-limitations&locale=dk#terraformtfvars)
>With IBM Cloud Schematics, you do not use a local terraform.tfvars file. Instead, you declare your variables in the Terraform configuration files, and enter the values for your variables when you create a workspace. You can later change the values of your variables by updating the variables from your workspace details page.

今回はこのようなファイルを準備しました。

>https://github.com/khayama/schematics-classic-vsi

```terraform:provider.tf
variable "iaas_classic_username" {
  description = "Enter the user name to access IBM Cloud classic infrastructure. You can retrieve the user name by following the instructions for retrieving your classic infrastructure API key."
}

variable "iaas_classic_api_key" {
  description = "Enter the API key to access IBM Cloud classic infrastructure. For more information for how to create an API key and retrieve it, see [Managing classic infrastructure API keys](https://cloud.ibm.com/docs/iam?topic=iam-classic_keys)."
}

provider "ibm" {
  iaas_classic_username = "${var.iaas_classic_username}"
  iaas_classic_api_key  = "${var.iaas_classic_api_key}"
}
```

```terraform:resource.tf
variable "datacenter" {
  type        = "string"
  description = "Ex) tok02, tok04, tok05, ..."
  default = "tok04"
}

variable "os_reference_code" {
  type        = "string"
  description = "Ex) CENTOS_LATEST_64, CENTOS_7_64, CENTOS_6_64, REDHAT_LATEST, UBUNTU_LATEST, WIN_LATEST_64, WIN_2016-STD_64, ..."
  default = "CENTOS_7_64"
}

variable "flavor_key_name" {
  type        = "string"
  description = "Ex) C1_1X1X100, B1_1X4X100, B1_2X4X100, B1_2X8X100, U1_1X2X100, U1_2X4X100, U1_4X8X100, ..."
  default = "B1_1X2X100"
}

resource "ibm_compute_vm_instance" "khayama-test" {
    hostname = "khayama-test"
    domain = "ibmcloud.com"
    os_reference_code = "${var.os_reference_code}"
    datacenter = "${var.datacenter}"
    network_speed = 100
    hourly_billing = true
    transient = true
    local_disk = false
    private_network_only = false
    flavor_key_name = "${var.flavor_key_name}"
    public_security_group_ids = [1287613]
    tags = ["user:khayama"]
    notes = "khayama's Resource created by Schematics"
}
```

# IBM Cloud Schematics ワークスペース作成
IBM Cloud コンソール ＞ Schematics ＞ Create Workspace から作成します。

![Kobito.pYVRVO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/3047a956-8fd4-c0a7-81b8-80d3c13d183d.png "Kobito.pYVRVO.png")

ワークスペース名を入力します。

![Kobito.MrxuTP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/dd05d6dd-348d-8d6a-5678-01e45f4952b3.png "Kobito.MrxuTP.png")

続いて、先ほど準備した `tf` ファイルがある Github レポジトリの URL を設定し、Retrieve input variables を押します。

![Kobito.Ras6Vx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/203a36dd-0644-40f5-1cb6-84eb4ea6afaa.png "Kobito.Ras6Vx.png")

ここで事前にファイルで設定した変数を設定できますが、変数はあとから設定もできるようになっています。
API Key などポータルに常に表示したくない場合は、このタイミングで設定し、Sensitive にチェックします。

![Kobito.YgrPyA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/832f15b7-f75e-4177-53b9-bd121e62228b.png "Kobito.YgrPyA.png")


# IBM Cloud Schematics 使い方
ワークスペース作成後の画面です。terraform のバージョンは、v0.11.14 でした。
先ほど設定したセキュアな変数は表示に対して保護されています。

![Kobito.wm4bJN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/73aa788a-bcd2-67f4-5c36-cc4975f4456d.png "Kobito.wm4bJN.png")

ここからは今まで通りの Terraform のやり方と同様です。

- Generate Plan = `terraform plan`
- Apply Plan = `terraform apply`
- Actions > Destroy resources = `terraform destroy`

リソースに変更を加える場合は、以下の流れになります。

- Github の `tf` ファイル変更 --> Pull Latest
- もしくは変数の中身変更
- Generate Plan
- Apply Plan

作業ログはこのような形で確認できます。

![Kobito.gKoFRa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/f62d907c-7b16-f1e1-aa65-3641712eb3f1.png "Kobito.gKoFRa.png")
![Kobito.BUkNwK.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/616581c6-b15a-afb0-b009-42b10aafb228.png "Kobito.BUkNwK.png")

# さいごに
実際には Apply Plan から Classic VSI のオーダーが確認できます。
今回はシンプルな構成でしたが、他にも IBM Cloud の様々なリソースタイプに対応しており、チュートリアルにあるような VPC の一連の構成を管理することもできるので、ぜひ試してみてください。

>[Getting started with IBM Cloud Schematics](https://cloud.ibm.com/docs/schematics?topic=schematics-getting-started)

# 参考

```
$ ibmcloud terraform version
                                              
Terraform version                          v0.11.14   
Terraform provider for IBM Cloud version   v0.19.1   
Helm Version                               v2.14.2   
Terraform provider for Helm version        v0.10.0   
```

# env

```
2019/12/10 16:16:56 Terraform apply | null_resource.example1: Creating...
 2019/12/10 16:16:56 Terraform apply | null_resource.example1: Provisioning with 'local-exec'...
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): Executing: ["/bin/sh" "-c" "env"]
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): OC_CLIENT_INSTALL_FILE=openshift-origin-client-tools-v3.11.0-0cbc58b-linux-64bit.tar.gz
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_MCCP_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): HOSTNAME=engine-1521-72d8n
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): TERRAFORM_GIT_URL=https://releases.hashicorp.com/terraform
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_UAA_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_IAM_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_CF_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): HOME=/home/nobody
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): OS_GIT_ASSET_ID=9096997
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_CSE_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_ACCOUNT_MANAGEMENT_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_CIS_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): OC_CLIENT_SHA256SUM=4b0f07428ba854174c58d2e38287e5402964c9a9355f6c359d1242efd0990da3
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_CR_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_CS_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): ANSIBLE_RECV_KEYS=93C4A3FD7BB9C367
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): TERRAFORM_SHA256SUM=9b9a4492738c69077b079e595f5b2a9ef1bc4e8fb5596610f69a6f322a8af8dd
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_GS_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_GT_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_IS_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_RESOURCE_CONTROLLER_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_RESOURCE_MANAGEMENT_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): TF_LOG=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): cccf35992f8f3cd8d1d28f0109dd953e26664531=7c28215aca87789f95b406b8dd91aa5198406750
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): GOPATH=/go
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): TERRAFORM_VERSION=0.11.14
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): OC_CLIENT_URL=https://api.github.com/repos/openshift/origin/releases/assets
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IC_IAM_REFRESH_TOKEN=ReXwyUl0PTn9v95vIiydYJ4uy07wIh1eA96ZY10o52DSR-xpjLyBD7Nzn9NbyNLBS1W4RLCCmERCzX9bCGnZcBTygtnv7yayUI6IfAODh-rxR1Nz0SjLKQS2CMi4AZdhGVaOIuLZCFKdry5CnxUxYOdlbZjFyhZhI-BjPq9667sB1jNmuK_MUXceYA7LmjVomXOoBxlFb_2j9EM2RvUs7jWbxMsbV07HJtdAts-HPlqqYXA206V9H35S2Byqx4kWokeY0tqlJsqFoh2NN9hKiwlzNKMPOdpMXadc1VVnpcD8rgm-4pNaU81MMJPHbCiG4qDXxRQmLHtEBTBE-XdSZEnJ71xjUvvLkoodGZHZyK4gNjvMkxEBzLt0afZjlhexBJ_jK_AC1EDbXCPQa0xL7C-uYd_6Il5MAU3l6CfyGPrIKwW5UezYTBZjiFUGaKD4VcDtH2LlDEoRWkgHjV_cj3yDmewlRLVJti8G9bPjP2xO2AQJtbW_lbZu8_MbLvnvqIFRWdUtnDQR_k2ztNQeSpeOYbIdU6ZJIgL3mIw5s-Zg7CSr-AcDDP6v5Sq7W2LIRbTpookLVkPnM3GgOON12NMtL1VPeUWDyoakszXXXlj7yO7UdSvbr94cO-bDiH6Nzoc-GfcZSDZWTqVuLjodLo7hG163fZWhY8jesmCnBOjG25I7CDlJEA4r05SFCzOF3YcaYWBteYSSYrbPxUFIKyZwUqBQv-sXl6xO0RRs5jaVkDLAkHtAFIn8PAFuaZ455_7lW1caEsyamtEn56SzVEmtA_LKhzGr6Agem8F0htygKCBcfjI1YnT0l30y7QLbidAY_AvAAJntc47FS_bTz-iNnN6FkD7FvndyXBBeJqEkTL7-Q_UeZWv2fKSJCRhtlHvUyEJiwD2T3qVOURnz5hJWFJdRyD9DL-SQN_TCYgsDcAq_-xYb82_CBxcabMvGJEQWB7NFVqhBjEvF3l4u5OnsbudQrm10x7eUUu3npyQ7kyvou5-K1pqKCANNPbewap0
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): PLUGIN_MIN_PORT=10000
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IC_IAM_TOKEN=eyJraWQiOiIyMDE5MDcyNCIsImFsZyI6IlJTMjU2In0.eyJpYW1faWQiOiJJQk1pZC0zMTAwMDBGR1lHIiwiaWQiOiJJQk1pZC0zMTAwMDBGR1lHIiwicmVhbG1pZCI6IklCTWlkIiwiaWRlbnRpZmllciI6IjMxMDAwMEZHWUciLCJnaXZlbl9uYW1lIjoiS3lvdWhlaSIsImZhbWlseV9uYW1lIjoiSGF5YW1hIiwibmFtZSI6Ikt5b3VoZWkgSGF5YW1hIiwiZW1haWwiOiJraGF5YW1hQGpwLmlibS5jb20iLCJzdWIiOiJLSEFZQU1BQGpwLmlibS5jb20iLCJhY2NvdW50Ijp7InZhbGlkIjp0cnVlLCJic3MiOiIwMzlkYmU2Nzk0MDg0YzdjYjUxNGEyNzZkZDIzNDVkYSIsImltc191c2VyX2lkIjoiNzQwNTk0NSIsImltcyI6IjE3NTY2MjMifSwiaWF0IjoxNTc1OTk0NTA5LCJleHAiOjE1NzU5OTgxMDksImlzcyI6Imh0dHBzOi8vaWFtLmNsb3VkLmlibS5jb20vaWRlbnRpdHkiLCJncmFudF90eXBlIjoiYXV0aG9yaXphdGlvbl9jb2RlIiwic2NvcGUiOiJpYm0gb3BlbmlkIiwiY2xpZW50X2lkIjoiYngiLCJhY3IiOjEsImFtciI6WyJwd2QiXX0.pbDWctLa_lQ18ajtdodcrVC84LnmpPgQbC7g_kMF2lHtBljIseaRiILDq7fbsH1GUUWfQ66hMGbUxTnoaeYObUFlaw3FN33DE5OAYWmgwZMVeeqTgDXLUjd0qNFiU68-U0ZeU4EZG5U_Jevncb5focO4oEE8M0VzNJ3dkyGRIdefrsAZPzpfD1COar_PiAQhh4dQiWCBL7HiOTrZ7FFWNj0mciQl6VLppL_oYC0RGpLmLJyjWkxA7Z2ddAke8smxaPgyklxHf997b80u5IoRCH7KA0JC8qDEXl07e8VoyozjbipdF1GOOpV_mYwHPvT72T8R-dsEdiwlFj4uS98H2w
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): PLUGIN_MAX_PORT=25000
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_RESOURCE_CATALOG_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): PWD=/tmp/tfws-978443656
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_IS_NG_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): TF_IN_AUTOMATION=1
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_IAMPAP_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): GOLANG_VERSION=1.12.13
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): IBMCLOUD_ICD_API_ENDPOINT=
 2019/12/10 16:16:56 Terraform apply | null_resource.example1 (local-exec): TF_PLUGIN_MAGIC_COOKIE=d602bf8f470bc67ca7faa0386276bbdd4330efaf76d1a219cb4d6991ca9872b2
 2019/12/10 16:16:56 Terraform apply | null_resource.example1: Creation complete after 1s (ID: 5367055281924629584)
```

# ping

```
2019/12/10 16:22:50 Terraform apply | null_resource.ping (local-exec): Executing: ["/bin/sh" "-c" "ping 10.0.80.11"]
2019/12/10 16:22:51 Terraform apply | null_resource.ping (local-exec): 64 bytes from 10.0.80.11: icmp_seq=2 ttl=251 time=0.344 ms
2019/12/10 16:22:52 Terraform apply | null_resource.ping (local-exec): 64 bytes from 10.0.80.11: icmp_seq=3 ttl=251 time=0.510 ms
2019/12/10 16:22:53 Terraform apply | null_resource.ping (local-exec): 64 bytes from 10.0.80.11: icmp_seq=4 ttl=251 time=0.394 ms
2019/12/10 16:22:54 Terraform apply | null_resource.ping (local-exec): 64 bytes from 10.0.80.11: icmp_seq=5 ttl=251 time=0.456 ms
```