Benutzerdefiniertes Betriebssystem-Image verwenden

Sie können ein benutzerdefiniertes Betriebssystem-Image für Ihre TPU-VMs verwenden, um Software vorab zu laden, eine bestimmte Betriebssystemdistribution zu verwenden oder benutzerdefinierte Kernel-Änderungen anzuwenden. Beim Erstellen eines benutzerdefinierten Images müssen während des Image-Erstellungsprozesses bestimmte Systemänderungen vorgenommen und das Image so konfiguriert werden, dass es die für die TPU-Funktionalität erforderlichen Boot-Aufgaben ausführt.

Beachten Sie die folgenden Haftungsausschlüsse, wenn Sie ein benutzerdefiniertes Betriebssystem-Image mit TPUs verwenden:

  • Google stellt standardmäßige TPU-optimierte Ubuntu-Images mit Langzeitsupport (LTS) bereit. Die auf dieser Seite aufgeführten Betriebssystemänderungen werden nur für die von Google unterstützten, TPU-optimierten Ubuntu LTS-Images validiert.
  • Sie sind dafür verantwortlich, die erforderlichen Betriebssystemänderungen für andere Betriebssystemdistributionen oder benutzerdefinierte Images zu extrapolieren. Google garantiert nicht, dass die auf dieser Seite aufgeführten Änderungen für Ubuntu mit anderen Betriebssystemdistributionen oder einem anderen Ubuntu-Image mit einem benutzerdefinierten Kernel funktionieren.
  • Google erstellt oder testet keine anderen Betriebssystem-Images als die standardmäßigen TPU-optimierten Ubuntu LTS-Images. Sie müssen Ihr benutzerdefiniertes Betriebssystem-Image erstellen und testen.

Weitere Informationen zu den standardmäßigen TPU-optimierten Ubuntu LTS-Images finden Sie unter TPU-Betriebssystem-Images.

Vorbereitung

Auf dem Basis-Image müssen die folgenden Komponenten installiert sein:

  • Python 3
  • gcloud-CLI

Für TPU7x-VMs muss Ihr Basis-Image mindestens die Linux-Kernel-Version 6.8 des Gastbetriebssystems verwenden.

Änderungen während der Image-Erstellung vornehmen

Wenden Sie die folgenden Änderungen an, während Sie Ihr benutzerdefiniertes Ubuntu-Image erstellen.

TPU-Geräte an VFIO binden

