BLOG | NGINX

Lastausgleich einer dynamischen Infrastruktur mit NGINX, Chef und Consul

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Kevin Reedy Miniaturbild
Kevin Reedy
Veröffentlicht am 22. Mai 2017


Dieser Beitrag basiert auf einer Präsentation von Kevin Reedy von Belly Card auf der nginx.conf im Oktober 2014. Das ist zwar schon ein paar Jahre her, aber der Inhalt ist auch heute noch hochaktuell. Sie können eine Aufzeichnung der Präsentation auf YouTube ansehen.

Inhaltsverzeichnis

0:00 Einführung
  Überblick
  Haftungsausschluss
1:16 Was ist Bauch?
  Bellys Stapel
1:44 Version 0: Das dunkle Zeitalter
2:04 Version 1: Eine neue Hoffnung
2:35 Version 2: Separate Homepage und API
  Schlagwort des Tages: Serviceorientierte Architektur!
  Aktivieren Sie SOA
  NGINX ersetzt ELB
  Upstream- und virtuelle Serverkonfiguration
  Ergebnisse
4:43 Konfiguration mit Chef
  Rezepte
  Dateien
  Vorlagen
  Kochbücher
6:49 Beispiel: Chef für NGINX
  Installation, Konfiguration und Optimierung
  Weiterleiten des API-Datenverkehrs
9:46 Beispiel eines echten Kochs
10:08 Version 2: Bereitstellen von Apps
10:40 Version 3: SOA - Alles
  Dann passierte Heartbleed
  SSL – alles
12:25 Version 4: Docker
  Vorteile
  Bereitstellen von Containern
15:45 Bereitstellungsstrategien
17:43 Service-Discovery-Optionen
18:33 Konsul Architektur
19:30 Consul-Funktionen
22:07 Konsul-Vorlage
  Befehl zum Starten der Consul-Vorlage
  NGINX-Konfiguration mit Consul-Vorlage
  Konfigurationsmanagement mit Consul-Vorlage
24:35 Verwenden von Chef zum Bereitstellen von Consul
25:44 Profi-Tipps
  Chef Teilsuche
  DNS
  Vermeidung veralteter Konfigurationen
30:35 Fragen
36:31 Kontaktinformationen

0:00 Einführung

Guten Morgen allerseits. Mein Name ist Kevin Reedy und ich arbeite für eine Firma namens Belly Card mit Sitz in Chicago. Wir haben etwa hundert Mitarbeiter und zwanzig Ingenieure. Heute werde ich mit Ihnen darüber sprechen, wie wir unseren Lastausgleich durchführen, insbesondere in einer sich ständig verändernden dynamischen Infrastruktur.

0:21 Übersicht

Also werde ich Ihnen zunächst etwas über unseren Infrastruktur-Stack im Laufe der Zeit erzählen, beginnend mit Version 0, die ich das „Dunkle Zeitalter“ nenne. Dann besprechen wir, wie wir Chef verwenden, um NGINX zu konfigurieren. Danach sprechen wir darüber, wie wir davon abgewichen sind und nun Daten von einer sogenannten Consul Service Discovery Platform verwenden, um NGINX zu konfigurieren. Wenn die Zeit es erlaubt, habe ich einige Profitipps zur Konfiguration von NGINX, insbesondere zum Konfigurationsmanagement.

0:49 Haftungsausschluss

Auch wenn ich mit Ihnen über Chef und Consul sprechen werde, möchte ich darauf hinweisen, dass sich dieser Vortrag nicht speziell auf diese beiden Unternehmen bezieht. Chef, Puppet, Ansible, Salt, CFEngine und alle anderen sind großartige Produkte und Sie sollten eines davon verwenden. Wir haben Spaß an Chef und ich bin sicher, dass das vielen anderen auch so geht.

Dasselbe gilt für die Diensterkennung. Consul, etcd und ZooKeeper sind alle großartig, verwenden Sie also, was für Sie funktioniert.

1:16 Was ist Bauch?

Was ist Bauch? Im Wesentlichen handelt es sich dabei um einen digitalen Ersatz für die Stempelkarte im Café, mit der Sie beim Kauf von zehn Getränken eins gratis bekommen. Wir stellen ein iPad in den Laden, die Kunden scannen es mit ihrem Telefon oder einer physischen Karte mit einem QR-Code, wir verfolgen ihre Punkte, vergeben die Prämien und entwickeln darüber hinaus auch noch Marketing-Tools.

1:36 Bellys Stapel

Aber ich bin nicht hier, um mit Ihnen über Belly als Unternehmen zu sprechen. Wenn Sie daran interessiert sind, können Sie einfach unsere Website besuchen. Ich werde mit Ihnen über unseren Infrastruktur-Stack sprechen.

1:44 Version 0: Das dunkle Zeitalter

Also Version 0. Damals, als wir noch drei Entwickler hatten und bevor ich dort arbeitete, war Belly eine monolithische Ruby-on-Rails-Anwendung, was bedeutete, dass jeder API-Aufruf und jeder Teil unserer Website an eine einzelne Rails-Anwendung ging. Es basierte auf MySQL, MongoDB und Memcached und wir haben es auf Heroku bereitgestellt, was ein großartiger Ausgangspunkt ist.

2:04 Version 1: Eine neue Hoffnung

Also Version 1 – Eine neue Hoffnung. Wir kamen zu dem Schluss, dass Heroku unseren Anforderungen nicht mehr gerecht wurde, und begannen daher mit der Bereitstellung von etwas namens Capistrano, das im Wesentlichen „besser als ein Shell-Skript“ ist, das in Ruby geschrieben ist. Es hilft Ihnen bei der Bereitstellung von Dingen.

Wir hatten ungefähr sechs Server auf Amazon Web Services EC2. Das war eine statische Zahl, aber wir haben sie erhöht, wenn wir wussten, dass etwas Großes passiert, und bei Bedarf wieder gesenkt. Davor hatten wir AWS Elastic Load Balancer.

