OCI Resource Manager で Terraform形式で記述したリソースをプロビジョニングしてみた。(Oracle Cloud Infrastructure)

OCI の Resource Manager は Terraform の Managed Service となります。

> リソース・マネージャの概要
> https://docs.oracle.com/ja-jp/iaas/Content/ResourceManager/Concepts/resourcemanager.htm
> リソース・マネージャは、Oracle Cloud Infrastructureリソースのプロビジョニング処理を自動化できるOracle Cloud Infrastructureサービスです。Terraformを使用する場合、リソース・マネージャでは、「infrastructure-as-code」モデルを使用してリソースをインストール、構成および管理できます。

手元のOCI環境を再構築する必要があり、かねてからやる必要を感じていた OCI Resource Manager による環境構築を実践してみたやで。
彡(ﾟ)(ﾟ)

# 1. 構築した環境

下記記事(Terraform)の環境を OCI Resource Manager で再構築してみました。アイコン群がちょっと懐かしい……。

https://qiita.com/ora_gonsuke777/items/8651c4075ec6bf436c4f

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/e28c12e4-cbe0-7daf-0cb5-4c3441436bb5.png)

# 2. GitHub の OCI Resource Managerサンプル
GitHub に OCI Resource Manager のサンプルをアップロードしました。

https://github.com/gonsuke777/terraform/tree/main

下記コマンドでリポジトリをクローンして下さい。gitコマンドが使用不可の場合は、上記URLから Codeボタン→Download ZIPして下さい。

```
git clone https://github.com/gonsuke777/terraform
```

3つディレクトリが作成されますが、本記事では OCI Resource Manager用 の oci_test_env1_rm を使用します。

# 3. SSHキーペアの作成と公開鍵の編集
下記マニュアルを参照してSSHキーペアを2つ作成して、それぞれの公開鍵を zzzzzzzz.pub と yyyyyyyy.pub にセットして下さい。ファイル名は変更可能です。ファイル名を変更した場合は後述の vars.tf を編集します。

> キー・ペアの作成
> https://docs.oracle.com/ja-jp/iaas/Content/GSG/Tasks/creatingkeys.htm

既に利用可能なSSHキーペアを保持している場合は、本作業はスキップして問題ありません。

# 4. vars.tf の変数を記述

vars.tf の変数を記述します。内容は以下の通りです。

| 変数 | 説明 |
|-|-|
|tenancy_ocid|テナントのOCIDを記述します。|
|region|リージョン名を記述します。ap-tokyo-1, us-phoenix-1 など|
|compartment_ocid|コンパートメントのOCIDを記述します。|
|pub_subnet_seclst_ingress_rule|パブリック・サブネットにアクセスする接続元(例：PCなど)のCIDRを記述します。制限しない場合は 0.0.0.0/0 を記述して下さい。|
|os_image_source_id|Provider OSイメージ(Oracle Linuxなど)のOCIDを記述します。https://docs.cloud.oracle.com/iaas/images/ を参照して下さい。デフォルト値は Oracle Linux 8.8 の TokyoリージョンのイメージOCIDとしています。|
|public_compute_ssh_key|パブリック・サブネットに作成する Compute の SSH鍵(公開鍵)のファイル名を記述します。|
|private_compute_ssh_key|プライベート・サブネットに作成する Compute の SSH鍵(公開鍵)のファイル名を記述します。|
|public_compute_ad_num|パブリック・サブネットに作成する Compute の AD(Availability Domain)番号を指定します。1ADリージョンの場合は 1 のみ指定可能です。|
|private_compute_ad_num|プライベート・サブネットに作成する Compute の AD(Availability Domain)番号を指定します。1ADリージョンの場合は 1 のみ指定可能です。|
|oci_resource_prefix|リソース名の接頭辞(プレフィックス)を4文字以内で記述します。|

