クラウドでのIaC:Terraformのインストールと最初のスクリプトの実行/IaC in the Cloud: Installing Terraform and Running Your First Script

原文はこちら:https://blogs.oracle.com/developers/iac-in-the-cloud:-installing-terraform-and-running-your-first-script

前回のポストでは、開発者向けのTerraform概要をお伝えしました。できればそちらを読んでおいていただければ(あるいは既にTerraformに詳しいか)と思います、というのも今回のポストでは、TerraformをインストールしてOracle Cloud Infrastructureテナンシーとやり取りするためのモジュールを作成するところを説明していくからです。

今回、Terraformはローカルで動かしていくので、まずはTerraformをダウンロードしてインストールする必要があります。Hashicorpのダウンロードページで正規のバイナリを見つけ、インストールしましょう。インストールしたら、バージョンのチェックでインストールをテストします。このブログの公開時点では、コマンドは以下のような出力でした。

$ terraform -v
Terraform v0.14.5
view rawtf-version.sh hosted with ❤ by GitHub

OCI Terraform Providerのインストールと認証

OCI Terraform Providerを手動でダウンロードすることもできますが、Terraformにダウンロードさせたほうが簡単です。これは provider ブロックを設定しておくだけでできるので、ここでは手動ダウンロードはスキップします。OCI Terraform Providerについて見ていく前に、今後たびたび参照することになるTerraformレジストリのOCI Terraform Providerのドキュメントをブックマークしておくと便利ですよ。

OCI Terraform Providerの認証にはいくつかの選択肢がありますが、ここではAPIキー認証を使います。このやり方をおすすめするのは、もし既にOCI CLIがインストールしてあるなら(しておくべきです!)、必要な情報はCLIの設定ファイルを読むだけで手に入るからです。

CLIがないって?問題ありません。このドキュメントに必要な情報はすべて載っています。

以下の情報をチェックしておく必要があります:

  • tenancy_ocid

  • user_ocid

  • private_key_path

  • private_key_password (Optional - if private key is password protected)

  • fingerprint

  • region

わたしのローカルマシンからは以下のように取得しました:

これらの値をTerraformにセットする簡単な方法として、 TF_VAR_から始まる環境変数として設定しておくやり方があります。この特殊なプレフィックスを持った環境変数がスクリプトの中で有効になるように、お使いのOSごとに適切な方法で設定しておきましょう。例えばわたしのMacではこれらを .zshrc ファイルの中に設定しておき、ターミナルで常に有効になるようにしています。bashスクリプトを書いてその中からセットするのも良いでしょう。以下の変数をセットしておく必要があります:

export TF_VAR_tenancy_ocid=<tenancy_OCID>
export TF_VAR_compartment_ocid=<compartment_OCID>
export TF_VAR_user_ocid=<user_OCID>
export TF_VAR_fingerprint=<key_fingerprint>
export TF_VAR_private_key_path=<private_key_path>
export TF_VAR_private_key_password=<private_key_password>
export TF_VAR_region=<region>
view rawconfig-vars.sh hosted with ❤ by GitHub

echoしてセットされたか確認しましょう:

これで最初の .tf ファイルを作成する準備ができました。空のディレクトリに移動し、 provider.tf というファイルを作成してお使いのIDEで開きましょう。

trsharp at ora-recursivecodes-mb in /projects/terraform
$ cd /projects/terraform
$ mkdir my-first-tf && cd my-first-tf
$ touch provider.tf
$ code . 
view rawcreate.sh hosted with ❤ by GitHub

 provider.tf を以下のように設定して保存しましょう:

provider "oci" {
    tenancy_ocid = var.tenancy_ocid
    user_ocid = var.user_ocid
    private_key_path = var.private_key_path
    private_key_password = var.private_key_password
    fingerprint = var.fingerprint
    region = var.region
}
view rawprovider.tf hosted with ❤ by GitHub

次に、同じディレクトリに variables.tf というファイルを作成します。このファイルで、プロジェクトで使う変数を宣言しておきます。環境変数としてセットした値はプロジェクト内のどこかで対応する値として宣言されていないと使えないので、このファイルによって前述の TF_VAR でセットした変数を宣言します。

