クラウド上でNested Virtualization対応のVMを構築する

### はじめに
OpenStackのお試し環境をクラウド上で構築しようとしたところ、OpenStackを実行するためにNested Virtualizationが必須だと知りました。
※Nested Virtualizationとは、VMの上にVMを入れ子につくることです。

残念ながら、OpenStackのお試し環境は結局うごかせていないのですが、
本記事では、AWS・GCP・AzureでNested Virtualizationの構築を試した内容について記載します。

### 目次
* AWS
* GCP
* Azure

### AWS
さっそくですが、AWSで構築する方法が分からなかったため、何も情報がありません。
何かわかれば、追記します。

### GCP
※cloud shellで実行しています。

#### 1. イメージを作成する

```bash
# GCPが提供するイメージを確認する
gcloud compute images list --standard-images | grep ubuntu
NAME                                                  PROJECT                 FAMILY                            DEPRECATED  STATUS
ubuntu-1804-bionic-v20201014                          ubuntu-os-cloud      ubuntu-1804-lts                               READY
ubuntu-2004-focal-v20201014                           ubuntu-os-cloud      ubuntu-2004-lts                               READY
# ※出力結果は、一部省略しています

# ベースイメージとして一時的に使用するソースディスクを作成する
gcloud compute disks create disk-nested-ubuntu \
--image-project ubuntu-os-cloud \
--image-family ubuntu-1804-lts \
--zone us-central1-a

# ※出力
Created [https://www.googleapis.com/compute/v1/projects/******/zones/us-central1-a/disks/disk-nested-ubuntu].
NAME   ZONE           SIZE_GB  TYPE         STATUS
disk-nested-ubuntu  us-central1-a  10       pd-standard  READY

# enable-vmxライセンスを指定してカスタムイメージを作成する
gcloud compute images create nested-ubuntu-image \
  --source-disk disk-nested-ubuntu --source-disk-zone us-central1-a \
  --licenses "https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx"

# ※出力
Created [https://www.googleapis.com/compute/v1/projects/******/global/images/nested-vm-image].
NAME             PROJECT FAMILY  DEPRECATED  STATUS
nested-vm-image  ******                      READY

# ソースディスクが不要になったので、削除する
gcloud compute disks delete disk-nested-ubuntu --zone us-central1-a
```

#### 2. イメージからインスタンスを作成する

インスタンスの作成時に、1でつくったイメージが選べるようになっています。
![](https://i.imgur.com/HdEyfFE.png)

#### 3. 作成結果を確認する

`/proc/cpuinfo`の`flags`に、`vmx`が存在していることを確認。
`flags`には、CPUにどんな機能があるのかが書かれています。

```bash
# SSHで接続する（一例）
gcloud compute ssh example-nested-vm

# cpuinfoに、vmxの存在を確認する
******@example-nested-vm:~$ cat /proc/cpuinfo | grep vmx
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat md_clear arch_capabilities
```

### Azure

[Azure コンピューティング ユニット (ACU)](https://docs.microsoft.com/ja-jp/azure/virtual-machines/acu)のリストのうち CPUコア数の列に`***` が付いているファミリーがNested Virtualizationに対応しているようです。
`*** ハイパースレッド化されており、入れ子になった仮想化を実行できます。`

例えば、[Dv3 および Dsv3 シリーズ](https://docs.microsoft.com/ja-jp/azure/virtual-machines/dv3-dsv3-series)に記載されている「Standard_D4_v3」で作成した結果が次の通りです。

```bash
# SSHで接続する
ssh $USERNAME@$PUBLIC_IP

# GCPと同じく、作成したVMにSSHで接続し、cpuinfoを確認
cat /proc/cpuinfo | grep vmx

# 「Standard_D4_v3」で作成しました。CPUが4つあるので4行出ています。
nested-user@nested-vm:~$ cat /proc/cpuinfo | grep vmx
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti tpr_shadow vnmi ept vpid fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt md_clear
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti tpr_shadow vnmi ept vpid fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt md_clear
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti tpr_shadow vnmi ept vpid fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt md_clear
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti tpr_shadow vnmi ept vpid fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt md_clear
```


## 参考
以下を参考にしました。

- GCP
    - [VM インスタンスのネストされた仮想化の有効化](https://cloud.google.com/compute/docs/instances/enable-nested-virtualization-vm-instances?hl=ja)
    - [GCEでNestedVirtualization対応のUbuntuインスタンスを立てる](https://qiita.com/Hi_Noguchi/items/c75f7a73c3538c117f43)
    - [カスタム オペレーティング システムの構築](https://cloud.google.com/compute/docs/images/building-custom-os?hl=ja)

- Azure
    - [Azure VM で入れ子になった仮想化を有効にする方法](https://docs.microsoft.com/ja-jp/azure/virtual-machines/windows/nested-virtualization)
    - [Azure コンピューティング ユニット (ACU)](https://docs.microsoft.com/ja-jp/azure/virtual-machines/acu)
    - [Azure で Nested Virtualization の使用が可能に](https://docs.microsoft.com/ja-jp/archive/blogs/jpitpro/nested-virtualization-in-azure)

- 構築後の確認
    - [/proc/cpuinfoファイル](https://linuc.org/study/knowledge/528/)
    - [22.13. 仮想化拡張機能を確認する](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/virtualization_administration_guide/sect-virtualization-tips_and_tricks-verifying_virtualization_extensions)

- OpenStack
    - [DevStack](https://docs.openstack.org/devstack/latest/)
    - [(Blog)devstackとvirtualBoxを使ってOpenstackのお試し環境を構築する](https://docs.openstack.org/devstack/latest/)
    - [(Blog)VirtualBox 6.1 で Intel CPU の Nested Virtualization が解除された](https://blog.kondoumh.com/entry/2020/02/13/212137)
    - [(Blog)VirtualBox で仮想マシンが入れ子 (Nested Virtualization) できるようになった](https://blog.amedama.jp/entry/virtualbox-nested-virtualization)

### おわりに
「完全に理解」していますので、間違いや誤解を与える表現等ありましたらコメント頂けると嬉しいです。

ちなみに、VirtualBoxでもNested Virtualizationを有効にできます。
1度だけVirtualBox上でOpenStackのお試し環境(DevStack)が動いたようなのですが、、。