Oracle Cloud Infrastructure の Resource Manager を使って Compute を自動構築する

Pocket

はじめまして。オープンストリームの mkrydik と申します。普段は Node.js を使ったフロントエンド中心のお仕事をしています。

最近 Oracle Cloud を触る機会があったので、今回は Oracle Cloud Infrastructure (OCI) の環境構築にまつわる便利機能をご紹介します。

今回やること

今回は、OCI が提供する OCI Resource Manager というサービスを使って Compute (VM) インスタンスを立ち上げ、そこに SSH 接続してみます。

前提条件

今回の記事は以下を前提条件とします。

  • OCI のアカウント、環境を有していること
  • Compute インスタンスを配置するコンパートメントが作成済であること
  • Terraform に関する基礎知識を有していること (細かな記法などは今回説明しません)

なお、今回作成する環境はあくまでサンプルであり、セキュアな構成ではありません。本番環境などにそのまま流用しないよう、ご注意ください。

OCI Resource Manager とは

OCI Resource Manager とは、Terraform というツールを実行してくれるサービスです。

Terraform はインフラリソースの定義をコード化する、いわゆる Infrastructure as Code (IaC) のためのツールですが、tfstate と呼ばれる状態管理ファイルを複数人のチーム内で管理するのが面倒だったりします。

そこで、OCI Resource Manager を使えば、実行環境を OCI Resource Manager に一元化できるので、コードや tfstate ファイルの管理から解放されます。また、通常 Terraform を実行する際に必要になる「リソース操作用の OCI ユーザ」の作成なども不要になります。

要するに、ローカル開発環境から Terraform を実行するよりも OCI Resource Manager を使う方がお手軽、ということですね。

作成するリソースの構成を確認

OCI の場合、Compute インスタンスは何らかの 「Subnet (サブネット)」 に所属させる必要があります。そして、Subnet は1つの 「VCN (Virtual Cloud Network)」 の中に作ります。また、Compute インスタンスに SSH 接続するには、インターネットと VCN との「出入口」となる、 「Internet Gateway」 というものを作ってやる必要があります。

図で表すと、以下のような構成です。

構成図

したがって、Compute インスタンスを作成するためには、最低限、

  1. VCN を作る
  2. VCN のデフォルト・ルート・テーブルを編集し Internet Gateway を設定する
  3. VCN の中に Subnet を作る
  4. Subnet の中に Compute インスタンスを作る

という手順が必要になります。この辺り、インフラの一般的な知識と、OCI の仕様に関する知識が必要になりますね。

Terraform コードを書いていく

それでは、早速 OCI Resource Manager で動かす Terraform コードを書いていきます。

Terraform は、作成するリソースの定義を見て自動的に依存関係を考慮してくれますので、とりあえず一つずつ必要なリソースを作っていきましょう。

  • main.tf
// 変数定義
variable "region"           { description = "リージョン名"            }
variable "tenancy_ocid"     { description = "テナンシーの OCID"       }
variable "compartment_ocid" { description = "コンパートメントの OCID" }
variable "instance_shape" {
  description = "Instance のシェイプ"
  default     = "VM.Standard1.1"
}
variable "instance_image_ocids" {
  description = "Instance イメージ"
  type        = "map"
  default     = {  // Oracle-Linux-7.6-2019.05.14-0
    ap-seoul-1     = "ocid1.image.oc1.ap-seoul-1.aaaaaaaalhbuvdg453ddyhvnbk4jsrw546zslcfyl7vl4oxfgplss3ovlm4q"
    ap-tokyo-1     = "ocid1.image.oc1.ap-tokyo-1.aaaaaaaamc2244t7h3gwrrci5z4ni2jsulwcg76gugupkb6epzrypawcz4hq"
    ca-toronto-1   = "ocid1.image.oc1.ca-toronto-1.aaaaaaaakjkxzw33dcocgu2oylpllue34tjtyngwru7pcpqn4qh2nwon7n7a"
    eu-frankfurt-1 = "ocid1.image.oc1.eu-frankfurt-1.aaaaaaaandqh4s7a3oe3on6osdbwysgddwqwyghbx4t4ryvtcwk5xikkpvhq"
    uk-london-1    = "ocid1.image.oc1.uk-london-1.aaaaaaaa2xe7cufdwkksdazshtmqaddgd72kdhiyoqurtoukjklktf4nxkbq"
    us-ashburn-1   = "ocid1.image.oc1.iad.aaaaaaaa4bfsnhv2cd766tiw5oraw2as7g27upxzvu7ynqwipnqfcfwqskla"
    us-phoenix-1   = "ocid1.image.oc1.phx.aaaaaaaavtjpvg4njutkeu7rf7c5lay6wdbjhd4cxis774h7isqd6gktqzoa"
  }
}
variable "instance_ssh_public_key" {
  description = "Instance に設定する SSH 公開鍵"
}

