VM-Startroutinen konfigurieren

Wenn Sie GKE on Bare Metal ab Version 1.13.0 verwenden, können Sie Startroutinen angeben, um die Initialisierung Ihrer VM beim Start anzupassen. Sie können Ihre VM so konfigurieren, dass Sie SSH-Schlüssel erstellen, Nutzer und Passwörter hinzufügen, Pakete installieren, Dateien schreiben, Netzwerkeinstellungen konfigurieren und vieles mehr.

Diese Startaufgaben werden entweder mit der cloud-init API oder mit der Startup Script API (nicht mit beiden) konfiguriert. Diese Startanweisungen sind in der YAML-Manifestdatei VirtualMachine angegeben und werden bei jedem Start Ihrer VM automatisch ausgeführt.

Vorbereitung

Damit Sie eine VM mit Startanweisungen konfigurieren können, müssen die folgenden Voraussetzungen erfüllt sein:

In den folgenden Abschnitten wird beschrieben, wie Sie Startroutinen im VM-Manifest entweder mit der cloud-init API oder mit Startup-Skripts angeben.

Mit der cloud-init API VMs initialisieren

Cloud-init wird häufig zur Initialisierung von Cloud-Instanzen und zur Anpassung von VMs beim Start verwendet. Die VM-Initialisierung umfasst in der Regel Aufgaben wie Paketinstallationen, Repository-Einrichtung, das Erstellen von SSH-Schlüsseln, das Schreiben von Daten in Dateien und das Einrichten anderer Aspekte Ihrer VM. Sie fügen die YAML-Konfigurationsdatei für cloud-init mit dem Feld spec.cloudInit in die benutzerdefinierte Ressource VirtualMachine ein. Beim Start der VM-Instanz liest cloud-init die bereitgestellten Daten und initialisiert die VM entsprechend.

Beachten Sie die folgenden Details unserer cloud-init-Implementierung:

  • Sie geben cloud-init-Daten im YAML-Manifest VirtualMachine an, wenn Sie eine VM erstellen oder aktualisieren. Eine Anleitung zum Erstellen einer VM durch Anwenden eines Manifests finden Sie in der Anleitung: Linux-VM in der VM-Laufzeit in Google Distributed Cloud erstellen und verwalten.

  • Wir verwenden die Datenquelle NoCloud spec.cloudInit.noCloud in der VM-Spezifikation.

  • Nutzerdaten und Netzwerkdaten geben Sie im VirtualMachine-Manifest in separaten Abschnitten an. Die Abschnittsbenennung und -struktur hängen vom Datenformat ab, für das Sie sich entscheiden.

  • Sie können cloud-init-Konfigurationsinformationen in den folgenden Datenformaten angeben:

    • Text entfernen
    • Base64-codierter String
    • Kubernetes Secret

Um Ihnen den Einstieg zu erleichtern, haben wir einige Konfigurationsbeispiele für gängige VM-Initialisierungsaufgaben bereitgestellt.

cloud-init-Nutzerdaten

VM-Laufzeit in Google Distributed Cloud unterstützt cloud-init-Nutzerdaten in der cloud-config-Syntax. Beginnen Sie Ihre Nutzerdaten daher mit #cloud-config. Sie können die Nutzerdaten als Klartext, als Base64-codierten String oder als Kubernetes-Secret formatieren.

Weitere Informationen zur Syntax von Nutzerdaten und zu Modulreferenzen finden Sie in der cloud-init-Dokumentation.

Cloud-init-Nutzerdaten als Klartext

Das folgende Beispielmanifest zeigt, wie Nutzerdaten als Klartext angegeben werden. In diesem Fall führt cloud-init beim Start der VM einen Befehl aus:

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        runcmd:
          - echo hello

Cloud-init-Nutzerdaten als base64-codierter String

Das folgende Beispiel zeigt, wie Nutzerdaten im base64-codierten Format angegeben werden. In diesem Beispiel bestehen die Nutzerdaten aus demselben echo hello-Befehl wie im Klartext-Beispiel:

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userDataBase64: I2Nsb3VkLWNvbmZpZwpydW5jbWQ6CiAgLSBlY2hvIGhlbGxvCg==

cloud-init-Nutzerdaten als Kubernetes Secret

Das folgende Beispiel zeigt ein YAML-Manifest für VirtualMachine und Secret. Der Abschnitt spec.cloudInit.noCloud.secretRef in der Konfiguration VirtualMachine gibt an, dass sich die cloud-init-Nutzerdaten in einem Kubernetes-Secret mit dem Namen my-sec befinden. In der entsprechenden Secret-Konfiguration werden die Nutzerdaten als Schlüssel/Wert-Paar angegeben. Der base64-codierte Wert ist in diesem Fall die cloud-init-Nutzerdaten in der Syntax von cloud-config.

