Google Distributed Cloud バージョン 1.13.0 以降を使用する場合、起動ルーティンを指定して、起動時に VM の初期化をカスタマイズできます。VM を構成することで、SSH 認証鍵の作成、ユーザーとパスワードの追加、パッケージのインストール、ファイルの書き込み、ネットワーク設定の構成などを行うことができます。
これらの起動タスクは、cloud-init API または起動スクリプト API のいずれかを使用して構成されます(両方は使用できません)。これらの起動ディレクティブは VirtualMachine YAML マニフェスト ファイルで指定され、VM の起動時に自動的に実行されます。
前提条件
起動ディレクティブを設定して VM を構成するには、次の前提条件を満たす必要があります。
- 検証済みの Linux ゲスト OS を使用し、VM マニフェストで - osTypeを- Linuxに設定する。Windows ゲスト OS は cloud-init をサポートしていないため、この機能はサポートされていません。
- ゲスト OS に cloud-init がインストールされていることを確認する。最新の Linux OS には cloud-init が含まれています。 
以下のセクションでは、cloud-init API または起動スクリプトを使用して、VM マニフェストで起動ルーティンを指定する方法について説明します。
cloud-init API を使用して VM を初期化する
cloud-init は、起動時におけるクラウド インスタンスの初期化や VM のカスタマイズによく使用されます。VM の初期化では通常、パッケージのインストール、リポジトリの設定、SSH 認証鍵の作成、ファイルへのデータの書き込み、VM の他の側面の設定などが行われます。spec.cloudInit フィールドを使用して cloud-init 構成 YAML を VirtualMachine カスタム リソースに組み込みます。VM インスタンスが起動されると、cloud-init によって指定されたデータが読み取られ、それに基づいて VM が初期化されます。
以下の cloud-init 実装の詳細に注意してください。
- VM を作成または更新するときに、cloud-init データを - VirtualMachineYAML マニフェストに指定します。マニフェストを適用して VM を作成する手順については、チュートリアル: GDC 上の VM ランタイムで Linux VM を作成、管理するをご覧ください。
- VM 仕様にある - NoCloudデータソースの- spec.cloudInit.noCloudを使用します。
- VirtualMachineマニフェストの各セクションで、ユーザーデータとネットワーク データを指定します。セクションの名前と構造は、使用するデータ形式によって異なります。
- cloud-init 構成情報は、次の形式で指定できます。 - クリアテキスト
- Base64 エンコードされた文字列
- Kubernetes Secret
 
作業を開始するにあたり、一般的な VM 初期化タスクの構成例を一部紹介しました。
cloud-init ユーザーデータ
GDC 上の VM ランタイムは、cloud-config 構文の cloud-init ユーザーデータをサポートしているため、#cloud-config でユーザーデータを開始します。ユーザーデータは、クリアテキスト、Base64 でエンコードされた文字列、または Kubernetes Secret としてフォーマットできます。
ユーザーデータの構文とモジュールのリファレンスの詳細については、cloud-init のドキュメントをご覧ください。
クリアテキストとしての cloud-init ユーザーデータ
次のマニフェストの例は、ユーザーデータをクリアテキストとして指定する方法を示しています。この場合、cloud-init によって VM の起動時にコマンドが実行されます。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        runcmd:
          - echo hello
Base64 でエンコードされた文字列としての cloud-init ユーザーデータ
次の例は、Base64 でエンコードされた形式でユーザーデータを指定する方法を示しています。この例では、ユーザーデータは、クリアテキストの例と同じ echo hello コマンドで構成されています。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userDataBase64: I2Nsb3VkLWNvbmZpZwpydW5jbWQ6CiAgLSBlY2hvIGhlbGxvCg==
Kubernetes Secret としての cloud-init ユーザーデータ
次の例は、VirtualMachine と Secret の両方の YAML マニフェストを示しています。VirtualMachine 構成の spec.cloudInit.noCloud.secretRef セクションは、cloud-init ユーザーデータが my-sec という名前の Kubernetes Secret にあることを示しています。対応する Secret 構成では、ユーザーデータを Key-Value ペアとして指定します。この場合、Base64 でエンコードされた値は cloud-config 構文の cloud-init ユーザーデータです。
参照される Secret で、データキー userData(表示)または userdata を使用して、cloud-init ユーザーデータを指定します。
この例では、ユーザーデータは、クリアテキストの例と同じ echo hello コマンドで構成されています。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      secretRef:
        name: my-sec
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: my-sec
data:
  userData: I2Nsb3VkLWNvbmZpZwpydW5jbWQ6CiAgLSBlY2hvIGhlbGxvCg==