// OCI プロバイダー
provider "oci" {
  region = "${var.region}"
}

// テナンシー内で利用可能な AD の一覧を取得する
data "oci_identity_availability_domains" "my_ads" {
  compartment_id = "${var.tenancy_ocid}"
}

// VCN
resource "oci_core_vcn" "my_vcn" {
  compartment_id = "${var.compartment_ocid}"
  cidr_block     = "10.0.0.0/16"
  display_name   = "my-vcn"
  dns_label      = "myvcn"
}

// Internet Gateway
resource "oci_core_internet_gateway" "internet_gateway" {
  compartment_id = "${var.compartment_ocid}"
  vcn_id         = "${oci_core_vcn.my_vcn.id}"
  display_name   = "internet-gateway"
}

// Route Table : Internet Gateway をアタッチする
resource "oci_core_default_route_table" "default_route_table" {
  manage_default_resource_id = "${oci_core_vcn.my_vcn.default_route_table_id}"
  display_name               = "default-route-table"
  route_rules {
    network_entity_id = "${oci_core_internet_gateway.internet_gateway.id}"
    destination       = "0.0.0.0/0"
  }
}

// Subnet : availability_domain を指定しないことでリージョナル・サブネットにする
resource "oci_core_subnet" "my_subnet" {
  compartment_id      = "${var.compartment_ocid}"
  vcn_id              = "${oci_core_vcn.my_vcn.id}"
  display_name        = "my-subnet"
  dns_label           = "mysubnet"
  cidr_block          = "10.0.10.0/24"
  security_list_ids   = [
    "${oci_core_vcn.my_vcn.default_security_list_id}"  // 自動作成されるデフォルトの Security List を使用する
  ]
}

// Compute インスタンス
resource "oci_core_instance" "my_instance" {
  compartment_id      = "${var.compartment_ocid}"
  availability_domain = "${lookup(data.oci_identity_availability_domains.my_ads.availability_domains[0], "name")}"
  shape               = "${var.instance_shape}"
  display_name        = "my-instance"
  source_details {
    source_type = "image"
    source_id   = "${var.instance_image_ocids[var.region]}"  // 対象リージョン用のイメージの OCID を指定する
  }
  create_vnic_details {
    subnet_id        = "${oci_core_subnet.my_subnet.id}"  // 作成した Subnet を割り当てる
    assign_public_ip = true
    hostname_label   = "myinstance"
  }
  metadata {
    ssh_authorized_keys = "${var.instance_ssh_public_key}"
  }
}

今回は簡単にするため、1つのファイルにまとめて書いてしまいましたが、本来は変数定義やリソースごとにファイルを分割しておいた方が分かりやすくなります。DNS ラベル名なども変数で注入する方が柔軟性があるでしょう。各リソースに指定するパラメータの詳細などは、公式のリファレンスを参考に作成しました。

Terraform コードを Zip ファイルに圧縮する

今回は上述の main.tf のみですが、このファイルを保存したディレクトリをまるごと Zip ファイルに固めます。OCI Resource Manager に Terraform コードをアップロードする際、Zip ファイルでないとアップロードできないためです。

OCI Resource Manager で Stack を作る

それでは、OCI の管理コンソールに移動します。

左上のハンバーガーメニューアイコンを押下し、「Solutions, Platform and Edge」セクションの「Resource Manager」から「Stacks」を押下します。

02 OCI メニュー

ここで任意のコンパートメントに移動し、**「Stack」**というものを作ります。Stack は OCI Resouce Manager で管理する OCI リソース群のまとまりで、Stack の単位で terraform applyterraform destroy 相当の操作が行えます。

03 Stack を作成する

「Create Stack」ボタンを押下すると、「Create Stack」画面の「Stack Information」ステップが開きます。

04 Create Stack 画面初期表示

作成した Zip ファイルをアップロード欄にドラッグ・アンド・ドロップし、任意で「Description (Stack の説明)」を入力して「Next」ボタンを押下します。

05 Zip ファイルをアップロード