Verwenden Sie im referenzierten Secret den Datenschlüssel userData (angezeigt) oder userdata, um die cloud-init-Nutzerdaten anzugeben.

In diesem Beispiel bestehen die Nutzerdaten aus demselben echo hello-Befehl wie im Klartext-Beispiel:

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==

Wenn das referenzierte Secret nicht gefunden wird oder der Datenschlüssel userData oder userdata nicht im Secret vorhanden ist, beachten Sie das folgende VM-Startverhalten:

  • Beim Erstellen einer VM wird die VM in den Status ErrorConfiguration mit einem detaillierten Grund und einer Meldung versetzt.

  • In anderen Fällen verwendet die VM weiterhin die alten cloud-init-Nutzerdaten, bis die VM richtig konfiguriert ist. Daher werden Updates für den Gast-Agent erst wirksam, wenn die VM richtig konfiguriert ist.

Verwenden Sie den folgenden Befehl, um VM-Informationen abzurufen, einschließlich der verwendeten cloud-init-Nutzerdaten:

kubectl get vm VM_NAME -o yaml --kubeconfig KUBECONFIG_PATH

Ersetzen Sie Folgendes:

  • VM_NAME ist der Name Ihrer VM.

  • KUBECONFIG_PATH: der Pfad zur kubeconfig-Datei für den Cluster, der Ihre VM enthält.

Verwenden Sie entweder kubectl get event oder kubectl describe gvm, um das zugehörige Kubernetes-Warnungsereignis abzurufen.

Cloud-init-Netzwerkdaten

Ähnlich wie bei Nutzerdaten können Sie die Netzwerkdaten als Klartext, als Base64-codierten String oder als Kubernetes-Secret formatieren. Im Gegensatz zu Nutzerdaten verwenden Netzwerkdaten keine cloud-config-Syntax.

Bei Verwendung von Klartext oder einem base64-codierten String ist die maximal zulässige Größe 2.048 Byte. Wenn die Nutzerdaten größer oder fast 2.048 Byte groß sind, geben Sie sie als Kubernetes-Secret an.

Weitere Informationen zur Syntax von Netzwerkdaten und zugehörige Details finden Sie unter Netzwerkkonfiguration Version 2 in der cloud-init-Dokumentation.

Cloud-init-Netzwerkdaten als Klartext

Das folgende Beispielmanifest zeigt, wie Netzwerkdaten als Klartext angegeben werden. In diesem Fall aktiviert cloud-init DHCP für alle Ethernet-Geräte, deren Namen mit einem "e" (e*) beginnen:

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

Cloud-init-Netzwerkdaten als base64-codierter String

Das folgende Beispiel zeigt, wie Netzwerkdaten im base64-codierten Format angegeben werden. In diesem Beispiel bestehen die Netzwerkdaten aus der gleichen DHCP-Konfiguration wie im Klartextbeispiel angegeben:

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      networkDataBase64: dmVyc2lvbjogMgpldGhlcm5ldHM6CiAgYWxsZXRoczoKICAgIG1hdGNoOgogICAgICBuYW1lOiBlKgogICAgZGhjcDQ6IHRydWUK

Cloud-init-Netzwerkdaten als Kubernetes-Secret

Das folgende Beispiel zeigt ein YAML-Manifest für VirtualMachine und Secret. Der Abschnitt spec.cloudInit.noCloud.networkDataSecretRef in der Konfiguration VirtualMachine gibt an, dass sich die cloud-init-Netzwerkdaten in einem Kubernetes-Secret mit dem Namen my-sec befinden. Die entsprechende Secret-Konfiguration gibt die Netzwerkdaten als Schlüssel/Wert-Paar an. Der base64-codierte Wert sind in diesem Fall die cloud-init-Netzwerkdaten.

Verwenden Sie im referenzierten Secret den Datenschlüssel networkData (angezeigt) oder networkdata, um die cloud-init-Netzwerkdaten anzugeben.

In diesem Beispiel bestehen die Netzwerkdaten aus der gleichen DHCP-Konfiguration wie im Klartextbeispiel angegeben:

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-Beispiele

Die folgenden Abschnitte enthalten Klartextbeispiele für einige häufige Anwendungsfälle für die VM-Initialisierung mit cloud-init:

Autorisierte SSH-Schlüssel konfigurieren

Im folgenden Beispiel für Nutzerdaten wird der autorisierte SSH-Schlüssel ssh-rsa AAAAB3NzaK8L93bWxnyp dem Standardnutzer zugewiesen.

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        ssh_authorized_keys:
          - ssh-rsa AAAAB3NzaK8L93bWxnyp

Neue Nutzer hinzufügen

Im folgenden Beispiel für Nutzerdaten wird ein Nutzer test erstellt und test vollständigen sudo-Zugriff gewährt. In diesem Beispiel wird dem Nutzer ein nicht ablaufendes Passwort von pwd zugewiesen.

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