2:35 Version 2: Separate Homepage und API

Dann kam ein Projekt auf, bei dem wir unsere Homepage vom Rest der API trennen wollten. Das wollten wir tun, damit wir mit unserer Homepage schneller vorankommen und verschiedene Entwickler daran arbeiten lassen können.

2:47 Schlagwort des Tages: Serviceorientierte Architektur!

Das große Schlagwort damals – und auch heute noch – ist serviceorientierte Architektur.

2:50 SOA implementieren

Version 2 unseres Stacks sollte also eine serviceorientierte Architektur ermöglichen. Unser erster Plan war, die Homepage von der API zu trennen. Das scheint wirklich einfach zu sein – wir haben nur www.bellycard.com und api.bellycard.com .

Es stellte sich jedoch als wirklich komplex und überhaupt nicht einfach heraus, da einige unserer mobilen Anwendungen statisch für die Verwendung von www.bellycard.com/api und /api‑assets geschrieben wurden. Unsere E-Mail-Anbieter und alle unsere Klicklinks, die bereits per E-Mail an Personen gesendet wurden, hatten /eo für „E-Mail öffnen“ und /ec für „E-Mail klicken“. Unsere Facebook-App wurde auf /facebook/callback konfiguriert.

3:28 NGINX ersetzt ELB

Das bedeutete, dass AWS Elastic Load Balancer uns nicht mehr die nötige Flexibilität bot, um diesen Datenverkehr an verschiedene Anwendungen weiterzuleiten. Also kam NGINX zur Rettung. Insbesondere könnten wir mehrere Upstreams haben und Regeln neu schreiben, um den Datenverkehr an unsere verschiedenen Anwendungen weiterzuleiten.

3:44 Upstream- und virtuelle Serverkonfiguration

In diesem sehr einfachen Beispiel definieren wir einen Upstream- Block mit sechs Servern für die API und einen Block mit zwei Servern für die Homepage.

Es gibt auch zwei Serverblöcke [die virtuelle Server definieren]. Auf einem hören wir auf api.bellycard.com und leiten den gesamten Datenverkehr an die API-Server weiter. Andererseits hören wir auf www.bellycard.com zu und leiten die Dinge entsprechend weiter.

4:02 Ergebnisse

Das hat super geklappt. Dadurch konnten unsere Entwickler schnell vorankommen. Unsere Frontend-Leute arbeiteten an einem Projekt und wurden nicht durch unsere API blockiert. Also haben wir einen dritten Dienst bereitgestellt. Ich glaube, es war für die Integration mit Apples Passbook gedacht. Und viertens: Wir haben alle unsere Facebook-Funktionen ausgelagert. Unser fünftes Ziel war die Behandlung von Benutzerereignissen auf unserer Website.

Dann kam jemand auf die Idee, das in Node.js zu schreiben, und so hatten wir nun fünf verschiedene Dienste in zwei Sprachen. Sie werden alle unabhängig voneinander und ohne viel Konfigurationsmanagement bereitgestellt und wir haben NGINX manuell bearbeitet, was sicherlich viele Leute als Einstieg nutzen.

4:43 Konfiguration mit Chef

Wir brauchten eine bessere Möglichkeit, diesen Prozess zu skalieren, also haben wir das mit Chef gemacht.

Chef ist eine Suite zur Konfigurationsverwaltung. Es ist in Ruby geschrieben und Sie können Ihr eigentliches Konfigurationsmanagement in Ruby schreiben, es ist also großartig für Entwickler. learnchef.com ist eine großartige Ressource, um mehr über Chef zu erfahren; Sie können dort viel mehr über Chef lernen als ich in 45 Minuten.

Ich werde jedoch einige der Grundlagen noch einmal durchgehen, damit wir alle auf dem gleichen Stand sind.

5:17 Rezepte

Die erste Art von Baustein in Chef ist ein Rezept . Der Koch verwendet viele clevere Namen, wie „Messer“ als Werkzeug und „Rezept“ , und alles steht in einem Kochbuch . Das macht es ziemlich lustig und ist leicht herauszufinden. Außerdem ist es eine tolle Metapher, macht es aber auch sehr schwer, bei Google nach irgendetwas zu suchen.

Hier ist das einfachste Rezept, das mir eingefallen ist. Installieren Sie das Paket nginx und starten und aktivieren Sie den nginx -Dienst.

5:56 Dateien

Sie können auch über Dateiressourcen verfügen. Beispielsweise möchte ich den Inhalt Hello World!“ in die Datei /usr/share/NGINX/html/index.html schreiben.

6:08 Vorlagen

Sie können das auch in ein Vorlagensystem integrieren. Hier habe ich ein paar Variablen g und w für „Hallo“ und „Kevin“ , und ich kann diese Variablen an eine Vorlagendatei im ERB-Format (ein Ruby-Vorlagenskript) übergeben.

Anstatt den Inhalt einfach manuell aufzuschreiben, können wir eine Vorlage zum Lesen und Begrüßen schreiben.

6:19 Kochbücher

Der letzte große Baustein ist ein Kochbuch, also eine Sammlung von Rezepten, Dateien und Vorlagen. Außerdem Ressourcen, Anbieter und Bibliotheken, die komplexere Ressourcen sind. Unter https://supermarket.getchef.com gibt es jede Menge Open Source und andere Kochbücher, darunter auch welche für NGINX, MySQL, Java, apt und yum , und sogar solche zur Verwaltung Ihrer ssh_known_hosts- Dateien. Die wichtigsten Bausteine dessen, was Sie im Konfigurationsmanagement erreichen möchten, finden Sie praktisch bereits in einem Kochbuch.

6:49 Beispiel: Chef für NGINX

Wir gehen mit Chef ein sehr kurzes NGINX-Beispiel durch, bei dem wir NGINX installieren und durch Ändern einiger Variablen konfigurieren. Wir verwenden Chef, um herauszufinden, wo unsere Anwendung ausgeführt wird, und konfigurieren dann NGINX so, dass der Datenverkehr an unsere Anwendung weitergeleitet wird.

