Redaktion – Dieser Beitrag ist Teil einer zehnteiligen Serie:
- Komplexität mit produktionsreifem Kubernetes reduzieren
- So verbessern Sie die Ausfallsicherheit in Kubernetes mit erweitertem Traffic-Management
- So verbessern Sie die Transparenz in Kubernetes
- Sechs Möglichkeiten, Kubernetes mithilfe von Traffic-Management-Tools abzusichern
- Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
- Leitfaden zur Auswahl eines Ingress-Controllers, Teil 2: Risiken und Zukunftssicherheit
- Leitfaden zur Auswahl eines Ingress-Controllers, Teil 3: Open Source vs. Standardlösung vs. kommerzielle Lösung
- Leitfaden zur Auswahl eines Ingress-Controllers, Teil 4: Optionen für NGINX Ingress Controller
- So wählen Sie ein Service Mesh aus
- Leistungstests von NGINX Ingress Controllern in einer dynamischen Kubernetes-Cloud-Umgebung (dieser Beitrag)
Sie können die vollständige Blogreihe auch als kostenloses E-Book herunterladen: „Kubernetes von der Test- in die Produktionsumgebung überführen“.
Da immer mehr Unternehmen containerisierte Anwendungen in Produktionsumgebungen einsetzen, festigt Kubernetes seine Position als Standardwerkzeug für die Container-Orchestrierung. Gleichzeitig ist die Nachfrage nach Cloud-Computing ihrer bisherigen Entwicklung um einige Jahre voraus, da die durch die COVID‑19-Pandemie bedingten Homeoffice-Initiativen das Wachstum des Internetverkehrs beschleunigt haben. Unternehmen arbeiten mit Hochdruck an der Modernisierung ihrer Infrastruktur, da ihre Kunden mit erheblichen Netzwerkausfällen und -überlastungen konfrontiert sind.
Um das erforderliche Leistungsniveau in cloudbasierten Microservices-Umgebungen zu erreichen, benötigen Sie schnelle, vollständig dynamische Software, die die Skalierbarkeit und Leistung von Hyperscale-Rechenzentren der nächsten Generation nutzt. Viele Unternehmen, die Kubernetes zur Verwaltung von Containern einsetzen, verlassen sich auf einen NGINX-basierten Ingress-Controller, um ihre Anwendungen für Benutzer bereitzustellen.
In diesem Blogbeitrag stellen wir die Ergebnisse unserer Leistungstests mit drei NGINX Ingress Controllern in einer realistischen Multi-Cloud-Umgebung vor, bei denen wir die Latenz von Clientverbindungen über das Internet gemessen haben:
- Der von der Kubernetes-Community gepflegte NGINX Ingress Controller basiert auf NGINX Open Source. Wie schon in früheren Blogbeiträgen bezeichnen wir ihn hier als Community Ingress Controller. Wir haben Version 0.34.1 mit einem Image getestet, das aus der Google Container Registry abgerufen wurde.
- NGINX Ingress Controller auf Basis von NGINX Open Source, Version 1.8.0, gepflegt von NGINX.
- NGINX Ingress Controller auf Basis von NGINX Plus, Version 1.8.0, gepflegt von NGINX.
Testprotokoll und erfasste Metriken
Wir verwendeten das Lastgenerierungsprogramm wrk2 zur Emulation eines Clients, der über einen festgelegten Zeitraum kontinuierlich Anfragen über HTTPS sendete. Der getestete Ingress-Controller – der Community-Ingress-Controller, der auf NGINX Open Source basierende NGINX Ingress Controller oder der auf NGINX Plus basierende NGINX Ingress Controller – leitete Anfragen an Backend-Anwendungen weiter, die in Kubernetes-Pods bereitgestellt waren, und gab die von den Anwendungen generierte Antwort an den Client zurück. Wir erzeugten einen gleichmäßigen Client-Datenverkehr, um die Ingress-Controller einem Belastungstest zu unterziehen, und erfassten die folgenden Leistungskennzahlen:
- Latenz – Die Zeitspanne zwischen dem Absenden einer Anfrage durch den Client und dem Empfang der Antwort. Wir geben die Latenzen als Perzentilverteilung an. Wenn beispielsweise 100 Messwerte aus Latenztests vorliegen, entspricht der Wert im 99. Perzentil der zweithöchsten Antwortlatenz unter den 100 Testläufen.
- Verbindungszeitüberschreitungen – TCP-Verbindungen, die stillschweigend getrennt oder verworfen werden, weil der Ingress-Controller nicht innerhalb einer bestimmten Zeit auf Anfragen reagiert.
- Lesefehler – Versuche, Daten über eine Verbindung zu lesen, schlagen fehl, weil ein Socket des Ingress-Controllers geschlossen ist.
- Verbindungsfehler – TCP-Verbindungen zwischen dem Client und dem Ingress-Controller, die nicht hergestellt werden.
Topologie
Für alle Tests verwendeten wir das Dienstprogramm wrk2, das auf einem Clientcomputer in AWS ausgeführt wurde, um Anfragen zu generieren. Der AWS-Client stellte eine Verbindung zur externen IP-Adresse des Ingress-Controllers her, der als Kubernetes-DaemonSet auf GKE-node-1 in einer Google-Kubernetes-Engine-Umgebung (GKE) bereitgestellt war. Der Ingress-Controller war für die SSL-Terminierung (unter Verweis auf ein Kubernetes-Secret) und das Layer-7-Routing konfiguriert und wurde über einen Kubernetes-Service vom Type LoadBalancer bereitgestellt. Die Backend-Anwendung wurde als Kubernetes-Deployment auf GKE-node-2 ausgeführt.