Befehle beim ersten Start ausführen

Im folgenden Beispiel für Nutzerdaten werden die Befehle echo und ls ausgeführt. Sie können Befehle zum Installieren von Paketen und mehr beim Start der VM verwenden.

apiVersion: vm.cluster.gke.io/v1
kind: VirtualMachine
metadata:
  name: "my-vm"
spec:
  ...
  cloudInit:
    noCloud:
      userData: |
        #cloud-config
        runcmd:
          - [ echo, hello ]
          - [ ls, -l, / ]

Dateien schreiben

Im folgenden Beispiel für Nutzerdaten wird ein Bash-Skript in die Datei test im Verzeichnis /var/lib/google Ihrer VM geschrieben. Mit den cloud-init-Anweisungen werden die Dateiberechtigungen zum Lesen, Schreiben und Ausführen (0744) für den Dateieigentümer festgelegt.

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

Fehlerbehebung bei cloud-init

Wenn bei der Initialisierung Ihrer VM Probleme auftreten und Sie cloud-init verwenden, prüfen Sie die folgenden cloud-init-Logs auf der VM:

  • /var/log/cloud-init.log: Standardmäßig schreibt cloud-init alle Ereignisse mit einer Ebene von DEBUG oder höher in dieses Log.

  • /var/log/cloud-init-output.log: Standardmäßig leitet cloud-init sowohl stdout als auch stderr aus allen cloud-init-Phasen an dieses Log weiter.

Bootlaufwerke zum Initialisieren von VMs verwenden

Startups führen Aufgaben während des Startvorgangs einer VM-Instanz aus. Sie können im Abschnitt spec.startupScripts der Spezifikation VirtualMachine ein oder mehrere Skripts angeben. Zum Initialisieren Ihrer VM können Startup-Skripts verwendet werden. Die VM-Initialisierung umfasst in der Regel Aufgaben wie Paketinstallationen, Repository-Einrichtung, das Erstellen von SSH-Schlüsseln, das Schreiben von Daten in Dateien und das Einrichten anderer Aspekte Ihrer VM.

Beachten Sie die folgenden Details für Startup-Skripts:

  • Sie geben Startup-Skripts im YAML-Manifest VirtualMachine an, wenn Sie eine VM erstellen oder aktualisieren. Eine Anleitung zum Erstellen einer VM durch Anwenden eines Manifests finden Sie in der Anleitung: Linux-VM in der VM-Laufzeit in Google Distributed Cloud erstellen und verwalten.

  • Die angegebenen Skripts werden bei jedem Start der VM ausgeführt.

  • Fügen Sie #!/bin/... am Anfang des Skripts ein, um den Skript-Interpreter anzugeben. Fügen Sie beispielsweise #!/bin/bash ein, um das Skript mit der Bash-Shell auszuführen.

  • Sie können nicht sowohl cloud-init-API-Anweisungen (spec.cloudInit) als auch Startup-Skripts (spec.startupScripts) im selben VirtualMachine-Manifest angeben.

Skriptformate

Sie können Startup-Skripts in den folgenden Datenformaten angeben:

  • Text entfernen
  • Base64-codierter String
  • Kubernetes Secret

Beachten Sie die folgenden Regeln für die Arbeit mit verschiedenen Skriptformaten:

  • Bei Verwendung von Klartext oder einem base64-codierten String beträgt die maximal zulässige Größe für Skriptinhalte 2.048 Byte. Wenn der Skriptinhalt 2.048 Byte oder mehr übersteigt, geben Sie Skripts als Kubernetes-Secret an.

  • Verwenden Sie bei Verwendung eines Kubernetes-Secrets den Datenschlüssel script im referenzierten Secret, um den Skriptinhalt anzugeben.

  • Wenn ein referenziertes Secret nicht gefunden wird oder der Datenschlüssel script im referenzierten Secret nicht vorhanden ist, führt die VM das Skript weiterhin aus. Die VM schreibt oder aktualisiert den Skriptinhalt jedoch nicht. In diesem Fall finden Sie das Kubernetes-Warnereignis mit kubectl get event oder kubectl describe gvm.

Das folgende Beispiel-YAML-Manifest VirtualMachine enthält drei Skripts, eines in jedem der unterstützten Formate. In diesem Fall führt jedes Skript den im Klartextbeispiel myscript1 gezeigten echo hello-Befehl aus.

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=

Script-Fehlerbehebung

Führen Sie den folgenden Befehl aus, um die Skriptergebnisse oder Logs zu prüfen:

journalctl -u cloud-final

Die Logeinträge des Startup-Skripts beginnen mit dem folgenden Text:

started to run the command /var/lib/google/startup-scripts/SCRIPT_NAME ...

Der Logeintrag enthält SCRIPT_NAME, den Namen des Bootlaufwerks.