設定 VM 啟動例行程序

使用 Google Distributed Cloud 1.13.0 以上版本時,您可以指定啟動常式,在 VM 啟動時自訂初始化作業。您可以設定 VM 建立 SSH 金鑰、新增使用者和密碼、安裝套件、寫入檔案,以及設定網路設定等。

這些啟動工作是透過 cloud-init API 或啟動指令碼 API 設定 (兩者擇一)。這些啟動指令會指定在 VirtualMachine YAML 資訊清單檔案中,並在每次 VM 啟動時自動執行。

必要條件

如要使用啟動指令設定 VM,必須符合下列先決條件:

以下各節說明如何使用 cloud-init API啟動指令碼,在 VM 資訊清單中指定啟動常式。

使用 cloud-init API 初始化 VM

Cloud-init 通常用於雲端執行個體初始化,以及在啟動期間自訂 VM。VM 初始化通常會涉及套件安裝、存放區設定、SSH 金鑰建立、將資料寫入檔案,以及設定 VM 的其他層面等工作。您可以使用 spec.cloudInit 欄位,將 cloud-init 設定 YAML 併入自訂資源中。VirtualMachineVM 執行個體啟動時,cloud-init 會讀取提供的資料,並據此初始化 VM。

請注意 cloud-init 實作的下列詳細資料:

  • 建立或更新 VM 時,您可以在 VirtualMachine YAML 資訊清單中指定 cloud-init 資料。如要瞭解如何套用資訊清單建立 VM,請參閱「教學課程:在 VM Runtime on GDC 中建立及管理 Linux VM」。

  • 我們在 VM 規格中使用 NoCloud 資料來源spec.cloudInit.noCloud

  • 您可以在 VirtualMachine 資訊清單的個別部分中,指定使用者資料網路資料。章節命名和結構取決於您決定使用的資料格式。

  • 您可以透過下列資料格式指定 cloud-init 設定資訊:

    • 清除文字
    • Base64 編碼字串
    • Kubernetes 密鑰

為協助您上手,我們提供了一些常見 VM 初始化工作的設定範例

Cloud-init 使用者資料

GDC 上的 VM 執行階段支援雲端設定語法的 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 設定會將使用者資料指定為鍵/值組合。在本例中,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,或 Secret 中沒有資料金鑰 userDatauserdata,請注意下列 VM 啟動行為:

  • 建立 VM 時,VM 會進入 ErrorConfiguration 狀態,並顯示詳細原因和訊息。

  • 在其他情況下,VM 會繼續使用舊的 cloud-init 使用者資料,直到 VM 正確設定為止。因此,必須正確設定 VM,訪客代理程式啟用或停用更新才會生效。

如要擷取 VM 資訊 (包括使用的 cloud-init 使用者資料),請使用下列指令:

kubectl get vm VM_NAME -o yaml --kubeconfig KUBECONFIG_PATH

更改下列內容:

  • VM_NAME:VM 名稱。

  • KUBECONFIG_PATH:包含 VM 的叢集 kubeconfig 檔案路徑。

如要擷取相關的 Kubernetes 警告事件,請使用 kubectl get eventkubectl describe gvm

Cloud-init 網路資料

與使用者資料類似,您可以將網路資料格式化為純文字、經過 Base64 編碼的字串或 Kubernetes Secret。與使用者資料不同,網路資料不會使用 cloud-config 語法。

使用明文或 Base64 編碼字串時,允許的最大大小為 2048 位元組。如果使用者資料大小接近或超過 2048 個位元組,請將其指定為 Kubernetes Secret。

如要進一步瞭解網路資料語法和相關詳細資料,請參閱 cloud-init 說明文件中的「Networking Config Version 2」。

以純文字形式提供 Cloud-init 網路資料

下列範例資訊清單說明如何以純文字指定網路資料。在本例中,cloud-init 會為名稱開頭為「e」的所有乙太網路裝置啟用 DHCP (e*):

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 資訊清單。設定中的 spec.cloudInit.noCloud.networkDataSecretRef 區段表示 cloud-init 網路資料位於名為 my-sec 的 Kubernetes Secret 中。VirtualMachine對應的 Secret 設定會將網路資料指定為鍵/值組合。在本例中,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-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, / ]

寫入檔案

以下使用者資料範例會將 bash 指令碼寫入 VM 的 /var/lib/google 目錄中的 test 檔案。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 問題

如果 VM 初始化時發生問題,且您使用 cloud-init,請檢查 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 區段中指定一或多個指令碼。開機指令碼可用於初始化 VM。VM 初始化通常會涉及套件安裝、存放區設定、SSH 金鑰建立、將資料寫入檔案,以及設定 VM 的其他層面等工作。

請注意開機指令碼的下列細節:

  • 建立或更新 VM 時,您可以在 VirtualMachine YAML 資訊清單中指定開機指令碼。如要瞭解如何套用資訊清單建立 VM,請參閱「教學課程:在 VM Runtime on GDC 中建立及管理 Linux VM」。

  • 每次啟動 VM 時,系統都會執行指定的指令碼。

  • 在指令碼頂端加入 #!/bin/...,指出指令碼解譯器。舉例來說,加入 #!/bin/bash 即可使用 Bash 殼層執行指令碼。

  • 您無法在同一個 VirtualMachine 資訊清單中,同時指定 cloud-init API 指令 (spec.cloudInit) 和啟動指令碼 (spec.startupScripts)。

指令碼格式

您可以透過下列資料格式指定開機指令碼:

  • 清除文字
  • Base64 編碼字串
  • Kubernetes 密鑰

請注意下列規則,瞭解如何使用不同格式的指令碼:

  • 使用明文或 base64 編碼字串時,指令碼內容的大小上限為 2048 位元組。如果指令碼內容大小接近或超過 2048 個位元組,請將指令碼指定為 Kubernetes 密鑰。

  • 使用 Kubernetes Secret 時,請在參照的 Secret 中使用資料金鑰 script 指定指令碼內容。

  • 如果找不到參照的 Secret,或參照的 Secret 中沒有資料金鑰 script,VM 會繼續執行指令碼。但 VM 不會撰寫或更新指令碼內容。在這種情況下,您可以使用 kubectl get eventkubectl describe gvm 找出 Kubernetes 警告事件。

下列 VirtualMachine YAML 資訊清單範例包含三個指令碼,每個指令碼都採用其中一種支援的格式。在本例中,每個指令碼都會執行 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,也就是開機指令碼的名稱。