variable "compartment_ocid" {}
variable "tenancy_ocid" {}
variable "user_ocid " {}
variable "private_key_path" {}
variable "private_key_password" {}
variable "fingerprint" {}
variable "region" {}
view rawvariables.tf hosted with ❤ by GitHub

IDEの(もしくはOSの)別のターミナルを開いて、 terraform initを実行しましょう。最初にこれを実行すると、あなたがOCI Terraform Providerを使おうとしていることにTerraformが気づき、自動的にダウンロードしてくれます。以下のような出力になるでしょう:

$ terraform init     
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/oci...
- Installing hashicorp/oci v4.11.0...
- Installed hashicorp/oci v4.11.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should 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, other
commands will detect it and remind you to do so if necessary.
view rawinit.sh hosted with ❤ by GitHub

Terraform実行計画の作成と適用

Terraform CLIでは多くのコマンドが用意されていますが、最も多く使うことになるものを3つ挙げるなら、 planと apply 、そして destroy でしょう。開発の際には、 console コマンドも記述の検証、実験に使いやすいです(consoleのドキュメント)。

Planはどうなったん?

 plan コマンドを使うことで、なってほしい状態と現在の状態とを比較し、差分の実行計画を生成することができます。このコマンドは実際には何もせず、計画を生成するだけです。 plan コマンドを実行するのは、典型的にはスクリプトを検証し、計画がやってほしいことをやるものになっているのかチェックするために使います。以下のように実行してみましょう:

$ terraform plan
No changes. Infrastructure is up-to-date.
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
view rawplan.sh hosted with ❤ by GitHub

なるほど、まだリソースを定義していないので、計画もまだなしというわけです!では variables.tf を同じディレクトリで開いて、 bucket_namespace という変数をあなたのObject Storageネームスペースの値を指定しましょう。

ネームスペースって何?という方も、簡単にわかります

variable "bucket_namespace" {
    default = "toddrsharp"
}
view rawvariables.tf hosted with ❤ by GitHub

変数がセットされたかちょっと確認してみましょう:

$ terraform console
> var.bucket_namespace
"toddrsharp"
view rawconsole.sh hosted with ❤ by GitHub

想定どおりですね、すばらしい!ターミナルを抜けて、別のファイルを作成しましょう。 test.tfという名前にします。

困った、 詰まっちゃった!そうしたら、Terraform consoleで help とタイプしてヘルプを開きましょう。exit や CTRL+D 、 CTRL+Cで抜けられます。

Object Storageデータソースを使ってテナンシーのObject Storageのバケットをリストしましょう。 test.tfで以下を追加します:

data "oci_objectstorage_bucket_summaries" "bucket_summaries" {
    compartment_id = var.compartment_ocid
    namespace = var.bucket_namespace
}
view rawtest.tf hosted with ❤ by GitHub

コンソールでデータソースの値をチェックしてみましょう。前回のポストに書いたとおり、データソースの出力は data のプレフィックスにしている必要があり、また、オペレーションタイプとローカルラベルを記載します。

$ terraform console
> data.oci_objectstorage_bucket_summaries.bucket_summaries
(known after apply)
view rawconsole.sh hosted with ❤ by GitHub

あーっと、まだこの情報は取得できませんね。取得するには、 plan apply する必要があります。

 

Applyはどうやるんだい?

この計画はそんなに派手なものではないでしょうが、計画は計画です。 apply してみましょう。でもその前に、 output ブロックを追加してバケットサマリーを出力させます。

output "bucket_summaries" {
    value = data.oci_objectstorage_bucket_summaries.bucket_summaries
}
view rawtest.tf hosted with ❤ by GitHub

このPlanをApplyすると、テナンシー/ネームスペースの各バケットについてバケットサマリーオブジェクトのリストが参照できます。Terraformのsplat syntaxを使って、もう少し読みやすくしてみましょう。