参照される Secret が見つからないか、データキー userData または userdata が Secret に存在しない場合は、次の VM の起動動作に注意してください。
- VM を作成する際、VM は詳細な理由とメッセージを提示し、 - ErrorConfiguration状態になります。
- それ以外の場合、VM が適切に構成されるまで、以前の cloud-init ユーザーデータを引き続き使用します。このため、ゲスト エージェントの有効化または無効化の更新は、VM が正しく構成されるまで有効になりません。 
使用された cloud-init ユーザーデータなどの VM 情報を取得するには、次のコマンドを使用します。
kubectl get vm VM_NAME -o yaml --kubeconfig KUBECONFIG_PATH
次のように置き換えます。
- VM_NAME: VM の名前。
- KUBECONFIG_PATH: VM を含むクラスタの kubeconfig ファイルのパス。
関連する Kubernetes 警告イベントを取得するには、kubectl get event または kubectl describe gvm のいずれかを使用します。
Cloud-init ネットワーク データ
ユーザーデータと同様に、ネットワーク データをクリアテキスト、Base64 でエンコードされた文字列、または Kubernetes Secret としてフォーマットできます。ユーザーデータとは異なり、ネットワーク データは cloud-config 構文を使用しません。
クリアテキストまたは Base64 でエンコードされた文字列を使用する場合、最大サイズは 2,048 バイトです。ユーザーデータのサイズが 2,048 バイトに近いか、超えている場合は、Kubernetes Secret として指定します。
ネットワーク データ構文と関連する詳細情報について詳しくは、cloud-init ドキュメントに記載されたネットワーク構成のバージョン 2 をご覧ください。
クリアテキストとしての cloud-init ネットワーク データ
次のマニフェストの例は、ネットワーク データをクリアテキストとして指定する方法を示しています。この場合、cloud-init によって名前が「e」(e*)で始まるすべてのイーサネット デバイスで DHCP が有効になります。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        runcmd:
          - echo hello
      networkData: |
        version: 2
        ethernets:
          alleths:
            match:
              name: e*
            dhcp4: true
Base64 でエンコードされた文字列としての cloud-init ネットワーク データ
次の例は、Base64 でエンコードされた形式でネットワーク データを指定する方法を示しています。この例では、ネットワーク データは、クリアテキストの例で指定されたものと同じ DHCP 構成で構成されています。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      networkDataBase64: dmVyc2lvbjogMgpldGhlcm5ldHM6CiAgYWxsZXRoczoKICAgIG1hdGNoOgogICAgICBuYW1lOiBlKgogICAgZGhjcDQ6IHRydWUK
Kubernetes Secret としての cloud-init ネットワーク データ
次の例は、VirtualMachine と Secret の両方の YAML マニフェストを示しています。VirtualMachine 構成の spec.cloudInit.noCloud.networkDataSecretRef セクションは、cloud-init ネットワーク データが my-sec という名前の Kubernetes Secret にあることを示しています。対応する Secret 構成では、ネットワーク データを Key-Value ペアとして指定します。この場合の Base64 でエンコードされた値は cloud-init ネットワーク データです。
参照される Secret で、データキー networkData(表示)または networkdata を使用して、cloud-init ネットワーク データを指定します。
この例では、ネットワーク データは、クリアテキストの例で指定されたものと同じ DHCP 構成で構成されています。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      networkDataSecretRef:
        name: my-sec
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: my-sec
data:
  networkData: dmVyc2lvbjogMgpldGhlcm5ldHM6CiAgYWxsZXRoczoKICAgIG1hdGNoOgogICAgICBuYW1lOiBlKgogICAgZGhjcDQ6IHRydWUK
cloud-init の例
以降のセクションでは、cloud-init を使用して VM を初期化する一般的なユースケースとしてクリアテキストの例を示します。
承認済みの SSH 認証鍵を構成する
次のユーザーデータの例では、認可された SSH 鍵 ssh-rsa AAAAB3NzaK8L93bWxnyp をデフォルト ユーザーに割り当てます。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        ssh_authorized_keys:
          - ssh-rsa AAAAB3NzaK8L93bWxnyp
新しいユーザーを追加する
次のユーザーデータの例では、ユーザー test を作成し、test に完全な sudo アクセス権を付与します。この例では、ユーザーに pwd という有効期限のないパスワードを割り当てます。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        users:
        - default
        - name: test
          sudo: ALL=(ALL) NOPASSWD:ALL
        chpasswd:
          list: |
            test:pwd
          expire: False
