Für den Clumio Protect Backup Service nutzen wir den Amazon Elastic Kubernetes Service (EKS) zur Verwaltung unserer Kubernetes-Cluster. Der Hauptvorteil der Nutzung eines verwalteten Kubernetes-Dienstes besteht darin, dass Sie eine enge Integration mit anderen Diensten Ihres Cloud-Anbieters erhalten. Konkret bedeutet dies: Wenn Sie einen neuen Kubernetes-Dienst erstellen, richtet ein von AWS bereitgestellter und im Cluster installierter Service-Controller eine neue Instanz des Elastic Load Balancer (ELB) ein und konfiguriert diese so, dass der Datenverkehr an den Dienst weitergeleitet wird. Gleichzeitig verwaltet dieser Controller den gesamten Lebenszyklus des entsprechenden Load Balancers: Er sorgt für eine korrekte Konfiguration der Zustandsprüfungen und hält die Zielgruppe des Load Balancers auf dem neuesten Stand, wenn Sie Knoten zum Cluster hinzufügen oder daraus entfernen. Schließlich löscht er den Load Balancer, wenn Sie Ihren Kubernetes-Dienst aus dem Cluster entfernen.
Die Nutzung von Kubernetes-Diensten, die auf AWS-Load-Balancern basieren, ist zwar sehr praktisch, doch gibt es dabei einige Aspekte zu beachten.
Die Cloud-native Architektur von Clumio
Unsere Architektur basiert auf Microservices, und jeder unserer Kubernetes-Cluster umfasst mehrere Dutzend dieser Dienste. Die Anzahl der Dienste fällt besonders bei unseren Entwicklungsclustern ins Auge, in denen wir so viele isolierte Entwicklungsumgebungen wie möglich in einem einzigen Cluster hosten. In einigen Entwicklungsclustern haben wir mehr als 300 Dienste, Tendenz steigend. Es versteht sich von selbst, dass jeder AWS-Load-Balancer kostenpflichtig ist und es für uns unzumutbar wäre, mehr als 300 AWS-Load-Balancer nur für einen einzigen Entwicklungscluster zu betreiben. Ein weiteres Problem ist die Begrenzung der Anzahl der Load-Balancer, die jeder EKS-Cluster unterstützen kann. Diese Begrenzung hängt mit der maximalen Anzahl der Regeln in der EC2-Sicherheitsgruppe zusammen. Konkret könnte unser durchschnittlicher EKS-Cluster nicht mehr als 60 klassische Load-Balancer haben. Um dieses Problem zu lösen, haben wir uns entschieden, für die meisten unserer Dienste Kubernetes Ingress zu nutzen. Der Ingress-Mechanismus ermöglicht es uns, einen ELB für mehrere Dienste in einem EKS-Cluster gemeinsam zu nutzen, was den Ressourcenverbrauch und die Kosten senkt.
Warum Kubernetes Ingress hinzufügen?
Die Einrichtung eines neuen AWS-Load-Balancers nimmt in der Regel einige Zeit in Anspruch. Diese Verzögerung ist für die meisten Vorgänge akzeptabel, doch bei bestimmten Änderungen – beispielsweise beim gleichzeitigen Bereitstellen mehrerer Microservices – wollten wir die Zeit bis zur Readiness so kurz wie möglich halten. Um diesen Anwendungsfall abzudecken, sorgt das Hinzufügen eines neuen Kubernetes-Ingresses für sofortige Readiness. Je nach konkreter Implementierung muss ein Ingress-Controller die neue Konfiguration neu laden – ähnlich wie bei Nginx-Ingress-Controllern – oder die neue Konfiguration zur Laufzeit anwenden – ähnlich wie bei Envoy-basierten Ingress-Controllern.
Bei der Arbeit mit Diensten geht man davon aus, dass jeder Dienst über einen DNS-Namen verfügt, möglicherweise sogar über einen externen. Beim Ansatz „ein ELB pro Dienst“ kann ein DNS-Name erst nach der Erstellung des ELB angelegt werden. Mit einem einzigen, vorab zugewiesenen ELB für den Ingress-Controller ist es möglich, diesem ELB im Voraus beliebig viele DNS-Aliase zuzuweisen, sodass alle unsere Dienste verfügbar sind, sobald wir Ingress-Definitionen für sie erstellen.
Einige unserer Dienste stellen eine REST-API bereit, doch die überwiegende Mehrheit unserer Dienste verfügt über gRPC-Endpunkte. Wir benötigten einen Ingress-Controller, der sowohl HTTPS als auch gRPC gleichzeitig unterstützt, und wir wollten TLS auf dem Ingress-Controller terminieren. Letzteres war keine zwingende Anforderung, und wir haben erwogen, Istio-Sidecars zu verwenden, um TLS direkt in einem Microservice-Pod zu beenden. Wir haben uns jedoch dafür entschieden, TLS über den Ingress-Controller zu beenden, da dies einfacher zu verwalten ist und im Allgemeinen weniger Overhead für den Cluster verursacht. Eine weitere Anforderung war, dass wir mehrere Instanzen des Ingress-Controllers im selben Cluster bereitstellen können. Eine bestimmte Ingress-Definition kann eine Annotation enthalten kubernetes.io/ingress.class , um anzugeben, welcher Ingress-Controller verwendet werden soll.
Wir haben mehrere Ingress-Controller getestet und festgestellt, dass es überraschend schwierig war, einen zu finden, der alle Anforderungen erfüllt. Einige Controller funktionierten nicht korrekt mit gRPC, andere unterstützten keine mehreren Controller-Instanzen im selben Cluster. Schließlich haben wir festgestellt, dass der NGINX-Ingress-Controller für uns geeignet ist. Wir mussten lediglich eine kleine Anpassung an der Konfiguration vornehmen, um die gRPC-Puffergröße zu erhöhen, damit er mit unserem gRPC-Stack funktioniert.
Wir verbessern kontinuierlich unsere Dienste auf Infrastrukturebene, um unsere Infrastruktur zu skalieren und die Wartungskosten zu optimieren. Anfangs nutzten wir für jeden Dienst einen eigenen Load Balancer, stießen jedoch sehr schnell an die Obergrenze der zulässigen Anzahl von Load Balancern pro Cluster. Zu diesem Zeitpunkt haben wir unsere Infrastruktur so angepasst, dass wir für die externe Anbindung unserer Dienste gehostete Ingress-Controller einsetzen, wodurch wir die Anzahl der für das Produkt benötigten klassischen AWS-Load-Balancer deutlich reduzieren konnten. Der Einsatz des AWS Application Load Balancer (ALB) kam zu diesem Zeitpunkt nicht in Frage, da der ALB gRPC nicht unterstützte. Ende 2020 gab AWS bekannt, dass der Application Load Balancer nun End-to-End-HTTP/2 und gRPC unterstützt. Nun können wir den AWS Load Balancer Controller nutzen, der früher als „AWS ALB Ingress Controller“ bekannt war und an die Kubernetes AWS Special Interest Group (SIG-AWS) gespendet wurde, damit AWS und andere SIG-AWS-Mitwirkende das Projekt offiziell weiterführen können. Wir freuen uns darauf, diesen Ingress-Controller für unsere Infrastruktur einzusetzen. Ein weiterer Schwerpunkt unseres Interesses ist die Kubernetes Gateway API, eine neue Kubernetes-API, die derzeit von der Network Special Interest Group (SIG-Network) entwickelt wird. Im Vergleich zur Ingress-API stellt die Gateway-API eine allgemeinere API für das Proxying bereit, die nicht nur für HTTP, sondern auch für weitere Protokolle genutzt werden kann, und modelliert mehr Infrastrukturkomponenten, um Cluster-Betreibern bessere Bereitstellungs- und Verwaltungsoptionen zu bieten. Wir freuen uns darauf, zukünftige Kubernetes-Controller auszuprobieren, die die Gateway-API implementieren.
Senkung des Ressourcenverbrauchs und der Kosten
Der Kubernetes-Ingress-Mechanismus hilft uns, den Ressourcenverbrauch und die Kosten zu senken. Wir sind nicht mehr durch die EC2- und EKS-Beschränkungen hinsichtlich der Anzahl der Dienste eingeschränkt, die in einem einzelnen verwalteten Kubernetes-Cluster bereitgestellt werden können. Einige der Open-Source-Ingress-Controller funktionieren von Haus aus mit gRPC-Diensten, erfordern jedoch eine zusätzliche Prüfung, ob sie für einen bestimmten Anwendungsfall geeignet sind. Die Kubernetes-Community stellt Kubernetes-APIs wie die Ingress-API oder die Gateway-API bereit und verbessert diese kontinuierlich, während kommerzielle und Open-Source-Anbieter verschiedene Implementierungen solcher APIs anbieten. Dies ermöglicht es, die richtige Implementierung für einen bestimmten Anwendungsfall auszuwählen und Implementierungen zu ersetzen, ohne größere Änderungen auf Anwendungsebene vornehmen zu müssen.