output "bucket_summaries" {
    value = data.oci_objectstorage_bucket_summaries.bucket_summaries.bucket_summaries[*].name
}
view rawtest.tf hosted with ❤ by GitHub

apply をもう一度実行すると、もう少し読みやすいように出力されます。

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
bucket_summaries = tolist([
  "archive-demo",
  "barn-captures",
  "custom-images",
  "doggos",
  "insulin-helper-uploads",
  "micronaut-lab-assets",
  "object-upload-demo-public",
  "oss-storage-bucket",
  "readme-assets",
  "rocket-chat-uploads",
  "usage_reports",
  "wallet",
])
view rawapply.sh hosted with ❤ by GitHub

ここまで、実リソースの作成はまだやっておらず、基本的な変数の宣言、プロバイダー設定、データソースの読み取りと表示だけをやってきました。 test.tf にリソースブロックを追加して、新しいバケットの作成をさせ結果を表示してみましょう。また、先程のバケットサマリーをリストするデータソースはもう不要なので削除します。

resource "oci_objectstorage_bucket" "create_bucket" {
    # required
    compartment_id = var.compartment_ocid
    name = "my_new_bucket"
    namespace = var.bucket_namespace
    # optional
    access_type = "ObjectRead"
}
output "new_bucket" {
    value = oci_objectstorage_bucket.create_bucket
}
view rawtest.tf hosted with ❤ by GitHub

 terraform planを実行すると生成された計画を見られます。

$ terraform plan
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:
  # oci_objectstorage_bucket.create_bucket will be created
  + resource "oci_objectstorage_bucket" "create_bucket" {
      + access_type                  = "ObjectRead"
      + approximate_count            = (known after apply)
      + approximate_size             = (known after apply)
      + bucket_id                    = (known after apply)
      + compartment_id               = "ocid1.compartment.oc1..[redacted]"
      + created_by                   = (known after apply)
      + defined_tags                 = (known after apply)
      + etag                         = (known after apply)
      + freeform_tags                = (known after apply)
      + id                           = (known after apply)
      + is_read_only                 = (known after apply)
      + kms_key_id                   = (known after apply)
      + name                         = "my_new_bucket"
      + namespace                    = "toddrsharp"
      + object_events_enabled        = (known after apply)
      + object_lifecycle_policy_etag = (known after apply)
      + replication_enabled          = (known after apply)
      + storage_tier                 = (known after apply)
      + time_created                 = (known after apply)
      + versioning                   = (known after apply)
    }
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
  - bucket_summaries = [
      - "archive-demo",
      - "barn-captures",
      - "custom-images",
      - "doggos",
      - "insulin-helper-uploads",
      - "micronaut-lab-assets",
      - "object-upload-demo-public",
      - "oss-storage-bucket",
      - "readme-assets",
      - "rocket-chat-uploads",
      - "usage_reports",
      - "wallet",
    ] -> null
  + new_bucket       = {
      + access_type                  = "ObjectRead"
      + approximate_count            = (known after apply)
      + approximate_size             = (known after apply)
      + bucket_id                    = (known after apply)
      + compartment_id               = "ocid1.compartment.oc1..[redacted]"
      + created_by                   = (known after apply)
      + defined_tags                 = (known after apply)
      + etag                         = (known after apply)
      + freeform_tags                = (known after apply)
      + id                           = (known after apply)
      + is_read_only                 = (known after apply)
      + kms_key_id                   = (known after apply)
      + metadata                     = null
      + name                         = "my_new_bucket"
      + namespace                    = "toddrsharp"
      + object_events_enabled        = (known after apply)
      + object_lifecycle_policy_etag = (known after apply)
      + replication_enabled          = (known after apply)
      + retention_rules              = []
      + storage_tier                 = (known after apply)
      + time_created                 = (known after apply)
      + timeouts                     = null
      + versioning                   = (known after apply)
    }
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
view rawplan.sh hosted with ❤ by GitHub

想定通り、バケットサマリーのリストは出力から削除され、新しいバケットの作成と結果の表示が追加されています。ただし最後のNoteを見てみましょう。 -out パラメータを追加すると、計画をディスクに保存することができます。やってみましょう。