7:14 Installation, Konfiguration und Tuning

In diesem Beispiel besteht das erste, was in der Chef-Konfiguration getan wird, darin, die NGINX-Knotenattribute zu optimieren, dann nginx zu installieren, Anwendungsknoten zu finden und eine Site-Konfiguration zu generieren

In diesem Beispiel legen wir zunächst einige Knotenattribute fest. Für jeden Knoten können Sie Attributwerte festlegen, indem Sie ein JSON-Dokument anhängen. Wir verwenden ein NGINX-Kochbuch eines Drittanbieters, das nach Einstellungen für diese Attribute sucht. Wir setzen worker_connections auf einen bestimmten Wert, die Direktive worker_rlimit_nofile , welchen Ereignistyp wir in NGINX verwenden werden und sogar client_max_body_size .

Danach fügen wir zwei Rezepte aus dem NGINX-Kochbuch ein. Das erste ist nginx::repo , das je nach Betriebssystem entweder ein Apt- oder ein Yum -Repository einrichtet. Dann installiert [das Nginx -Rezept] NGINX. Sie können NGINX auch aus der Quelle installieren, aber die Verwendung von Paketen ist schneller.

Als nächstes nutzen wir die Suchfunktionen von Chef. Wenn Sie Chef ausführen, können Sie es entweder als Agent auf der Maschine ausführen oder im Solomodus, der es im Wesentlichen wie ein Skript durchläuft. Wenn Sie einen Agenten auf einer Maschine haben, können Sie den Chef-Server nach Knoten und anderen Attributen abfragen.

Hier bitten wir Chef, uns eine Liste aller Knoten zu geben, an die die Rezept- Belly-API angehängt ist. Danach erstellen wir eine Site-Datei-Vorlage mit dem Namen /sites‑enabled/api . Die Quelle ist die Vorlage [Datei mit dem Namen api.erb, die] ich Ihnen als Nächstes zeigen werde. Die Variablen, die wir übergeben, sind die Knoten, nach denen wir gerade gesucht haben.

Die letzte Neuerung hier ist eine Benachrichtigungsanweisung zum Neuladen des Nginx -Dienstes. Dies bedeutet, dass Sie diesen Dienst neu laden müssen, wenn sich diese Vorlage ändert.

8:54 Routing des API-Verkehrs

Unsere Vorlagendatei hier ist also ziemlich einfach. Wir haben einen Upstream namens API und in ERB iterieren wir über alle Server, die wir als Variable durchlaufen, und geben den Server über die IP-Adresse und den Port 8080 an. Wir fügen sogar einen Kommentar mit dem Servernamen ein. Wenn ein Betreiber wissen möchte, was mit diesem Dienst los ist, ist das für ihn ein netter Kommentar.

Wir definieren auch einen Serverblock , um auf api.bellycard.com zu lauschen. Ich leite einfach den gesamten Datenverkehr an die Upstream -API weiter.

9:46 Beispiel eines echten Kochs

Ich möchte auch ein Beispiel aus der Praxis geben. Es ist vielleicht zu klein zum Lesen, aber Sie bekommen zumindest einen Eindruck davon, wie kompliziert Ihre Chefkoch-Rezepte werden können. Dies ist die aktuelle Vorlage und das Rezept von einigen unserer heutigen Produktionsserver.



10:08 Version 2: Bereitstellen von Apps

So, nun zurück zu unserem Stapel. Ich habe Ihnen gesagt, dass wir etwa fünf Anwendungen bereitgestellt haben und dass alles großartig läuft. Wir hatten nun eine Möglichkeit, den Datenverkehr zu ihnen umzuleiten, also haben unsere Entwickler das einfach aufgegriffen und heute verfügen wir über ungefähr 40 Ruby-Anwendungen, die mit Chef auf unseren Servern bereitgestellt werden. Der Datenverkehr wird über NGINX vollständig dynamisch weitergeleitet.

Unsere Entwickler müssen eigentlich nichts weiter tun, als ein Rezept zu bearbeiten, um den Namen ihres neuen Dienstes einzufügen. Der gesamte Datenverkehr wird von NGINX geleitet und dynamisch mit Chef konfiguriert.

10:40 Version 3: SOA - Alles

Wir hatten außerdem etwa zehn Front-End-JavaScript-Anwendungen, bei denen es sich lediglich um statische Dateien handelt, die wir auf S3 mit einem davor liegenden CDN, [Amazon] CloudFront, bereitstellen. Wir haben index.html aus dem S3-Bucket bereitgestellt und die restlichen Assets liefen über CloudFront. Wir hatten außerdem noch etwa fünf weitere Apps, die die Entwickler einfach zu Heroku gepusht haben, weil es sich um eine einmalige Sache handelte, die schließlich in die Produktion überging und niemand wirklich darüber informiert wurde.

11:10 Dann passierte Heartbleed

[Die fünf Apps auf Heroku] waren getrennt – völlig außerhalb unserer Infrastruktur – bis zu einem schönen Tag im April, als der Heartbleed-Bug angekündigt wurde. Viele Leute gerieten in Panik. Heartbleed war ein Fehler in OpenSSL, der es anderen ermöglichte, Ihre privaten Schlüssel zu extrahieren.

Da wir Chef verwenden, konnten wir unsere OpenSSL-Infrastruktur auf allen unseren Boxen aktualisieren, sobald ein Patch verfügbar war. Ich glaube, es wurde in etwa 20 Minuten überall in unserer gesamten Infrastruktur bereitgestellt. Allerdings benötigte AWS (und damit auch Heroku) etwa 24 Stunden, um seine Elastic Load Balancer zu patchen.

Dies hat uns dazu veranlasst, unseren gesamten Lastausgleich und die SSL-Terminierung in NGINX zu verschieben, unabhängig davon, wo es bereitgestellt wurde – sowohl in S3 als auch in Heroku. Dafür muss man zwar eine kleine Strafe in Kauf nehmen, aber zumindest an diesem Tag im April war es uns das wert.

