構成の作成

Terraformを使用すると、HashiCorp Configuration Language (HCL)フォーマットでOracle Cloud InfrastructureについてTerraform構成ファイルに記述できます(構成構文を参照)。Terraform構成ファイルでは2つのフォーマットのいずれかを使用できます。Terraformドメイン固有の言語(HashiCorp Configuration Language (HCL)フォーマット)をお薦めします。また、マシン判読可能のファイルが必要な場合のためのJSONフォーマットがあります。HCLフォーマットを使用する構成ファイルのファイル拡張子は.tfです。JSONフォーマットを使用するファイルのファイル拡張子は.tf.jsonです。Terraformフォーマットは人が読むことができますが、JSONフォーマットはマシン判読可能です。

Terraform構成を使用して、Oracle Cloud Infrastructure (OCI)のリソース、変数定義、データ・ソース、その他多数を定義します。その後、Terraformは、OCI構成をOCI APIエンドポイントに対する一連のAPIコールに変換します。Terraform構成の作成で重要なのは、必要なインフラストラクチャをTerraform構成構文として概念的に抽象化する方法を理解することです。

重要

Oracle Cloud Infrastructure APIではキャメルケースのみが使用されますが、Terraformの構成ファイルではキャメルケースはサポートされません。このため、構成ではセパレータとして大文字ではなくアンダースコアが示されます。たとえば、APIではavailabilityDomainが使用されますが、Terraform構成ではavailability_domainが使用されます。

構成ファイルの要件

Terraform構成(.tf)ファイルには、ファイルで定義されるコンポーネントに応じて固有の要件があります。たとえば、Terraformプロバイダを1つのファイル(provider.tf)で定義し、変数を別のファイル(variables.tf)、データ・ソースをさらに別のファイルで定義することがあります。

ノート

構成ファイルの例は、Oracle Cloud Infrastructure GitHubのTerraformプロバイダの例を参照してください。

プロバイダの定義

次のTerraform構文の使用例では、OCI Terraformプロバイダ定義の要件を示し、さらに関連する変数定義も示しています。プロバイダ定義では、構成ファイル自体に機密データが含まれないように変数が利用されます。機密データが含まれていると、構成ファイルの交換時または共有時にセキュリティ・リスクが発生します。

variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "region" {}

provider "oci" {
   tenancy_ocid = "${var.tenancy_ocid}"
   user_ocid = "${var.user_ocid}"
   fingerprint = "${var.fingerprint}"
   private_key_path = "${var.private_key_path}"
   region = "${var.region}"
}

region属性は、プロバイダ・リソースが作成される地理的リージョンを指定します。単一の構成で複数のリージョンを対象にするには、各リージョンのプロバイダ定義を作成してから、次の例に示すようにプロバイダの別名を使用して区別します。「oci」という名前のプロバイダが1つのみ定義されていますが、ociプロバイダ定義は、us-phoenix-1リージョン(別名「phx」)に対して1回とus-ashburn-1リージョン(別名「iad」)に対して1回、計2回入力されています。

variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "compartment_ocid" {}

provider "oci" {
   region = "us-phoenix-1"
   alias = "phx"
   tenancy_ocid = "${var.tenancy_ocid}"
   user_ocid = "${var.user_ocid}"
   fingerprint = "${var.fingerprint}"
   private_key_path = "${var.private_key_path}"
}

provider "oci" {
   region = "us-ashburn-1"
   alias = "iad"
   tenancy_ocid = "${var.tenancy_ocid}"
   user_ocid = "${var.user_ocid}"
   fingerprint = "${var.fingerprint}"
   private_key_path = "${var.private_key_path}"
}

詳細は、Provider Configurationを参照してください。

変数の定義

Terraformの変数は、Terraformモジュールのパラメータを表します。変数の定義では、各ブロックが1つの入力変数を構成します。また、各定義に3つのオプションの引数のいずれか、またはすべてを指定できます:

  • type (オプション): 許可されている3つの値(stringlistmap)の1つとして、変数タイプを定義します。この引数が使用されない場合、変数の型はdefaultに基づいて推測されます。defaultが指定されない場合、型はstringであるとみなされます。
  • default (オプション): 変数のデフォルト値を設定します。デフォルト値が指定されない場合、コール元が値を指定する必要があります。指定しない場合はTerraformによってエラーがスローされます。
  • description (オプション): 人が読むことができる変数の説明です。

次に、いくつかの変数定義の例を示します。一部の定義には、オプション・パラメータが含まれます。

variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "region" {}

variable "AD" {
    default     = "1"
    description = "Availability Domain"
}

variable "CPUCoreCount" {
    default = "2"
    type    = "string"
}

詳細は、Input Variable Configurationを参照してください。Input Variablesも参照してください。

出力の構成