```terraform:vars.tf
# Variables

## Provider Variables
### tenant ocid
variable "tenancy_ocid" {
  default = "ocid1.tenancy.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

### OCI region (ex:ap-tokyo-1, us-phoenix-1, etc...)
variable "region" {
  default = "ap-tokyo-1"
}

### Compartment OCID
variable "compartment_ocid" {
  description = "The compartment which resources will be created"
  default     = "ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

## Networking Variables
### Public Subnet - Security List Ingress Rule
variable "pub_subnet_seclst_ingress_rule" {
  description = "Describe the CIDR of the connection source (ex: your PC, etc..). If you want to allow from all networks, describe 0.0.0.0/0."
  default     = "xxx.xxx.xxx.xxx/xx"
}

## Compute Variables
### Regional OS Image ID, this ID is different for each region. Look https://docs.cloud.oracle.com/iaas/images/
variable "os_image_source_id" {
  description = "For OS Image Source ID, look https://docs.cloud.oracle.com/iaas/images/"
  default     = "ocid1.image.oc1.ap-tokyo-1.aaaaaaaaqgqr35z52xjqh3nxinud7ixdft3dxdsescidrgeh2v5rp6dqfwea"
}

### Compute ssh key path(pub format)
variable "public_compute_ssh_key" {
  description = "Public Compute ssh key file (in pub format) path (.../.../<key_filename>)"
  default     = "./zzzzzzzz.pub"
}

variable "private_compute_ssh_key" {
  description = "Private Compute ssh key file (in pub format) path (.../.../<key_filename>)"
  default     = "./yyyyyyyy.pub"
}

### Compute Availability Domain(1 or 2 or 3)
variable "public_compute_ad_num" {
  description = "Public Compute Availability Domain Num(1 or 2 or 3)"
  default     = "1"
}

variable "private_compute_ad_num" {
  description = "Private Compute Availability Domain Num(1 or 2 or 3)"
  default     = "1"
}

## Resource Prefix
variable "oci_resource_prefix" {
  description = "The prefix of all the resources to be created. Maximum 4 characters."
  default     = "AYS"
}
```

# 5. Resource Manager の Stack作成 および plan, apply によるプロビジョニング

OCIコンソールの Resouce Manager Stacks画面に遷移して Stack を作成します。
vars.tf を編集した oci_test_env1_rmディレクトリを Stack にアップロードして下さい。
![OCI_RM_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/e8b3bf69-ec4b-3144-e861-87d79f6702a7.png)
![OCI_RM_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/46eaca4c-8c6f-6ae8-cc24-99c1a313f552.png)
![OCI_RM_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/616f1983-1a8b-5316-895a-dd99920eb8af.png)
![OCI_RM_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/96c2fc13-2c37-5b1d-411f-40e46fda11d0.png)
![OCI_RM_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/1fc35f41-3cd7-29b5-110a-7a216f23fbdf.png)
![OCI_RM_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/032fba42-cd19-ab8d-5e85-a381f933f244.png)
![OCI_RM_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/a4ab59c0-89d7-729b-5964-289b12023854.png)
　
作成した Resource Manager Stack を plan, apply します。
![OCI_RM_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/c5bf301a-9727-180d-afa7-f855d5805dd0.png)
![OCI_RM_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/4d412014-01a4-7925-d23e-2668e0a098d4.png)

成功しました。Compute も作成されてますやね彡(^)(^)
![OCI_RM_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/48bba217-65da-1461-be04-beff62c876e8.png)

ログインもできています。
![OCI_RM_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/9e9c1826-02a8-9f09-ceeb-1bbc349442b6.png)

# 6. 元記事からの変更点

vars.tf および provider.tf の user_ocid, fingerprint, private_key_path は削除しています。

Terraform の場合は Terraform を実行するためのOCIユーザー関連の情報が必要ですが、OCI Resource Manager の場合はOCIコンソールにログインしたOCIユーザーの権限(ポリシー)で実行されるため、これらの情報は不要だからです。

```terraform:provider.tf
# Terraform Provider

provider "oci" {
  tenancy_ocid     = "${var.tenancy_ocid}"
  user_ocid        = "${var.iam_user_ocid}" #削除
  fingerprint      = "${var.iam_user_fingerprint}" #削除
  private_key_path = "${var.iam_user_private_key_path}" #削除
  region           = "${var.region}"
}
```
```terraform:vars.tf
:
### IAM User OCID --削除
variable "iam_user_ocid" {
  default = "ocid1.user.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

### API fingerprint of IAM User --削除
variable "iam_user_fingerprint" {
  default = "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
}

### IAM User private key path(pair of API fingerprint) --削除
variable "iam_user_private_key_path" {
  default = "./sshkey/oci-terraform.pem"
}
```

Compute のシェイプは VM.Standard.E2.1 から VM.Standard.E4.flex に変更しています。
OSイメージが元のシェイプに対応していませんでした。流石にシェイプが古すぎた^q^

```terraform:compute.tf
:
shape               = "VM.Standard.E2.1"
:
```
↓
```terraform:compute.tf
:
  shape               = "VM.Standard.E4.Flex"
  shape_config {
    memory_in_gbs = "16"
    ocpus = "1"
  }
:
```

パブリック・サブネットにアタッチするセキュリティ・リストの Ingress Rule は CIDR を変数として入力するようにしました。0.0.0.0/0 は必要に応じて設定しましょう。