11:57 SSL – Alles

Daher wurde in Version 3 unseres Stacks der Vorgänger „SOA für alles“ zu „SSL für alles“ geändert. Unser gesamter Datenverkehr zu bellycard.com und seinen Subdomains läuft über unsere Lastenverteiler. Aus Leistungsgründen werden unsere Assets tatsächlich immer noch von CloudFront in einer anderen Domäne bereitgestellt. Wir möchten den SSL-Overhead nicht und sind außerdem nur ein einziges Rechenzentrum an der Ostküste.

12:25 Version 4: Docker

Version 4 – das Schlagwort, über das dieses Jahr alle reden, ist Docker. Da Docker, glaube ich, bei der Version 0.5 vorlag, waren unsere Entwickler begeistert, es verwenden zu können.

12:38 Vorteile

Die Gründe [für die Verwendung von Docker] sind einfach.

Es vereinfacht die Bereitstellung von Anwendungen erheblich. Es gibt keine Rezepte zum Schreiben. Sie müssen sich keine Gedanken darüber machen, wie Sie die Asset-Zusammenstellung durchführen. Es spielt keine Rolle, ob Sie Ihre App in Ruby schreiben, wenn jemand anderes seine App in Python schreibt.

Im Wesentlichen werden dadurch die Verantwortlichkeiten zwischen Entwicklung und Betrieb getrennt. Ihre Entwickler können sich um den Code kümmern, darüber, welche Bibliotheken verwendet werden sollen, und sogar darüber, welche Linux-Pakete installiert werden sollen. Der Betrieb kann sich um weitere Dinge kümmern, beispielsweise: Wo werde ich das einsetzen? Wie erfasse ich die Protokollierung davon? Wie überwache ich es? Sobald Sie diese Probleme und Vorgänge gelöst haben, funktioniert jede Anwendung, unabhängig davon, in welcher Sprache sie geschrieben ist.

Ein Vorteil hiervon besteht darin, dass unsere Entwickler abhängige Dienste problemlos auf ihren eigenen Laptops starten können. Wie erwähnt haben wir mittlerweile etwa 55 verschiedene Anwendungen, viele davon befinden sich jetzt in Docker-Containern.

Angenommen, Sie arbeiten an einem neuen Dienst zum Versenden von E-Mail-Kampagnen. Es basiert auf dem E-Mail-Dienst. Normalerweise würden Sie also auf Ihrem Entwicklungscomputer den Code herunterladen, „bundle install“ ausführen, ihn im Hintergrund starten und „oh – aber eigentlich basiert das auf einem anderen Dienst, dem Benutzerdienst“.

Dieser Dienst ist auf etwas anderes und noch etwas anderes angewiesen. Tatsächlich basiert der neue E-Mail-Kampagnendienst auf etwa fünf weiteren Diensten plus MySQL, Elasticsearch, Redis, und die Liste geht noch weiter.

Mit Docker können wir diese Container tatsächlich aus denselben Chef-Rezepten erstellen, die wir in der Produktion verwenden, und unseren Entwicklern Container bereitstellen, die sie extrem schnell herunterladen können.

Dadurch werden Bereitstellung und Entwicklung beschleunigt.

14:23 Container bereitstellen

Deshalb sind wir in Version 4 von der Bereitstellung unserer Anwendungen mit Chef zur Bereitstellung in Containern übergegangen. Es gibt hierfür unzählige Lösungen und ich bin sicher, dass es noch mehr werden.

Das erste sind CoreOS und Fleet. CoreOS ist ein abgespecktes Linux-Betriebssystem, auf dem eine Service Discovery Engine namens etcd läuft. Mit Fleet können Sie Dinge definieren wie: „Ich möchte, dass ein Container fünfmal ausgeführt wird, und ich möchte nicht, dass er auf denselben Maschinen wie dieser andere Dienst ausgeführt wird.“

Es gibt ein weiteres namens Deis, das Heroku insofern ähnelt, als dass es über eine Git-Push-Schnittstelle verfügt. Es gibt Apache Mesos und Google Kubernetes; Flynn ist ein weiteres, das erst kürzlich herausgekommen ist. Wir haben tatsächlich unser eigenes geschrieben, weil die meisten dieser Tools sich zu Beginn dieser Reise nicht an einem Ort befanden, an dem wir sie verwenden konnten.

Unserer heißt „Jockey“ und hat wirklich gut funktioniert, da unser Bereitstellungsprozess äußerst eigensinnig ist. Das Tolle an Docker ist, dass es im Wesentlichen einen Satz allgemeiner APIs für die Containerisierung bereitstellt. Wir müssen uns um viele Dinge keine Gedanken machen, die wir uns machen müssten, wenn wir einfach die LXC-Container von Linux verwenden würden.

Wir planen, es als Open Source bereitzustellen, aber wie ich bereits erwähnt habe, sind Bereitstellungen sehr eigentümlich und was für uns funktioniert, funktioniert für Sie möglicherweise nicht.

15:45 Bereitstellungsstrategien

Auch unsere Bereitstellungsstrategie hat sich geändert, als wir zu Docker gewechselt sind. Zuvor haben wir Bereitstellungen ohne Ausfallzeiten durchgeführt, indem wir eine neue Version der Anwendung an Ort und Stelle bereitgestellt haben. Dies bedeutet, dass wir, wenn wir diesen Benutzerfaxdienst auf vier Maschinen hätten, Chef verwenden würden, um die neue Version herunterzuladen, sie über [der alten Version] zu installieren und dann ein Signal an den Webserver zum Neuladen senden würden. Unicorn ist eine großartige Ruby-Engine dafür.

Container sind jedoch unveränderlich. Wenn Sie über einen laufenden Container verfügen und einen neuen Build erstellen möchten, sollten Sie einen neuen Container erstellen. Sie können es anhängen, zusätzliche Befehle ausführen und es dann speichern – ähnlich wie Sie es in Git tun würden. Wenn Sie Docker jedoch wirklich optimal nutzen möchten, sollte Ihr Container völlig unveränderlich sein.