$ terraform plan -out test
[removed for brevity]
This plan was saved to: test
To perform exactly these actions, run the following command to apply:
    terraform apply "test"
view rawsave-plan.sh hosted with ❤ by GitHub

計画が保存されました。見てみましょう。

うーん、、、バイナリー形式みたいですね。読むのは難しそうです。でもこの保存された計画をapplyすることはできます。

$ terraform apply test    
oci_objectstorage_bucket.create_bucket: Creating...
oci_objectstorage_bucket.create_bucket: Creation complete after 1s [id=n/toddrsharp/b/my_new_bucket]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the <code class="code-inline">terraform show</code> command.
State path: terraform.tfstate
Outputs:
new_bucket = {
  "access_type" = "ObjectRead"
  "approximate_count" = "0"
  "approximate_size" = "0"
  "bucket_id" = "ocid1.bucket.oc1.[redacted]"
  "compartment_id" = "ocid1.compartment.oc1..[redacted]"
  "created_by" = "ocid1.user.oc1..[redacted]"
  "defined_tags" = tomap({
    "Oracle-Tags.CreatedBy" = ""
    "Oracle-Tags.CreatedOn" = "2021-02-02T14:00:30.661Z"
  })
  "etag" = "b92e2a05-8d63-466b-afe3-0932605f0ce7"
  "freeform_tags" = tomap({})
  "id" = "n/toddrsharp/b/my_new_bucket"
  "is_read_only" = false
  "kms_key_id" = tostring(null)
  "metadata" = tomap(null) /* of string */
  "name" = "my_new_bucket"
  "namespace" = "toddrsharp"
  "object_events_enabled" = false
  "object_lifecycle_policy_etag" = tostring(null)
  "replication_enabled" = false
  "retention_rules" = toset([])
  "storage_tier" = "Standard"
  "time_created" = "2021-02-02 14:00:30.676 +0000 UTC"
  "timeouts" = null /* object */
  "versioning" = "Disabled"
}
view rawapply.sh hosted with ❤ by GitHub

素晴らしい!バケットが作成されたようです。OCI CLIを使って確認してみましょう。

$ oci os bucket get --bucket-name my_new_bucket --region us-phoenix-1 \
> | jq '.data | {name: .name, createdOn: ."time-created"}’           
{
  "name": "my_new_bucket",
  "createdOn": "2021-02-02T14:00:30.676000+00:00"
}
view rawbucket.sh hosted with ❤ by GitHub

OCIコンソールでも確認できます。

待ってください!間違えてバケットをパブリックバケットとして作ってしまいました。これではダメです、プライベートに変更する必要があります。Terraformスクリプトに戻ってプロパティを更新し、 apply を再実行しましょう。

resource "oci_objectstorage_bucket" "create_bucket" {
    # required
    compartment_id = var.compartment_ocid
    name = "my_new_bucket"
    namespace = var.bucket_namespace
    # optional
    access_type = "NoPublicAccess" # <---- updated
}
view rawtest.tf hosted with ❤ by GitHub

再実行すると、Terraformが現状(バケットが既に存在している)を理解しており、作成するのではなく更新することに決めたのに気づくでしょう。また、アクセスタイプの変更も指摘し、何をしようとしているかも教えてくれます。

$ terraform apply
oci_objectstorage_bucket.create_bucket: Refreshing state... [id=n/toddrsharp/b/my_new_bucket]
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place
Terraform will perform the following actions:
  # oci_objectstorage_bucket.create_bucket will be updated in-place
  ~ resource "oci_objectstorage_bucket" "create_bucket" {
      ~ access_type           = "ObjectRead" -> "NoPublicAccess"
        id                    = "n/toddrsharp/b/my_new_bucket"
        name                  = "my_new_bucket"
        # (16 unchanged attributes hidden)
    }