Damit das Gastbetriebssystem auf die TPU-Hardware zugreifen kann, müssen Sie TPU-Geräte an den vfio-pci-Treiber binden.

  1. Erstellen Sie in /etc/udev/rules.d/ eine udev-Regeldatei mit dem Namen 99-tpu-vfiopci.rules:

    # Rules for binding vfio-enabled TPU devices to vfio-pci.
    
    # v5p
    SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x0062", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00ad", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci"
    
    # v6e
    SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x006f", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00d1", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci"
    
    # TPU7x
    SUBSYSTEM=="pci", ACTION=="add", ATTRS{vendor}=="0x1ae0", ATTRS{device}=="0x0076", ATTRS{subsystem_vendor}=="0x1ae0", ATTRS{subsystem_device}=="0x00f2", DRIVER!="vfio-pci", TAG+="bind_to_vfio_pci"
    
    # Bind all 'bind_to_vfio_pci' tagged devices to vfio-pci.
    TAG=="bind_to_vfio_pci", RUN+="/lib/udev/bind_to_vfio_pci.sh $kernel"
    
  2. Erstellen Sie in /lib/udev/ ein Script mit dem Namen bind_to_vfio_pci.sh:

    #!/bin/bash
    #!/usr/bin/env bash
    
    # Run ./bind_to_vfio_pci.sh <DBDF>
    # Binds the device at <DBDF> to vfio-pci.
    # If the device is already bound to a driver, unbinds it first.
    
    # Load the vfio-pci module into the kernel. No-op if already loaded.
    modprobe vfio-pci
    
    DBDF_REGEX="^[[:xdigit:]]{4}:[[:xdigit:]]{2}:[[:xdigit:]]{2}.[[:xdigit:]]$"
    
    unset BDF
    if [[ $1 =~ $DBDF_REGEX ]]; then
        BDF=$1
    else
        echo "Error: BDF arg ($1) is not in form dddd:bb:dd.f"
        exit 1
    fi
    
    PCI_PATH="/sys/bus/pci/devices/$BDF"
    
    echo "vfio-pci" > "$PCI_PATH/driver_override"
    
    PCI_DRIVER_PATH="$PCI_PATH/driver"
    if [[ -d "$PCI_DRIVER_PATH" ]]; then
        curr_driver=$(readlink "$PCI_DRIVER_PATH")
            curr_driver=${curr_driver##*/}
        if [[ $curr_driver == "vfio-pci" ]]; then
            echo "$BDF already bound to vfio-pci"
            exit 0
        else
            echo "$BDF" > "$PCI_DRIVER_PATH/unbind"
            if [[ -d "$PCI_DRIVER_PATH" ]]; then
                echo "Error: Unable to unbind $PCI_DRIVER_PATH"
                exit 1
            fi
            echo "Unbound $BDF from driver $curr_driver"
        fi
    fi
    echo "$BDF" > /sys/bus/pci/drivers_probe
    echo "Bound $BDF to vfio-pci"
    
    # Grant read/write access on VFIO device to all users
    IOMMU_GROUP=$(readlink "$PCI_PATH/iommu_group" | xargs basename)
    VFIO_DEV="/dev/vfio/$IOMMU_GROUP"
    if [[ -c "$VFIO_DEV" ]]; then
        chmod 0666 "$VFIO_DEV"
    else
        echo "$VFIO_DEV not found"
        exit 1
    fi
    
    # Set allow_unsafe_interrupts for x86 platforms.
    (uname -a | grep -q x86_64) && echo 1 > /sys/module/vfio_iommu_type1/parameters/allow_unsafe_interrupts
    
    # This is only needed to avoid non-zero exit code from previous command.
    echo "All Done!"
    
  3. Machen Sie das Skript ausführbar:

    chmod +x /lib/udev/bind_to_vfio_pci.sh
    
  4. Gewähren Sie allen Nutzern im System Zugriff auf das TPU-Gerät:

    echo 'KERNEL=="accel*" MODE="0666"' >> /etc/udev/rules.d/99-tpu.rules
    

Bild optimieren, um die Leistung zu verbessern

Passen Sie die folgenden Systemlimits und Parameter an, um eine optimale Leistung zu erzielen.

Beschränkungen des Arbeitsspeichers

Aktualisieren Sie /etc/security/limits.conf, um einem einzelnen Prozess zu erlauben, unbegrenzten Arbeitsspeicher zu sperren:

echo '*  hard  memlock  unlimited' >> /etc/security/limits.conf
echo '*  soft  memlock  unlimited' >> /etc/security/limits.conf

Dateilimits

Erhöhen Sie die Anzahl der geöffneten Dateien, indem Sie /etc/security/limits.conf aktualisieren:

echo "*    soft    nofile       100000" >> /etc/security/limits.conf
echo "*    hard    nofile       100000" >> /etc/security/limits.conf
echo "root soft    nofile       100000" >> /etc/security/limits.conf
echo "root hard    nofile       100000" >> /etc/security/limits.conf

Kernelparameter

Aktualisieren Sie Ihre GRUB-Konfiguration (normalerweise in /etc/default/grub), um die folgenden Parameter in GRUB_CMDLINE_LINUX einzufügen:

  • idle=poll: Verhindert, dass die CPU in den Energiesparmodus wechselt.
  • intel_iommu=on,sm_on: Aktiviert die Intel Input-Output Memory Management Unit (IOMMU). Erforderlich für TPU7x- und v5p-Architekturen.
  • transparent_hugepage=always: Aktiviert Transparent Huge Pages (THP).

In den folgenden Schritten wird beschrieben, wie Sie diese Kernelparameter aktualisieren:

  1. Verhindern Sie, dass die CPU in einen inaktiven Zustand mit geringem Stromverbrauch wechselt, indem Sie die folgende Variable festlegen, die Sie im nächsten Schritt verwenden werden.

    kernel_cmdline="idle=poll"
    
  2. Aktivieren Sie die Intel Input-Output Memory Management Unit (IOMMU). Dieser Schritt ist für TPU7x und TPU v5p erforderlich.

    kernel_cmdline="${kernel_cmdline} intel_iommu=on,sm_on";
    sed -i "s/GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"${kernel_cmdline}\"/" /etc/default/grub
    echo "Status: New kernel cmdline: $(cat /etc/default/grub | grep -e '^GRUB_CMDLINE_LINUX=')"
    
    update-grub
    
  3. Aktivieren Sie Transparent Huge Pages (THP):

    echo "Status: Enabling THP"
    sed -i -r 's/GRUB_CMDLINE_LINUX="[a-zA-Z0-9_= ]*/& transparent_hugepage=always/' /etc/default/grub
    
    update-grub
    

vBar-Agent installieren

Der vBar-Agent ist erforderlich, damit das ICI-Netzwerk (Inter-Chip Interconnect) funktioniert.

Führen Sie die folgenden Befehle aus, um den vBar-Agent zu installieren:

  1. Authentifizieren Sie Docker bei Artifact Registry:

    gcloud auth configure-docker us-docker.pkg.dev
    
  2. Docker-Image aus Artifact Registry abrufen:

    docker pull gcr.io/cloud-tpu-v2-images/vbar_control_agent:0.0.1
    
  3. Führen Sie einen Container mit dem vBar-Agent-Image aus:

    docker run --privileged --net=host vbar_control_agent:0.0.1
    

Optional: AI Telemetry Collector installieren und ausführen

Der AI Telemetry Collector wird in der TPU-VM ausgeführt und ermöglicht Ihnen den Zugriff auf Laufzeit- und Infrastrukturmesswerte über Cloud Monitoring oder über Ihre eigene Prometheus-basierte Monitoring-Pipeline. Sie können den AI Telemetry Collector mit einem benutzerdefinierten Betriebssystem verwenden, indem Sie das Docker-Image ai-telemetry-collector verwenden. Sie können das Image auf Ihrem benutzerdefinierten Betriebssystem installieren und mit einer config.yaml-Datei die Erfassungsintervalle festlegen, bestimmte Messwerte aktivieren oder deaktivieren oder die Exportziele ändern.

Führen Sie die folgenden Befehle aus, um den AI Telemetry Collector zu installieren:

  1. Authentifizieren Sie Docker bei Artifact Registry:

    gcloud auth configure-docker us-docker.pkg.dev
    
  2. Docker-Image aus Artifact Registry abrufen:

    docker pull gcr.io/cloud-tpu-v2-images/ai-telemetry-collector:latest
    
  3. Führen Sie einen Container mit dem AI Telemetry Collector-Image und der Standardkonfiguration aus:

    docker run --privileged --net=host ai-telemetry-collector:latest
    

    Informationen zur Verwendung einer benutzerdefinierten Konfigurationsdatei oder zum Hinzufügen zusätzlicher Konfigurationsdateien finden Sie unter AI Telemetry Collector.

Änderungen an der Startzeit vornehmen

Konfigurieren Sie Ihr Image so, dass die Aufgaben in den folgenden Abschnitten bei jedem Start einer VM ausgeführt werden. Mit dem Tool cloud-init können Sie Aufgaben für die Bootzeit konfigurieren, indem Sie Metadaten an Ihre Instanzen übergeben. In den Konfigurationen in den folgenden Abschnitten werden Module wie write_files und runcmd verwendet. Snippets, die zu schreibende Dateien definieren, sollten unter dem Schlüssel write_files: und Befehle, die beim Booten ausgeführt werden sollen, unter dem Schlüssel runcmd: in Ihrer cloud-init-Konfiguration enthalten sein.

vBar-Agent starten

Starten Sie den vBar-Steuerungs-Agent mit den entsprechenden Nutzer- und Gruppen-IDs:

vbar_control_agent --logtostderr --gid= --uid=  --chroot= --census_enabled=false --loas_pwd_fallback_in_corp

Umgebungsvariablen konfigurieren

Damit Ihre Umgebung für TPU-Arbeitslasten korrekt initialisiert wird, müssen Sie während des Systemstartvorgangs Laufzeitkonfigurationsvariablen vom Compute Engine-Metadatenserver abrufen. Fügen Sie dazu das folgende Snippet in den Abschnitt write_files: Ihrer cloud-init-Konfiguration ein. Dadurch wird ein Skript mit dem Namen /var/scripts/configure-env-vars.sh erstellt. Dieses Skript automatisiert das Abrufen von Attributen aus dem Metadatenschlüssel tpu-env und speichert sie in /${HOME}/tpu-env, damit sie vom TPU-Software-Stack verwendet werden können.

 - path: /var/scripts/configure-env-vars.sh
    permissions: 0444
    owner: root
    content: |
      grep -q CLOUDSDK_PYTHON /etc/environment || echo "CLOUDSDK_PYTHON=/usr/bin/python3" >> /etc/environment

      export HOME=/home/tpu-runtime
      curl -s 'http://metadata.google.internal/computeMetadata/v1/instance/attributes/tpu-env' -H 'Metadata-Flavor: Google' > /tmp/tpu-env.yaml

      eval $(python3 -c '''
      import yaml
      stream_in=open("/tmp/tpu-env.yaml", "r")
      for k,v in yaml.safe_load(stream_in).items():
        print("{var}=\"{value}\"".format(var = k, value = str(v)))
      ''' > "/${HOME}/tpu-env"
      )

      rm -f "/tmp/tpu-env.yaml"

      printenv
      cat ${HOME}/tpu-env

VM-Metadaten abrufen

Im folgenden Snippet wird ein Script mit dem Namen /var/scripts/get-vm-metadata.py erstellt, ein Python-Dienstprogramm, mit dem der Metadatenserver programmatisch nach bestimmten Instanzattributen und benutzerdefinierten Metadaten-Tags abgefragt wird. Fügen Sie dem Abschnitt write_files: Ihrer cloud-init-Konfiguration Folgendes hinzu:

 - path: /var/scripts/get-vm-metadata.py
    permissions: 0444
    owner: root
    content: |
      import sys, requests, os

      if len(sys.argv) < 2:
        sys.stderr.write('Must provide key')
        os._exit(1)

      key = sys.argv[1]
      default = None
      if len(sys.argv) > 2:
        default = sys.argv[2]

      attribute_type = 'attributes'
      if len(sys.argv) > 3:
        attribute_type = sys.argv[3]

      request = requests.get("http://metadata.google.internal/computeMetadata/v1/instance/{}/{}".format(attribute_type, key), headers={'Metadata-Flavor': 'Google'})
      if request.status_code == 200:
        print(request.content)
      elif request.status_code == 404 or request.status_code == '403':
        sys.stderr.write('Metadata key: {} does not exist\n'.format(key))
        if default:
          print(default)
      else:
        sys.stderr.write('Lookup failed with: {}'.format(request))

Cloud Storage-Zeitlimits erhöhen

Wenn Ihre Arbeitslast mit Cloud Storage interagiert, erhöhen Sie die Zeitlimits, indem Sie /etc/environment Zeitlimitwerte hinzufügen. Fügen Sie dazu das folgende Snippet in den Abschnitt write_files: Ihrer cloud-init-Konfiguration ein. Dadurch wird ein Script mit dem Namen /var/scripts/configure-gcs-timeouts.sh erstellt.

 - path: /var/scripts/configure-gcs-timeouts.sh
    permissions: 0444
    owner: root
    content: |
      echo "GCS_RESOLVE_REFRESH_SECS=60" >> /etc/environment
      echo "GCS_REQUEST_CONNECTION_TIMEOUT_SECS=300" >> /etc/environment
      echo "GCS_METADATA_REQUEST_TIMEOUT_SECS=300" >> /etc/environment
      echo "GCS_READ_REQUEST_TIMEOUT_SECS=300" >> /etc/environment
      echo "GCS_WRITE_REQUEST_TIMEOUT_SECS=600" >> /etc/environment

Nächste Schritte