Das bedeutet, dass wir uns eine neue Bereitstellungsstrategie überlegen mussten, da wir die Bereitstellung vor Ort nicht mehr durchführen können. Es gibt da draußen ein paar. Blaugrün ist interessant. Wenn Sie beispielsweise eine Anwendung auf vier Maschinen ausführen, starten Sie sie auf vier neuen Maschinen und richten Ihren Load Balancer auf die neuen Maschinen aus. Wenn Sie sicher sind, dass es tatsächlich wie erwartet funktioniert, können Sie Ihr Blau entfernen und Ihr Grün wird zu Blau. Amazon verfügt hierfür mit AWS über einige wirklich großartige Tools.

Es gibt auch „Canary“-Bereitstellungen, bei denen ich eine Version der neuen Maschine bereitstelle, sie überwache und, wenn sie die Metrik- und Integritätsprüfungen besteht, mit der Bereitstellung fortfahren kann.

Der Unterschied bei Containern besteht darin, dass Sie diese tatsächlich abbauen und neue erstellen. Sie benötigen daher eine Art System, um den Standort aller in Ihrer Infrastruktur ausgeführten Anwendungen zu verfolgen.

Chef beginnt sich tatsächlich zu einer wirklich guten Möglichkeit dafür zu entwickeln. Es wird ein Cookbook namens „Chef Metal“ integriert, mit dem Sie Container tatsächlich wie jede andere Ressource in Ihrer Chef-Infrastruktur behandeln können.

17:43 Service-Erkennungsoptionen

Es gibt auch Service Discovery. ZooKeeper ist ein sehr beliebtes Tool, das überall in Hadoop verwendet wird. [Airbnb] hat ein großartiges Produkt namens SmartStack , mit dem Sie Bereitstellungen durchführen und diese in ZooKeeper verfolgen können.

Ich habe etcd erwähnt, im Wesentlichen ein verteilter Schlüssel-Wert-Speicher mit einer REST-Schnittstelle. Dies ist großartig im Vergleich zu ZooKeeper, das eher eine Java-Clientbibliothek ist, da Sie jetzt von jeder Ihrer Anwendungen aus mit etcd kommunizieren können. Viele der Open-Source-Platform-as-a-Service-Dinge, die ich zuvor erwähnt habe – wie Deis und Flynn und sogar Googles Kubernetes – verwenden etcd. Wenn Sie CoreOS verwenden, ist etcd bereits für Sie vorhanden und integriert.

Ein weiteres Produkt ist erschienen, ebenfalls REST-basiert, mit dem Namen Consul . Es wird von den Leuten von HashiCorp veröffentlicht, die Vagrant und Packer und jede Menge anderer toller Tools herstellen. Wir haben uns tatsächlich für die Verwendung von Consul entschieden.

18:33 Konsul Architektur

Hier ist ein Diagramm mit den Grundlagen von Consul. Sie sehen, dass es mehrere Rechenzentren mit jeweils drei Servern gibt. Im Rechenzentrum 1 befinden sich auch Clients. Interessant ist, dass Sie unter Ihren Server-Agenten einen primären Agenten auswählen und dann alle Ihre Clients tatsächlich nicht nur über alle Server, sondern auch über alle anderen Clients informiert sind. Sie verwenden dann ein Gossip-Protokoll, um mit allen anderen Agenten zu kommunizieren.

Es erinnert mich an einen alten Werbespot von AT&T, in dem man es zwei Freunden erzählt, die es zwei Freunden erzählen und die es wiederum zwei Freunden erzählen, und die Nachricht verbreitet sich auf diese Weise in Ihrem gesamten Knotennetzwerk. [ Anm. d. Red.: Fast: Es war ein Werbespot für das Shampoo von Fabergé Organics . ] Dies ist ein Vergleich zu etcd oder ZooKeeper, wo man im Wesentlichen nur Server-Agenten hat und die Clients sich mit ihnen verbinden.

Mit der Vorgehensweise von Consul würden Sie tatsächlich auf praktisch jedem Server einen Consul-Client ausführen, überall dort, wo wir Docker einsetzen und überall dort, wo wir unsere Load Balancer ausführen. Sie können also immer über den lokalen Port 8500 mit dieser API kommunizieren.

19:30 Consul-Funktionen

Genau wie etcd ist [Consul] ein verteilter Schlüssel-Wert-Speicher. Sie können Schlüssel festlegen und abrufen und ihre Linearisierbarkeit beibehalten, sodass Sie sicherstellen können, dass sie immer konsistent sind. Es gibt dort einige Fallstricke, aber ihre Dokumentation zu diesen Problemen ist phänomenal. Im Gegensatz zu etcd behandeln sie die Diensterkennung jedoch als etwas Erstklassiges.

Anstatt nur Schlüssel-Wert-Paare zu registrieren, können Sie auch Dienste registrieren, zum Beispiel eine API. Wenn Sie einen Dienst registrieren, teilen Sie Consul mit, auf welchem Knoten er ausgeführt wird. Dies bedeutet, dass wir beim Bereitstellen eines Containers Consul auch anweisen, diese Service-API auch auf diesem Host zu registrieren.

Darüber hinaus verfügt Consul über verteilte Integritätsprüfungen, sodass Sie jetzt Integritätsprüfungen im Nagios-Stil direkt in Ihrer Service-Discovery-Plattform definieren können. Wenn Sie sich für eine Abfrage bei Consul entscheiden, können Sie eine Liste aller Standorte anfordern, an denen der API-Dienst ausgeführt wird. Sie können eine Markierung für „alle“, „nur bestanden“ oder „nur ungesund“ senden.

Es unterstützt auch mehrere Rechenzentren. Ich habe erwähnt, dass Sie diesen Consul-Client überall ausführen sollten. Beim Start übergeben Sie einen Parameter, der das Rechenzentrum angibt. Wenn Sie über ein Rechenzentrum Ost und ein Rechenzentrum West verfügen, können Sie Ihren lokalen Consul-Client abfragen, ohne sich mit dem Rechenzentrum auskennen oder nach einer Adresse oder Ähnlichem fragen zu müssen.

