Dieser Blog ist der zweite in einer Reihe von Blogs, die verschiedene Aspekte dessen behandeln, was für den Aufbau und Betrieb unseres SaaS- Dienstes erforderlich war:
In einem früheren Blog haben wir einige Hintergrundinformationen zu unseren Anforderungen bereitgestellt, die uns zum Aufbau einer neuen Plattform veranlasst haben. Mithilfe dieser Plattform ermöglichen wir unseren Kunden den Aufbau eines komplexen und vielfältigen Anwendungsspektrums – etwa in den Bereichen intelligente Fertigung, Videoforensik für die öffentliche Sicherheit, algorithmischer Handel und 5G-Telekommunikationsnetze.
Der erste Blog dieser Reihe behandelte eine verteilte Steuerungsebene zur Bereitstellung mehrerer mandantenfähiger, auf Kubernetes basierender Anwendungscluster in der öffentlichen Cloud, unseren privaten Netzwerk-PoPs und Edge-Sites.
In diesem speziellen Blog werden die Herausforderungen der Verbindung und Sicherung dieser verteilten Anwendungscluster aus drei Blickwinkeln behandelt: Anwendung zu Anwendung, Benutzer/Maschine zu Anwendung und Anwendung zum öffentlichen Internet. Wir werden einen brandneuen und vollständig integrierten L3-L7+-Datenpfad, eine global verteilte Steuerebene und unser leistungsstarkes globales Netzwerk vorstellen. Die Kombination dieser drei Dinge ergibt ein umfassendes Set an Netzwerk- und Sicherheitsdiensten im Edge, innerhalb jedes Cloud-VPC oder in unseren globalen Netzwerk-PoPs. Nachdem wir die Lösung über ein Jahr lang in der Produktion bei mehr als 35 Kunden eingesetzt haben, haben wir mit der Skalierung der Bereitstellung begonnen und sind der Meinung, dass jetzt ein guter Zeitpunkt ist, unsere Erfahrungen mitzuteilen.
Da unsere Kunden relativ komplexe und unternehmenskritische Anwendungen entwickeln – etwa intelligente Fertigung, Videoforensik für die öffentliche Sicherheit, algorithmischen Handel oder die 5G-Umstellung im Telekommunikationsbereich – müssen wir für die Anwendungen und ihre Endbenutzer eine stets verfügbare, vernetzte und zuverlässige Benutzererfahrung gewährleisten. Einige dieser Anwendungen führen Datenpipelines über Cluster innerhalb einer Cloud aus, müssen Daten bei verschiedenen Cloud-Anbietern sichern, benötigen eine zuverlässige Übermittlung von Anfragen einer globalen Benutzerbasis an App-Backends oder benötigen eine Hochleistungsverbindung von ihren Maschinen zu den in zentralisierten Clouds ausgeführten Backends.
Um diesen Bedarf zu decken, gab es zwei Anforderungen an das physische Netzwerk:
R1 – Cloud to Cloud – Hohe Leistung und On-Demand-Konnektivität von Anwendungen über öffentliche oder private Cloud-Standorte auf der ganzen Welt
R2 – Vom Internet zur Cloud – Damit Geräte und Maschinen an Randstandorten eine zuverlässige Verbindung zum Anwendungs-Backend herstellen können, mussten wir mehrere redundante Pfade bereitstellen und die Verbindungen so nah wie möglich an diesen Benutzern beenden, anstatt den Datenverkehr über das Internet bis zu den Backends zurückzuleiten.
Wir hätten die Anforderungen R1 und R2 erfüllen können, indem wir uns an einen Netzwerkdienstanbieter wie AT&T gewandt hätten. Dieser hätte uns jedoch kein nahtloses Netzwerkerlebnis und keine Integration mit unseren Anwendungsdiensten bieten können (API-basierte Konfiguration, Streaming-Telemetrie, Möglichkeit zum einfachen Hinzufügen unserer eigenen oder der IP-Präfixe unserer Kunden, API-basierte Netzwerkdienste usw.). Darüber hinaus ist es sehr schwierig oder unerschwinglich, von Dienstanbietern eine weltweite Abdeckung zu erhalten. Wir hätten zur Lösung all dieser Probleme auf zwei oder drei verschiedene Dienstanbieter zurückgreifen können, doch dann hätten wir am Ende ein Durcheinander aus unterschiedlichen Systemen gehabt, die sich unterschiedlich verhalten, unterschiedliche Fehlermodi, unterschiedliche SLAs und Supportsysteme aufweisen und über unterschiedliche (oder keine) APIs verfügen.
Letztendlich mussten wir also unser eigenes Netzwerk aufbauen. Das bedeutete, dass das Netzwerk drei Eigenschaften haben musste:
Um diese drei Eigenschaften zu erfüllen, mussten wir viele Dinge tun. Wir möchten jedoch fünf wichtige Punkte hervorheben:
Uns wurde schon sehr früh in unserer Entwicklung klar, dass der Aufbau und Betrieb eines globalen Netzwerks Zeit und Fähigkeiten erfordert und dass wir dieses Fachwissen einbringen mussten. Nach monatelangen Diskussionen mit den Gründern von Acorus Networks (Sicherheitsanbieter mit Sitz in Paris, Frankreich) haben wir Acorus schließlich mit Volterra fusioniert. Dies hat uns geholfen, das Problem unserer globalen Infrastruktur und des Netzwerkausbaus zu lösen. Acorus hatte ein großartiges Netzwerk und ein Betriebsteam aufgebaut, das die physische Netzwerkkonfiguration mit Ansible vollständig automatisiert hatte und externe APIs für Telemetrie und Konfiguration erstellte, die von unserem Softwareteam verwendet werden konnten.
Da wir nun ein Team hatten, das sich auf den Aufbau eines globalen privaten Netzwerks mit hoher Zuverlässigkeit und Leistung konzentrierte, konnten wir die Probleme sowohl des Datenverkehrs zwischen Anwendungen als auch des Datenverkehrs zwischen Benutzern/Maschinen über Edge- oder Cloud-Standorte hinweg problemlos lösen, wie in Abbildung 1 dargestellt. Darüber hinaus konnten wir mithilfe der Rechen- und Speicherinfrastruktur in unseren Netzwerk-PoPs unserem Netzwerk auch API-Terminierung, App-Sicherheit und Workload-Offload (von Edge oder Cloud) hinzufügen. Dadurch sind wir in der Lage, unsere Fähigkeiten auch in den kommenden Jahren weiterzuentwickeln und unsere Netzwerkpräsenz und unseren Servicekatalog je nach Bedarf problemlos zu erweitern.
Nachdem wir über ein funktionierendes globales Netzwerk verfügten, mussten wir damit beginnen, Anwendungscluster und unsere Workloads hinzuzufügen. Diese Workloads benötigen ihren eigenen Satz an Konnektivitäts- und Sicherheitsdiensten auf Anwendungsebene.
Wie wir in unserem früheren Blog erklärt haben, bestand unser Ziel mit der Plattform darin, die Produktivität zu verbessern und die Komplexität für unsere Teams zu reduzieren, die Workloads verwalten, die in mehreren Umgebungen (Cloud, Edge und unsere Netzwerk-PoPs) ausgeführt werden.
Jeder Cloud-Anbieter muss für eine sichere Verbindung zu Anwendungsclustern viele verschiedene Cloud-Ressourcen konfigurieren, verwalten und überwachen. Um beispielsweise in Google Cloud einen End-to-End-Netzwerkdienst für einen Anwendungscluster zu konfigurieren, müssen wir viele verschiedene Dienstsätze verwalten:
Großartig, denn auch wenn dies eine große Herausforderung wäre, hätten wir uns dazu entschließen können, dies durch den Aufbau einer Konfigurations- und Betriebsebene anzugehen, um eine Harmonisierung zwischen allen Cloud-Anbietern sicherzustellen. Wir wussten jedoch, dass unsere Probleme dadurch nicht gelöst worden wären, da die Dienste der Cloud-Anbieter nicht alle unsere Anforderungen erfüllten (z. B. fehlt bei CSPs die Fähigkeit zur Anwendungs- und API-Sicherheit), nicht die besten ihrer Art sind und sich ständig ändern.
Und was ist mit unseren Netzwerk-PoPs und Edge-Sites? Wir müssten uns ähnliche Funktionen von Hardware- oder Softwareanbietern besorgen und sie alle miteinander integrieren – z. B. Cisco/Juniper für Routing+NAT+VPN, F5 für Lastausgleich und Firewall usw. An den Randstandorten wird das Problem noch verschärft, da weder die Cloud-Anbieter noch die großen Netzwerkanbieter die Probleme der Netzwerkdienste für eine Umgebung mit eingeschränkten Ressourcen lösen konnten. Eine weitere mögliche Option für den Edge hätte darin bestehen können, die gesamte Anwendungskonnektivität, Sicherheit und Netzwerkdienste in unser globales Netzwerk zu verschieben. Es war jedoch klar, dass dies nicht funktionieren würde, da der App-zu-App-Verkehr innerhalb derselben Edge-Site einige dieser Dienste ebenfalls benötigte.
Nach zahlreichen Diskussionen und einer Bestandsaufnahme stellten wir fest, dass die Integration über viele Dienstanbieter und Lieferanten hinweg – Konfiguration, Telemetrie, Überwachung, Warnmeldungen – und das Aufrechterhalten ihrer Roadmap- und API-Änderungen unserem Ziel der Einfachheit und Geschwindigkeit zuwiderlief.
Ein weiteres Problem, das wir plattformübergreifend lösen mussten, war die Mandantenfähigkeit. Dies war bei WAN-Diensten und Netzwerkrouting einfacher umzusetzen, stellte jedoch bei Anwendungsnetzwerkdiensten eine Herausforderung dar, da die meisten Load Balancer auf dem Markt keine oder nur eine sehr eingeschränkte Unterstützung für Mandantenfähigkeit bieten.
Aus diesem Grund haben wir uns entschlossen, diese Herausforderung anzunehmen und einen Hochleistungsnetzwerkdatenpfad aufzubauen, der nicht nur Netzwerkroutingdienste, sondern auch Anwendungs-, Sicherheits- und Weitverkehrsdienste bereitstellt. Dadurch könnten wir das Serviceportfolio in unserer hybriden und verteilten Cloudumgebung vereinheitlichen und wären auf ein Minimum an nativen Services in öffentlichen Clouds angewiesen.
Da das Team über umfangreiche Netzwerkerfahrung verfügte und wir in unserem früheren Leben mit Contrail/Juniper bereits mit derartigen Problemen zu tun hatten, dachten wir, der beste Weg zur Lösung dieses Problems wäre, ganz von vorne anzufangen und eine brandneue Netzwerklösung zu entwickeln, die Dienste von L3 bis L7+ in einem einzigen Datenpfad integriert, der in jeder Cloud oder an jedem Rand ausgeführt werden kann und gleichzeitig zentral von unserer Plattform verwaltet wird.
Wir haben die besten Projekte ausgewählt, um mit der Entwicklung dieses neuen Datenpfads zu beginnen: OpenContrail vRouter (für L3-L4), für dessen Entwicklung wir bereits sechs Jahre gebraucht hatten, und Envoy für L7, da es über enorme Unterstützung aus der Community verfügt. Allerdings mussten wir mehrere Änderungen und Ergänzungen vornehmen, um einen neuen einheitlichen L3-L7+-Datenpfad zu erstellen – Multi-Tenancy für Envoy, dpdk für Envoy, dpdk-TCP-Stack im Benutzerbereich, Netzwerkrichtlinie, SSL/IPSec-VPNs, HTTP-Verbindung, dynamischer Reverse-Proxy, transparenter Forward-Proxy, API-Gateway, programmierbare Anwendungsrichtlinie, schnelle ACLs für DDoS-Schutz, PKI-Identitätsintegration, Chrome v8-Engine, Anwendungs- und Netzwerksicherheit usw.
Dieser Datenpfad (siehe Abbildung 2 ) wird als Eingangs-/Ausgangs-Gateway für unsere Anwendungscluster, als Software-Gateway im Edge-Bereich, zur Bereitstellung von Service-Mesh-Funktionen innerhalb eines Clusters oder über mehrere Cluster hinweg oder zur Bereitstellung von Netzwerkdiensten von unseren globalen PoPs eingesetzt.
Um unserem Bedarf an Multi-Tenancy für die Plattform gerecht zu werden (wie im vorherigen Blog beschrieben), mussten wir auch für diesen Netzwerkdatenpfad vollständige Multi-Tenancy bereitstellen. Für die Routing-Ebene war dies relativ unkompliziert, da der vRouter bereits VRFs unterstützte. Wir mussten jedoch Änderungen in Envoy vornehmen, um es für mehrere Mandanten nutzbar zu machen. Da wir den TCP-Stack des Kernels nicht verwendeten, haben wir die TCP-Socket-Schnittstelle von Envoy geändert und VRF-Erkennung hinzugefügt.
Dieser Datenpfad musste auch API-Sicherheit, Anwendungs-Firewalls und Netzwerksicherheit gewährleisten – wir verwendeten hierfür eine Kombination aus algorithmischen Techniken und maschineller Inferenz und werden dieses Thema in einem kommenden Blogbeitrag behandeln.
Durch den Aufbau dieses Netzwerkdatenpfads haben wir viele Vorteile erzielt:
Umfassende L3-L7+-Funktionen mit einheitlicher Konfiguration, Steuerung und Beobachtbarkeit
Durch die Unterstützung von Scale-Out innerhalb eines einzelnen Clusters können wir eine Bandbreite von sehr kleinem Platzbedarf und Edge-Geräten mit geringerer Leistung bis hin zu einer Kapazität von über 100 Gbit/s oder mehr in unserem Netzwerk oder an öffentlichen Cloud-Standorten unterstützen.
Fügen Sie dem Netzwerkdatenpfad schnell neue Funktionen hinzu, ohne von einem Netzwerkanbieter und/oder Cloud-Anbieter abhängig zu sein.
Gemeinsame Lösung mit ähnlichen Fehler- und Leistungsmerkmalen in allen Umgebungen – sehr wichtig für unsere Betriebsteams.
Nachdem wir nun mit diesem neuen Netzwerkdatenpfad mehrere App-Cluster bereitstellen konnten, war es von entscheidender Bedeutung, eine global verteilte Steuerungsebene für die Konfiguration, Steuerung und Überwachung dieser Cluster aufzubauen.
Beim Aufbau einer verteilten Steuerungsebene zur Verwaltung einer großen Anzahl verteilter Datenpfadverarbeitungsknoten musste unser Plattformteam zahlreiche Probleme bewältigen. Da wir einen neuen Datenpfad erstellt haben, gab es keine sofort einsatzbereite Steuerebene, die genutzt werden konnte, und wir mussten unsere eigene schreiben: Lokale Steuerebene zur Verwaltung mehrerer Datenpfade, die innerhalb eines einzelnen Clusters (Cloud, Edge oder Netzwerk-PoP) ausgeführt werden. Diese Datenpfadknoten benötigten eine lokale Steuerebene, um Konfigurationsänderungen zu verwalten, Routenaktualisierungen durchzuführen, Integritätsprüfungen durchzuführen, die Diensterkennung durchzuführen, über ein Protokoll wie BGP eine Peering-Verbindung mit anderen Netzwerkgeräten herzustellen, Metriken und Zugriffsprotokolle zu aggregieren usw. Verteilte Steuerebene zum Verwalten mehrerer lokaler Steuerebenen – In unseren globalen Netzwerk-PoPs wird eine verteilte Steuerebene ausgeführt ( Abbildung 3 ). Diese Steuerebene ist für das Konfigurationsmanagement der lokalen Steuerebenen, die Verteilung des Betriebszustands auf jede der lokalen Steuerebenen und die Datenerfassung von jedem der Knoten verantwortlich. Zur Verteilung des Betriebszustands haben wir uns für die Verwendung von BGP entschieden, da es letztendlich konsistent und robust ist. Da wir im Rahmen von OpenContrail eine sehr groß angelegte und mehrfädige Implementierung von BGP erstellt hatten, nutzten wir diese und fügten Erweiterungen für den Lastenausgleich hinzu – Verteilung von Integritätsprüfungen, HTTP/API-Endpunkte, Richtlinienverbreitung usw.
Darüber hinaus gibt es eine zentralisierte Verwaltungsebene, die in zwei Cloud-Regionen – AWS und Azure – ausgeführt wird und zusammen mit der verteilten Steuerungsebene verwendet wird, um Multi-Tenancy zu ermöglichen (siehe Abbildung 4) . Unser SRE-Team kann mehrere Mandanten erstellen und jeder Mandant ist in unserem globalen Netzwerk vollständig von anderen Mandanten isoliert. Sie können nur über das „öffentliche Netzwerk“ miteinander routen. Innerhalb eines Mandanten können Dienste über Namespaces hinweg basierend auf HTTP-/API-/Netzwerkrouting- und Sicherheitsregeln miteinander kommunizieren.
Die Steuerebenen werden als Kubernetes-Workloads in einem separaten Mandanten und einem isolierten Namespace ausgeführt, der ausschließlich von unseren SRE-Teams kontrolliert wird. Daher kann kein Entwickler und/oder Kunde diesen Dienst stören. Da die Steuerebene verteilt ist, wirkt sich der Ausfall einer Steuerebene an einem Standort außerdem nicht auf den Gesamtdienst aus.
Nachdem wir die Anforderungen für unser globales Netzwerk ermittelt und die Anforderungen an L3-L7+-Netzwerkdienste für App-Cluster (einen neuen Datenpfad und eine verteilte Steuerungsebene) definiert hatten, entwickelte unser Produktteam weitere Anforderungen, die unser Leben noch spannender machten. Im Wesentlichen wollten sie von uns die Bereitstellung eines globalen, clusterübergreifenden Service-Mesh mit den folgenden Funktionen:
Bei Anforderung Nr. 2 und Nr. 3 bestand das Ziel darin, die Reaktionszeit und Leistung der Client-Server-Konnektivität zu verbessern, was bei der Kommunikation zwischen Anwendungen oder bei groß angelegten SaaS-Anwendungen von entscheidender Bedeutung ist. Um die Anforderungen 2 und 3 zu erfüllen, war es klar, dass der beste Ansatz darin bestand, einen verteilten Proxy zu erstellen (Abbildung 5) – einen Ingress-Proxy und einen Egress-Proxy sowie ein Routing basierend auf der Anwendungsadressierung und nicht auf der Netzwerkadressierung. Darüber hinaus haben wir uns entschieden, die Integrität der Bereitstellungsendpunkte (oder Server) durch Nutzung der verteilten Steuerungsebene und BGP-Erweiterungen zu verteilen (wie zuvor beschrieben). Diese Implementierung des verteilten Proxys wird im folgenden Diagramm dargestellt.
Da es sich um einen verteilten Proxy mit einem vollständigen L3-L7+-Netzwerkstapel handelt, bezeichnen wir dies als global verteiltes Anwendungsgateway. Alle in unserem Netzwerkdatenpfad verfügbaren Funktionen sind jetzt in unserem gesamten globalen Netzwerk verfügbar – beispielsweise Lastausgleich und Routing basierend auf HTTP oder APIs, Richtliniendurchsetzung am Rand, API-Transformation, TLS-Terminierung näher am Benutzer usw.
Durch die Implementierung eines global verteilten Anwendungsgateways konnte das Team zahlreiche Vorteile erzielen. Diese Zugewinne betrafen die Bereiche Betriebsverbesserungen, Sicherheit, Leistung und Gesamtbetriebskosten:
In dieser Blogserie werden verschiedene Aspekte dessen behandelt, was für den Aufbau und Betrieb unseres weltweit verteilten SaaS-Dienstes mit vielen Anwendungsclustern in der öffentlichen Cloud, unseren privaten Netzwerk-PoPs und Edge-Sites erforderlich war. Als nächstes kommt die Plattform- und Datensicherheit …