Optimieren des Betriebssystems - Amazon Elastic Compute Cloud

Optimieren des Betriebssystems

Um auf Instances mit Enhanced Networking eine maximale Netzwerkleistung zu erreichen, müssen Sie möglicherweise die Standardkonfiguration des Betriebssystems ändern. Wir empfehlen die folgenden Konfigurationsänderungen für Anwendungen, die eine hohe Netzwerkleistung erfordern.

Zusätzlich zu diesen Betriebssystemoptimierungen sollten Sie auch die Maximum Transmission Unit (MTU, maximale Übertragungseinheit) Ihres Netzwerkverkehrs berücksichtigen und an Ihren Workload und Ihre Netzwerkarchitektur anpassen. Weitere Informationen finden Sie unter Netzwerk-MTU (Maximum Transmission Unit) für Ihre EC2-Instance.

AWS misst regelmäßig die durchschnittlichen Umlauflatenzen zwischen den Instances, die in einer Cluster Placement-Gruppe von 50us gestartet werden, und Tail-Latenzen von 200us beim Perzentil 99,9. Wenn Ihre Anwendungen konsistent niedrige Latenzen erfordern, empfehlen wir, die neueste Version der ENA-Treiber auf Nitro-basierten Instances mit fester Leistung zu verwenden.

Diese Prozeduren wurden für Amazon Linux 2 und Amazon Linux AMI geschrieben. Sie funktionieren jedoch möglicherweise auch für andere Linux-Verteilungen mit Kernel-Version 3.9 oder höher. Weitere Informationen finden Sie in der systemspezifischen Dokumentation.

