ディスクサイズ 8GB の Azure Linux VM を作ってみた

## 背景と目的

Azure Linux VM の規定のディスクサイズは 30GB です。たまにしか起動しない VM でもディスクサイズに応じたディスク利用料はかかり続けます。自分が以前書いた「[パブリックプレビューの Azure Managed Disk ライブ拡張（ディスクをマウントしたまま容量を増やすやつ）をやってみた](https://qiita.com/mnrst/items/a8d9c53ffdc7a96150d7)」のように、データディスクのディスクサイズをライブ拡張出来るようになりました。OS 領域は最低限のディスクサイズでデータ領域をライブ拡張していく使い方を想定したいと思います。Azure に用意されているディスクイメージは、ディスクサイズを小さくすることが出来ないため、あらかじめ小さいディスクサイズの OS イメージを用意する必要があります。そこで今回は Hyper-V 環境で CentOS をインストールして VHD を Azure にアップロードして Azure Linux VM を作ってみました。

## 前提条件

* Hyper-V 環境があること
* azcopy がインストール済みであること

## Hyper-V 環境にディスクサイズ 8GB の CentOS を作る

<https://docs.microsoft.com/ja-jp/virtualization/hyper-v-on-windows/quick-start/create-virtual-machine#create-a-virtual-machine-with-powershell>

こちらのドキュメントを参考に、仮想マシンを作成します。

```powershell:powershell
# 環境変数をセットします
$VMName = 'testvm'
$Switch = 'Default Switch'
$InstallMedia = 'C:\Users\Public\Documents\ISO\CentOS-7-x86_64-Minimal-1611.iso'

# 仮想マシンを作成します
New-VM -Name $VMName `
  -MemoryStartupBytes 1GB `
  -Generation 1 `
  -NewVHDPath "C:\Users\Public\Documents\Hyper-V\Virtual hard disks\$VMName.vhdx" `
  -NewVHDSizeBytes 8GB `
  -Path "C:\Users\Public\Documents\Hyper-V\Virtual Machines\$VMName" `
  -SwitchName $Switch

# インストールメディアをセットします
Set-VMDvdDrive -VMName $VMName -Path $InstallMedia
```

次に、画面を開いて VM を起動し OS をインストールします。私の場合、ディスクは標準パーティションで SWAP なしで作成しました。

## 固定サイズの VHD を作る

```powershell:powershell
# 仮想マシンを停止します
Stop-VM -Name $VMName

# 固定サイズの VHD に変換します
Convert-VHD `
  -Path "C:\Users\Public\Documents\Hyper-V\Virtual hard disks\$VMName.vhdx" `
  -DestinationPath "C:\Users\Public\Documents\Hyper-V\Virtual hard disks\$VMName.vhd" `
  -VHDType Fixed

# 固定サイズの VHD で別の仮想マシンを作成します
New-VM -Name ${VMName}2 `
  -MemoryStartupBytes 1GB `
  -Generation 1 `
  -VHDPath "C:\Users\Public\Documents\Hyper-V\Virtual hard disks\$VMName.vhd" `
  -Path "C:\Users\Public\Documents\Hyper-V\Virtual Machines\${VMName}2" `
  -SwitchName $Switch
```

次に、固定サイズの VHD で起動した仮想マシンに SSH ログインします。コンソールログインでも良いです。

## Azure 用に OS をカスタマイズ

インストールメディアで使用した CentOS のバージョンを固定したい場合、今回の例では 7.3 なので、以下のようにします。

```bash:bash
echo 7.3.1611 > /etc/yum/vars/releasever
```

<https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/create-upload-centos#centos-70>

こちらのドキュメントを参考に、以下のようにカスタマイズしてみました。また、今回はディスクを一般化（イメージ化）しないでインストール時に作成した root ログイン情報もそのまま Azure に持って行きたいと思います。イメージ化したい場合は、「[リリース前の Ubuntu 22.04 イメージを Azure に持ち込み VM 作成までやってみた](https://qiita.com/mnrst/items/3a754e53e4d1d778efb0)」を参考にしてみてください。

```bash:bash
cat << EOF > /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=localhost.localdomain
EOF

cat << EOF > /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=dhcp
TYPE=Ethernet
USERCTL=no
PEERDNS=yes
IPV6INIT=no
EOF

ln -s /dev/null /etc/udev/rules.d/75-persistent-net-generator.rules

cat << "EOF" > /etc/yum.repos.d/CentOS-Base.repo
[openlogic]
name=CentOS-$releasever - openlogic packages for $basearch
baseurl=http://olcentgbl.trafficmanager.net/openlogic/$releasever/openlogic/$basearch/
enabled=1
gpgcheck=0

[base]
name=CentOS-$releasever - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
baseurl=http://ftp.riken.jp/Linux/centos-vault/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#released updates
[updates]
name=CentOS-$releasever - Updates
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra
baseurl=http://ftp.riken.jp/Linux/centos-vault/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
baseurl=http://ftp.riken.jp/Linux/centos-vault/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra
baseurl=http://ftp.riken.jp/Linux/centos-vault/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
EOF

yum clean all

yum -y update

sed -i 's/GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet"/GRUB_CMDLINE_LINUX="rootdelay=300 console=ttyS0 earlyprintk=ttyS0 net.ifnames=0"/' /etc/default/grub

grub2-mkconfig -o /boot/grub2/grub.cfg

sed -i 's/#add_drivers+=""/add_drivers+=" hv_vmbus hv_netvsc hv_storvsc "/' /etc/dracut.conf

dracut -f -v

yum -y install python-pyasn1 WALinuxAgent

systemctl enable waagent

poweroff
```

## 固定サイズの VHD をマネージドディスクに直接アップロード

```powershell:powershell
# 変数をセットします
$region = "japaneast"
$prefix = "mnrcent"
$filesize = (Get-VHD "C:\Users\Public\Documents\Hyper-V\Virtual hard disks\$VMName.vhd").FileSize

# リソースグループを作成します
az group create `
  --name ${prefix}-rg `
  --location $region

# 空のマネージドディスクを作成します
az disk create `
  --name ${prefix}-vmOSDisk `
  --resource-group ${prefix}-rg `
  --os-type Linux `
  --for-upload `
  --upload-size-bytes $filesize `
  --sku Standard_LRS `
  --hyper-v-generation V1

# マネージドディスクに書き込み出来るようにします
$sasurl = $(az disk grant-access `
  --name ${prefix}-vmOSDisk `
  --resource-group ${prefix}-rg `
  --access-level Write `
  --duration-in-seconds 86400 `
  --query accessSas `
  --output tsv)

# 固定サイズの VHD をマネージドディスクに直接アップロードします
azcopy copy "C:\Users\Public\Documents\Hyper-V\Virtual hard disks\$VMName.vhd" $sasurl --blob-type PageBlob

# マネージドディスクへのアクセスを閉じます
az disk revoke-access `
  --name ${prefix}-vmOSDisk `
  --resource-group ${prefix}-rg

# 仮想マシンを作成します
az vm create `
  --resource-group ${prefix}-rg `
  --name ${prefix}-vm `
  --os-type linux `
  --attach-os-disk ${prefix}-vmOSDisk `
  --size Standard_B1ls `
  --nsg-rule NONE `
  --public-ip-address-dns-name ${prefix}

# 自身の IP から SSH アクセス出来るようにします
az network nsg rule create `
  --resource-group ${prefix}-rg `
  --name Allow-SSH `
  --nsg-name ${prefix}-vmNSG `
  --priority 100 `
  --source-address-prefixes $((curl -UseBasicParsing inet-ip.info/ip).Content) `
  --destination-port-ranges 22 `
  --access Allow `
  --protocol Tcp

# root ユーザーで SSH 接続します
ssh root@${prefix}.$region.cloudapp.azure.com
```

## 参考

作成したリソースを削除します。

```powershell:powershell
# リソースグループを削除します
az group delete `
  --name ${prefix}-rg
```

参考サイトです。

<https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/disks-upload-vhd-to-managed-disk-cli>