GCE起動スクリプトでWindowsServerの基本設定を行う

# はじめに
GCEのWindows VMにて、WindowsServerの以下の基本設定のうち、起動スクリプトでの設定方法について記述します。
起動スクリプトで設定することで、初期起動時にWindowsServerにRDP接続してコマンドやGUIで各種設定する手間を削減することができ、ヒューマンエラーによる設定ミスも防止することができます。

|設定内容|設定方法|本記事の対象|備考|
|---|---|---|---|
|OpsAgentのインストール|起動スクリプト|○|参考：[個々のVMにOpsエージェントをインストールする](https://cloud.google.com/stackdriver/docs/solutions/agents/ops-agent/installation?hl=ja)|
|コンピューター名|起動スクリプト|○||
|アカウント名|起動スクリプト|○||
|ローカライズ（言語・地域・日付と時刻）|GUI|×||

ローカライズは設定処理に数十分かかるため、起動スクリプトでの設定はお勧めしません。
GUIでの設定方法はネットで検索すれば簡単にヒットするので、本記事では割愛します。

# Windows VMの起動スクリプトについて

Windows VMの起動スクリプトについてザックリ説明すると以下の通りです。（詳細は[公式ドキュメント](https://cloud.google.com/compute/docs/instances/startup-scripts/windows)参照）
* 起動スクリプトは、VMインスタンスの起動プロセス中にタスクを実行するファイルのこと
* 起動スクリプトは、プロジェクト内のすべての VM または単一の VM に適用でき、プロジェクトまたはVMインスタンスのメタデータに設定する
* プロジェクトレベルで設定した起動スクリプトよりも、VMレベルのものの方が優先される
* Windows VMの起動スクリプトは大きく分けて、以下の2種類が存在する
    * sysprep-specialize-script-*：VMインスタンスの初期起動時に実行する
    * windows-startup-script-*：初期起動後の各起動時に実行する

:::note 
Windows Serverの基本設定は初期起動時のみに実行するため、sysprep-specialize-script-*を使用します。
:::

# 前提条件
* イメージはWindowsServer2019
* Windows VMを作成するのに必要な前提条件は満たしていること（[公式ドキュメント](https://cloud.google.com/compute/docs/instances/windows/creating-managing-windows-instances#start_instance)）
* Cloud Shellで操作する

# 設定手順

以降、Cloud Shellで実行します。

## 起動スクリプトを作成する

以下のコマンドで起動スクリプトファイルを作成します。
```shell
vim sysprep_specialize_script_ps1.sh.tpl
```

起動スクリプトファイルの内容を以下の通りに記述します。

```powershell
echo 'Start'

# メタデータサーバからパラメータ値を取得
$ComputerName   = (Invoke-RestMethod -Headers @{'Metadata-Flavor' = 'Google'} -Uri "http://metadata.google.internal/computeMetadata/v1/instance/attributes/computer-name")
$AdminName      = (Invoke-RestMethod -Headers @{'Metadata-Flavor' = 'Google'} -Uri "http://metadata.google.internal/computeMetadata/v1/instance/attributes/admin-name")

# Opsエージェントのインストール
(New-Object Net.WebClient).DownloadFile("https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.ps1", "${env:UserProfile}\add-google-cloud-ops-agent-repo.ps1") | Out-Null
Invoke-Expression "${env:UserProfile}\add-google-cloud-ops-agent-repo.ps1 -AlsoInstall"

# コンピューター名の設定
Rename-Computer -NewName $ComputerName

# 管理者アカウント追加
New-LocalUser -Name $AdminName -FullName $AdminName -NoPassword   # パスワードはgcloud compute reset-windows-passwordコマンドで設定する
Add-LocalGroupMember -Group 'Administrators' -Member $AdminName

echo 'Finish'
```

## Windows VMの作成

インスタンスのメタデータにコンピュータ名とアカウント名、起動スクリプトファイルを指定します。

```shell
gcloud compute instances create windows-vm \
    --zone=asia-northeast1-a \
    --image-project windows-cloud \
    --image-family windows-2019 \
    --machine-type e2-medium \
    --boot-disk-size 50 \
    --boot-disk-type pd-balanced \
    --metadata=^,@^computer-name=sample-server,@admin-name=sample-admin \
    --metadata-from-file=sysprep-specialize-script-ps1=sysprep_specialize_script_ps1.sh.tpl
```

## インスタンスの正常起動の確認

「Instance setup finished. sample-server is ready to use.」と表示されればOKです。

```shell
gcloud compute instances get-serial-port-output windows-vm --zone asia-northeast1-a
```

## Windows認証情報の生成
WindowsServerへのログインユーザーのパスワードを発行します。

```shell
gcloud compute reset-windows-password windows-vm --user=sample-admin --zone=asia-northeast1-a

# 出力例
ip_address: [外部IPアドレス]
password:   [パスワード]
username:   sample-admin
```

# 設定内容の確認
Windows PowerShellで以下コマンドを実行します。

## Opsエージェント

```powershell
Get-Service google-cloud-ops-agent

# 出力例
Status   Name               DisplayName
------   ----               -----------
Running  google-cloud-op... Google Cloud Ops Agent
```

## コンピューター名

```powershell
HOSTNAME.EXE

# 出力例
sample-server
```

## アカウント名

```powershell
Get-WmiObject Win32_UserAccount

# 出力例
…（省略）
AccountType : 512
Caption     : SAMPLE-SERVER\sample-admin
Domain      : SAMPLE-SERVER
SID         : [SID]
FullName    : sample-admin
Name        : sample-admin
…（省略）
```

# 補足
Opsエージェントのインストールは、すべてのエージェントのインストールとオプションの自動アップグレードを適切に行うことができる、[エージェントポリシー](https://cloud.google.com/stackdriver/docs/solutions/agents/ops-agent/managing-agent-policies?hl=ja)を使用することをお勧めします。

今回は、組織ポリシーでCompute Engine メタデータのゲスト属性の使用（[constraints/compute.disableGuestAttributesAccess](https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints?hl=ja#constraints-for-specific-services)）が許可されておらず、[エージェントポリシーを使用するための前提条件を満たさない](https://cloud.google.com/stackdriver/docs/solutions/agents/ops-agent/managing-agent-policies?hl=ja#the_os_config_agent_is_installed_but_it_does_not_install_the_ops_agents)ため、個々のVMにOpsエージェントをインストールする方法を採用しました。

以上です。ありがとうございました。