本日も乙

ただの自己満足な備忘録。

Spinnakerで Bake ステージを作成する

Spinnakerで Bake ステージと呼ばれる、デプロイするためのマシンイメージを作成する工程をパイプライン上に作成することができます。AWS では AMI, GCP では VM イメージ が該当します。
Spinnaker では Hashicorp 社の Pakcer というツールを使ってマシンイメージを生成します。Spinnaker で予め用意されている Packer テンプレート を使うこともできますが、カスタム Packer テンプレートを使うことも可能です。
今回はカスタム Packer テンプレートを使って Bake ステージを設定してみます。

目次

前提条件

  • 本記事では Packer および Packer テンプレートについての説明は深く取り上げません。詳細を知りたい人はドキュメントを見てください
  • 今回は私が取り組んでいるプロジェクトの都合上、GCP の Windows Server の VM イメージを作成しますが、AWS や Linux ユーザであったとしても、Packer テンプレートのパラメータが異なるだけでやり方は同じなので安心して読んでください

Packer テンプレート

GCP かつ Windows Server の Packer テンプレートがなかったため、自分でカスタムして作成しました。一般公開できるような形にしたのを GitHub にアップしました。

gcp-windows-2012-r2.json

variables セクション内の gce_xxxx パラメータは後述の hal コマンドや Bake ステージで渡されます。指定がなければ、テンプレートにあるデフォルト値が使われます。デフォルトで外部IPアドレスを持たせずに、内部IPアドレスのみで通信させるようにしています。変更したい場合は gce_use_internal_ip および gce_omit_external_ipfalse に指定してください。
provisioners セクションでは、Sysprep をGCE用にラップした GCESysprep を実行しています。
Windows Remote Management(WinRM) で接続して実行するため、起動時に専用ユーザ(packer)を起動時に作成するようにしています。

Packer テンプレートファイルの設置

上記の Packerテンプレートファイルと PowerShell スクリプトを /opt/rosco/config/packer 配下に置きます。

# Packer テンプレート
/opt/rosco/config/packer/gcp-windows-2012-r2.json

実行ユーザの設定も忘れずに。

$ sudo chown spinnaker:spinnaker /opt/rosco/config/packer/gcp-windows-2012-r2.json

hal コマンドでの設定

Spinnaker の設定は hal コマンドで行います。

$ PROJECT=$(gcloud info --format='value(config.project)')

# GCEのデフォルトネットワークから変更したい場合
$ hal config provider google bakery edit \
    --network "sample-network" \
    --network-project-id $PROJECT \
    --use-internal-ip "true" \
    --zone "asia-northeast1-a"

# イメージの追加
$ hal config provider google bakery base-image add "windows-2012-r2" \
  --source-image-family "windows-2012-r2" \
  --short-description "Windows Server 2012 R2" \
  --detailed-description "Windows Server 2012 R2 Datacenter Edition, x86_64" \
  --package-type nupkg \
  --template-file gcp-windows-2012-r2.json

# 確認
$ hal config provider google bakery base-image get "windows-2012-r2"
+ Get current deployment
  Success
+ Get windows-2012-r2 base image
  Success
+ Settings for windows-2012-r2 ingoogle's bakery:
GoogleBaseImage(baseImage=GoogleBaseImage.GoogleImageSettings(super=BaseImage.ImageSettings(id=windows-2012-r2, shortDescription=Windows Server 2012 R2, detailedDescription=Windows Server 2012 R2 Datacenter Edition, x86_64, packageType=nupkg, templateFile=gcp-windows-2012-r2.json), isImageFamily=false), virtualizationSettings=GoogleBaseImage.GoogleVirtualizationSettings(sourceImage=null, sourceImageFamily=windows-2012-r2))

hal deploy apply で反映させます。 *1 数分程度かかります。

$ sudo hal deploy apply
$ sudo systemctl daemon-reload

Pipeline での設定

