概要
「Infrastructure as Code」ということで、Terraform を用いて Azure環境上に Ubuntu のVMを作成し、SSH接続してみます。 この記事は Windows10 ですが、今回は Linux を構築します。
ローカル環境
- macOS Monterey 12.1
- python 3.8.3
- Azure CLI 2.28.0
- terraform v1.0.11
前提条件
- Azure環境がすでに用意されていること(テナント/サブスクリプション)
- ローカル環境に「azure cli」がインストールされていること
- ローカル環境に「terraform」環境が構成されていること
- TerraformでAzure上に環境構築するためのサービスプリンシパルが作成されており、Terraform のためのローカル環境変数が定義されていること
事前準備
ローカル環境からインターネットアクセス時に自動割当されているグローバルアドレスの取得
## 利用グローバルアドレス
$ curl inet-ip.info
153.134.22.135
構築する仮想マシンのImage情報の取得
## Image
$ az vm image list --location japaneast --offer UbuntuServer --sku 18.04-LTS --all --output table
Offer Publisher Sku Urn Version
------------ ----------- --------- ------------------------------------------------ ---------------
UbuntuServer Canonical 18.04-LTS Canonical:UbuntuServer:18.04-LTS:18.04.201804262 18.04.201804262
UbuntuServer Canonical 18.04-LTS Canonical:UbuntuServer:18.04-LTS:18.04.201805170 18.04.201805170
UbuntuServer Canonical 18.04-LTS Canonical:UbuntuServer:18.04-LTS:18.04.201805220 18.04.201805220
UbuntuServer Canonical 18.04-LTS Canonical:UbuntuServer:18.04-LTS:18.04.201806130 18.04.201806130
:
省略
:
UbuntuServer Canonical 18.04-LTS Canonical:UbuntuServer:18.04-LTS:18.04.202111300 18.04.202111300
UbuntuServer Canonical 18.04-LTS Canonical:UbuntuServer:18.04-LTS:18.04.202112020 18.04.202112020
UbuntuServer Canonical 18.04-LTS Canonical:UbuntuServer:18.04-LTS:18.04.202201060 18.04.202201060
UbuntuServer Canonical 18.04-LTS Canonical:UbuntuServer:18.04-LTS:18.04.202201180 18.04.202201180
Terraform で Ubuntu の VM を作成してみる
terraform 定義ファイルの作成
プロバイダの定義
main.tf
# プロバイダーの定義
terraform {
required_providers {
azurerm = "~> 2.33"
}
}
provider "azurerm" {
features {}
tenant_id = var.ARM_TENANT_ID
client_id = var.ARM_CLIENT_ID
client_secret = var.ARM_CLIENT_SECRET
}
# リソースグループ
resource "azurerm_resource_group" "this" {
name = var.resource_group_name
location = var.region
tags = var.tags_def
}
パラメータ定義ファイル
variables.tf
# 環境変数(Azureサービスプリンシパル)
variable ARM_TENANT_ID {}
variable ARM_CLIENT_ID {}
variable ARM_CLIENT_SECRET {}
# タグ情報
variable tags_def {
default = {
owner = "ituru"
period = "2022-03-31"
CostCenter = "PSG2"
Environment = "Demo"
Project = "DUP_IaC"
}
}
# 各種パラメータ
variable region {} // 利用リージョン
variable resource_group_name {} // リソースグループ名
variable vnet_name {} // vNet名
variable vnet_address_space {} // vNetアドレス範囲
variable subnet_name {} // サブネット名
variable subnet_address {} // サブネットアドレス
variable public_ip_name {} // パブリックIP名
variable security_group_name {} // セキュリティグループ名
variable network_interface_name {} // ネットワーク・インターフェース名
variable vm_name {} // 仮想マシン名
variable vm_size {} // 仮想マシンサイズ
variable computer_name {} // コンピュータ名
variable admin_username {} // 管理者名
パラメータ値定義ファイル
terraform.tfvars
# 環境変数の定義(Azureサービスプリンシパル)
ARM_TENANT_ID = "zzzzzzzz-cccc-4645-5757-zzzzzzzzzzzz"
ARM_CLIENT_ID = "xxxxxxxx-xxxx-4444-9922-xxxxxxxxxxxx"
ARM_CLIENT_SECRET = "hogehogehogehogehogehogehogehogege"
# パラメータ値の定義
region = "japaneast" // 利用リージョン
resource_group_name = "rg_ituru_vm02" // リソースグループ名
vnet_name = "vnet_ituru_vm02" // vNet名
vnet_address_space = "10.0.0.0/16" // vNetアドレス範囲
subnet_name = "snet_ituru_vm02" // サブネット名
subnet_address = "10.0.1.0/24" // サブネットアドレス
public_ip_name = "pip_ituru_vm02" // パブリックIP名
security_group_name = "nsg_ituru_vm02" // セキュリティグループ名
network_interface_name = "nic_ituru_vm02" // ネットワーク・インターフェース名
vm_name = "vm-ituru-ubuntu" // 仮想マシン名
vm_size = "Standard_D11_v2" // 仮想マシンサイズ
computer_name = "ubuntu1804" // コンピュータ名
admin_username = "nmcadmin" // 管理者名
仮想マシン定義ファイル
computer.tf
# Linux(Ubuntu 18.04) 仮想マシン
resource "azurerm_linux_virtual_machine" "this" {
name = var.vm_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
size = var.vm_size
computer_name = var.computer_name
admin_username = var.admin_username
network_interface_ids = [
azurerm_network_interface.this.id,
]
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
admin_ssh_key {
username = var.admin_username
public_key = tls_private_key.this.public_key_openssh
}
tags = var.tags_def
}
# SSHキーの作成
resource "tls_private_key" "this" {
algorithm = "RSA"
rsa_bits = 4096
}
ネットワーク+セキュリティ定義ファイル
network.tf
// 仮想ネットワーク
resource "azurerm_virtual_network" "this" {
name = var.vnet_name
address_space = [var.vnet_address_space]
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
tags = var.tags_def
}
// サブネット
resource "azurerm_subnet" "internal" {
name = var.subnet_name
resource_group_name = azurerm_resource_group.this.name
virtual_network_name = azurerm_virtual_network.this.name
address_prefixes = [var.subnet_address]
}
// パブリック IP アドレス
resource "azurerm_public_ip" "this" {
name = var.public_ip_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
allocation_method = "Dynamic"
tags = var.tags_def
}
// ネットワーク セキュリティ グループ
resource "azurerm_network_security_group" "this" {
name = var.security_group_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
security_rule {
name = "SSH"
description = "Allow SSH Access"
priority = 1002
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "153.134.22.135/32"
destination_address_prefix = "*"
}
tags = var.tags_def
}
// ネットワーク インターフェイス
resource "azurerm_network_interface" "this" {
name = var.network_interface_name
location = azurerm_resource_group.this.location
resource_group_name = azurerm_resource_group.this.name
ip_configuration {
name = "ipconfig"
subnet_id = azurerm_subnet.internal.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.this.id
}
tags = var.tags_def
}
// ネットワークインターフェースへのネットワークセキュリティグループの割当
resource "azurerm_network_interface_security_group_association" "this" {
network_interface_id = azurerm_network_interface.this.id
network_security_group_id = azurerm_network_security_group.this.id
}
terraform の実行
## init
$ terraform init
:
Terraform has been successfully initialized!
## plan
$ terraform plan
:
Plan: 9 to add, 0 to change, 0 to destroy.
## apply
$ terraform apply
:
Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
Outputs:
admin_username = "nmcadmin"
public_ip_id = [
"/subscriptions/xxxxxxxx-1717-dada-9779-zzzzzzzzzzzz/resourceGroups/rg_ituru_vm02/providers/Microsoft.Network/publicIPAddresses/pip_ituru_vm02",
]
tls_private_key = <sensitive>
ローカルの作業ディレクトの状況
$ tree -a
.
├── .terraform
│ └── providers
│ └── registry.terraform.io
│ └── hashicorp
│ ├── azurerm
│ │ └── 2.93.0
│ │ └── darwin_amd64
│ │ └── terraform-provider-azurerm_v2.93.0_x5
│ └── tls
│ └── 3.1.0
│ └── darwin_amd64
│ └── terraform-provider-tls_v3.1.0_x5
├── .terraform.lock.hcl
├── compute.tf
├── main.tf
├── network.tf
├── outputs.tf
├── terraform.tfstate
├── terraform.tfstate.backup
├── terraform.tfvars
├── variables.tf
└── vm_ubuntu.pem
terraform 実行後の確認
リソースグループ の確認
$ az group show --name <Resource_Group_name>
{
"id": "/subscriptions/xxxxxxxx-1717-dada-9779-zzzzzzzzzzzz/resourceGroups/rg_ituru_vm02",
"location": "japaneast",
"managedBy": null,
"name": "rg_ituru_vm02",
"properties": {
"provisioningState": "Succeeded"
},
"tags": {
"CostCenter": "PSG2",
"Environment": "Demo",
"Project": "DUP_IaC",
"owner": "ituru",
"period": "2022-03-31"
},
"type": "Microsoft.Resources/resourceGroups"
}
仮想マシン の確認
$ az vm list -g <Resource_Group_Name> -d --output table
Name ResourceGroup PowerState PublicIps Fqdns Location Zones
--------------- --------------- ------------ ------------- ------- ---------- -------
vm-ituru-ubuntu rg_ituru_vm02 VM running 20.188.24.42 japaneast
ネットワークセキュリティグループ の確認
$ az network nsg rule list -g <Resource_Group_Name> --nsg-name <Network_Security_Group_Namr> -o table
Name ResourceGroup Priority SourcePortRanges SourceAddressPrefixes SourceASG Access Protocol Direction DestinationPortRanges DestinationAddressPrefixes DestinationASG
------ --------------- ---------- ------------------ ----------------------- ----------- -------- ---------- ----------- ----------------------- ---------------------------- ----------------
SSH rg_ituru_vm02 1002 * 153.134.22.135/32 None Allow Tcp Inbound 22 * None
仮想マシンへの接続
グローバルアドレスの取得
$ az vm list-ip-addresses --resource-group <Resource_Group_Name> --name <VM_Name> --output table
VirtualMachine PublicIPAddresses PrivateIPAddresses
---------------- ------------------- --------------------
vm-ituru-ubuntu 20.188.24.42 10.0.1.4
秘密鍵の取得とパーミッションの変更
$ terraform output -raw tls_private_key > vm_ubuntu.pem
$ chmod 600 vm_ubuntu.pem
SSH接続
$ ssh -i vm_ubuntu.pem nmcadmin@20.188.24.42
The authenticity of host '20.188.24.42 (20.188.24.42)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx64.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '20.188.24.42' (ED25519) to the list of known hosts.
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1067-azure x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Mon Jan 24 09:05:02 UTC 2022
System load: 0.0 Processes: 116
Usage of /: 4.6% of 28.90GB Users logged in: 0
Memory usage: 1% IP address for eth0: 10.0.1.4
Swap usage: 0%
0 updates can be applied immediately.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
nmcadmin@ubuntu1804:~$
接続(ログイン)後の確認
## OSバージョン
nmcadmin@ubuntu1804:~$ uname -a
Linux ubuntu1804 5.4.0-1067-azure #70~18.04.1-Ubuntu SMP Thu Jan 13 19:46:01 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
## IPアドレス
nmcadmin@ubuntu1804:~$ ip add show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:22:48:e7:02:80 brd ff:ff:ff:ff:ff:ff
inet 10.0.1.4/24 brd 10.0.1.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::222:48ff:fee7:280/64 scope link
valid_lft forever preferred_lft forever
## グローバルアドレス
nmcadmin@ubuntu1804:~$ curl ifconfig.me
20.188.24.42
terraform による作成したリソースの削除
$ terraform destroy
まとめ
これで、Terraform でサクッと Azure環境上に Ubuntu を構成し SSH接続 できました。 Azure Portal や Azure CLI で構築するのもいいですが、IaC化もいいですね。
参考記事
以下の記事を参考にさせていただきました。感謝申し上げます。
SSH公開鍵認証で接続するまで