Ausführliche Informationen zu den Cloud-Maschinentypen und Softwarekonfigurationen finden Sie im Anhang.
Testmethodik
Client-Bereitstellung
Wir haben das folgende wrk2-Skript (Version 4.0.0) auf dem AWS-Clientcomputer ausgeführt. Es startet 2 wrk-Threads, die zusammen 1000 Verbindungen zum in GKE bereitgestellten Ingress-Controller herstellen. Während jedes dreiminütigen Testlaufs generiert das Skript 30.000 Anfragen pro Sekunde (RPS), was unserer Ansicht nach die Last auf einem Ingress-Controller in einer Produktionsumgebung gut simuliert.
wrk -t2 -c1000 -d180s -L -R30000 https://app.example.com:443/wobei:
-t– Legt die Anzahl der Threads fest (2)-c– Legt die Anzahl der TCP-Verbindungen fest (1000)-d– Legt die Dauer des Testlaufs in Sekunden fest (180 bzw. 3 Minuten)-L– Erzeugt detaillierte Informationen zu den Latenzperzentilen für den Export in Analysetools-R– Legt die Anzahl der Anfragen pro Sekunde fest (30.000)
Für die TLS-Verschlüsselung verwendeten wir RSA mit einer Schlüssellänge von 2048 Bit und Perfect Forward Secrecy.
Jede Antwort der Back-End-Anwendung (erreichbar unter https://app.example.com:443) umfasst etwa 1 KB grundlegende Servermetadaten sowie den HTTP-Statuscode 200 OK.
Bereitstellung der Back-End-Anwendung
Wir führten Testläufe sowohl mit einer statischen als auch mit einer dynamischen Bereitstellung der Back-End-Anwendung durch.
Bei der statischen Bereitstellung gab es fünf Pod-Replikate, und über die Kubernetes-API wurden keine Änderungen vorgenommen.
Für die dynamische Bereitstellung haben wir das folgende Skript verwendet, um die Anzahl der Pod-Replikate der Backend-nginx-Bereitstellung regelmäßig von fünf auf sieben zu erhöhen und anschließend wieder auf fünf zu reduzieren. Dadurch wird eine dynamische Kubernetes-Umgebung simuliert und getestet, wie effektiv sich der Ingress-Controller an Änderungen der Endpunkte anpasst.
while [ 1 -eq 1 ]
do
kubectl scale deployment nginx --replicas=5
sleep 12
kubectl scale deployment nginx --replicas=7
sleep 10
doneLeistungsergebnisse
Latenzergebnisse für die statische Bereitstellung
Wie aus dem Diagramm hervorgeht, erzielten alle drei Ingress-Controller bei einer statischen Bereitstellung der Backend-Anwendung eine ähnliche Leistung. Dies ist nachvollziehbar, da sie alle auf NGINX Open Source basieren und die statische Bereitstellung keine Neukonfiguration durch den Ingress-Controller erfordert.

Latenzergebnisse für die dynamische Bereitstellung
Das Diagramm zeigt die Latenz der einzelnen Ingress-Controller in einer dynamischen Bereitstellung, bei der wir die Back-End-Anwendung regelmäßig von fünf Replikat-Pods auf sieben hoch- und anschließend wieder herunterskaliert haben (weitere Informationen finden Sie unter „Bereitstellung der Back-End-Anwendung“).
Es ist klar, dass nur der auf NGINX Plus basierende Ingress-Controller in dieser Umgebung eine gute Leistung erzielt und bis zum 99,99. Perzentil praktisch keine Latenz aufweist. Sowohl beim Community-Ingress-Controller als auch beim auf NGINX Open Source basierenden Ingress-Controller treten bereits bei relativ niedrigen Perzentilen merkliche Latenzen auf, allerdings mit recht unterschiedlichen Verläufen. Beim Community-Ingress-Controller steigt die Latenz langsam, aber stetig bis zum 99. Perzentil an und pendelt sich dort bei etwa 5000 ms (5 Sekunden) ein. Beim auf NGINX Open Source basierenden Ingress-Controller steigt die Latenz bis zum 99. Perzentil sprunghaft auf etwa 32 Sekunden und bis zum 99,99. Perzentil erneut auf 60 Sekunden an.
Wie wir unter „Ergebnisse zu Zeitüberschreitungen und Fehlern bei der dynamischen Bereitstellung“ näher erläutern, wird die bei den Community- und den auf NGINX Open Source basierenden Ingress-Controllern auftretende Latenz durch Fehler und Zeitüberschreitungen verursacht, die auftreten, nachdem die NGINX-Konfiguration als Reaktion auf die sich ändernden Endpunkte der Backend-Anwendung aktualisiert und neu geladen wurde.

Hier sehen Sie eine detailliertere Darstellung der Ergebnisse für den Community-Ingress-Controller und den auf NGINX Plus basierenden Ingress-Controller unter denselben Testbedingungen wie im vorherigen Diagramm. Der auf NGINX Plus basierende Ingress-Controller verursacht bis zum 99,99. Perzentil praktisch keine Latenz. Ab diesem Punkt steigt sie an und erreicht beim 99,9999. Perzentil annähernd 254 ms. Beim Community-Ingress-Controller nimmt die Latenz kontinuierlich zu und erreicht beim 99. Perzentil 5000 ms; danach bleibt sie konstant.

Zeitüberschreitungs- und Fehlerergebnisse für die dynamische Bereitstellung
Diese Tabelle zeigt die Ursache der Latenzergebnisse genauer.
NGINX Open Source Community NGINX PlusVerbindungsfehler 33365 0 0Verbindungszeitüberschreitungen 309 8809 0Lesefehler 4650 0 0
Beim auf NGINX Open Source basierenden Ingress-Controller führt die Notwendigkeit, die NGINX-Konfiguration bei jeder Änderung an den Endpunkten der Backend-Anwendung zu aktualisieren und neu zu laden, zu zahlreichen Verbindungsfehlern, Verbindungszeitüberschreitungen und Lesefehlern. Verbindungs-/Socket-Fehler treten während der kurzen Zeit auf, die NGINX zum Neuladen benötigt, wenn Clients versuchen, eine Verbindung zu einem Socket herzustellen, der dem NGINX-Prozess nicht mehr zugewiesen ist. Verbindungszeitüberschreitungen treten auf, wenn Clients eine Verbindung zum Ingress-Controller hergestellt haben, der Backend-Endpunkt jedoch nicht mehr verfügbar ist. Sowohl Fehler als auch Zeitüberschreitungen beeinträchtigen die Latenz erheblich, mit Spitzen von 32 Sekunden beim 99. Perzentil und sogar 60 Sekunden beim 99,99. Perzentil.
Beim Community-Ingress-Controller kam es aufgrund der Änderungen an den Endpunkten beim Hoch- und Herunterskalieren der Backend-Anwendung zu 8.809 Verbindungszeitüberschreitungen. Der Community-Ingress-Controller verwendet Lua-Code, um das erneute Laden der Konfiguration bei Änderungen an Endpunkten zu vermeiden. Die Ergebnisse zeigen, dass die Ausführung eines Lua-Handlers innerhalb von NGINX zur Erkennung von Endpunktänderungen einige der Leistungseinschränkungen der auf NGINX Open Source basierenden Version behebt, die darauf zurückzuführen sind, dass die Konfiguration nach jeder Änderung an den Endpunkten neu geladen werden muss. Dennoch treten weiterhin Verbindungszeitüberschreitungen auf, die bei höheren Perzentilen zu erheblichen Latenzen führen.
Beim auf NGINX Plus basierenden Ingress-Controller traten weder Fehler noch Zeitüberschreitungen auf – die dynamische Umgebung hatte praktisch keine Auswirkungen auf die Leistung. Das liegt daran, dass er die NGINX Plus API verwendet, um die NGINX-Konfiguration bei Änderungen an den Endpunkten dynamisch zu aktualisieren. Wie bereits erwähnt, betrug die höchste Latenz 254 ms und trat nur beim 99,9999. Perzentil auf.
Fazit
Die Leistungsergebnisse zeigen, dass sich der Ingress-Controller dynamisch an Änderungen der Backend-Endpunkte anpassen muss, ohne Ereignishandler oder Konfigurationsneuladungen zu verwenden, um Zeitüberschreitungen und Fehler in einer dynamischen Kubernetes-Cloud-Umgebung vollständig zu vermeiden. Auf Grundlage der Ergebnisse können wir sagen, dass die NGINX Plus API die optimale Lösung für die dynamische Neukonfiguration von NGINX in einer dynamischen Umgebung ist. In unseren Tests erzielte nur der auf NGINX Plus basierende Ingress-Controller die einwandfreie Leistung in hochdynamischen Kubernetes-Umgebungen, die erforderlich ist, um Ihre Benutzer zufriedenzustellen.
Anhang
Spezifikationen der Cloud-Maschine
Maschine Cloud-Anbieter MaschinentypClient AWS m5a.4xlargeGKE-node-1 GCP e2-standard-32GKE-node-2 GCP e2-standard-32
Konfiguration für NGINX Open Source und NGINX Plus Ingress Controller
Kubernetes-Konfiguration
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-ingress
namespace: nginx-ingress
spec:
selector:
matchLabels:
app: nginx-ingress
template:
metadata:
labels:
app: nginx-ingress
#annotations:
#prometheus.io/scrape: "true"
#prometheus.io/port: "9113"
spec:
serviceAccountName: nginx-ingress
nodeSelector:
kubernetes.io/hostname: gke-rawdata-cluster-default-pool-3ac53622-6nzr
hostNetwork: true
containers:
- image: gcr.io/nginx-demos/nap-ingress:edge
imagePullPolicy: Always
name: nginx-plus-ingress
ports:
- name: http
containerPort: 80
hostPort: 80
- name: https
containerPort: 443
hostPort: 443
- name: readiness-port
containerPort: 8081
#- name: prometheus
#containerPort: 9113
readinessProbe:
httpGet:
path: /nginx-ready
port: readiness-port
periodSeconds: 1
securityContext:
allowPrivilegeEscalation: true
runAsUser: 101 #nginx
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
args:
- -nginx-plus
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secretHinweise:
- Diese Konfiguration ist für NGINX Plus vorgesehen. Verweise auf
nginx‑pluswurden in der Konfiguration für NGINX Open Source entsprechend angepasst. - NGINX App Protect ist im Image enthalten (
gcr.io/nginx-demos/nap-ingress:edge), wurde jedoch deaktiviert (das Flag-enable-app-protectwurde weggelassen).
ConfigMap
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-config
namespace: nginx-ingress
data:
worker-connections: "10000"
worker-rlimit-nofile: "10240"
keepalive: "100"
keepalive-requests: "100000000"Konfiguration für den Community-NGINX-Ingress-Controller
Kubernetes-Konfiguration
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
helm.sh/chart: ingress-nginx-2.11.1
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 0.34.1
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
spec:
nodeSelector:
kubernetes.io/hostname: gke-rawdata-cluster-default-pool-3ac53622-6nzr
hostNetwork: true
containers:
- name: controller
image: us.gcr.io/k8s-artifacts-prod/ingress-nginx/controller:v0.34.1@sha256:0e072dddd1f7f8fc8909a2ca6f65e76c5f0d2fcfb8be47935ae3457e8bbceb20
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
args:
- /nginx-ingress-controller
- --election-id=ingress-controller-leader
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
runAsUser: 101
allowPrivilegeEscalation: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
readinessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
periodSeconds: 1
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
- name: webhook
containerPort: 8443
protocol: TCP
volumeMounts:
- name: webhook-cert
mountPath: /usr/local/certificates/
readOnly: true
serviceAccountName: ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admissionConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
max-worker-connections: "10000"
max-worker-open-files: "10204"
upstream-keepalive-connections: "100"
keep-alive-requests: "100000000"Konfiguration für die Back-End-App
Kubernetes-Konfiguration
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
nodeSelector:
kubernetes.io/hostname: gke-rawdata-cluster-default-pool-3ac53622-t2dz
containers:
- name: nginx
image: nginx
ports:
- containerPort: 8080
volumeMounts:
- name: main-config-volume
mountPath: /etc/nginx
- name: app-config-volume
mountPath: /etc/nginx/conf.d
readinessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 3
volumes:
- name: main-config-volume
configMap:
name: main-conf
- name: app-config-volume
configMap:
name: app-conf
---ConfigMaps
apiVersion: v1
kind: ConfigMap
metadata:
name: main-conf
namespace: default
data:
nginx.conf: |+
user nginx;
worker_processes 16;
worker_rlimit_nofile 102400;
worker_cpu_affinity auto 1111111111111111;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 100000;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
sendfile on;
tcp_nodelay on;
access_log off;
include /etc/nginx/conf.d/*.conf;
}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-conf
namespace: default
data:
app.conf: "server {listen 8080;location / {default_type text/plain;expires -1;return 200 'Server address: $server_addr:$server_portnServer name:$hostnamenDate: $time_localnURI: $request_urinRequest ID: $request_idn';}location /healthz {return 200 'I am happy and healthy :)';}}"
---Dienst
apiVersion: v1
kind: Service
metadata:
name: app-svc
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: nginx
---Über den Autor

Ähnliche Blogbeiträge
Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.
Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.
Ankündigung von NGINX Plus R16
NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.
5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.