So optimieren Sie Ihre Amazon Linux-Instance für Enhanced Networking

  1. Prüfen Sie die Clock Source für Ihre Instance:

    cat /sys/devices/system/clocksource/clocksource0/current_clocksource
  2. Wenn die Clock Source xen lautet, führen Sie die folgenden Unterschritte aus. Fahren Sie andernfalls mit Schritt 3 fort.

    1. Bearbeiten Sie die GRUB-Konfiguration und fügen Sie xen_nopvspin=1 und clocksource=tsc zu den Kernel-Startoptionen hinzu.

      • Bearbeiten Sie für Amazon Linux 2 die Datei /etc/default/grub und fügen Sie diese Optionen zur Zeile GRUB_CMDLINE_LINUX_DEFAULT hinzu, wie im Folgenden dargestellt:

        GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 nvme_core.io_timeout=4294967295 xen_nopvspin=1 clocksource=tsc" GRUB_TIMEOUT=0
      • Bearbeiten Sie für Amazon Linux AMI die Datei /boot/grub/grub.conf und fügen Sie diese Optionen zur Zeile kernel hinzu, wie im Folgenden dargestellt:

        kernel /boot/vmlinuz-4.14.62-65.117.amzn1.x86_64 root=LABEL=/ console=tty1 console=ttyS0 selinux=0 nvme_core.io_timeout=4294967295 xen_nopvspin=1 clocksource=tsc
    2. (Nur Amazon Linux 2) Erstellen Sie Ihre GRUB-Konfigurationsdatei neu, damit diese Änderungen übernommen werden:

      sudo grub2-mkconfig -o /boot/grub2/grub.cfg
  3. Wenn Ihr Instance-Typ als von Steuerung des Prozessorzustands für Ihre EC2-Instance unterstützt aufgeführt ist, verhindern Sie, dass das System tiefere C-Zustände verwendet, um sicherzustellen, dass die Systemleistung eine geringe Latenz hat. Weitere Informationen finden Sie unter Hohe Performance und geringe Latenz durch die Beschränkung von tieferen C-Zuständen.

    1. Bearbeiten Sie die GRUB-Konfiguration und fügen Sie intel_idle.max_cstate=1 den Kernel-Startoptionen hinzu.

      • Bearbeiten Sie für Amazon Linux 2 die Datei /etc/default/grub und fügen Sie diese Option der Zeile GRUB_CMDLINE_LINUX_DEFAULT hinzu, wie im Folgenden dargestellt:

        GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 nvme_core.io_timeout=4294967295 xen_nopvspin=1 clocksource=tsc intel_idle.max_cstate=1" GRUB_TIMEOUT=0
      • Bearbeiten Sie für Amazon Linux AMI die Datei /boot/grub/grub.conf und fügen Sie diese Option der Zeile kernel hinzu, wie im Folgenden dargestellt:

        kernel /boot/vmlinuz-4.14.62-65.117.amzn1.x86_64 root=LABEL=/ console=tty1 console=ttyS0 selinux=0 nvme_core.io_timeout=4294967295 xen_nopvspin=1 clocksource=tsc intel_idle.max_cstate=1
    2. (Nur Amazon Linux 2) Erstellen Sie Ihre GRUB-Konfigurationsdatei neu, damit diese Änderungen übernommen werden:

      sudo grub2-mkconfig -o /boot/grub2/grub.cfg
  4. Stellen Sie sicher, dass Ihr reservierter Kernel-Speicher ausreicht, um eine hohe Zahl an Paket-Puffer-Zuweisungen zu fassen. Der Standardwert ist möglicherweise zu klein.

    1. Öffnen Sie mit dem Editor Ihrer Wahl die Datei /etc/sysctl.conf (als root oder mit sudo).

    2. Fügen Sie die Zeile vm.min_free_kbytes der Datei mit dem Wert des reservierten Kernel-Speichers (in Kilobyte) für Ihren Instance-Typ hinzu. In der Regel sollten Sie diesen Wert auf eine Zahl zwischen 1 und 3 % des verfügbaren Systemspeichers festlegen. Passen Sie den Wert nach oben oder unten an, damit er den Anforderungen Ihrer Anwendung entspricht.

      vm.min_free_kbytes = 1048576
    3. Wenden Sie diese Konfiguration mit dem folgenden Befehl an:

      sudo sysctl -p
    4. Stellen Sie sicher, dass die Einstellung angewendet wurde, indem Sie den folgenden Befehl verwenden:

      sudo sysctl -a 2>&1 | grep min_free_kbytes
  5. Starten Sie Ihre Instance neu, damit die neue Konfiguration übernommen wird:

    sudo reboot
  6. (Optional) Verteilen Sie die Interrupts beim Erhalten von Paketen manuell so, dass sie mit unterschiedlichen CPUs verknüpft sind, die alle zum selben NUMA-Knoten gehören. Verwenden Sie diese Methode jedoch mit Vorsicht, da irqbalancer global deaktiviert ist.

    Anmerkung

    Die Konfigurationsänderung in diesem Schritt hält einem Neustart nicht Stand.

    1. Erstellen Sie eine Datei mit dem Namen smp_affinity.sh und fügen Sie den folgenden Codeblock in diese Datei ein:

      #/bin/sh service irqbalance stop affinity_values=(00000001 00000002 00000004 00000008 00000010 00000020 00000040 00000080) irqs=($(grep eth /proc/interrupts|awk '{print $1}'|cut -d : -f 1)) irqLen=${#irqs[@]} for (( i=0; i<${irqLen}; i++ )); do echo $(printf "0000,00000000,00000000,00000000,${affinity_values[$i]}") > /proc/irq/${irqs[$i]}/smp_affinity; echo "IRQ ${irqs[$i]} =" $(cat /proc/irq/${irqs[$i]}/smp_affinity); done
    2. Führen Sie das Skript mit dem folgenden Befehl aus:

      sudo bash ./smp_affinity.sh
  7. (Optional) Wenn die vCPUs, die Receive-IRQs verarbeiten, überladen sind, oder die Netzwerkverarbeitung Ihrer Anwendung viel CPU fordert, können Sie einen Teil der Netzwerkverarbeitung auf andere Cores verlagern, die über Receive Packet Steering (RPS) verfügen. Stellen Sie sicher, dass die für RPS verwendeten Cores zum selben NUMA-Knoten gehören, um Sperren zwischen NUMA-Knoten zu vermeiden. Um beispielsweise die Cores 8-15 für die Paketverarbeitung einzusetzen, verwenden Sie den folgenden Befehl.

    Anmerkung

    Die Konfigurationsänderung in diesem Schritt hält einem Neustart nicht Stand.

    for i in `seq 0 7`; do echo $(printf "0000,00000000,00000000,00000000,0000ff00") | sudo tee /sys/class/net/eth0/queues/rx-$i/rps_cpus; done
  8. (Optional) Sorgen Sie nach Möglichkeit dafür, dass die ganze Verarbeitung auf demselben NUMA-Knoten stattfindet.

    1. Installieren Sie numactl:

      sudo yum install -y numactl
    2. Verknüpfen Sie Ihr Netzwerkverarbeitungsprogramm bei der Ausführung mit einem einzigen NUMA-Knoten. Beispielsweise verknüpft der folgende Befehl das Shell-Skript run.sh mit dem NUMA-Knoten 0:

      numactl --cpunodebind=0 --membind=0 run.sh
    3. Wenn Hyperthreading aktiviert ist, können Sie Ihre Anwendung so konfigurieren, dass pro CPU-Core nur ein einziger Hardware-Thread verwendet wird.

      • Sie können mit folgendem lscpu-Befehl anzeigen, welche CPU-Cores einem NUMA-Knoten zugeordnet sind:

        lscpu | grep NUMA

        Ausgabe:

        NUMA node(s): 2 NUMA node0 CPU(s): 0-15,32-47 NUMA node1 CPU(s): 16-31,48-63
      • Sie können mit folgendem Befehl anzeigen, welche Hardware-Threads zu einem physischen CPU gehören:

        cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list

        Ausgabe:

        0,32

        In diesem Beispiel sind die Threads 0 und 32 dem CPU 0 zugeordnet.

      • Um zu vermeiden, dass die Ausführung mit Threads 32-47 (die eigentlich Hardware-Threads desselben CPUs sind wie 0-15) erfolgt, verwenden Sie den folgenden Befehl:

        numactl --physcpubind=+0-15 --membind=0 ./run.sh
  9. Verwenden Sie mehrere Elastic Network-Schnittstellen für verschiedene Datenverkehrsklassen. Wenn Sie beispielsweise einen Webserver nutzen, der auf einer Backend-Datenbank basiert, verwenden Sie eine Elastic Network-Schnittstelle für das Webserver-Frontend und eine andere für die Datenbankverbindung.