Ein paar Worte darüber, was wir tun. DINS ist an der Entwicklung und Unterstützung von UCaaS-Diensten auf dem internationalen Markt für Firmenkunden beteiligt. Der Service wird sowohl von kleinen Unternehmen als auch von Start-ups und großen Unternehmen genutzt. Clients stellen über das Internet eine Verbindung über das SIP-Protokoll über TCP, TLS oder WSS her. Dies führt zu einer ziemlich großen Last: Fast 1,5 Millionen Verbindungen von Endgeräten - Polycom / Cisco / Yealink-Telefone und Soft-Clients für PC / Mac / IOS / Android.
In diesem Artikel spreche ich darüber, wie VoIP-Einstiegspunkte angeordnet sind.
Hintergrund
Am Umfang des Systems (zwischen den Endgeräten und dem Kernel) befinden sich kommerzielle SBC (Session Border Controller).
Seit 2012 verwenden wir Lösungen von Acme Packet, die später von Oracle übernommen wurden. Vorher haben wir NatPASS verwendet.
Listen Sie kurz die Funktionen auf, die wir verwenden:
• NAT-Durchquerung;
• B2BUA;
• SIP-Normalisierung (zulässige / nicht zulässige Header, Regeln zur Manipulation von Headern usw.)
• TLS- und SRTP-Offload;
• Konvertierung des Transports (innerhalb des Systems verwenden wir SIP über UDP);
• MOS-Überwachung (über RTCP-XR);
• ACLs, Bruteforce-Erkennung;
• Reduzierter Registrierungsverkehr aufgrund eines erhöhten Kontaktablaufs (geringer Ablauf auf der Zugriffsseite, hoher Ablauf auf der Kernseite);
• Drosselung der SIP-Nachrichten pro Methode.
Kommerzielle Systeme haben ihre offensichtlichen Vor- und Nachteile (sofort einsatzbereite Funktionalität, kommerzieller Support) und Nachteile (Preis, Lieferzeit, mangelnde Möglichkeiten oder zu lange Fristen für die Implementierung neuer Funktionen, Fristen für die Lösung von Problemen usw.). Allmählich überwogen die Mängel, und es wurde klar, dass die Notwendigkeit reif war, eigene Lösungen zu entwickeln.
Die Entwicklung wurde vor anderthalb Jahren gestartet. Im Grenzsubsystem haben wir traditionell zwei Hauptkomponenten unterschieden: SIP- und Medienserver; Load Balancer über jeder Komponente. Ich arbeite hier an Einstiegspunkten / Balancern, also werde ich versuchen, darüber zu sprechen.
Anforderungen
- Fehlertoleranz: Das System sollte einen Service bereitstellen, wenn eine oder mehrere Instanzen im Rechenzentrum oder im gesamten Rechenzentrum ausfallen
- Wartungsfreundlichkeit: Wir möchten Lasten von einem Rechenzentrum in ein anderes umschalten können
- Skalierbarkeit: Ich möchte die Kapazität schnell und kostengünstig erhöhen
Ausbalancieren
Wir haben IPVS (auch bekannt als LVS) im IPIP-Modus (Traffic Tunneling) ausgewählt. Ich werde nicht auf eine vergleichende Analyse von NAT / DR / TUN / L3DSR eingehen (Sie können zum Beispiel hier über die Modi lesen), ich werde nur die Gründe erwähnen:
- Wir möchten Backends nicht die Anforderung auferlegen, dass sie sich im selben Subnetz wie LVS befinden müssen (Pools enthalten Backends sowohl von unseren eigenen als auch von Remote-Rechenzentren).
- Das Backend muss die ursprüngliche Quell-IP des Clients (oder dessen NAT) erhalten. Mit anderen Worten, Quell-NAT ist nicht geeignet.
- Das Backend muss die gleichzeitige Arbeit mit mehreren VIPs unterstützen.
Wir gleichen den Medienverkehr aus (es stellte sich als sehr schwierig heraus, wir werden ihn ablehnen), daher lautet das aktuelle Bereitstellungsschema im Rechenzentrum wie folgt:

Die derzeitige IPVS-Ausgleichsstrategie lautet „sed“ (Shortest Expected Delay), mehr dazu. Im Gegensatz zu Weighted Round Robin / Weighted Least-Connection können Sie den Datenverkehr erst dann an Backends mit geringerer Gewichtung übertragen, wenn ein bestimmter Schwellenwert erreicht ist. Die kürzeste erwartete Verzögerung wird nach der Formel (Ci + 1) / Ui berechnet, wobei Ci die Anzahl der Verbindungen im Backend i und Ui das Gewicht des Backends ist. Wenn sich beispielsweise Backends im Pool mit Gewichten von 50.000 und 2 befinden, werden neue Verbindungen von den ersten verteilt, bis jeder Server 25.000 Verbindungen erreicht oder bis der Schwellenwert erreicht ist - eine Begrenzung der Gesamtzahl der Verbindungen.
Lesen Sie mehr über Ausgleichsstrategien in man ipvsadm .
Der IPVS-Pool sieht folgendermaßen aus (hier und unten werden fiktive IP-Adressen aufgelistet):
# ipvsadm -ln Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 1.1.1.1:5060 sed -> 10.11.100.181:5060 Tunnel 50000 5903 4 -> 10.11.100.192:5060 Tunnel 50000 5905 1 -> 10.12.100.137:5060 Tunnel 2 0 0 -> 10.12.100.144:5060 Tunnel 2 0 0
Die Last auf dem VIP wird auf Server mit einem Gewicht von 50.000 verteilt (sie werden im selben Rechenzentrum wie eine bestimmte LVS-Instanz bereitgestellt). Wenn sie überlastet sind oder in eine schwarze Liste aufgenommen werden, wird die Last an den Sicherungsteil des Pools gesendet - Server mit einem Gewicht von 2, die sich in befinden benachbartes Rechenzentrum.
Genau der gleiche Pool, jedoch mit Skalen, wird im benachbarten Rechenzentrum konfiguriert (im Produktionssystem ist die Anzahl der Backends natürlich viel größer).
Durch die Synchronisierung von Verbindungen über die IPvs-Synchronisierung kann das Backup-LVS alle aktuellen Verbindungen ermitteln.
Für die Synchronisation zwischen Rechenzentren wurde eine "schmutzige" Technik angewendet, die dennoch gut funktioniert. Die IPVS-Synchronisation funktioniert nur über Multicast, was für uns schwierig war, korrekt an den benachbarten DC zu liefern. Anstelle von Multicast duplizieren wir den Synchronisationsverkehr über das iptables-Ziel-TEE vom IPvs-Master zum IP-IP-Tunnel zum Server im benachbarten DC. Möglicherweise gibt es mehrere Zielhosts / Rechenzentren:
#### start ipvs sync master role: ipvsadm --start-daemon master --syncid 10 --sync-maxlen 1460 --mcast-interface sync01 --mcast-group 224.0.0.81 --mcast-port 8848 --mcast-ttl 1 #### duplicate all sync packets to remote LVS servers using iptables TEE target: iptables -t mangle -A POSTROUTING -d 224.0.0.81/32 -o sync01 -j TEE --gateway 172.20.21.10 # ip-ip remote lvs server 1 iptables -t mangle -A POSTROUTING -d 224.0.0.81/32 -o sync01 -j TEE --gateway 172.20.21.14 # ip-ip remote lvs server 2 #### start ipvs sync backup role: ipvsadm --start-daemon backup --syncid 10 --sync-maxlen 1460 --mcast-interface sync01 --mcast-group 224.0.0.81 --mcast-port 8848 --mcast-ttl 1 #### be ready to receive sync sync packets from remote LVS servers: iptables -t mangle -A PREROUTING -d 224.0.0.81/32 -i loc02_srv01 -j TEE --gateway 127.0.0.1 iptables -t mangle -A PREROUTING -d 224.0.0.81/32 -i loc02_srv02 -j TEE --gateway 127.0.0.1
Tatsächlich spielt jeder unserer LVS-Server beide Rollen gleichzeitig (Master & Backup). Dies ist zum einen nur praktisch, da der Rollenwechsel beim Umschalten des Datenverkehrs entfällt, zum anderen ist er erforderlich, da jeder DC standardmäßig den Datenverkehr seiner Gruppe verarbeitet öffentliche VIPs.
Lastumschaltung zwischen Rechenzentren
Im normalen Betrieb wird jede öffentliche IP-Adresse von überall im Internet angekündigt (in diesem Diagramm von zwei Rechenzentren). Der in den VIP eintretende Datenverkehr wird mithilfe des BGP-Attributs MED (Multi Exit Discriminator) mit unterschiedlichen Werten für Active DC und Backup DC an den derzeit benötigten DC weitergeleitet. Gleichzeitig ist Backup DC immer bereit, Datenverkehr zu akzeptieren, wenn etwas mit dem aktiven passiert:

Durch Ändern der Werte von BGP-MEDs und Verwendung der standortübergreifenden IPVS-Synchronisierung erhalten wir die Möglichkeit, den Datenverkehr nahtlos von den Backends eines Rechenzentrums zu einem anderen zu übertragen, ohne die etablierten Telefonanrufe zu beeinträchtigen, die früher oder später auf natürliche Weise enden werden. Der Prozess ist vollständig automatisiert (für jeden VIP haben wir eine Schaltfläche in der Verwaltungskonsole) und sieht folgendermaßen aus:
SIP-VIP ist in DC1 (links) aktiv, der Cluster in DC2 (rechts) ist redundant, dank IPvs-Synchronisation hat er Informationen über hergestellte Verbindungen in seinem Speicher. Links werden aktive VIPs mit einem Wert von MED 100 angekündigt, rechts mit einem Wert von 500:

Die Schaltertaste bewirkt eine Änderung der sogenannten "Target_state" (ein internes Konzept, das die Werte von BGP-MEDs zu einem bestimmten Zeitpunkt deklariert). Hier hoffen wir nicht, dass DC1 in Ordnung ist und bereit ist, Verkehr zu verarbeiten, daher tritt LVS in DC2 in den Zustand "aktiv erzwingen" ein, senkt den MED-Wert auf 50 und zieht somit den Verkehr auf sich selbst. Wenn die Backends in DC1 aktiv und verfügbar sind, werden die Anrufe nicht unterbrochen. Alle neuen TCP-Verbindungen (Registrierungen) werden an Backends in DC2 gesendet:

DC1 hat eine neue Replikation target_state erhalten und den Sicherungswert MEDs (500) festgelegt. Wenn DC2 davon erfährt, normalisiert es seinen Wert (50 => 100). Es bleibt zu warten, bis alle aktiven Anrufe in DC1 abgeschlossen sind und die hergestellten TCP-Verbindungen unterbrochen werden. SBC-Instanzen in DC1 führen die notwendigen Dienste in die sogenannten ein Status "Graceful Shutdown": "503" reagiert auf die nächsten SIP-Anforderungen und trennt die Verbindung, akzeptiert jedoch keine neuen Verbindungen. Außerdem fallen diese Instanzen in die schwarze Liste von LVS. Beim Unterbrechen stellt der Client eine neue Registrierung / Verbindung her, die bereits in DC2 enthalten ist:

Der Prozess endet, wenn der gesamte Datenverkehr in DC2 erfolgt.

DC1 und DC2 wechselten die Rollen.

Bei konstant hoher Belastung der Einstiegspunkte erwies es sich als sehr praktisch, den Verkehr jederzeit wechseln zu können. Der gleiche Mechanismus wird automatisch gestartet, wenn der Backup-DC plötzlich Datenverkehr empfängt. Gleichzeitig wird zum Schutz vor Flattern das Umschalten nur einmal in eine Richtung ausgelöst und das Schloss auf automatisches Umschalten eingestellt, um es zu entfernen, ist ein menschliches Eingreifen erforderlich.
Was ist drin?
VRRP-Cluster & IPVS-Manager: Keepalived. Keepalived ist verantwortlich für den VIP-Wechsel innerhalb des Clusters sowie für das Backend Healthchecking / Blacklisting.
BGP-Stapel: ExaBGP. Er ist verantwortlich für die Ankündigung von Routen zu VIP-Adressen und die Anbringung der entsprechenden BGP-MEDs. Vollständig vom Verwaltungsserver gesteuert. Ein zuverlässiger BGP-Daemon, der in Python geschrieben wurde, entwickelt sich aktiv und erfüllt seine Aufgabe zu 100%.
Verwaltungsserver (API / Überwachung / Verwaltung von Unterkomponenten): Pyro4 + Flask. Es ist ein Bereitstellungsserver für Keepalived und ExaBGP, verwaltet alle anderen Systemeinstellungen (sysctl / iptables / ipset / etc), bietet Überwachung (gnlpy), fügt Backends auf Anfrage hinzu und entfernt sie (sie kommunizieren mit seiner API).
Zahlen
Eine virtuelle Maschine mit vier Kernen Intel Xeon Gold 6140 CPU bei 2,30 GHz bedient einen Verkehrsfluss von 300 Mbit / s / 210 Kpps (Medienverkehr, über den in Spitzenzeiten etwa 3.000 gleichzeitige Anrufe verarbeitet werden). CPU-Auslastung gleichzeitig - 60%.
Dies reicht jetzt aus, um den Datenverkehr von bis zu 100.000 Endgeräten (Desktop-Telefonen) zu bedienen. Um den gesamten Datenverkehr (mehr als 1 Million Endgeräte) zu bedienen, bauen wir in mehreren Rechenzentren etwa 10 Paare solcher Cluster auf.