MACにTerraformをインストールして、OCIのCompute Instanceを作成する

# はじめに
MACにTerraformをインストールして、OCI（Oracle Cloud Infrastructure）の構築を自動化します。
使用するMACのバージョンは以下です。

```
macOS Ventura 13.2.1
```

# Terraformのインストール
## tfenvのインストール
Homebrewでインストールします。

```
% brew install tfenv
Running `brew update --auto-update`...
==> Downloading https://formulae.brew.sh/api/formula.jws.json
######################################################################## 100.0%
==> Downloading https://formulae.brew.sh/api/cask.jws.json
######################################################################## 100.0%
==> Fetching dependencies for tfenv: pcre2 and grep
==> Fetching pcre2
==> Downloading https://ghcr.io/v2/homebrew/core/pcre2/manifests/10.42
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/pcre2/blobs/sha256:7f414ed9d561dc85aa
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:7
######################################################################## 100.0%
==> Fetching grep
==> Downloading https://ghcr.io/v2/homebrew/core/grep/manifests/3.10
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/grep/blobs/sha256:30e1ff24dec06dd3762
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:3
######################################################################## 100.0%
==> Fetching tfenv
==> Downloading https://ghcr.io/v2/homebrew/core/tfenv/manifests/3.0.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/tfenv/blobs/sha256:4905c2390b0254348b
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:4
######################################################################## 100.0%
==> Installing dependencies for tfenv: pcre2 and grep
==> Installing tfenv dependency: pcre2
==> Pouring pcre2--10.42.ventura.bottle.tar.gz
🍺  /usr/local/Cellar/pcre2/10.42: 230 files, 6.3MB
==> Installing tfenv dependency: grep
==> Pouring grep--3.10.ventura.bottle.tar.gz
🍺  /usr/local/Cellar/grep/3.10: 19 files, 1MB
==> Installing tfenv
==> Pouring tfenv--3.0.0.all.bottle.tar.gz
🍺  /usr/local/Cellar/tfenv/3.0.0: 28 files, 98.8KB
==> Running `brew cleanup tfenv`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Upgrading 1 dependent of upgraded formulae:
Disable this behaviour by setting HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
git 2.38.2 -> 2.40.0
==> Fetching git
==> Downloading https://ghcr.io/v2/homebrew/core/git/manifests/2.40.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/git/blobs/sha256:578773328bed8eb71718
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:5
######################################################################## 100.0%
==> Upgrading git
  2.38.2 -> 2.40.0 

==> Pouring git--2.40.0.ventura.bottle.tar.gz
==> Caveats
The Tcl/Tk GUIs (e.g. gitk, git-gui) are now in the `git-gui` formula.
Subversion interoperability (git-svn) is now in the `git-svn` formula.

zsh completions and functions have been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/git/2.40.0: 1,625 files, 47.8MB
==> Running `brew cleanup git`...
Removing: /usr/local/Cellar/git/2.38.2... (1,592 files, 47.6MB)
Removing: /Users/komachid/Library/Caches/Homebrew/git--2.38.2... (17.5MB)
==> Checking for dependents of upgraded formulae...
==> No broken dependents found!
==> `brew cleanup` has not been run in the last 30 days, running now...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Removing: /usr/local/Cellar/pcre2/10.40... (230 files, 6.4MB)
Removing: /Users/komachid/Library/Caches/Homebrew/pcre2--10.40... (2MB)
Removing: /Users/komachid/Library/Logs/Homebrew/gettext... (64B)
Removing: /Users/komachid/Library/Logs/Homebrew/pcre2... (64B)
Removing: /Users/komachid/Library/Logs/Homebrew/git... (64B)
Pruned 13 symbolic links and 1 directories from /usr/local
==> Caveats
==> git
The Tcl/Tk GUIs (e.g. gitk, git-gui) are now in the `git-gui` formula.
Subversion interoperability (git-svn) is now in the `git-svn` formula.

zsh completions and functions have been installed to:
  /usr/local/share/zsh/site-functions  
```

バージョンを確認します。

```
% tfenv --version
tfenv 3.0.0
```

## Terraformのインストール
インストール可能なTerraformのバージョンを確認します。

```
% tfenv list-remote
1.5.0-alpha20230405
1.4.4
1.4.3
・・・
```

ここでは1.4.4をインストールします。