初回起動時にコマンドを実行する
次のユーザーデータの例では、echo コマンドと ls コマンドを実行します。コマンドを使用して、VM の起動時にパッケージなどをインストールできます。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        runcmd:
          - [ echo, hello ]
          - [ ls, -l, / ]
ファイルを書き込む
次のユーザーデータの例では、VM の /var/lib/google ディレクトリにある test ファイルに bash スクリプトを書き込みます。cloud-init ディレクティブは、ファイル オーナーに対して読み取り、書き込み、実行(0744)のファイル権限を設定します。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        write_files:
        - path: /var/lib/google/test
          permissions: 0744
          content: |
            #!/bin/bash
            echo hello
cloud-init のトラブルシューティング
cloud-init を使用していて VM の初期化で問題が発生した場合、VM で次の cloud-init ログを確認します。
- /var/log/cloud-init.log: デフォルトでは、cloud-init は- DEBUGレベル以上のすべてのイベントをこのログに書き込みます。
- /var/log/cloud-init-output.log: デフォルトでは、cloud-init はすべての cloud-init ステージで stdout と stderr の両方をこのログに書き込みます。
起動スクリプトを使用して VM を初期化する
起動スクリプトは、仮想マシン(VM)インスタンスの起動プロセス中にタスクを実行します。VirtualMachine 仕様の spec.startupScripts セクションで、1 つ以上のスクリプトを指定できます。また、起動スクリプトを使用して VM を初期化できます。VM の初期化では通常、パッケージのインストール、リポジトリの設定、SSH 認証鍵の作成、ファイルへのデータの書き込み、VM の他の側面の設定などが行われます。
起動スクリプトについては、次のことに留意してください。
- VM を作成または更新するときに、起動スクリプトを - VirtualMachineYAML マニフェストに指定します。マニフェストを適用して VM を作成する手順については、チュートリアル: GDC 上の VM ランタイムで Linux VM を作成、管理するをご覧ください。
- 指定されたスクリプトは VM が起動されるたびに実行されます。 
- スクリプトの先頭に - #!/bin/...を追加して、スクリプト インタープリタを指定します。たとえば、Bash シェルでスクリプトを実行するには、- #!/bin/bashを含めます。
- cloud-init API ディレクティブ( - spec.cloudInit)および起動スクリプト(- spec.startupScripts)の両方を同じ- VirtualMachineマニフェストで指定することはできません。
スクリプトの形式
起動スクリプトは、次のデータ形式で指定できます。
- クリアテキスト
- Base64 エンコードされた文字列
- Kubernetes Secret
個別のスクリプト形式を使用する場合は、次のルールに注意してください。
- クリアテキストまたは Base64 でエンコードされた文字列を使用する場合、スクリプトのコンテンツに許容される最大サイズは 2,048 バイトです。スクリプト コンテンツのサイズが 2,048 バイトに近いか、超えている場合は、Kubernetes Secret としてスクリプトを指定します。 
- Kubernetes Secret を使用する場合は、参照される Secret のデータキー - scriptを使用してスクリプト コンテンツを指定します。
- 参照される Secret が見つからないか、参照される Secret にデータキー - scriptが存在しない場合、VM は引き続きスクリプトを実行します。ただし、VM はスクリプトのコンテンツの作成や更新は行いません。この場合、- kubectl get eventまたは- kubectl describe gvmを使用して Kubernetes 警告イベントを見つけることができます。
次の VirtualMachine YAML マニフェストのサンプルには、サポートされている各形式で 1 つずつで 3 つのスクリプトが含まれています。この場合、各スクリプトがクリアテキストの例にある myscript1 に示されている echo
hello コマンドを実行します。
apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  startupScripts:
  - name: myscript1
    script: |
      #!/bin/bash
      echo hello
  - name: myscript2
    scriptBase64: IyEvYmluL2Jhc2gKICAgICAgZWNobyBoZWxsbwo=
  - name: myscript3
    scriptSecretRef:
      name: my-sec
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: my-sec
data:
  script: IyEvYmluL2Jhc2gKICAgICAgZWNobyBoZWxsbwo=
スクリプトのトラブルシューティング
スクリプトの結果またはログを確認するには、次のコマンドを実行します。
journalctl -u cloud-final
起動スクリプトのログエントリは、次のテキストで始まります。
started to run the command /var/lib/google/startup-scripts/SCRIPT_NAME ...
ログエントリには、起動スクリプトの名前である SCRIPT_NAME が含まれます。