```terraform:networking.tf
:
  ingress_security_rules {
    source      = "0.0.0.0/0"
    source_type = "CIDR_BLOCK"
    protocol    = "6"
    stateless   = "false"
    tcp_options {
      max = "22"
      min = "22"
    }
  }
:
```
↓
```terraform:networking.tf
:
ingress_security_rules {
    source      = "${var.pub_subnet_seclst_ingress_rule}"
    source_type = "CIDR_BLOCK"
    protocol    = "6"
    stateless   = "false"
    tcp_options {
      max = "22"
      min = "22"
    }
  }
:
```

vars.tf に定義した OSイメージ の OCID は Tokyoリージョン Oracle Linux 8.8(x86版) の OCID としています。
```terraform:vars.tf
:
### Regional OS Image ID, this ID is different for each region. Look https://docs.cloud.oracle.com/iaas/images/
variable "os_image_source_id" {
  description = "For OS Image Source ID, look https://docs.cloud.oracle.com/iaas/images/"
  default     = "ocid1.image.oc1.ap-tokyo-1.aaaaaaaaqgqr35z52xjqh3nxinud7ixdft3dxdsescidrgeh2v5rp6dqfwea"
}
:
```

# 7. リソースの削除(Destroy)

Resource Manager の Stack から Destroy を実行すると、該当Stack から作成されたリソースが削除されます。

![OCI_RM_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/d48eeea3-3d4b-2dc7-ace7-da17dc52f2da.png)
![OCI_RM_13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/d59e3af1-d795-c433-dc96-cf37b95c5951.png)


Destroy でリソースが削除されました。簡単に削除できるのは基本エエんですが、誤削除の危険も有るため要注意です。

個人的な考えとして、データストア系のリソース(OCI の場合は BaseDB, Autonomous Database, ExaDB-D など)は OCI Resource Manager や Terraform では作らない、あるいは Resource Manager や Terraform の実行ユーザーからリソースの削除権限(ポリシー)は剥奪しておいた方が良いと認識しています。
(ﾟεﾟ )

これは下記マニュアルにも同様の記載があります。Resource Manager Stack の Plan と Apply のジョブのみ許可することで、Destroy のジョブ実行を制限しています。

> スタックとジョブの管理
> https://docs.oracle.com/ja-jp/iaas/Content/Security/Reference/resourcemanager_security.htm#iam-policies__stacks-jobs
> グループが破棄ジョブの実行を明示的に禁止するには、このポリシーを作成します
> ：
> Allow group <group_name> to manage orm-jobs in tenancy where any {target.job.operation = 'PLAN', target.job.operation = 'APPLY'}


# 8. まとめ
OCI Resource Manager で各種リソースをプロビジョニングできました。個人的には諸事情で定期的に環境の再構築が発生するため、それが OCI RM化できたのは大きい……。
彡(^)(^)

皆さんどんどん活用して下さいね。

# 9. 追記(デフォルトのセキュリティ・リストの編集)
デフォルトのセキュリティ・リストでは Ingress Rule が 0.0.0.0/0 で設定されているため、必要に応じて編集/削除して下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/aa82e836-9977-e580-92cc-5cb791edb870.png)

(更に追記)デフォルトのセキュリティ・リストは oci_core_default_security_list で定義できる事が判明したので、Terraform定義に追記しておきました。

```terraform:networking.tf
：
resource oci_core_default_security_list export_DEFAULT_SECURITY_LIST1 {
  manage_default_resource_id = oci_core_vcn.export_VCN1.default_security_list_id
  compartment_id = "${var.compartment_ocid}"
  display_name   = "${upper(var.oci_resource_prefix)}-DEFAULT-SECURITY-LIST1"
  egress_security_rules {
    destination      = "0.0.0.0/0"
    destination_type = "CIDR_BLOCK"
    protocol         = "6"
    stateless        = "false"
  }
  ingress_security_rules {
    source      = "${var.pub_subnet_seclst_ingress_rule}"
    source_type = "CIDR_BLOCK"
    protocol    = "6"
    stateless   = "false"
    tcp_options {
      max = "22"
      min = "22"
    }
  }
}
：
```
![OCI_RM_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/65433bd7-92ed-6eed-ec01-9af91f355a24.png)

本項(oci_core_default_security_list)は下記が参考になります。

https://docs.oracle.com/ja-jp/iaas/Content/API/SDKDocs/terraformbestpractices_topic-vcndefaults.htm

https://github.com/oracle-terraform-modules/terraform-oci-vcn/blob/main/vcn_defaultresources.tf