```
% tfenv install 1.4.4
Installing Terraform v1.4.4
Downloading release tarball from https://releases.hashicorp.com/terraform/1.4.4/terraform_1.4.4_darwin_amd64.zip
############################################################################### 100.0%
Downloading SHA hash file from https://releases.hashicorp.com/terraform/1.4.4/terraform_1.4.4_SHA256SUMS
Not instructed to use Local PGP (/usr/local/Cellar/tfenv/3.0.0/use-{gpgv,gnupg}) & No keybase install found, skipping OpenPGP signature verification
Archive:  /var/folders/5c/rxgvrpyn73v7d83brc3s9wph0000gn/T/tfenv_download.XXXXXX.dS6MYsLA/terraform_1.4.4_darwin_amd64.zip
  inflating: /usr/local/Cellar/tfenv/3.0.0/versions/1.4.4/terraform  
Installation of terraform v1.4.4 successful. To make this your default version, run 'tfenv use 1.4.4'
```

確認します。

```
% tfenv list
  1.4.4
No default set. Set with 'tfenv use <version>'
komachid@komachid-mac tf % tfenv use 1.4.4 
Switching default version to v1.4.4
Default version (when not overridden by .terraform-version or TFENV_TERRAFORM_VERSION) is now: 1.4.4
komachid@komachid-mac tf % tfenv list     
* 1.4.4 (set by /usr/local/Cellar/tfenv/3.0.0/version)
```

```
% terraform -v
Terraform v1.4.4
on darwin_amd64
```

# RSAキーの作成
以降はこちらのチュートリアルに沿って設定します。

https://oracle-japan.github.io/ocitutorials/intermediates/terraform/

MACからOCIへアクセスするためのRSAキーを作成します。

## 秘密鍵の作成
秘密鍵を作成し、権限を変更します。
```
% mkdir $HOME/.oci
% openssl genrsa -out $HOME/.oci/tf-key.pem 2048
Generating RSA private key, 2048 bit long modulus
....................................+++++
.......................+++++
e is 65537 (0x10001)
% chmod 600 $HOME/.oci/tf-key.pem
```

## 公開鍵の作成
公開鍵を作成します。
```
% openssl rsa -pubout -in $HOME/.oci/tf-key.pem -out $HOME/.oci/tf-key.pem_public.pem
writing RSA key
```
```
% ls -l $HOME/.oci
total 16
-rw-------  1 komachid  staff  1675  4  9 06:08 tf-key.pem
-rw-r--r--  1 komachid  staff   451  4  9 06:10 tf-key.pem_public.pem
```

## APIキーの登録
作成した公開鍵をOCIのAPIキーに登録します。

作成した公開鍵を開いてコピーします。

```
% cat $HOME/.oci/tf-key.pem_public.pem 
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmMKX9NPo+baqYRpRPbLx
xxxxxxxxxxx
-----END PUBLIC KEY-----
```

コピーした鍵をOCIコンソールに貼り付けてAPIキーを登録します。

![スクリーンショット 2023-04-09 7.50.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/d86d7e9d-8903-60d6-1ed3-327ace941ee7.png)

追加をクリックすると以下の情報が表示されるので、メモ帳などに控えておきます。


![スクリーンショット 2023-04-09 7.52.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/93b7762b-1095-1a44-c436-bf1e05fab8e2.png)

# Terraform設定ファイルの作成
今回はCompute Instanceを一つTerraformで作成します。
そのために必要な4つのファイルを作成します。

## 事前準備
### OCIリソース
VCNとサブネット、セキュリティリストなどを作成、設定します。
（詳細割愛）

### sshキー

作業用のディレクトリを作成します。
```
% mkdir tf
% cd tf
```

インスタンス作成時に登録する公開鍵を作成します。

```
ssh-keygen -t rsa -N "" -b 2048 -C tf-ssh.key -f tf-ssh.key

Generating public/private rsa key pair.
Your identification has been saved in tf-ssh.key
Your public key has been saved in tf-ssh.key.pub
The key fingerprint is:
SHA256:Rm1t0T74vo+YZkjqEo9R1eTcl73O2XexRRy08PbKhP8 tf-ssh.key
The key's randomart image is:
+---[RSA 2048]----+
|           ooo.o |
|         ..+.o+.=|
|        ..o =o.==|
|       ... ...+oo|
|       .S   ...+o|
|      o.  .  ++.*|
|       = o . .+=+|
|      o o . oo.oo|
|       o.  oo ooE|
+----[SHA256]-----+
% ls -l
total 16
-rw-------  1 komachid  staff  1811  4  9 08:03 tf-ssh.key
-rw-r--r--  1 komachid  staff   392  4  9 08:03 tf-ssh.key.pub
```

## provider.tfファイル
認証に使用する以下のファイルを作成します。

```provider.tf
provider "oci" {
  tenancy_ocid = "<tenancy-ocid>"
  user_ocid = "<user-ocid>" 
  private_key_path = "<rsa-private-key-path>"
  fingerprint = "<fingerprint>"
  region = "<region-identifier>"
}
```