Wir nutzen das Rechenzentrum tatsächlich als Grenze für unsere Staging- und Produktionsumgebungen. Unsere Konfiguration für eine Anwendung im Staging-Bereich könnte lauten: „Fragen Sie mich, wo MySQL.services.consul ist.“ Unabhängig davon, ob dies tatsächlich auf einem Staging-Knoten oder einem Produktionsknoten ausgeführt wird, erhalten Sie den richtigen Wert, ohne jemals rechenzentrums- oder umgebungsbewusst sein zu müssen.

Das andere Tolle daran (und auch an etcd) ist, dass es über Long-Polling auf seiner HTTP-Schnittstelle verfügt. Das bedeutet, dass Sie eine Liste aller Server, auf denen dieser Dienst ausgeführt wird, abfragen und anfordern können, aber auch die Verbindung 60 Sekunden lang offen halten und sofort benachrichtigt werden können, wenn sich etwas ändert. Die Umfrage kann tatsächlich bis zu 10 Minuten dauern. Das bedeutet, dass Sie sofort über alle Änderungen an Ihrer Infrastruktur benachrichtigt werden können.

Die andere Sache, die ich bereits erwähnt habe, ist, dass Sie die Möglichkeit zum Skalieren Ihrer Agenten schaffen können, indem Sie Clients überall haben. Das ist großartig, weil Sie immer mit dem lokalen Host sprechen können.

Die große Frage ist jedoch: Wie konfiguriere ich NGINX anhand der Daten, nachdem ich diese Daten nun auf einer verteilten Service-Discovery-Plattform gespeichert habe?

22:07 Konsul-Vorlage

Zum Glück gibt es ein Tool namens Consul Template . Es wurde buchstäblich gestern veröffentlicht, was mich dazu veranlasst hat, meine Folien für heute von diesem Zeitpunkt an zu ändern. Früher hieß es „Consul HAProxy“, was ein schrecklicher Name war, weil er sich nicht wirklich auf HAProxy bezog.

Consul Template bietet Ihnen eine sehr einfache Schnittstelle zum Erstellen von Vorlagen zum Abonnieren von Änderungen an Diensten, den Integritätsprüfungen dieser Dienste und sogar einem Schlüssel-Wert-Speicher. Auf diese Weise können Sie Einstellungen wie [die Anzahl der] NGINX-Worker im Schlüssel-Wert-Speicher speichern und Ihre Konfiguration neu generieren, wenn sich diese ändert.

Die große Fähigkeit besteht hier darin, Dateien aus Vorlagen zu generieren, was sehr ähnlich klingt zu dem, was wir vorher mit Chef gemacht haben. Der größere Unterschied besteht darin, dass die Vorlagensprache Golang verwendet wird und nicht ERB (Ruby). Wenn Sie eine Datei ändern, können Sie optional einen Befehl für die Änderung aufrufen, zum Beispiel service nginx reload .

22:59 Befehl zum Starten der Consul-Vorlage

Hier ist ein Beispiel für die Ausführung einer Consul-Vorlage in der Befehlszeile. Sie richten es auf Ihren tatsächlichen Consul-Host, in diesem Fall consul‑prod.example.com . In einer echten Produktionsumgebung würde ich vorschlagen, Consul überall auszuführen und eine Verbindung mit localhost herzustellen.

Anschließend übergeben Sie eine Vorlagendatei, bei der es sich um eine Golang-Vorlage handelt. In unserem Fall übergeben wir /etc/consul‑templates/api . Dann geben Sie an, welche Datei tatsächlich ausgegeben werden soll, in unserem Fall also /etc/NGINX/sites‑enabled/api . Anschließend ein aufzurufender Befehl: service nginx reload .

23:32 NGINX-Konfiguration mit Consul-Vorlage

Die Consul-Vorlage sieht einer Folie, die ich vorher hatte, sehr ähnlich, nur dass hier statt ERB Golang verwendet wird. Daher definieren wir hier zwei Upstreams. Eine heißt API und die andere Homepage . Wir haben eine Bereichsanweisung für die Service-API und es gibt integrierte Variablen zum Erfassen der IP und des Ports, wo der Service tatsächlich ausgeführt wird.

23:54 Konfigurationsmanagement mit Consul-Vorlage

Das Tolle an Consul Template und seiner Verwendung auf diese Weise ist, dass die Konvergenz bei Serviceänderungen schnell erfolgt. Vor der Bereitstellung mit Docker lief Chef bei uns je nach Maschine etwa alle 5 bis 10 Minuten. Für uns war das schnell genug, da wir die Bereitstellung vor Ort erledigten.

Da wir jetzt ein fortschrittlicheres Bereitstellungssystem entwickeln, müssen wir über diese Änderungen innerhalb von Sekunden und nicht innerhalb von Minuten benachrichtigt werden. Wir erreichen es tatsächlich im Millisekundenbereich, im Durchschnitt wahrscheinlich in etwa 200 Millisekunden.

Zum Generieren von Vorlagen ist jedoch weiterhin ein Konfigurationsmanagement erforderlich. Wir können Chef nicht einfach durch Consul ersetzen. Wir müssen noch herausfinden, wie wir Consul und Consul Template und alles andere bereitstellen.

24:35 Verwenden von Chef zum Bereitstellen von Consul

Wir verwenden also tatsächlich Chef-Vorlagen, um unsere Consul-Vorlagen bereitzustellen, was etwas umständlich erscheint. Als Erstes fragen wir in unserem Chef-Rezept unseren Consul-Host nach einer Liste aller Dienste. Dann generieren wir eine Consul-Vorlage [mit den Vorlagen- und Quellanweisungen ], übergeben unser SSL-Zertifikat und die Schlüsselspeicherorte und laden „consul‑template“ neu. [ Anm.: Herr Reedy bezog sich zunächst auf „consul‑haproxy“ , das in der ersten Benachrichtigungsanweisung auf der Folie erscheint . Anschließend korrigierte er sich selbst und stellte klar, dass die Folie vor der Veröffentlichung von Consul Template erstellt wurde. ]