出力変数によって、Terraformエンド・ユーザー問合せをサポートする手段が提供されます。ユーザーは、これによって、複雑なインフラストラクチャに関連する潜在的な大量データから、意味のあるデータを抽出できます。たとえば、どのような時点でも関心を持つ重要な値はごく少数しかありません。出力変数を定義することによって、必要な情報を正確に抽出できます。

次に示す単純な例では、ごくわずかの出力変数(インスタンスのIPアドレスとブート・ボリュームID)が定義されています:

# Output the private and public IPs of the instance
output "InstancePrivateIPs" {
value = ["${oci_core_instance.TFInstance.*.private_ip}"]
}

output "InstancePublicIPs" {
value = ["${oci_core_instance.TFInstance.*.public_ip}"]
}

# Output the boot volume IDs of the instance
output "BootVolumeIDs" {
  value = ["${oci_core_instance.TFInstance.*.boot_volume_id}"]
}

詳細は、Output Variablesを参照してください。Output Configurationも参照してください。

リソース

リソースは、Oracle Cloud Infrastructureのコンポーネントです。このようなリソースには、下位レベルのコンポーネント(物理サーバーや仮想サーバーなど)から上位レベルのコンポーネント(電子メール・プロバイダ、データベース・プロバイダ、DNSレコードなど)まですべてが含まれます。

OCI Terraformプロバイダのサポートされているリソースおよびデータ・ソースの完全なリファレンスには、使用方法、引数および属性の詳細が含まれます。詳細は、docs.oracle.comおよびHashiCorp参照してください。

データ・ソースおよびリソースは、参照内のサービス別にグループ化されます。

注意

Terraform状態ファイルには、構成ファイルの一部として指定されているすべてのリソース属性が含まれています。データベース、ユーザー・パスワード、インスタンス秘密キーなどの機密データをTerraformで管理する場合は、状態ファイル自体を機密データとして扱う必要があります。詳細は、「機密データの状態」を参照してください。

リソースの宣言

次に示すのは、基本的な構造が記述されたリソース定義の簡単な例です。

resource "oci_core_virtual_network" "vcn1" {
   cidr_block = "10.0.0.0/16"
   dns_label = "vcn1"
   compartment_id = "${var.compartment_ocid}"
   display_name = "vcn1"
}

この例の最初の行のリソース宣言では、キーワードresourceが使用され、2つのパラメータとしてリソースのtypeとリソースの名前name (この例ではoci_core_virtual_networkとvcn1)が指定されています。その後のコード・ブロック内には、リソース構成があります。

詳細は、Resource Configurationを参照してください。

リソース依存性

リソースがそのリソース・ブロック内の別のリソースを参照する場合、Terraformは、参照されるリソースに対するプライマリ・リソースの依存性を自動的に推測します。リソースは、そのブロック内で明示的に参照されていないリソースに依存する場合もあります。たとえば、リソース自体を作成する前に、リソースのポリシーを作成する必要がある場合があります。

Terraformで自動的に推測できない非表示の依存性を定義するには、リソース・ブロックでdepends_onメタ引数を使用します。

次の例では、関連ポリシーのoci_datascience_notebook_sessionリソースおよびoci_identity_policyリソースを作成します。depends_onメタ引数をoci_datascience_notebook_sessionリソースに追加すると、ポリシーが最初に作成されます。

resource "oci_datascience_notebook_session" "ods-notebook-session" {
  count = var.enable_ods ? var.ods_number_of_notebooks : 0
 
  #Required
  compartment_id = var.compartment_ocid
  notebook_session_configuration_details {
   #Required
   shape = var.ods_compute_shape
   subnet_id = local.private_subnet_id
 
  #Optional
  block_storage_size_in_gbs = var.ods_storage_size
  }
  project_id = oci_datascience_project.ods-project[0].id
 
  display_name = "${var.ods_notebook_name}-${count.index}"

  depends_on = ["oci_identity_policy.ods-policy"]
 }

resource "oci_identity_policy" "ods-policy" {
  provider = oci.home
  compartment_id = var.compartment_ocid
  description = "Data Science Policies"
  name = var.ods_policy_name
  statements = var.enable_vault ? concat(local.ods_policies , local.vault_policies) : local.ods_policies
 }

別のスタック内のリソースの参照

他のスタックに存在するリソースを参照できます。Terraformのremote_stateデータ・ソースを使用すると、状態ファイルから出力変数を読み取ることができます。

たとえば、新しいWebアプリケーション用のTerraform構成を記述するとき、ネットワーク・スタックで以前に作成したサブネットをそのWebアプリケーションで使用できます(必要なサブネット値がネットワーク・スタックの状態ファイルに出力された場合のみ)。新しいWebアプリケーションのTerraform構成で、次を行います:

  • 既存のネットワーク・スタックの状態ファイルを現行のTerraform構成のコンテキストにプルします。
  • プルした状態ファイルを、リモート状態ファイルのデータ・ソースにロードします。
  • 現在の構成のサブネット・データ・ソースに、参照する状態ファイルの対応する出力変数の値を移入します。
  • オプションで、移入されたデータ・ソースの識別情報を出力し、予期した値であることを確認します。
