在 Linux VM 中使用開機指令碼

本文說明如何在 Google Distributed Cloud (GDC) 氣隙環境中,使用開機指令碼啟動虛擬機器 (VM) 執行個體及其相關聯的程式。

開機指令碼是一種自動化工具,可在 VM 啟動程序期間執行工作。使用開機指令碼,自動執行新執行個體或現有執行個體的 VM 設定和部署作業,節省時間並減少手動設定工作。

本文適用於平台管理員或應用程式運算子群組的開發人員,他們想在 Distributed Cloud 環境中使用 VM 的開機指令碼。詳情請參閱 GDC 氣隙環境適用的目標對象說明文件

事前準備

如要使用 gdcloud 指令列介面 (CLI) 指令,請務必下載、安裝及設定 gdcloud CLI。Distributed Cloud 的所有指令都使用 gdcloudkubectl CLI,且需要作業系統 (OS) 環境。

取得 kubeconfig 檔案路徑

如要對 Management API 伺服器執行指令,請確認您具備下列資源:

  1. 登入並產生 Management API 伺服器的 kubeconfig 檔案 (如果沒有)。

  2. 使用 Management API 伺服器的 kubeconfig 檔案路徑,取代這些操作說明中的 MANAGEMENT_API_SERVER

要求 IAM 角色

如要在 VM 中使用啟動指令碼,請聯絡專案 IAM 管理員,要求在專案中授予下列角色:

  • 虛擬機器專案管理員 (project-vm-admin):在專案命名空間中建立、修改、列出及刪除 VM。

  • Secret 管理員 (secret-admin):在專案命名空間中取得、列出、建立、更新、刪除、修補及監控 Kubernetes Secret。使用這個角色指定開機指令碼密鑰。指定純文字啟動指令碼時,不需要這個角色。

所有 VM 角色都必須繫結至 VM 所在的專案命名空間。 按照步驟驗證存取權。

傳遞開機指令碼

您可以使用 bash 或非 bash 指令碼做為啟動指令碼。如要這麼做,請在指令碼開頭加入 #!/bin/…,指出指令碼解譯器。舉例來說,如要使用 Python 3 開機指令碼,請在指令碼開頭新增 #! /usr/bin/python3

Google Distributed Cloud (GDC) 氣隙隔離解決方案會依啟動指令碼在 startupScripts 陣列中的顯示順序執行指令碼。

下表列出不同大小的腳本應使用的格式:

腳本大小 腳本格式
指令碼最多 2048 個位元組 清除文字
指令碼超過 2048 個位元組 Kubernetes Secret

定義開機指令碼

如要使用開機指令碼,您必須將 startupScripts 欄位新增至 VM spec 欄位。您可以在這個欄位中,以純文字或 Kubernetes 密碼的形式指定多個啟動指令碼。

以下範例會將開機指令碼指定為明文和 Kubernetes Secret:

apiVersion: virtualmachine.gdc.goog/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  # …
  startupScripts:
  - name: hello-world
    script: |
      #!/bin/bash
      echo hello
  - name: add-user
    scriptSecretRef:
      name: add-user
---

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: add-user
data:
  script:
    IyEvYmluL2Jhc2gKYWRkdXNlciB1c2VyCg==

請注意下列事項:

  • 開機指令碼會在每次開機時執行。
  • 開機指令碼預設具有根權限。
  • 在 Kubernetes 密鑰中,VM spec 中的 scriptSecretRef 名稱必須與 metadata.name 欄位相符。
  • 在 Kubernetes 密鑰中,將 script 鍵新增至 data 欄位,指定開機指令碼內容。

使用開機指令碼建立新的 VM