続いて「Configure Variables」ステップに移動します。この画面で、Terraform コード内の variable 宣言に対する値を設定していきます。いくつか注意点があるので箇条書きでまとめます。

  • regiontenancy_ocidcompartment_ocid の3つの変数については、この Stack を作成した「us-ashburn-1」リージョンの情報、テナンシーの OCID、Stack を作成したコンパートメントの OCID がそれぞれ初期入力されていました。
  • 一方、variable 内の default 指定は自動入力されない他、変数の値だけを記入する terraform.tfvars ファイルが Zip 内に同梱されていても値の自動入力はされませんでした。
  • この画面で空欄があると先には進めず、全項目の入力が必須になっていましたので、default 値のまま変更がない場合でも、全ての変数の値をこの画面で入力する必要があります。
  • arraymap 型の変数も、1行テキストボックスに入力 (コピペ) すれば正常に認識されるようです。
  • この中に instance_ssh_public_key という変数があります。これは Compute インスタンスに SSH 接続する際の公開鍵を設定するための項目です。予め $ ssh-keygen -t rsa -b 4096 -f "${HOME}/.ssh/id_rsa" といったコマンドで鍵ペアを作成しておき、~/.ssh/id_rsa.pub (公開鍵) ファイルの内容をコピペして設定します。

06 Configure Variables 画面

全ての変数の値を設定したら「Next」ボタンを押下し、「Review」ステップで内容を確認したら「Create」ボタンを押下します。これで Stack が作成できました。

Plan (Dry-Run) を実行する

作成した Stack の画面に移動すると、「Terraform Actions」というプルダウンが見えるかと思います。マウスでフォーカスするとリストが表示されるので、「Plan」を選択します。

07 「Terraform Actions」から「Plan」を選択する

これは terraform plan コマンドに相当するもので、いわゆる Dry-Run ができます。実際にはリソースを作成せず、どのようなリソースが作成できそうか確認するためのものです。

「Plan」ボタンを押下して実行してみると、Stack 画面の「Jobs」欄に plan-job-YYYYMMDDHHMMSS という項目が登場します。「Plan」「Apply」「Destroy」の各アクションは、1回実行するごとに「Job」という単位で管理されます。Job は terraform コマンドの実行履歴、ともいえるでしょう。

Job 名のリンクを押下すると Job 詳細画面が表示されます。初期表示では「Logs」欄が表示されていると思うので、Terraform の実行が完了するまで数分待ちます。

ここで OCI Resouce Manager の難点ですが、Terraform の実行速度が物凄く遅いです。通常の terraform plan コマンドであれば数秒程度で結果が出力されるのですが、OCI Resource Manager で実行すると5分程度待たされます。実行速度はもう少し改善してほしいですね…。

コーヒーでも飲みながら完了を待つと、ようやく実行結果が「Logs」欄に出力されました。アップロードした Terraform コードで問題なくリソースが作成できそうです。

08 Plan の実行結果

Apply を実行して実際にリソースを作成する

Dry-Run で問題が見つからなかったので、実際に実行してみます。

Stack 詳細画面に戻って、今度は「Terraform Actions」プルダウンから「Apply」を選択します。こちらも実行には5〜10分ほどかかりますので、コーヒーを飲み干して待ちます。

09 Apply の実行結果

実行が完了しました。5つのリソースが無事作成されたようです。

作成されたリソースを確認する

作成されたリソースが OCI 管理コンソール上でどのように見えているのか、確認してみましょう。

まずは Networking メニューより Virtual Cloud Networks を選択し、VCN が作成されていることを確認します。

10 VCN

VCN の中には Subnet が1つ作成されています。

Subnet には「Security List」というファイアウォール設定を割り当てることで、トラフィックを制御できます。今回は VCN を作成すると自動的に作成されるデフォルトの Security List を割り当てました。この Security List のルールを見てみると、デフォルトで SSH 接続 (22番ポートでのアクセス) が許可されています。

11 Security List Ingress Rules

そして、Compute メニューより Instances を選択し、Compute インスタンスが作成されていることを確認します。VM 名のリンクを押下すると、以下のような詳細が表示されます。

12 Instance 詳細

この中の「Public IP Address:」欄に、パブリック IP が表示されています。このパブリック IP を指定すれば、この VM に SSH 接続できます。

Compute インスタンスに SSH 接続する

macOS の場合は標準の「ターミナル.app」、Windows の場合は「Git for Windows」などを利用して、ssh コマンドで SSH 接続してみます。OCI の Compute インスタンスは、デフォルトで opc というユーザが用意されているので、これを指定します。

13 SSH 接続

このように、作成した Compute インスタンスに SSH 接続できました。

まとめ

OCI Resource Manager というサービスを使うと、Terraform コードを OCI 上で簡単に実行できることが確認できました。

実行に時間がかかる点は気になりますが、実行内容をチームで共有しやすいので、OCI で IaC を行う際は OCI Resouce Manager の利用をおすすめします。

Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です