ノート

リソース・マネージャ操作に必要な権限に加え、参照しているリソース・タイプの適切な権限が、それらを参照しているコンパートメントで必要です。この例では、ネットワーク・リソースが配置されているコンパートメントで、ネットワーク・リソースに対する読取り権限が必要です。

次のTerraform構成の抜粋は、別のスタック内のサブネットを参照しています。

# The following example assumes that the source stack (defined by `stack_id`) has output a value named `subnet_id`
# Terraform v0.12 is assumed

variable "stack_id" {}

# Pull the state file of the existing Resource Manager stack (the network stack) into this context
data "oci_resourcemanager_stack_tf_state" "stack1_tf_state" {
  stack_id   = "${var.stack_id}"
  local_path = "stack1.tfstate"
}

# Load the pulled state file into a remote state data source
data "terraform_remote_state" "external_stack_remote_state" {
  backend = "local"
  config = {
    path = "${data.oci_resourcemanager_stack_tf_state.stack1_tf_state.local_path}"
  }
}

# Populate a data source in this configuration using a value from the remote state data source
data "oci_core_subnet" "subnet1" {
  subnet_id = "${data.terraform_remote_state.external_stack_remote_state.outputs.subnet_id}"
}

# Print the values of the populated data source
output "print-subnet1" {
  value = "${data.oci_core_subnet.subnet1}"
}

データ・ソース

データ・ソースは、既存インフラストラクチャの読取り専用ビューを表し、Terraform構成でセマンティックとしての使用を対象としています。次のデータソース構成の単純な例は、基本的な構造を示しています:

# Gets a list of Availability Domains
data "oci_identity_availability_domains" "ADs" {
  compartment_id = "${var.tenancy_ocid}"
}

# Get DB node list
data "oci_database_db_nodes" "DBNodeList" {
  compartment_id = "${var.compartment_ocid}"
  db_system_id = "${oci_database_db_system.TFDBNode.id}"
}

# Get DB node details
data "oci_database_db_node" "DBNodeDetails" {
  db_node_id = "${lookup(data.oci_database_db_nodes.DBNodeList.db_nodes[0], "id")}"
}

# Gets the OCID of the first (default) vNIC
data "oci_core_vnic" "DBNodeVnic" {
  vnic_id = "${data.oci_database_db_node.DBNodeDetails.vnic_id}"
}

詳細は、Data Source Configurationを参照してください。

データ・ソースのフィルタリング

リソースのリストを返すデータ・ソースでは、フィルタリング・セマンティクスがサポートされます。フィルタを使用するには、データ・ソース定義に次のブロックを含めます:

filter {
    name = ""
    values = [""]
}

name値はフィルタに使用する修飾プロパティ名に対応し、valuesリストにはフィルタに使用する1つ以上の値を含めることができます。

ネストしたプロパティおよびマップ要素は、プロパティ名を親プロパティ名で修飾することで指定できます。例のr1は、source_typeイメージを持つすべてのインスタンスを提供します。例のr2は、ネームスペースOperationsのキーCostCenterで値が「42」の定義済タグを含むすべてのインスタンスを提供します。

data "oci_core_instances" "r1" {
  ...
  filter {
    name = "source_details.source_type"
    values = ["image"]
  }
}

data "oci_core_instances" "r2" {
  ...
  filter {
    name = "defined_tags.Operations.CostCenter"
    values = ["42"]
  }
}

複数のvaluesは、ORタイプ・フィルタとして機能します。次のシェイプの例では、結果のデータ・ソースにVMシェイプのStandard 1.1Standard 1.2の両方が含まれます:

data "oci_core_shape" "t" {
  ...
  filter {
    name = "name"
    values = ["VM.Standard1.1", "VM.Standard1.2"]
  }
}

複数のフィルタ・ブロックを組み合せると、ANDタイプ比較を構成できます。次の例では、リージョンの最初のAD実行中のインスタンスを含むデータ・ソースが返されます:

data "oci_core_instances" "s" {
    ...
  filter {
    name = "availability_domain"
    values = ["\\w*-AD-1"]
    regex = true
  }

  filter {
    name = "state"
    values = ["RUNNING"]
  }
}

前述のように、フィルタでは正規表現も使用できます。regex = trueを設定すると、valuesリストの各項目は正規表現として扱われます。正規表現の特殊文字の文字列内にあるバックスラッシュは、前述の"\\w*-AD-1"に含まれる\wの前の最初の\のように、別のスラッシュでエスケープする必要があります。

ノート

構造化オブジェクトのリストへのドリルは現在サポートされていません。これらのプロパティがターゲット指定されている場合、データソースから結果は返されません。

ファンクション

Terraformには、構成ファイルで使用できる多数の組込みファンクションが用意されています。これらのファンクションを使用して、文字列の変更、数値に対する計算の実行、コレクションの管理などを行うことができます。

詳細は、ファンクションを参照してください。