Cloud Deployment Managerで雑にGCEインスタンスを作成する

# はじめに
- Terraformが使える場合は、Terraformを使ったほうが良いのですが、Terraformを使うのがマッチしないケースのみ、Deployment Managerを使うことをおすすめします。
    - 想定しているケースとしては、一部のみコード化したい...など...。
- 基本的な流れとしては、GCEインスタンスの状態を定義したファイルを用意し、gcloudコマンドでそのファイルを指定、インスタンスを作成しています。

# Deployment ManagerのYAMLサンプル

2つのファイルを用意しています。今回は、 `load-foo-compute-engine.yaml` を環境別に用意するケースを想定しています。

- load-foo-compute-engine.yaml
    - 変数を記載したファイル
    - gcloudコマンドで指定して呼び出される
    - 内部で、jinjaファイルをimportしている（後述）
- foo-compute-engine.jinja
    - 実際にもろもろインスタンスの設定等を記載しているファイル。
    - yamlのpropertiesから渡された値を元に、インスタンスを作成している。

後述のjinjaファイルで使う変数を定義しています。

```load-foo-compute-engine.yaml（変数を記載したファイル）
imports:
- path: foo-compute-engine.jinja

resources:
- name: foo-compute-engine
  type: foo-compute-engine.jinja
  properties:
    zone: asia-northeast1-a
    vm_image : foo-image-name
    instance_type: n1-standard-1
    swap_size: 100
    swap_file_size: 95

```

- startup-scriptで、swap fileを作成しています。
- 見ての通り、startup-scriptには通常のシェルスクリプトが記述できるのでやろうと思えば何でもできます。


```foo-compute-engine.jinja

# 使う変数をsetしている
{% set instance_name = env["deployment"] %}
{% set disk_name = env["deployment"] + "-swap-disk" %}
{% set device_name = "swap-disk" %}

resources:
- name: {{ disk_name }}
  type: compute.v1.disk
  properties:
    zone: {{ properties["zone"] }}
    sizeGb: {{ properties["swap_size"] }}
    type: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/zones/{{ properties["zone"] }}/diskTypes/pd-ssd
- name: {{ instance_name }}
  type: compute.v1.instance
  properties:
    zone: {{ properties["zone"] }}
    vm_image : {{ properties["vm_image"] }}
    machineType: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/zones/{{ properties["zone"] }}/machineTypes/{{ properties['instance_type'] }}
    disks:
    - deviceName: boot
      type: PERSISTENT
      boot: true
      autoDelete: true
      initializeParams:
        sourceImage: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/global/images/{{ properties["vm_image"] }}
    - deviceName: {{ device_name }}
      type: PERSISTENT
      source: $(ref.{{ disk_name }}.selfLink)
      autoDelete: true
    # 作成するnetworkの指定
    networkInterfaces:
    - network: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/global/networks/foo-vpc-network
      subnetwork: https://www.googleapis.com/compute/v1/projects/{{ env["project"] }}/regions/asia-northeast1/subnetworks/foo-subnet
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT
    # network tag(firewall rule)を指定する
    tags:
      items:
        - foo-tags
    # インスタンスに付与するラベル
    labels:
      foo: bar
    # インスタンス作成時に実行されるscriptを記載
    metadata:
      items:
      - key: startup-script
        value: |
          #!/bin/bash

          # swapの作成
          sudo mkfs.ext4 -F /dev/sdb
          sudo mkdir -p /mnt/disk/ssd-swap
          sudo mount /dev/sdb /mnt/disk/ssd-swap
          sudo chmod a+w /mnt/disk/ssd-swap
          echo UUID=`sudo blkid -s UUID -o value /dev/disk/by-id/google-{{ device_name }}` /mnt/disk/ssd-swap ext4 discard,defaults,nofail 0 2 | sudo tee -a /etc/fstab
          sudo fallocate -l {{ properties["swap_file_size"] }}G /mnt/disk/ssd-swap/swapfile
          sudo chmod 600 /mnt/disk/ssd-swap/swapfile
          sudo mkswap /mnt/disk/ssd-swap/swapfile
          sudo swapon /mnt/disk/ssd-swap/swapfile
          echo '/mnt/disk/ssd-swap/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

          exit 0
    
    serviceAccounts:
      - email: foo-serviceaccount@foo-project.iam.gserviceaccount.com
        # Cloud API access scopes の指定
        # 指定方法はこのあたり https://developers.google.com/identity/protocols/googlescopes
        scopes:
          - https://www.googleapis.com/auth/devstorage.read_write
          - https://www.googleapis.com/auth/monitoring.write
```

# GCEインスタンス作成コマンド

- `foo-instance` が `env["deployment"]` と対応しています。
- `--preview` をつけることでdry-runも可能です。詳細は[コマンドリファレンス](https://cloud.google.com/sdk/gcloud/reference/deployment-manager/deployments/create)を参照してください。

```
gcloud deployment-manager deployments create foo-instance --config load-foo-compute-engine.yaml
```