TerraformでVM作成（Azure）

こちらは [エーピーコミュニケーションズAdvent Calendar 2021](https://qiita.com/advent-calendar/2021/ap-com) 
の22日目の記事です。

[こちらで](https://www.udemy.com/course/iac-with-terraform/
)Terraformを自己学習しているので（AWS）

Azureでもできないかなと思いやってみました。

## ゴール
- VM作成し、秘密鍵も取得する（GUIでのVM作成と同じようにしたい）
- OSはCentOS

## VM作成以外で必要なリソース（こちらもTerraformで作成します）
- リソースグループ
- 仮想ネットワーク
- サブネット
- パブリックIP
- NSGと通信ルール（SSH許可）
- NIC
- ディスク

## ここでは扱わないこと
Terraform実行環境の方法



## tfファイルの内容
ファイル構成はmain.tfのみで記載しました
locationは東日本(japaneast)です

```
provider "azurerm" {
  features {}
}

# リソースグループの作成
resource "azurerm_resource_group" "myazrg" {
  name     = "aztest_rg"
  location = "japaneast"
}

# 仮想ネットワークの作成
resource "azurerm_virtual_network" "vnet" {
  name                = "aztest_vnet"
  address_space       = ["10.0.0.0/16"]
  location            = "japaneast"
  resource_group_name = azurerm_resource_group.myazrg.name
}

# サブネットの作成
resource "azurerm_subnet" "subnet" {
  name                 = "default"
  resource_group_name  = azurerm_resource_group.myazrg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

# パブリックIPの作成
resource "azurerm_public_ip" "publicip" {
    name                         = "myPublicIP"
    location                     = "japaneast"
    resource_group_name          = azurerm_resource_group.myazrg.name
    allocation_method            = "Dynamic"

}

#  NSGの作成と通信ルールの設定（SSH許可）
resource "azurerm_network_security_group" "nsg" {
    name                = "mynsg"
    location            = "japaneast"
    resource_group_name = azurerm_resource_group.myazrg.name

    security_rule {
        name                       = "SSH"
        priority                   = 1001
        direction                  = "Inbound"
        access                     = "Allow"
        protocol                   = "Tcp"
        source_port_range          = "*"
        destination_port_range     = "22"
        source_address_prefix      = "<"*"でも良いですがクライアントのIPに絞るのがセキュリティ的によいと思います>"
        destination_address_prefix = "*"
    }
}

# ネットワークインターフェイスの作成
resource "azurerm_network_interface" "nic" {
  name                      = "nic"
  location                  = "japaneast"
  resource_group_name       = azurerm_resource_group.myazrg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
  }
}

# SSHキーの作成
resource "tls_private_key" "myazssh" {
  algorithm = "RSA"
  rsa_bits = 4096
}
output "tls_private_key" { 
    value = tls_private_key.myazssh.private_key_pem 
    sensitive = true
}

# 仮想マシンの作成
# OSはCentOS7.6
resource "azurerm_linux_virtual_machine" "myazvm" {
  name                = "myszvm"
  resource_group_name = azurerm_resource_group.myazrg.name
  location              = "japaneast"
  size                = "Standard_DS1_v2"
  admin_username = "azureuser"
  network_interface_ids = [
    azurerm_network_interface.nic.id,
  ]
  
  admin_ssh_key {
    username       = "azureuser"
    public_key     = tls_private_key.myazssh.public_key_openssh
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "OpenLogic"
    offer     = "CentOS"
    sku       = "7.6"
    version   = "latest"
  }
}

```

## Terraformの実行

### 初期化(terraform init)

```
$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/tls...
- Reusing previous version of hashicorp/azurerm from the dependency lock file
- Installing hashicorp/tls v3.1.0...
- Installed hashicorp/tls v3.1.0 (self-signed, key ID 34365D9472D7468F)

Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html

Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.

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 validate)
だいたいここでエラーが出るので、出たところを都度修正していきます

```
$ terraform validate
Success! The configuration is valid.
```

### 実行の予行(terraform plan) 
AnsibleでいうDry Runみたいなもの

```
$ terraform plan -out main.tfplan
tls_private_key.myazssh: Refreshing state... [id=xxx]
azurerm_resource_group.rg: Refreshing state... [id=/subscriptions/xxx/resourceGroups/aztest_rg]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

（略）

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

------------------------------------------------------------------------

This plan was saved to: main.tfplan

To perform exactly these actions, run the following command to apply:
    terraform apply "main.tfplan"
```

### 実行(terraform apply) 

```
$ terraform apply main.tfplan
azurerm_resource_group.myazrg: Creating...
(略)
azurerm_linux_virtual_machine.myazvm: Creating...
azurerm_linux_virtual_machine.myazvm: Still creating... [10s elapsed]
azurerm_linux_virtual_machine.myazvm: Still creating... [20s elapsed]
azurerm_linux_virtual_machine.myazvm: Still creating... [30s elapsed]
azurerm_linux_virtual_machine.myazvm: Still creating... [40s elapsed]
azurerm_linux_virtual_machine.myazvm: Still creating... [50s elapsed]
azurerm_linux_virtual_machine.myazvm: Still creating... [1m0s elapsed]
azurerm_linux_virtual_machine.myazvm: Still creating... [1m10s elapsed]
azurerm_linux_virtual_machine.myazvm: Creation complete after 1m17s [id=/subscriptions/xxx/resourceGroups/aztest_rg/providers/Microsoft.Compute/virtualMachines/myszvm]

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

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

Outputs:

tls_private_key = <sensitive>
```

こちらで、Azure Portalを見ると作成されています。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369281/7ec67ba0-6aaa-5fde-fc0c-c389342d4a72.png)

### 秘密鍵取得
```
terraform output -raw tls_private_key
-----BEGIN RSA PRIVATE KEY-----
（略）
-----END RSA PRIVATE KEY-----
```
こちらで秘密鍵が取得できます

鍵をコピペして、sshでログイン完了です。

### 感想
コマンド4回でVM作成ができるのは楽ですね。
GUIの変更で都度手順作成直しなども気にならなくなると思いました。
次は、ホスト名、IP変えて複数VM作成とか、WindowsOSでの作成などを行う予定です。
ご覧いただきありがとうございました。

### 参考
[公式：Terraform を使用して Azure で Linux VM とインフラストラクチャを構成する](https://docs.microsoft.com/ja-jp/azure/developer/terraform/create-linux-virtual-machine-with-infrastructure)
[AzureのIaaS検証環境をTerraformで用意する](https://techstep.hatenablog.com/entry/2020/02/02/134958
)