`private_key_path` は [秘密鍵の作成](#秘密鍵の作成)で作成した鍵のフルパスです。
その他の項目は[APIキーの登録](#apiキーの登録)後に表示されたプレビューに記載されています。

## availability-domains.tfファイル
Availability Domainに関する情報を記載します。
今回はコンパートメントを使用していますので、Tenancy-ocidではなく、コンパートメントOCIDを指定します。

コンパートメントOCIDはこちらでコピーします。

![スクリーンショット 2023-04-09 7.59.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/1d363ac6-8462-a500-3776-6265b2942cf8.png)


```availability-domains.tf
# Source from https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_availability_domains

# <tenancy-ocid> is the compartment OCID for the root compartment.
# Use <tenancy-ocid> for the compartment OCID.

data "oci_identity_availability_domains" "ads" {
  compartment_id = "<tenancy-ocid>" #コンパートメントOCID
}
```

## compute.tfファイル
TerraformでプロビジョニングするInstanceの設定情報を記載します。

```compute.tf
resource "oci_core_instance" "ol_instance" {
    # Required
    availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
    compartment_id = "<compartment-ocid>"
    shape = "VM.Standard.E4.Flex"　# Instanceのシェイプを指定
    shape_config {

        #Optional
        memory_in_gbs = 8　# メモリ容量をGB単位で指定
        ocpus = 1 # OCPU数を指定
    }
    source_details {
        source_id = "<source-ocid>"　# 使用するOSイメージのOCID
        source_type = "image"
    }

    # Optional
    display_name = "ol-instance-tf"　# Instanceの名称
    create_vnic_details {
        assign_public_ip = true
        subnet_id = "<subnet-ocid>"　# プロビジョニングするサブネットのOCID
    }
    metadata = {
        ssh_authorized_keys = file("<ssh-public-key-path>") # 事前準備で作成したsshキーの公開鍵のフルパス
    } 
    preserve_boot_volume = false
}
```

- source-ocid
    - 使用するOSイメージのOCIDを指定します。
    - リージョンごとにOCIDが異なるので、マニュアルで確認します。
    - 今回は[大阪リージョンのOracle Linux 8.7](https://docs.oracle.com/en-us/iaas/images/image/87759354-290a-4c29-9ee8-058359e18222/)を指定します。

## output.tfファイル
出力に関する設定ファイルを作成します。

```output.tf
# Outputs for compute instance

output "public-ip-for-compute-instance" {
  value = oci_core_instance.ol_instance.public_ip
}

output "instance-name" {
  value = oci_core_instance.ol_instance.display_name
}

output "instance-OCID" {
  value = oci_core_instance.ol_instance.id
}

output "instance-region" {
  value = oci_core_instance.ol_instance.region
}

output "instance-shape" {
  value = oci_core_instance.ol_instance.shape
}

output "instance-state" {
  value = oci_core_instance.ol_instance.state
}

output "instance-OCPUs" {
  value = oci_core_instance.ol_instance.shape_config[0].ocpus
}

output "instance-memory-in-GBs" {
  value = oci_core_instance.ol_instance.shape_config[0].memory_in_gbs
}

output "time-created" {
  value = oci_core_instance.ol_instance.time_created
}

# The "name" of the availability domain to be used for the compute instance.
output "name-of-first-availability-domain" {
  value = data.oci_identity_availability_domains.ads.availability_domains[0].name
}
```

# プロビジョニング
Terraformを実行して、インスタンスをプロビジョニングします。

## 初期化
作業ディレクトリを初期化します。

```
% terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/oci...
- Installing hashicorp/oci v4.115.0...
- Installed hashicorp/oci v4.115.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.

╷
│ Warning: Additional provider information from registry
│ 
│ The remote registry returned warnings for registry.terraform.io/hashicorp/oci:
│ - For users on Terraform 0.13 or greater, this provider has moved to oracle/oci. Please update your source in
│ required_providers.
╵

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の実行計画を作成します。

```
% terraform plan
data.oci_identity_availability_domains.ads: Reading...
data.oci_identity_availability_domains.ads: Read complete after 1s [id=IdentityAvailabilityDomainsDataSource-23752778]

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # oci_core_instance.ol_instance will be created
  + resource "oci_core_instance" "ol_instance" {
      + availability_domain                 = "TGjA:AP-OSAKA-1-AD-1"
      + boot_volume_id                      = (known after apply)
      + capacity_reservation_id             = (known after apply)
      + compartment_id                      = "ocid1.compartment.oc1..aaaaaaaamyemvazvbgl42f5pi7gzlpgq5tcmxlipjm2uitoihfschylliy5a"
      + compute_cluster_id                  = (known after apply)
      + dedicated_vm_host_id                = (known after apply)
      + defined_tags                        = (known after apply)
      + display_name                        = "ol-instance-tf"
      + fault_domain                        = (known after apply)
      + freeform_tags                       = (known after apply)
      + hostname_label                      = (known after apply)
      + id                                  = (known after apply)
      + image                               = (known after apply)
      + ipxe_script                         = (known after apply)
      + is_pv_encryption_in_transit_enabled = (known after apply)
      + launch_mode                         = (known after apply)
      + metadata                            = {
          + "ssh_authorized_keys" = <<-EOT
                -----BEGIN OPENSSH PRIVATE KEY-----
                b3BlbnNzaC1rZXktdjExxxxxxxxxxxxxxxxxxxxxx
-----END OPENSSH PRIVATE KEY-----
            EOT
        }
      + preserve_boot_volume                = false
      + private_ip                          = (known after apply)
      + public_ip                           = (known after apply)
      + region                              = (known after apply)
      + shape                               = "VM.Standard.E4.Flex"
      + state                               = (known after apply)
      + subnet_id                           = (known after apply)
      + system_tags                         = (known after apply)
      + time_created                        = (known after apply)
      + time_maintenance_reboot_due         = (known after apply)

      + create_vnic_details {
          + assign_public_ip       = "true"
          + defined_tags           = (known after apply)
          + display_name           = (known after apply)
          + freeform_tags          = (known after apply)
          + hostname_label         = (known after apply)
          + private_ip             = (known after apply)
          + skip_source_dest_check = (known after apply)
          + subnet_id              = "ocid1.subnet.oc1.ap-osaka-1.aaaaaaaawslb2rki46ebefwmmxxxxxxxxxxxxxxxxxxx"
          + vlan_id                = (known after apply)
        }

      + shape_config {
          + baseline_ocpu_utilization     = (known after apply)
          + gpu_description               = (known after apply)
          + gpus                          = (known after apply)
          + local_disk_description        = (known after apply)
          + local_disks                   = (known after apply)
          + local_disks_total_size_in_gbs = (known after apply)
          + max_vnic_attachments          = (known after apply)
          + memory_in_gbs                 = 8
          + networking_bandwidth_in_gbps  = (known after apply)
          + nvmes                         = (known after apply)
          + ocpus                         = 1
          + processor_description         = (known after apply)
        }

      + source_details {
          + boot_volume_size_in_gbs = (known after apply)
          + boot_volume_vpus_per_gb = (known after apply)
          + source_id               = "ocid1.image.oc1.ap-osaka-1.aaaaaaaaklxl2jnwxxxxxxxxxxxx"
          + source_type             = "image"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + instance-OCID                     = (known after apply)
  + instance-OCPUs                    = 1
  + instance-memory-in-GBs            = 8
  + instance-name                     = "ol-instance-tf"
  + instance-region                   = (known after apply)
  + instance-shape                    = "VM.Standard.E4.Flex"
  + instance-state                    = (known after apply)
  + name-of-first-availability-domain = "TGjA:AP-OSAKA-1-AD-1"
  + public-ip-for-compute-instance    = (known after apply)
  + time-created                      = (known after apply)

─────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee
to take exactly these actions if you run "terraform apply" now.
```

## 適用
実行計画を適用し、インスタンスをプロビジョニングします。

```
% terraform apply
data.oci_identity_availability_domains.ads: Reading...
data.oci_identity_availability_domains.ads: Read complete after 0s [id=IdentityAvailabilityDomainsDataSource-23752778]

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # oci_core_instance.ol_instance will be created
  + resource "oci_core_instance" "ol_instance" {
      + availability_domain                 = "TGjA:AP-OSAKA-1-AD-1"
      + boot_volume_id                      = (known after apply)
      + capacity_reservation_id             = (known after apply)
      + compartment_id                      = "ocid1.compartment.oc1..aaaaaaaamyemvaxxxxxxxxxxxxxxxxxxxxxxxxx"
      + compute_cluster_id                  = (known after apply)
      + dedicated_vm_host_id                = (known after apply)
      + defined_tags                        = (known after apply)
      + display_name                        = "ol-instance-tf"
      + fault_domain                        = (known after apply)
      + freeform_tags                       = (known after apply)
      + hostname_label                      = (known after apply)
      + id                                  = (known after apply)
      + image                               = (known after apply)
      + ipxe_script                         = (known after apply)
      + is_pv_encryption_in_transit_enabled = (known after apply)
      + launch_mode                         = (known after apply)
      + metadata                            = {
          + "ssh_authorized_keys" = <<-EOT
                ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChiyKxOXc6N56ZEty/C8e/m7JiXjoVHYDhUa0KpNN17lknS5qstN3W1sTSpbT7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX tf-ssh.key
            EOT
        }
      + preserve_boot_volume                = false
      + private_ip                          = (known after apply)
      + public_ip                           = (known after apply)
      + region                              = (known after apply)
      + shape                               = "VM.Standard.E4.Flex"
      + state                               = (known after apply)
      + subnet_id                           = (known after apply)
      + system_tags                         = (known after apply)
      + time_created                        = (known after apply)
      + time_maintenance_reboot_due         = (known after apply)

      + create_vnic_details {
          + assign_public_ip       = "true"
          + defined_tags           = (known after apply)
          + display_name           = (known after apply)
          + freeform_tags          = (known after apply)
          + hostname_label         = (known after apply)
          + private_ip             = (known after apply)
          + skip_source_dest_check = (known after apply)
          + subnet_id              = "ocid1.subnet.oc1.ap-osaka-1.aaaaaaaawslb2rki46ebexxxxxxxxxxxxxxxxxxxxxxxxxxxx"
          + vlan_id                = (known after apply)
        }

      + shape_config {
          + baseline_ocpu_utilization     = (known after apply)
          + gpu_description               = (known after apply)
          + gpus                          = (known after apply)
          + local_disk_description        = (known after apply)
          + local_disks                   = (known after apply)
          + local_disks_total_size_in_gbs = (known after apply)
          + max_vnic_attachments          = (known after apply)
          + memory_in_gbs                 = 8
          + networking_bandwidth_in_gbps  = (known after apply)
          + nvmes                         = (known after apply)
          + ocpus                         = 1
          + processor_description         = (known after apply)
        }

      + source_details {
          + boot_volume_size_in_gbs = (known after apply)
          + boot_volume_vpus_per_gb = (known after apply)
          + source_id               = "ocid1.image.oc1.ap-osaka-1.aaaaaaaaprjpeoyjeuxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
          + source_type             = "image"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + instance-OCID                     = (known after apply)
  + instance-region                   = (known after apply)
  + instance-state                    = (known after apply)
  + public-ip-for-compute-instance    = (known after apply)
  + time-created                      = (known after apply)

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_core_instance.ol_instance: Creating...
oci_core_instance.ol_instance: Still creating... [10s elapsed]
oci_core_instance.ol_instance: Still creating... [20s elapsed]
oci_core_instance.ol_instance: Still creating... [30s elapsed]
oci_core_instance.ol_instance: Creation complete after 36s [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqczk5tfmenxxxxxxxxxxxxxxx]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

instance-OCID = "ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqczk5tfmxxxxxxxxxxxxxxxxxxxx"
instance-OCPUs = 1
instance-memory-in-GBs = 8
instance-name = "ol-instance-tf"
instance-region = "ap-osaka-1"
instance-shape = "VM.Standard.E4.Flex"
instance-state = "RUNNING"
name-of-first-availability-domain = "TGjA:AP-OSAKA-1-AD-1"
public-ip-for-compute-instance = "168.138.47.39"
time-created = "2023-04-09 00:28:39.728 +0000 UTC"
```

applyが終わると、状態を記録した`terraform.tfstate`ファイルが作成されています。

```
% ls -l
total 64
-rw-r--r--  1 komachid  staff   392  4  9 08:17 availability-domains.tf
-rw-r--r--  1 komachid  staff   912  4  9 09:27 compute.tf
-rw-r--r--  1 komachid  staff   991  4  9 08:45 output.tf
-rw-r--r--  1 komachid  staff   356  4  9 08:14 provider.tf
-rw-r--r--  1 komachid  staff  7461  4 27 15:31 terraform.tfstate
-rw-------  1 komachid  staff  1811  4  9 08:03 tf-ssh.key
-rw-r--r--  1 komachid  staff   392  4  9 08:03 tf-ssh.key.pub
```

```
% cat terraform.tfstate
{
  "version": 4,
  "terraform_version": "1.4.4",
  "serial": 2,
  "lineage": "c9bd8062-7f0c-5bac-ada1-2e031ea57c9c",
  "outputs": {
    "instance-OCID": {
      "value": "ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqc7aqfyufs2ajxxxxxxxxxxxxxx",
      "type": "string"
    },
    "instance-OCPUs": {
      "value": 1,
      "type": "number"
・・・
```

## 確認

コンソールにログインして、インスタンスがプロビジョニングされていることを確認します。

![スクリーンショット 2023-04-09 9.33.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/0b4b667b-2fc1-3888-aa88-88578831de71.png)

sshキーとパブリックIPアドレスを指定して、インスタンスにログインします。

```
% ssh -i tf-ssh.key opc@168.138.47.39
The authenticity of host '168.138.47.39 (168.138.47.39)' can't be established.
ED25519 key fingerprint is SHA256:XpsZ4P0Glf360RmAiN52Wk9CI8YpQYd3jtAG3oHDGPo.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '168.138.47.39' (ED25519) to the list of known hosts.
Activate the web console with: systemctl enable --now cockpit.socket

[opc@ol-instance-tf ~]$ $ cat /etc/oracle-release 
Oracle Linux Server release 8.7
[opc@ol-instance-tf ~]$ hostname
ol-instance-tf
```

Terraformからも確認できます。

```
% terraform show
# data.oci_identity_availability_domains.ads:
data "oci_identity_availability_domains" "ads" {
    availability_domains = [
        {
            compartment_id = "ocid1.compartment.oc1..aaaaaaaamyemvazvbgl42f5pi7gzlpgq5tcmxlipjm2uitoihf"
            id             = "ocid1.availabilitydomain.oc1..aaaaaaaa77hdxjj7p7rigpiptedsboears4a5foue5ccb4tv4tika"
            name           = "TGjA:AP-OSAKA-1-AD-1"
        },
    ]
    compartment_id       = "ocid1.compartment.oc1..aaaaaaaamyemvazvbgl42f5pi7gzlpgq5tcmxliphylliy5a"
    id                   = "IdentityAvailabilityDomainsDataSource-237778"
}

# oci_core_instance.ol_instance:
resource "oci_core_instance" "ol_instance" {
    availability_domain  = "TGjA:AP-OSAKA-1-AD-1"
    boot_volume_id       = "ocid1.bootvolume.oc1.ap-osaka-1.abvwsljrrhwxmfejohtadlc352kovq7nfp5g4nx5tkm3hsunjmjq"
    compartment_id       = "ocid1.compartment.oc1..aaaaaaaamyemvazvbgl42f5pi7gzlpgq5pjm2uitoihfschylliy5a"
    defined_tags         = {}
    display_name         = "ol-instance-tf"
    fault_domain         = "FAULT-DOMAIN-1"
    freeform_tags        = {}
    hostname_label       = "ol-instance-tf"
    id                   = "ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqc7aqfyufs2ajozreuadmkjkymh3bx5j7o6yq"
    image                = "ocid1.image.oc1.ap-osaka-1.aaaaaaaaprjpeoyjeuqos3c6z32dd5vzsmzswtev2lkqgsnpadiq"
    launch_mode          = "PARAVIRTUALIZED"
    metadata             = {
        "ssh_authorized_keys" = <<-EOT
            ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChiyKxOXc6N56ZEty/C8e/m7JiXjoVHYDhUa0KpNN17lknS5qstN3W1sTSpbT7C1oras2e6ik/Qq8N3xJLXewZCvigFsMnUvmAOX5MP0Pb0HU75t344YCL+Y2K7WFeUdj9ewOf91i6diFA1SBs1OOZrnlL8G2m3WmtNvbSLpK1CrU0LdVCNPOiwpYEOg0xI2Kzxi3XiAVQuj1X9lo/De+NczGmD8v5qnlpDZZUb/zhPTEjX tf-ssh.key
        EOT
    }
    preserve_boot_volume = false
    private_ip           = "10.0.11.251"
    public_ip            = "152.69.197.118"
    region               = "ap-osaka-1"
    shape                = "VM.Standard.E4.Flex"
    state                = "RUNNING"
    subnet_id            = "ocid1.subnet.oc1.ap-osaka-1.aaaaaaaawslb2rki46ebefwmmxsvvavuvbbpo4p2lmpuq"
    system_tags          = {}
    time_created         = "2023-04-27 06:30:59.185 +0000 UTC"

    agent_config {
        are_all_plugins_disabled = false
        is_management_disabled   = false
        is_monitoring_disabled   = false
    }

    availability_config {
        is_live_migration_preferred = false
        recovery_action             = "RESTORE_INSTANCE"
    }

    create_vnic_details {
        assign_private_dns_record = false
        assign_public_ip          = "true"
        defined_tags              = {}
        display_name              = "ol-instance-tf"
        freeform_tags             = {}
        hostname_label            = "ol-instance-tf"
        private_ip                = "10.0.11.251"
        skip_source_dest_check    = false
        subnet_id                 = "ocid1.subnet.oc1.ap-osaka-1.aaaaaaaawslb2rki46ebefwmmxsvvavuvbbpo4p2lmputz"
    }

    instance_options {
        are_legacy_imds_endpoints_disabled = false
    }

    launch_options {
        boot_volume_type                    = "PARAVIRTUALIZED"
        firmware                            = "UEFI_64"
        is_consistent_volume_naming_enabled = true
        is_pv_encryption_in_transit_enabled = false
        network_type                        = "PARAVIRTUALIZED"
        remote_data_volume_type             = "PARAVIRTUALIZED"
    }

    shape_config {
        gpus                          = 0
        local_disks                   = 0
        local_disks_total_size_in_gbs = 0
        max_vnic_attachments          = 2
        memory_in_gbs                 = 8
        networking_bandwidth_in_gbps  = 1
        nvmes                         = 0
        ocpus                         = 1
        processor_description         = "2.55 GHz AMD EPYC™ 7J13 (Milan)"
    }

    source_details {
        boot_volume_size_in_gbs = "47"
        boot_volume_vpus_per_gb = "10"
        source_id               = "ocid1.image.oc1.ap-osaka-1.aaaaaaaaprjpeoyjeuqos3c6z32dd5vzsmzswtev2lkqgq"
        source_type             = "image"
    }
}


Outputs:

instance-OCID = "ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqc7aqfyufs2ajozreuadmkjkyn2q"
instance-OCPUs = 1
instance-memory-in-GBs = 8
instance-name = "ol-instance-tf"
instance-region = "ap-osaka-1"
instance-shape = "VM.Standard.E4.Flex"
instance-state = "RUNNING"
name-of-first-availability-domain = "TGjA:AP-OSAKA-1-AD-1"
public-ip-for-compute-instance = "152.69.197.118"
time-created = "2023-04-27 06:30:59.185 +0000 UTC"
```


## 削除
作成したインスタンスを削除します。

```
% terraform destroy
data.oci_identity_availability_domains.ads: Reading...
data.oci_identity_availability_domains.ads: Read complete after 0s [id=IdentityAvailabilityDomainsDataSource-23752778]
oci_core_instance.ol_instance: Refreshing state... [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqczk5tfmenoxxxxxxxxxxxxxxxxxxxx]

Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # oci_core_instance.ol_instance will be destroyed
  - resource "oci_core_instance" "ol_instance" {
      - availability_domain  = "TGjA:AP-OSAKA-1-AD-1" -> null
      - boot_volume_id       = "ocid1.bootvolume.oc1.ap-osaka-1.abvwsljranw3ysngsf32xbpa3k3ntxxxxxxxxxxxxxxxxxxxx" -> null
      - compartment_id       = "ocid1.compartment.oc1..aaaaaaaamyemvazvbgl42f5pi7gzlxxxxxxxxxxxxxxxxxxxx" -> null
      - defined_tags         = {} -> null
      - display_name         = "ol-instance-tf" -> null
      - extended_metadata    = {} -> null
      - fault_domain         = "FAULT-DOMAIN-1" -> null
      - freeform_tags        = {} -> null
      - hostname_label       = "ol-instance-tf" -> null
      - id                   = "ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqczk5tfmenovqk3ytfxxxxxxxxxxxxxxxxxxxx" -> null
      - image                = "ocid1.image.oc1.ap-osaka-1.aaaaaaaaprjpeoyjeuqos3c6z32dd5vzsmzxxxxxxxxxxxxxxxxxxxx" -> null
      - launch_mode          = "PARAVIRTUALIZED" -> null
      - metadata             = {
          - "ssh_authorized_keys" = <<-EOT
                ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQChiyKxOXc6N56ZEty/C8e/m7JiXjoVHYDhUa0KpNxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx tf-ssh.key
            EOT
        } -> null
      - preserve_boot_volume = false -> null
      - private_ip           = "10.0.11.169" -> null
      - public_ip            = "168.138.47.39" -> null
      - region               = "ap-osaka-1" -> null
      - shape                = "VM.Standard.E4.Flex" -> null
      - state                = "RUNNING" -> null
      - subnet_id            = "ocid1.subnet.oc1.ap-osaka-1.aaaaaaaawslb2rki46ebefwmmxsvvaxxxxxxxxxxxxxxxxxxxx" -> null
      - system_tags          = {} -> null
      - time_created         = "2023-04-09 00:28:39.728 +0000 UTC" -> null

      - agent_config {
          - are_all_plugins_disabled = false -> null
          - is_management_disabled   = false -> null
          - is_monitoring_disabled   = false -> null
        }

      - availability_config {
          - is_live_migration_preferred = false -> null
          - recovery_action             = "RESTORE_INSTANCE" -> null
        }

      - create_vnic_details {
          - assign_private_dns_record = false -> null
          - assign_public_ip          = "true" -> null
          - defined_tags              = {} -> null
          - display_name              = "ol-instance-tf" -> null
          - freeform_tags             = {} -> null
          - hostname_label            = "ol-instance-tf" -> null
          - nsg_ids                   = [] -> null
          - private_ip                = "10.0.11.169" -> null
          - skip_source_dest_check    = false -> null
          - subnet_id                 = "ocid1.subnet.oc1.ap-osaka-1.aaaaaaaawslb2rki46ebefwmmxsvvxxxxxxxxxxxxxxxxxxxx" -> null
        }

      - instance_options {
          - are_legacy_imds_endpoints_disabled = false -> null
        }

      - launch_options {
          - boot_volume_type                    = "PARAVIRTUALIZED" -> null
          - firmware                            = "UEFI_64" -> null
          - is_consistent_volume_naming_enabled = true -> null
          - is_pv_encryption_in_transit_enabled = false -> null
          - network_type                        = "PARAVIRTUALIZED" -> null
          - remote_data_volume_type             = "PARAVIRTUALIZED" -> null
        }

      - shape_config {
          - gpus                          = 0 -> null
          - local_disks                   = 0 -> null
          - local_disks_total_size_in_gbs = 0 -> null
          - max_vnic_attachments          = 2 -> null
          - memory_in_gbs                 = 8 -> null
          - networking_bandwidth_in_gbps  = 1 -> null
          - nvmes                         = 0 -> null
          - ocpus                         = 1 -> null
          - processor_description         = "2.55 GHz AMD EPYC™ 7J13 (Milan)" -> null
        }

      - source_details {
          - boot_volume_size_in_gbs = "47" -> null
          - boot_volume_vpus_per_gb = "10" -> null
          - source_id               = "ocid1.image.oc1.ap-osaka-1.aaaaaaaaprjpeoyjeuqos3c6z32dd5vxxxxxxxxxxxxxxxxxxxx" -> null
          - source_type             = "image" -> null
        }
    }

Plan: 0 to add, 0 to change, 1 to destroy.

Changes to Outputs:
  - instance-OCID                     = "ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqczk5tfmenovqk3ytxxxxxxxxxxxxxxxxxxxx" -> null
  - instance-OCPUs                    = 1 -> null
  - instance-memory-in-GBs            = 8 -> null
  - instance-name                     = "ol-instance-tf" -> null
  - instance-region                   = "ap-osaka-1" -> null
  - instance-shape                    = "VM.Standard.E4.Flex" -> null
  - instance-state                    = "RUNNING" -> null
  - name-of-first-availability-domain = "TGjA:AP-OSAKA-1-AD-1" -> null
  - public-ip-for-compute-instance    = "168.138.47.39" -> null
  - time-created                      = "2023-04-09 00:28:39.728 +0000 UTC" -> 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_core_instance.ol_instance: Destroying... [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqczk5tfmenovqk3ytf6shy3uvxvjg5qvvnafkr4tgdp7va]
oci_core_instance.ol_instance: Still destroying... [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrs...enovqk3ytf6shy3uvxvjg5qvvnafkr4tgdp7va, 10s elapsed]
oci_core_instance.ol_instance: Still destroying... [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrs...enovqk3ytf6shy3uvxvjg5qvvnafkr4tgdp7va, 20s elapsed]
oci_core_instance.ol_instance: Still destroying... [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrs...enovqk3ytf6shy3uvxvjg5qvvnafkr4tgdp7va, 30s elapsed]
oci_core_instance.ol_instance: Still destroying... [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrs...enovqk3ytf6shy3uvxvjg5qvvnafkr4tgdp7va, 40s elapsed]
oci_core_instance.ol_instance: Still destroying... [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrs...enovqk3ytf6shy3uvxvjg5qvvnafkr4tgdp7va, 50s elapsed]
oci_core_instance.ol_instance: Still destroying... [id=ocid1.instance.oc1.ap-osaka-1.anvwsljrs...enovqk3ytf6shy3uvxvjg5qvvnafkr4tgdp7va, 1m0s elapsed]
oci_core_instance.ol_instance: Destruction complete after 1m5s

Destroy complete! Resources: 1 destroyed.
```

コンソールで削除されたことを確認します。

![スクリーンショット 2023-04-09 9.38.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/63528762-2ca0-2412-0435-611f24362b89.png)

`terraform.tfstate`ファイルも更新されています。

```
% cat terraform.tfstate
{
  "version": 4,
  "terraform_version": "1.4.4",
  "serial": 5,
  "lineage": "c9bd8062-7f0c-5bac-ada1-2e031ea57c9c",
  "outputs": {},
  "resources": [],
  "check_results": null
}
```

以前の状態は`terraform.tfstate.backup`ファイルで保存されています。

```
 % cat terraform.tfstate.backup
{
  "version": 4,
  "terraform_version": "1.4.4",
  "serial": 2,
  "lineage": "c9bd8062-7f0c-5bac-ada1-2e031ea57c9c",
  "outputs": {
    "instance-OCID": {
      "value": "ocid1.instance.oc1.ap-osaka-1.anvwsljrssl65iqc7aqfyufs2ajozreua",
      "type": "string"
    },
    "instance-OCPUs": {
      "value": 1,
      "type": "number"
・・・
```