はじめに
この記事では、Terraformを利用してOCI環境にVCNのネットワークリソースを構築し、さらにOracle Linux 9とApacheを実装したインスタンスを作成する方法について詳しく紹介します。
この記事の目的は、OCI環境の基本的な構築方法から、ネットワーク設定、インスタンスの作成、そしてローカルPCからのSSH接続までを一連の手順として解説することです。
Terraformとは
HashiCorpが開発しているインフラ構成をコードを使って管理するためのツールです。
HCLという記法でコードを記述し、インフラの状態を管理することができます。
IaC(Infrastructure as Code) を実現するツールのことであり、
サーバーやネットワークといったインフラの構成をプログラムのコードで書いて、書いたコードを元にインフラを構築することができます。
Terraformはシンプルな構文を使用し、複数のクラウドとオンプレミスのデータセンターにわたってインフラストラクチャーをプロビジョニングし、構成の変更に応じてインフラストラクチャーを安全かつ効率的に再プロビジョニングします。
前提条件
-
開発環境:開発環境としてVisual Studio Code(VSCode)を使用しています。
-
Terraformのインストール:VSCode上でTerraformが利用できるようにインストールをしてください。Terraformの拡張機能がVSCodeにインストールされているか、Terraform CLIがローカルマシンにインストールされていることを確認してください。
-
OCIアカウント: Oracle Cloud Infrastructureのアカウントを持っていることを確認んしてください。必要なAPIキーや秘密鍵などの設定も事前に行っておいてください。OCI上にAPIキーを登録する方法は、TerraformでOCIの構築を自動化するのチュートリアルの、「2.Terraform環境の構築」で登録方法が記載されていますので、ご参照をして頂ければと思います。
-
SSHキーの準備:ローカルPCからインスタンスにSSH接続するための公開鍵と秘密鍵を事前に生成しておいてください。
Terraformで作成するリソースの構成図
ローカルのPCからインスタンスにSSH接続できるようにする環境のイメージです。 VCNを作成して、その中にインスタンスを起動し、そのインスタンスにApacheをインストールして、インターネット経由でアクセスできる環境を構築します。
ディレクトリの構造
以下は、本記事で作成するtfファイルのディレクトリの構成を記載しています。
1 2 3 4 5 6 7 8 9 10 |
terraform/ ├── compute.tf ├── main.tf ├── network.tf ├── provider.tf ├── variables.tf ├── variable.tfvars └── ssh_keys/ ├── ssh-key-ins └── ssh-key-ins.pub |
ファイルとディレクトリの説明
以下に、各ディレクトリとファイルの役割についてを説明します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
・compute.tf:インスタンスの設定を定義するファイル。Oracle Linux 9とApacheをインストールしたインスタンスのプロビジョニングを行います。 ・main.tf:メインのTerraform設定ファイル。プロジェクト全体のインフラストラクチャを定義します。 ・network.tf:ネットワークリソース(VCNやサブネット)の設定を定義するファイルです。 ・provider.tf:プロバイダー(OCI)の設定を定義するファイル。OCIアカウント情報やリージョン設定を含みます。 ・variables.tf:変数の定義をまとめたファイル。各リソースの設定に使用する変数を定義します。 ・terraform.tfvars:変数の値を設定するファイル。variables.tfで定義された変数に具体的な値を割り当てます。 ・ssh_keys/:SSHキーを保存するディレクトリ。ローカルPCからインスタンスにSSH接続するための鍵ファイル(id_rsaとid_rsa.pub)を含みます。 |
実行環境
本記事に記載している手順は、以下の環境にて実施しています。
1 2 3 |
・OSバージョン: Oracle Linux 9 ・Terraformバージョン: v1.3.7 ・OCI Providerバージョン: v4.123.0 |
tfファイルの作成
本記事では、Terraformを利用してOCI(Oracle Cloud Infrastructure)環境にリソースを作成するための設定ファイルについて解説します。
まずは、Terraformのバージョンとプロバイダーのバージョンを指定するためのmain.tfファイルの中身を説明します。
main.tfファイルの構造
ファイルの中身は、HCL(HashiCorp Configuration Language)形式で記載しています。
今回はOCIにリソースを作成するため、providersブロックはociを指定します。
terraformブロック内で使用するTerraformのバージョンとOCIプロバイダーのソースとバージョンを追記しています。
以下がその具体的な内容です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 使用するTerraformのバージョンを指定 terraform { required_version = "1.3.7" } # 使用するプロバイダーを指定 terraform { required_providers { oci = { # OCIプロバイダーのソースとバージョンを指定 source = "hashicorp/oci" version = "4.123.0" } } } |
説明
・terraformブロック: 使用するTerraformのバージョンを指定します。本記事では、バージョン1.3.7を使用しています。
・required_providersブロック: 使用するプロバイダーを指定します。OCIプロバイダーを使用するために、hashicorp/ociをソースとして指定し、バージョン4.123.0を使用しています。
このように、プロバイダーのバージョンを明示的に指定することで、プロジェクトの依存関係を明確にし、一貫性のある環境を構築することができます。
provider.tfファイルの構造
以下は、プロバイダーを設定するためのファイルであるprovider.tfの内容について解説します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# OCI(Oracle Cloud Infrastructure)プロバイダーの設定 provider "oci" { # テナンシーのOCID(Oracle Cloud Identifier)を設定 tenancy_ocid = "ocid1.tenancy.oc1..XXXXX" # ユーザーのOCIDを設定 user_ocid = "ocid1.user.oc1..XXXX" # プライベートキーのファイルパスを設定 private_key_path = "/XXXX/XXXX.pem" # フィンガープリントを設定 fingerprint = "XXXXXX" # リージョンを設定 region = "ap-tokyo-1" } |
説明
・provider "oci"ブロック: OCIプロバイダーを指定しています。これにより、TerraformがOCI上でのリソースの作成や管理を行うことが可能になります。
・tenancy_ocid: テナンシーのOCID(Oracle Cloud Identifier)を設定します。この値は、OCIアカウントのテナンシーを一意に識別します。
・user_ocid: ユーザーのOCIDを設定します。この値は、TerraformがOCIにアクセスする際のユーザーを識別します。
・private_key_path: プライベートキーのファイルパスを設定します。このファイルは、OCIにアクセスするための認証情報として使用されます。
・fingerprint: フィンガープリントを設定します。この値は、SSHキーのフィンガープリントとして使用され、認証時に使用されます。
・region: リージョンを設定します。OCIリソースが作成される地理的な場所を指定します。
variables.tfファイルの構造
以下は、グローバル変数のファイルの構造で、外部から変数の値を変更できます。
.tf拡張子のファイルでvariableブロックを定義し、.tfvars拡張子のファイルで変数に代入します。
また、特別なファイルを使用せず環境変数から値を渡すことも可能です。その場合はTF_VAR_変数名という環境変数に値を代入します。
グローバル変数に設定された値を参照するにはvar.変数名を使用します。
変数に設定できる型については、Terraformの公式ホームページで公開しているTypes and Valuesを参照してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# コンパートメントIDを保持するための変数を定義 variable "compartment_id" { type = string } # VCN(仮想クラウドネットワーク)のCIDRブロックを保持するための変数を定義 variable "vcn_cidr_block" { type = string } # VCNの表示名を設定 variable "vcn_display_name" { type = string } # VCNのDNSラベルを設定 variable "vcn_dns_label" { type = string } # サブネットの表示名 variable "subnet_display_name" { type = string } # サブネットのDNSラベル variable "subnet_dns_label" { type = string } # サブネットのCIDRブロックを保持するための変数を定義 variable "subnet_cidr_block" { type = string } # セキュリティリストの表示名 variable "security_list_display_name" { type = string } # インバウンドのプロトコルを設定(TCP) variable "ingress_protocol_TCP" { type = string } # インバウンドのプロトコルを設定(ICMP) variable "ingress_protocol_ICMP" { type = string } # インバウンドの送信元CIDRブロック variable "ingress_source_cidr_block" { type = string } # アウトバウンドのプロトコルを設定(6はTCPを表す) variable "egress_protocol" { type = string } # アウトバウンドの送信先CIDRブロック variable "egress_source_cidr_block" { type = string } # ルートルールの宛先CIDRブロックを指定する変数 variable "route_rule_destination" { type = string } # ルートテーブルの表示名を指定する変数 variable "route_table_display_name" { type = string } # インターネットゲートウェイの表示名を設定 variable "internet_gateway_display_name" { type = string } # SSH公開鍵を指定する変数 variable "instance_ssh_public_key" { default = "ssh-rsa XXXXX" } |
説明
・variables.tfファイルでは、プロジェクト全体で使用されるグローバル変数を定義しています。
・各変数には、typeで型を指定しています。これにより、Terraformが入力値を適切にバリデーションし、型が一致しない場合はエラーを返します。
variable.tfvarsファイルの構造
以下は、variable.tfvarsファイルを使用することで、プロジェクトごとに異なる設定値を簡単に管理し、再利用することができるファイルの構造です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# コンパートメントID compartment_id = "ocid1.compartment.oc1..XXXX" # VCN(仮想クラウドネットワーク)のCIDRブロック vcn_cidr_block = "10.0.0.0/16" # VCNの表示名を設定 vcn_display_name = "my-vcn" # VCNのDNSラベルを設定 vcn_dns_label = "myvcn" # サブネットの表示名 subnet_display_name = "my-subnet" # サブネットのDNSラベル subnet_dns_label = "mysubnet" # サブネットのCIDRブロック subnet_cidr_block = "10.0.1.0/24" # セキュリティリストの表示名 security_list_display_name = "my-security-list" # インバウンドのプロトコルを設定(6はTCPを表す) ingress_protocol_TCP = "6" # インバウンドのプロトコルを設定(1はICMPを表す) ingress_protocol_ICMP = "1" # インバウンドの送信元CIDRブロック ingress_source_cidr_block = "0.0.0.0/0" # アウトバウンドのプロトコルを設定(6はTCPを表す) egress_protocol = "6" # アウトバウンドの送信先CIDRブロック egress_source_cidr_block = "0.0.0.0/0" # ルートルールの宛先CIDRブロックを指定する変数 route_rule_destination = "0.0.0.0/0" # ルートテーブルの表示名を指定する変数 route_table_display_name = "my-route-table" # インターネットゲートウェイの表示名を指定する変数 internet_gateway_display_name = "my-internet-gateway" |
説明
・variable.tfvarsファイルでは、プロジェクトに固有の変数の値を指定します。
・各変数には、その名前と値が含まれています。これらの値は、Terraformコードで使用され、OCI環境を構築する際のパラメーターとして機能します。
network.tfファイルの構造
以下は、network.tfファイルを使用して、ネットワークリソースを一元的に管理し、インフラストラクチャの構成を簡単に設定できるファイルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# VCN(仮想クラウドネットワーク)を作成 resource "oci_core_virtual_network" "my_vcn" { # VCNのCIDRブロックを設定 cidr_block = var.vcn_cidr_block # VCNが属するコンパートメントのIDを設定 compartment_id = var.compartment_id # VCNの表示名を設定 display_name = var.vcn_display_name # VCNのDNSラベルを設定 dns_label = var.vcn_dns_label } # サブネットを作成 resource "oci_core_subnet" "my_subnet" { # サブネットのCIDRブロックを設定 cidr_block = var.subnet_cidr_block # サブネットが属するコンパートメントのIDを設定 compartment_id = var.compartment_id # サブネットが属するVCNのIDを設定 vcn_id = oci_core_virtual_network.my_vcn.id # サブネットの表示名を設定 display_name = var.subnet_display_name # サブネットのDNSラベルを設定 dns_label = var.subnet_dns_label # セキュリティリストのIDを設定 security_list_ids = [oci_core_security_list.my_security_list.id] # ルートテーブルのIDを設定 route_table_id = oci_core_route_table.my_route_table.id } # セキュリティリストを作成 resource "oci_core_security_list" "my_security_list" { # セキュリティリストが属するコンパートメントのIDを設定 compartment_id = var.compartment_id # セキュリティリストが属するVCNのIDを設定 vcn_id = oci_core_virtual_network.my_vcn.id # セキュリティリストの表示名を設定 display_name = var.security_list_display_name # インバウンドのセキュリティルールを設定 ingress_security_rules { # プロトコルを設定(TCP) protocol = var.ingress_protocol_TCP # 許可する送信元のCIDRブロックを設定 source = var.ingress_source_cidr_block # TCPオプションを設定 tcp_options { # 許可するポート範囲の最大値を設定 max = 22 # 許可するポート範囲の最小値を設定 min = 22 } } ingress_security_rules { # 許可する送信元のCIDRブロックを設定 source = var.ingress_source_cidr_block # プロトコルを設定(TCP) protocol = var.ingress_protocol_TCP # ステートフルルールを設定 stateless = false # TCPオプションを設定 tcp_options { # 許可するポート範囲の最小値を設定(HTTP) min = 80 # 許可するポート範囲の最大値を設定(HTTP) max = 80 } } ingress_security_rules { # 許可する送信元のCIDRブロックを設定 source = var.ingress_source_cidr_block # プロトコルを設定(ICMP) protocol = var.ingress_protocol_ICMP # ステートフルルールを設定 stateless = false } # アウトバウンドのセキュリティルールを設定 egress_security_rules { # プロトコルを設定(TCP) protocol = var.egress_protocol # 許可する宛先のCIDRブロックを設定 destination = var.egress_source_cidr_block } } # ルートテーブルを作成 resource "oci_core_route_table" "my_route_table" { # ルートテーブルが属するコンパートメントのIDを設定 compartment_id = var.compartment_id # ルートテーブルが属するVCNのIDを設定 vcn_id = oci_core_virtual_network.my_vcn.id # ルートテーブルの表示名を設定 display_name = var.route_table_display_name # ルートルールを設定 route_rules { # ルールの宛先CIDRブロックを設定 destination = var.route_rule_destination # ルールのネットワークエンティティIDを設定 network_entity_id = oci_core_internet_gateway.my_internet_gateway.id } } # インターネットゲートウェイを作成 resource "oci_core_internet_gateway" "my_internet_gateway" { # インターネットゲートウェイが属するコンパートメントのIDを設定 compartment_id = var.compartment_id # インターネットゲートウェイが属するVCNのIDを設定 vcn_id = oci_core_virtual_network.my_vcn.id # インターネットゲートウェイの表示名を設定 display_name = var.internet_gateway_display_name } |
説明
・oci_core_virtual_networkリソースはVCN(仮想クラウドネットワーク)を作成します。
CIDRブロック、コンパートメントID、表示名、およびDNSラベルを設定します。
・oci_core_subnetリソースは、作成したVCN内にサブネットを作成します。
CIDRブロック、コンパートメントID、表示名、DNSラベル、セキュリティリスト、およびルートテーブルを指定します。
・oci_core_security_listリソースは、セキュリティリストを作成し、インバウンドおよびアウトバウンドのセキュリティルールを定義します。
これにより、特定のプロトコル(TCP、ICMP)とポート範囲が許可されます。
・oci_core_route_tableリソースは、ルートテーブルを作成し、ルートルールを定義します。
ここでは、すべてのトラフィック(0.0.0.0/0)がインターネットゲートウェイにルーティングされるように設定します。
・oci_core_internet_gatewayリソースは、インターネットゲートウェイを作成し、VCNに接続します。
これにより、インターネットアクセスが可能になります。
compute.tfファイルの構造
以下は、コンピュートインスタンスを構築するためのcompute.tfファイルの内容です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# OCIコンピュートインスタンスのリソース定義 resource "oci_core_instance" "Terraform_Oracle_Linux9" { # インスタンスを配置するアベイラビリティドメイン availability_domain = "OSrA:AP-TOKYO-1-AD-1" # 作成するインスタンスの数 count = 1 # コンパートメントIDを変数から取得 compartment_id = var.compartment_id # インスタンスの形状を指定 shape = "VM.Standard.E4.Flex" # VNIC(仮想ネットワークインターフェースカード)の設定 create_vnic_details { # サブネットIDを指定 subnet_id = oci_core_subnet.my_subnet.id # パブリックIPを割り当てる assign_public_ip = true } # インスタンスのシェイプ構成 shape_config { # CPU数を設定 ocpus = 1 # メモリサイズを設定 memory_in_gbs = 16 } # インスタンスのソースイメージの設定 source_details { # ソースイメージのOCIDを指定 source_id = "ocid1.image.oc1.ap-tokyo-1.aaaaaaaabpvi5mxrcpw5hfzm7rxdrzcq72f6diwwenefkye4k7fhd7d2aafa" # ソースタイプを指定(イメージ) source_type = "image" } # インスタンスの表示名を設定 display_name = "Terraform_Oracle_Linux9" # インスタンス終了時にブートボリュームを保持しない preserve_boot_volume = false # インスタンスのメタデータを設定 metadata = { # SSH公開鍵を指定 ssh_authorized_keys = var.instance_ssh_public_key # 起動時に実行するスクリプトを指定(Base64エンコード) user_data = base64encode(<<-EOF #!/bin/bash # Apache HTTPサーバーをインストール sudo yum install -y httpd # Apache HTTPサーバーを起動 sudo systemctl start httpd # Apache HTTPサーバーを自動起動設定 sudo systemctl enable httpd # Firewalldを起動 sudo systemctl start firewalld # Firewalldを自動起動設定 sudo systemctl enable firewalld # HTTPサービスをFirewalldのパブリックゾーンに追加 sudo firewall-cmd --add-service=http --zone=public --permanent # Firewalldを再起動 sudo systemctl restart firewalld EOF ) } } |
説明
・oci_core_instanceリソースは、Oracle Cloud Infrastructureでインスタンスを作成します。
・availability_domainは、インスタンスを配置するアベイラビリティドメインを指定します。
・compartment_idは、インスタンスが属するコンパートメントのIDを指定します。
・shapeは、インスタンスの形状を指定します。
ここでは、"VM.Standard.E4.Flex"を使用しています。
・create_vnic_detailsブロックでは、VNIC(仮想ネットワークインターフェースカード)の詳細を設定します。
ここでは、サブネットIDとパブリックIPの割り当てを指定しています。
・shape_configブロックでは、インスタンスのCPU数とメモリサイズを設定します。
・source_detailsブロックでは、インスタンスのソースイメージIDとソースタイプを指定します。
・display_nameは、インスタンスの表示名を設定します。
・preserve_boot_volumeは、インスタンスが終了した後にブートボリュームを保持するかどうかを指定します。
ここではfalseを設定しています。
・metadataブロックでは、インスタンスのメタデータを設定します。
ここでは、SSH公開鍵とuser_dataを指定しています。
リソースのプロビジョニング
.tfファイルの作成が完了したら、Terraformのコマンドを使用してリソース作成します。
terraform init
Terraformの設定に必要なプラグインやモジュールをダウンロードし、Terraformの環境を初期化します。
terraform validate
.tfファイルの構文と設定の妥当性をチェックをしてくれます。
terraform plan
Terraformがリソースを作成、変更、削除する前に実行計画を確認できます。
今回は、-var-file オプションを使用して、変数を定義したvariable.tfvarsファイルを指定して、variable.tfvars ファイルから変数の値を読み込んで、Terraformのプランを作成するコマンドを使います。
これにより、変数を外部ファイルで管理し、異なる設定ファイルを簡単に切り替えて使用することができます。
terraform apply
実際にリソースの追加・更新・削除が実行されます。 Enter a value:が表示されたあとにyesを入力してEnterキーを押下すると、リソースの作成が開始されます。
terraform planと同様に、-var-fileオプションを使用して、variable.tfvars ファイルから変数の値を読み込み、それを使用してインフラストラクチャの変更を適用するコマンドを使います。
OracleLinux9にSSH接続
作成したインスタンスのパブリックIPアドレスにSSH接続してみます。 SSH接続時に使用する秘密鍵は、事前に作成した鍵を使用します。
また、Apacheが自動で立ち上がっているか確認をしてみます。
上記の画像の通り、Terraformでインスタンスを作成時に、Apacheのインストールから自動で立ち上がっていることの確認ができました。
Apacheのテストページへ接続
最後に、ブラウザでのHTTPアクセスでApacheのテストページを見れるかどうか確認をしてみます。
上記の通り、http接続が確認でき、Apacheのテストページも確認ができました。
まとめ
今回のブログでは、Terraformを利用してOCI上にOracle Linux 9のインスタンスを構築し、VCNの作成からインスタンスのセットアップ、さらにApacheのインストールとそのテストページの確認までの一連の手順を詳しく説明しました。
この一連の作業を通じて、以下の点が確認できました:
Terraformの利便性: インフラの構築から設定までをコードベースで管理できるため、再現性と効率性が向上します。手動で行うとミスが発生しやすい設定作業も自動化できるため、安定した環境の構築が可能です。
この記事を通じて、Terraformを使用したインフラの自動化に興味を持ち、実際にOCI上での環境構築に挑戦してみたいと思った方も多いのではないでしょうか。
インフラの自動化は、運用の効率化やエラーの減少に大きく貢献します。ぜひ、この記事を参考に、ご自身のプロジェクトでも試してみてください。