Wir schreiben auch eine Konfigurationsdatei für die Consul-Vorlage und übergeben [Variablen, die] den Consul-Host, die Quelle, das Ziel und den Neuladebefehl angeben. Dies ist im Grunde der Kern der gemeinsamen Verwendung von Chef und Consul, um sofortige Updates für unsere NGINX-Konfigurationen zu erhalten.

25:44 Profi-Tipps

Als Nächstes habe ich einige Profi-Tipps sowohl zur Chef-, Consul- als auch zur NGINX-Konfiguration im Allgemeinen.

25:52 Chef Teilsuche

Der erste Tipp: Wenn Sie die Chef-Suche verwenden, um herauszufinden, wo Ihre Dienste ausgeführt werden, sollten Sie sich die Chef-Teilsuche ansehen. Das Problem bei der Chef-Suche besteht darin, dass eine Kopie des gesamten Knotens einschließlich aller Attribute erstellt wird. Wenn Sie viele Dinge in den Attributen Ihres Knotens speichern, müssen Sie diese während der Kommunikation mit Ihrem Chef-Server über die Leitung ziehen und sie auch im Speicher ablegen.

Wenn die Chef-Suche Hunderte oder Tausende von Servern zurückgibt, können Sie leicht erkennen, dass Ihnen für Ihr eigentliches Rezept möglicherweise der Speicher ausgehen könnte. Mit der partiellen Suche können Sie nur die Schlüssel zurückgeben, die für Sie von Bedeutung sind.

Wir hatten zum Beispiel zuerst

Knoten = Suche(:Knoten, 'Rezept:Bauch-API')

Diese Suche gibt jede einzelne Information zu jedem Objekt zurück. Hierzu gehören Informationen zu Festplattenspeicher, RAM, CPU und allen Anwendungen, die ihre eigenen Knotenattribute geschrieben haben.

Stattdessen können wir eine partielle Suche verwenden, bei der wir einen neuen Hash mit dem Namen „search_keys“ erstellen und ihm eine Liste der Schlüssel zuweisen, die für uns von Bedeutung sind – in diesem Fall nur den Namen und die IP-Adresse. Dann rufen wir die sehr ähnliche API namens partial_search auf und übergeben den zusätzlichen Parameter [ keys ].

26:53 DNS

Das zweite Problem, das uns beim Wechsel zum Lastenausgleich vor S3 und Heroku auffiel, war, dass NGINX DNS nur beim Neuladen der Konfiguration zum Auflösen der Hostnamen in den Upstream- Blöcken verwendet. Dies bedeutet, dass Ihr Load Balancer die neue IP-Adresse erst beim nächsten Neuladen erfährt, wenn Sie einen Upstream-Server auf s3.amazonaws.com oder anything.herokuapp.com einstellen und dieser sich ändert.

Wir haben dieses Problem umgangen, indem wir die DNS-Auflösung in Chef durchführen und dann das Neuladen von NGINX auslösen, wenn sich dies ändert. Dies führte zu einem zweiten Problem: [Die Reihenfolge der Adressen in einer DNS-Antwort] ist nicht immer gleich. Stellen Sie daher sicher, dass Sie die Antwort auch sortieren, bevor Sie sie in Ihre Vorlage schreiben.

27:36 Veraltete Konfiguration vermeiden

Das andere Problem, wenn Sie mit der Bereitstellung einer großen Anzahl von Diensten beginnen, besteht darin, dass Sie veraltete Konfigurationen vermeiden möchten. [ Herr Reedy unterbricht die Präsentation kurz, um eine Frage aus dem Publikum zu beantworten. ] In Apache, NGINX und anderen UNIX-Dingen besteht ein gängiges Konfigurationsmuster darin, einen Ordner conf.d zu haben und dann alles daraus zu laden. Wenn ich also die Dienste A, B und C bereitstelle, erstelle ich service-a.conf , service-b.conf und service-c.conf .

Dann entscheide ich, Dienst B durch D zu ersetzen, und habe jetzt vier Konfigurationen im NGINX-Konfigurationsordner, aber Dienst B existiert nicht mehr. Es kann zu Konflikten zwischen B und D kommen, weil sie einen ähnlichen Hostnamen haben.

Wir haben dies [durch Entfernen veralteter Konfigurationen] in der Vergangenheit auf zwei Arten erreicht. Mit Vorlagen können Sie eine :delete -Funktion hinzufügen, aber das wurde ziemlich schnell unhandlich. Wir hatten im Wesentlichen eine Liste alter Dienste, die wir immer zu löschen versuchten, sofern sie noch vorhanden waren. Das war nicht wirklich skalierbar.

Sie können außerdem alle Ihre Site-Konfigurationen in einer einzigen Datei rendern. Viele Leute haben dies als „Idempotenz nach oben verschieben“ bezeichnet. Im Wesentlichen bedeutet das, dass Sie, anstatt eine NGINX-Konfiguration zu haben, die aus mehreren Quellen geladen wird, alles in Ihre nginx.conf werfen.

Das macht es etwas umständlich, wenn Sie sich tatsächlich bei der Box anmelden, aber hoffentlich kommen wir bald an den Punkt, an dem Sie keine Probleme mit einer Konfigurationsdatei live in der Produktion mehr haben. Wenn es in Ihren Chef-Rezepten immer noch zu unhandlich ist, erstellen wir eine nginx.conf , die eine Reihe verschiedener Sites lädt. Beispielsweise listet eine unserer Site-Konfigurationsdateien etwa 30 Dienste auf, und dann haben wir eine für den Heroku-Dienst, eine für alle S3-Dienste usw.

