原文はこちら: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 |
OCI Terraform Providerを手動でダウンロードすることもできますが、Terraformにダウンロードさせたほうが簡単です。これは provider
ブロックを設定しておくだけでできるので、ここでは手動ダウンロードはスキップします。OCI Terraform Providerについて見ていく前に、今後たびたび参照することになるTerraformレジストリのOCI Terraform Providerのドキュメントをブックマークしておくと便利ですよ。
OCI Terraform Providerの認証にはいくつかの選択肢がありますが、ここではAPIキー認証を使います。このやり方をおすすめするのは、もし既にOCI CLIがインストールしてあるなら(しておくべきです!)、必要な情報はCLIの設定ファイルを読むだけで手に入るからです。
CLIがないって?問題ありません。このドキュメントに必要な情報はすべて載っています。
以下の情報をチェックしておく必要があります:
わたしのローカルマシンからは以下のように取得しました:
これらの値を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> |
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 . |
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 |
| } |
次に、同じディレクトリに 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" {} |
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. |
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. |
なるほど、まだリソースを定義していないので、計画もまだなしというわけです!では variables.tf
を同じディレクトリで開いて、 bucket_namespace
という変数をあなたのObject Storageネームスペースの値を指定しましょう。
ネームスペースって何?という方も、簡単にわかります。
| variable "bucket_namespace" { |
| default = "toddrsharp" |
| } |
変数がセットされたかちょっと確認してみましょう:
| $ terraform console |
| > var.bucket_namespace |
| "toddrsharp" |
想定どおりですね、すばらしい!ターミナルを抜けて、別のファイルを作成しましょう。 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 |
| } |
コンソールでデータソースの値をチェックしてみましょう。前回のポストに書いたとおり、データソースの出力は data
のプレフィックスにしている必要があり、また、オペレーションタイプとローカルラベルを記載します。
| $ terraform console |
| > data.oci_objectstorage_bucket_summaries.bucket_summaries |
| (known after apply) |
あーっと、まだこの情報は取得できませんね。取得するには、 plan
を apply
する必要があります。
Applyはどうやるんだい?
この計画はそんなに派手なものではないでしょうが、計画は計画です。 apply
してみましょう。でもその前に、 output
ブロックを追加してバケットサマリーを出力させます。
| output "bucket_summaries" { |
| value = data.oci_objectstorage_bucket_summaries.bucket_summaries |
| } |
このPlanをApplyすると、テナンシー/ネームスペースの各バケットについてバケットサマリーオブジェクトのリストが参照できます。Terraformのsplat syntaxを使って、もう少し読みやすくしてみましょう。
| output "bucket_summaries" { |
| value = data.oci_objectstorage_bucket_summaries.bucket_summaries.bucket_summaries[*].name |
| } |
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", |
| ]) |
ここまで、実リソースの作成はまだやっておらず、基本的な変数の宣言、プロバイダー設定、データソースの読み取りと表示だけをやってきました。 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 |
| } |
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. |
想定通り、バケットサマリーのリストは出力から削除され、新しいバケットの作成と結果の表示が追加されています。ただし最後の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" |
計画が保存されました。見てみましょう。
うーん、、、バイナリー形式みたいですね。読むのは難しそうです。でもこの保存された計画を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" |
| } |
素晴らしい!バケットが作成されたようです。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" |
| } |
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 |
| } |
再実行すると、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. |
コンソールで変更が適用されたことを確認しましょう。
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. |
まとめ
このポストでは、TerraformとTerraform OCI Providerをインストールし、Oracle Cloudのインフラストラクチャを管理するための最初のTerraformスクリプトを作成、計画、適用しました。OCI ProviderはOracle Cloudのすべてのインフラストラクチャ要素をフルサポートしていることは覚えておいてくださいね。あなたのテナンシーで行う必要のあるオペレーションの仕様の詳細についてはドキュメントを参照ください。次のポストでは、ローカルではなくOracle Cloud上でTerraformを使用します!
0 件のコメント:
コメントを投稿