[GCP]GCEのWindows Server上にWindows10を構築する手順（ネストされた仮想化）

# はじめに
GCEの仮想環境上に仮想環境を構築するには以下の準備をする必要がありますが、ドキュメントに若干わかりづらい部分があったので、自分用に手順をまとめました。

> VM インスタンスのネストされた仮想化の有効化
> https://cloud.google.com/compute/docs/instances/enable-nested-virtualization-vm-instances?hl=ja

なお以下にGCP側で動作確認しているホストOSとゲストOSの組み合わせの記載がありますが、「ホストOSにWindows Server + ゲストOSにWindows10」の記載はありませんでした。
そのためここに記載している方法で実施した場合は、後に不具合が発生する可能性があります。

> テスト済みの KVM バージョン
> https://cloud.google.com/compute/docs/instances/enable-nested-virtualization-vm-instances?hl=ja#tested_os_versions

# 手順
## 1. インスタンス上でネストされた仮想化を有効にする

### 公開イメージの確認
まずホストOSとして使用したいイメージの情報を確認するために以下のコマンドを実行します。

```sh
gcloud compute images list
```

以下のような結果が得られますので、自分が使用したいホストOSの行を探してください。
そして、`PROJECT`と`FAMILY`をメモしてください。
今回は`windows-server-2019-dc-v20200310`を使用します。

```sh
NAME                                                  PROJECT            FAMILY                            DEPRECATED  STATUS
略
windows-server-2019-dc-v20200310                      windows-cloud      windows-2019                                  READY
略
```

### 公開イメージからブートディスクを作成
前の手順で取得したimageの情報を使い、ブートディスクを作成します。
PROJECT（`windows-cloud`）とFAMILY（`windows-2019`）を指定して、ブートディスク（`windows-vm`）を作成します。
ブートディスク名はなんでも良いです。

```sh
gcloud compute disks create windows-vm --image-project windows-cloud --image-family windows-2019 --zone asia-northeast1-b
```

以下の結果が得られます。

```sh
NAME        ZONE               SIZE_GB  TYPE         STATUS
windows-vm  asia-northeast1-b  50       pd-standard  READY
```

### ブートディスクからカスタムイメージを作成
前の手順で作成したブートディスク（`windows-vm`）に対して、仮想化に必要なライセンスキーを使用して、カスタムイメージ（`nested-windows-image`）を作成します。
カスタムイメージ名はなんでも良いです。
これには数分かかります。

```sh
gcloud compute images create nested-windows-image \
  --source-disk windows-vm --source-disk-zone asia-northeast1-b \
  --licenses "https://compute.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx"
```

以下の結果が得られます。

```sh
NAME                  PROJECT    FAMILY  DEPRECATED  STATUS
nested-windows-image  socengine                      READY
```

### カスタムイメージからVMインスタンスを作成
前の手順で作成したカスタムイメージ（`nested-windows-image`）から、VMインスタンス（`nested-windows-vm`）を作成します。
VMインスタンス名はなんでも良いです。

```sh
gcloud compute instances create nested-windows-vm --zone asia-northeast1-b \
  --min-cpu-platform "Intel Haswell" \
  --boot-disk-size 500GB \
  --image nested-windows-image
```

以下の結果が得られます。

```sh
NAME               ZONE               MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
nested-windows-vm  asia-northeast1-b  n1-standard-1               xx.xx.xx.xx   xx.xx.xx.xx  RUNNING
```

## 2. 作成したホストOSにリモートデスクトップ接続するための準備
### GCP側のファイアウォールの設定
VPCネットワーク -> ファイアウォールルール を開き[ファイアウォールルールを作成]をクリックします。
以下の項目を入力した後、[作成]をクリックします。

|変更する項目|変更内容|
|:------|:------|
|名前|適当に入力します|
|ターゲットタグ|適当に入力します。私は上記の[名前]と同じにしています|
|ソースIPの範囲|RDPする接続元のIPアドレスを入力します|
|指定したプロトコルとポート|tcpにチェックを入れ、3389と入力します|

### ホストOS側でファイアウォールルールの適用
Compute Engineの画面から作成したホストOSを選択し、右上の[編集]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/0c86d4aa-0364-8b1d-5309-a513c11e6365.png)

次に[ネットワークタグ]にファイアウォールの設定時に入力した「ターゲットタグ」を入力します。
これで先ほど作成したファイアウォールルールが適用されます。
最後に[保存]をクリックします。

### リモートデスクトップ接続
お好きなツールを使用してリモートデスクトップしてください。

## 3. 仮想化ソフトウェアのインストール
今回は無料のVirtualBoxをインストールしました。
https://www.virtualbox.org/wiki/Downloads

あとは通常のゲストOSを作成する手順で、Windows10が作成できました。

# 参考情報
VMware Workstationだと以下のエラーがでてゲストOSを作成できませんでした。

> This host supports Intel VT-x, but the Intel VT-x implementation is incompatible with VMware Workstation.
> This host does not support "Intel EPT" hardware assisted MMU virtualization.
> Module 'CPUIDEarly' power on failed.
> Failed to start the virtual machine.

CPUを新しいものにすれば上記のエラーが回避できる場合があるという情報があったため、VMインスタンスを作成する際に以下のように`Intel Cascade Lake`を指定しましたがやはり同じエラーになりました。

```sh
gcloud compute instances create nested-windows-vm-cascadelake --zone asia-northeast1-b \
  --min-cpu-platform "Intel Cascade Lake" \
  --boot-disk-size 500GB \
  --machine-type n2-standard-8 \
  --image nested-windows-image
```

*マシンタイプと対応するプロセッサ一覧*
*https://cloud.google.com/compute/docs/machine-types?hl=ja#machine_type_comparison*