Pipeline で Bake ステージの設定をします。Pipeline の作成は省略しています。
Add stage をクリックし、 TypeBake に選択します。
下図のように、 Base OS に先ほど追加したイメージ( windows-2012-r2 )が追加されていますのでそれを選択します。
Show Advanced Options をチェックして、Extended Attributes で、環境変数として渡すパラメータ( gce_subnetwork, gce_service_account_email )を入力します。
設定できたら右下にある Save Changes をクリックして保存します。

spinnaker-bake

Pipeline の実行

Pipeline の手動実行は Start Manual Execition をクリックします(下図①)

spinnaker-bake

実行中、 Packer の実行状況やエラー調査は View Bakery Details から確認できます(上図②)

正常に完了すると、 windows-2012-r2-YYYYMMDDHHmmss のイメージが作成されます。

正常時のログを貼っておきます。

==> googlecompute: Checking image does not exist...
==> googlecompute: Creating temporary SSH key for instance...
==> googlecompute: Using image: windows-server-2012-r2-dc-v20190225
==> googlecompute: Creating instance...
    googlecompute: Loading zone: asia-northeast1-a
    googlecompute: Loading machine type: n1-standard-1
    googlecompute: Requesting instance creation...
    googlecompute: Waiting for creation operation to complete...
    googlecompute: Instance has been created!
==> googlecompute: Creating windows user for instance...
    googlecompute: Waiting for windows password to complete...
    googlecompute: Created password.
==> googlecompute: Waiting for the instance to become running...
    googlecompute: IP: 10.63.6.44
==> googlecompute: Waiting for WinRM to become available...
    googlecompute: WinRM connected.
    googlecompute: #< CLIXML
    googlecompute: System.Management.Automation.PSCustomObjectSystem.Object1Preparing modules for first use.0-1-1Completed-1 1Preparing modules for first use.0-1-1Completed-1
==> googlecompute: Connected to WinRM!
==> googlecompute: Provisioning with Powershell...
==> googlecompute: Provisioning with powershell script: /tmp/packer-powershell-provisioner475077573
    googlecompute: 2019/03/05 05:04:01 GCESysprep: Beginning GCESysprep.
    googlecompute: 2019/03/05 05:04:01 GCESysprep: No answer file was specified. Using default file.
    googlecompute: 2019/03/05 05:04:01 GCESysprep: Running 'schtasks' with arguments '/delete /tn GCEStartup /f'
    googlecompute: 2019/03/05 05:04:01 GCESysprep: --> SUCCESS: The scheduled task "GCEStartup" was successfully deleted.
    googlecompute: 2019/03/05 05:04:02 GCESysprep: Clearing events in EventViewer.
    googlecompute: 2019/03/05 05:04:06 GCESysprep: Running 'C:\Windows\System32\Sysprep\sysprep.exe' with arguments '/generalize /oobe /quit /unattend:C:\Program Files\Google\Compute Engine\sysprep\unattended.xml'
    googlecompute: 2019/03/05 05:05:43 GCESysprep: Waiting for sysprep to complete.
    googlecompute: 2019/03/05 05:05:43 GCESysprep: Setting new startup command.
    googlecompute: 2019/03/05 05:05:44 GCESysprep: Forgetting persistent disks.
    googlecompute: 2019/03/05 05:05:44 GCESysprep: Clearing self signed certs.
    googlecompute: 2019/03/05 05:05:44 GCESysprep: Shutting down.
    googlecompute: 2019/03/05 05:05:44 GCESysprep: Running 'shutdown' with arguments '/s /t 00 /d p:2:4 /f'
==> googlecompute: Deleting instance...
    googlecompute: Instance has been deleted!
==> googlecompute: Creating image...
==> googlecompute: Deleting disk...
    googlecompute: Disk has been deleted!
Build 'googlecompute' finished.

==> Builds finished. The artifacts of successful builds are:
--> googlecompute: A disk image was created: windows-2012-r2-20190305050100

まとめ

Spinnaker で GCE イメージを作成する、 Bake ステージの設定やカスタムイメージの設定方法を紹介しました。

参考文献

*1:hal config provider google bakery base-image add で更新されるはずだが反映されなかった