VM の起動ルーティンを構成する

GKE on Bare Metal バージョン 1.13.0 以降を使用する場合、起動ルーティンを指定して、起動時に VM の初期化をカスタマイズできます。VM を構成することで、SSH 認証鍵の作成、ユーザーとパスワードの追加、パッケージのインストール、ファイルの書き込み、ネットワーク設定の構成などを行うことができます。

これらの起動タスクは、cloud-init API または起動スクリプト API のいずれかを使用して構成されます(両方は使用できません)。これらの起動ディレクティブは VirtualMachine YAML マニフェスト ファイルで指定され、VM が起動するたびに自動的に実行されます。

前提条件

起動ディレクティブを設定して VM を構成するには、次の前提条件を満たす必要があります。

  • GDC で VM ランタイムを有効にします

  • 検証済みの Linux ゲスト OS を使用し、VM マニフェストで osTypeLinux に設定する。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 ユーザーデータ

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 ユーザーデータ

次の例は、VirtualMachineSecret の両方の 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 ネットワーク データ

次の例は、VirtualMachineSecret の両方の 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 を作成または更新するときに、起動スクリプトを VirtualMachine YAML マニフェストに指定します。マニフェストを適用して VM を作成する手順については、チュートリアル: GDC 上の VM ランタイムで Linux VM を作成、管理するをご覧ください。

  • 指定されたスクリプトは VM が起動されるたびに実行されます。

  • スクリプトの先頭に #!/bin/... を追加して、スクリプト インタープリタを指定します。たとえば、Bash シェルでスクリプトを実行するには、#!/bin/bash を含めます。

  • cloud-init API ディレクティブspec.cloudInit)および起動スクリプト(spec.startupScripts)の両方を同じ VirtualMachine マニフェストで指定することはできません。

スクリプトの形式

起動スクリプトは、次のデータ形式で指定できます。

  • テキストを消去
  • Base64 でエンコードされた文字列
  • Kubernetes シークレット

個別のスクリプト形式を使用する場合は、次のルールに注意してください。

  • クリアテキストまたは 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 が含まれています。