Wenn Sie also alle Ihre Site-Konfigurationen in einer einzigen Datei oder einer kleinen Anzahl von Dateien rendern, müssen Sie sich keine Gedanken über das Aufräumen machen. Wenn aus Sicht von Chef ein Dienst wegfällt, beendet Chef einfach die Darstellung in der eigentlichen Datei.

30:35 Fragen

Q: Wie hat Consul bisher für Sie funktioniert?

A: Wir sind von Consul begeistert und was mir im Vergleich zu etcd wirklich daran gefällt, ist, dass weiterhin Dienste darauf aufgebaut werden. Ich muss mir keine Gedanken über die Diensterkennung machen. Wenn Sie über Legacy-Anwendungen verfügen und beispielsweise Ihre MySQL-Server mit Consul bereitstellen, stellt Consul auch eine DNS-Schnittstelle bereit.

Ihre Anwendung muss Consul nicht kennen; sie kann einfach abfragen: „Welche Adresse erhalte ich von mysqldb.services.consul ?“. In diesem Fall ist Consul der DNS-Server. Sie richten Ihre DNS-Infrastruktur so ein, dass die Abfrage an Consul weitergeleitet wird, wenn die TLD [Top-Level-Domain] auf .consul endet.

Für uns ist es großartig skaliert. Uns gehen in der Produktion etwa 3 Knoten für Server-Agenten und etwa 60 Clients aus. Es gab keine Probleme. Sie fügen einfach ständig neue Funktionen hinzu und beeinträchtigen die Abwärtskompatibilität nicht, sodass Upgrades immer großartig waren.

Q: Verwenden Sie NGINX Plus?

A: Das tun wir nicht. Genau aus diesem Grund haben wir uns damit befasst, als wir mit Consul zusammenzuarbeiten begannen. Wenn wir kein Vorlagensystem bräuchten, wäre das großartig, weil wir einfach ein Skript hätten, das dieses HTTP-Long-Polling abhört und dann in Ihrem Namen mit der NGINX-API kommuniziert. Das einzige Problem besteht darin, dass Sie wahrscheinlich auch ein Vorlagensystem für den Fall eines Neustarts von NGINX benötigen. Ihre Upstream-Konfigurationen würden direkt dort neu geladen.

Es gibt auch einige Arbeiten, die andere Leute in NGINX Lua durchgeführt haben, um Consul direkt abzufragen. Ich habe noch keine gute Implementierung gesehen, weil sie dazu neigen, in eine von zwei Kategorien zu fallen. Das erste ist, dass sie bei jeder HTTP-Anfrage Consul abfragen, was langsam ist. Zweitens laden sie es zur Konfigurationslaufzeit und Sie haben am Ende das gleiche Problem wie mit DNS. Daher ist die Sache mit der Vorlage derzeit am besten, aber es würde mich nicht überraschen, wenn wir in Zukunft eine Möglichkeit sehen, dies mit NGINX Lua zu tun.

Q: Würden Sie jemals von Chefkoch abrücken?

A: Es gibt in Consul keine gute integrierte Möglichkeit, diese Vorlagen zu verwalten, und wir setzen NGINX bereits mit Chef ein. Unsere dortigen Rezepte sind mittlerweile Hunderte, wenn nicht Tausende von Zeilen lang für alle anderen Dinge, die wir mit NGINX tun, einschließlich Protokollierung, Ablaufverfolgung und etwas OAuth. Ich glaube nicht, dass wir in unserer Infrastruktur von Chef abrücken und es ersetzen werden, aber es ist eine großartige Erweiterung und eine gute Möglichkeit, um schnelle Benachrichtigungen zu erhalten.

Q: Wie viele Gemeinkosten deckt Chef ab?

A: Da die meisten unserer Maschinen eine einzelne Aufgabe ausführen, ist unser tatsächlicher Chef-Overhead ziemlich gering. Im Leerlauf ist die RAM-Nutzung gering. Es sitzt tatsächlich in einem Timer und kann abgezweigt werden. Andere Leute führen es auch in einem Cron aus, wenn ihnen die Konvergenzgeschwindigkeit egal ist. Bei einigen unserer schwereren Rezepte stellen wir eine leichte Erhöhung der CPU-Auslastung fest, aber nichts, was wir nicht einfach durch Bereitstellung eines anderen Servers beheben könnten.

Q: Wie viel haben Sie mit CloudFormation gemacht?

A: Wir verwenden CloudFormation noch nicht. Wir haben es im Blick, haben aber eine Änderung vorgenommen, die darin besteht, viel mehr Auto-Scaling-Gruppen zu nutzen. Das funktioniert folgendermaßen: Wenn eine Instanz startet, verfügt sie über Benutzerdaten, die ihre Chef-Ausführungsliste enthalten.

Eine neue Maschine wird in einem Cluster mit einem Schlüssel aufgenommen, der bereits auf ihrem Image basiert, sodass sie mit unserem Chef-Server kommunizieren, sich registrieren und die benötigten Cookbooks herunterladen kann. Damit sind die meisten CloudFormation-Probleme für uns gelöst, da wir nicht viele andere AWS-Tools verwenden, die damit einhergehen würden.

Q: Wie gehen Sie mit der Zerstörung eines Servers um?

A: Wenn ein Server in einer Auto Scaling-Gruppe ausfällt, können Sie Amazon SNS [Simple Notification Service] verwenden, um eine Benachrichtigung darüber zu erhalten. Wir haben einen sehr einfachen Dienst, der auf diese Benachrichtigungen wartet und dann den Chef-Server bereinigt.

Q: Haben Sie OpsWorks von AWS verwendet?

A: Das haben wir nicht. Wir nutzen den gehosteten Chef von Anfang an und er hat für uns großartig funktioniert. Ich bin mir nicht sicher, aber ich glaube, dass OpsWorks eher wie Chef Solo ist, wo Sie es nur für die Bereitstellung verwenden. Wir führen auf fast allen unseren Maschinen immer noch Chef Agent aus und verwenden dieselben Chef-Rezepte, um Docker-Container für die Entwicklung zu generieren.

36:31 Kontaktinformationen


„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."