無論您使用哪個映像檔建立 VM,都適用這些操作說明。完成下列步驟:

  1. 如要將開機指令碼建立為 Kubernetes 密鑰,請執行下列指令:

    cat <<EOF >>FILE_NAME
    STARTUP_SCRIPT_CONTENT
    EOF
    
    kubectl --kubeconfig MANAGEMENT_API_SERVER \
      -n PROJECT \
      create secret generic SECRET_NAME \
      --from-file=script=FILE_NAME
    
    rm FILE_NAME
    
  2. 請參閱「建立 VM」頁面所述步驟建立 VM。 在步驟一中,請先在 spec 欄位中新增開機指令碼,再執行指令建立 VM。

    這個範例定義的開機指令碼同時包含明文和 Kubernetes 密鑰:

    apiVersion: virtualmachine.gdc.goog/v1
    kind: VirtualMachine
    metadata:
      name: VM_NAME
      namespace: PROJECT
    spec:
      # …
      startupScripts:
      - name: CLEAR_TEXT_SCRIPT_NAME
        script: |
          #!/bin/bash
          CLEAR_TEXT_SCRIPT
      - name: SECRET_SCRIPT_NAME
        scriptSecretRef:
          name: SECRET_NAME
    

    這些變數的定義如下:

    變數定義
    MANAGEMENT_API_SERVER Management API 伺服器 kubeconfig 檔案。
    PROJECT 要在其中建立 VM 的 Distributed Cloud 雲端專案。
    VM_NAME VM 名稱。
    FILE_NAME 儲存啟動指令碼的檔案名稱。
    STARTUP_SCRIPT_CONTENT 要執行的指令 (開機指令碼的一部分)
    CLEAR_TEXT_SCRIPT_NAME 明文開機指令碼的名稱。
    CLEAR_TEXT_SCRIPT 您定義的明文指令碼。
    SECRET_NAME Kubernetes Secret 的名稱。
    SECRET_SCRIPT_NAME 開機指令碼的名稱 (Kubernetes 密鑰)。
  3. 請按照下列步驟建立 VM。

    以下範例說明如何使用開機指令碼建立 VM,並透過 Kubernetes 密鑰和明文新增使用者。

    kubectl --kubeconfig MANAGEMENT_API_SERVER \
      -n PROJECT \
      apply -f - <<EOF
    apiVersion: virtualmachine.gdc.goog/v1
    kind: VirtualMachineDisk
    metadata:
      name: VM_BOOT_DISK_NAME
    spec:
      source:
        image:
          name: BOOT_DISK_IMAGE_NAME
          namespace: vm-system
      size: BOOT_DISK_SIZE
    ---
    apiVersion: v1
    kind: Secret
    type: Opaque
    metadata:
      name: add-user
    data:
      script:
        IyEvYmluL2Jhc2gKYWRkdXNlciB1c2VyCg==
    ---
    apiVersion: virtualmachine.gdc.goog/v1
    kind: VirtualMachine
    metadata:
      name: VM_NAME
    spec:
      compute:
        virtualMachineType: MACHINE_TYPE
      disks:
      - virtualMachineDiskRef:
          name: VM_BOOT_DISK_NAME
        boot: true
        autoDelete: BOOT_DISK_AUTO_DELETE
      startupScripts:
      - name: add-user
        scriptSecretRef:
          name: add-user
      - name: add-to-sudoers
        script: |
          #!/bin/bash
          usermod -aG sudo user
    EOF
    

    在範例中,變數定義如下。

    變數定義
    MANAGEMENT_API_SERVER Management API 伺服器 kubeconfig 檔案。
    PROJECT 要在其中建立 VM 的 Distributed Cloud 雲端專案。
    VM_NAME 新 VM 的名稱。
    VM_BOOT_DISK_NAME 新 VM 開機磁碟的名稱。
    BOOT_DISK_IMAGE_NAME 新 VM 開機磁碟要使用的映像檔名稱。
    BOOT_DISK_SIZE 開機磁碟大小,例如 20G
    這個值一律必須大於或等於開機磁碟映像檔的 minimumDiskSize
    BOOT_DISK_AUTO_DELETE truefalse,指出刪除 VM 執行個體時,是否要自動刪除開機磁碟。
    MACHINE_TYPE 新 VM 的預先定義機型。如要選取可用的機型,請執行下列指令:
    kubectl --kubeconfig MANAGEMENT_API_SERVER get virtualmachinetype.virtualmachine.gdc.goog --namespace vm-system

使用開機指令碼更新現有 VM

您也可以使用開機指令碼更新現有 VM。您必須先關閉 VM,才能執行更新。

按照步驟更新 VM 屬性,並使用要執行的開機指令碼更新 spec 欄位。

查看開機指令碼的輸出內容

  1. 按照步驟連線至 VM
  2. 在客層 VM 內執行下列指令,取得您執行的開機指令碼記錄:

    sudo journalctl -u cloud-final
    

    開機指令碼記錄檔開頭如下:

    Started to run the command: /var/lib/google/startup-scripts/<script-name> ...