Plan: 0 to add, 1 to change, 0 to destroy.
Changes to Outputs:
  ~ new_bucket = {
      ~ access_type                  = "ObjectRead" -> "NoPublicAccess"
        # (22 unchanged elements hidden)
    }
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
oci_objectstorage_bucket.create_bucket: Modifying... [id=n/toddrsharp/b/my_new_bucket]
oci_objectstorage_bucket.create_bucket: Modifications complete after 3s [id=n/toddrsharp/b/my_new_bucket]
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
view rawapply.sh hosted with ❤ by GitHub

コンソールで変更が適用されたことを確認しましょう。

 

 

Destroyはどうやるのい?

なんらかの理由でTerraformプロジェクトで作成したすべてのインフラストラクチャを削除したい場合は、 terraform destroyを実行することでそれができます。

$ terraform destroy           
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy
Terraform will perform the following actions:
  # oci_objectstorage_bucket.create_bucket will be destroyed
  - resource "oci_objectstorage_bucket" "create_bucket" {
      - access_type           = "NoPublicAccess" -> null
      - approximate_count     = "0" -> null
      - approximate_size      = "0" -> null
      - bucket_id             = "ocid1.bucket.oc1.[redacted]" -> null
      - compartment_id        = "ocid1.compartment.oc1..[redacted]" -> null
      - created_by            = "ocid1.user.oc1..[redacted]" -> null
      - defined_tags          = {
        } -> null
      - etag                  = "ac1ae994-7a46-4709-bf22-28e78fc28a62" -> null
      - freeform_tags         = {} -> null
      - id                    = "n/toddrsharp/b/my_new_bucket" -> null
      - is_read_only          = false -> null
      - metadata              = {} -> null
      - name                  = "my_new_bucket" -> null
      - namespace             = "toddrsharp" -> null
      - object_events_enabled = false -> null
      - replication_enabled   = false -> null
      - storage_tier          = "Standard" -> null
      - time_created          = "2021-02-02 14:00:30.676 +0000 UTC" -> null
      - versioning            = "Disabled" -> null
    }
Plan: 0 to add, 0 to change, 1 to destroy.
Changes to Outputs:
  - new_bucket = {
      - access_type                  = "NoPublicAccess"
      - approximate_count            = "0"
      - approximate_size             = "0"
      - bucket_id                    = "ocid1.bucket.oc1.[redacted]"
      - compartment_id               = "ocid1.compartment.oc1..[redacted]"
      - created_by                   = "ocid1.user.oc1..[redacted]"
      - defined_tags                 = {
        }
      - etag                         = "ac1ae994-7a46-4709-bf22-28e78fc28a62"
      - freeform_tags                = {}
      - id                           = "n/toddrsharp/b/my_new_bucket"
      - is_read_only                 = false
      - kms_key_id                   = null
      - metadata                     = {}
      - name                         = "my_new_bucket"
      - namespace                    = "toddrsharp"
      - object_events_enabled        = false
      - object_lifecycle_policy_etag = null
      - replication_enabled          = false
      - retention_rules              = []
      - storage_tier                 = "Standard"
      - time_created                 = "2021-02-02 14:00:30.676 +0000 UTC"
      - timeouts                     = null
      - versioning                   = "Disabled"
    } -> null
Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.
  Enter a value: yes
oci_objectstorage_bucket.create_bucket: Destroying... [id=n/toddrsharp/b/my_new_bucket]
oci_objectstorage_bucket.create_bucket: Destruction complete after 3s
Destroy complete! Resources: 1 destroyed.
view rawdestroy.sh hosted with ❤ by GitHub

まとめ

このポストでは、TerraformとTerraform OCI Providerをインストールし、Oracle Cloudのインフラストラクチャを管理するための最初のTerraformスクリプトを作成、計画、適用しました。OCI ProviderはOracle Cloudのすべてのインフラストラクチャ要素をフルサポートしていることは覚えておいてくださいね。あなたのテナンシーで行う必要のあるオペレーションの仕様の詳細についてはドキュメントを参照ください。次のポストでは、ローカルではなくOracle Cloud上でTerraformを使用します!

0 件のコメント:

コメントを投稿