Konfigurationsmanagement: Push versus Pull-basierte Topologie

22

Die etablierteren Konfigurationsmanagementsysteme (CM) wie Puppet und Chef verwenden einen Pull-basierten Ansatz: Clients fragen regelmäßig bei einem zentralen Master nach Aktualisierungen. Einige von ihnen bieten auch einen meisterlosen Ansatz (also Push-basiert), geben jedoch an, dass er nicht für die Produktion (Saltstack) oder weniger skalierbar (Puppet) ist. Das einzige System, von dem ich weiß, dass es von Anfang an Push-basiert ist, ist der Zweitplatzierte Ansible.

Was ist der spezifische Skalierbarkeitsvorteil eines Pull-basierten Systems? Warum ist es angeblich einfacher, mehr Pullmaster als Pushagenten hinzuzufügen?

Beispielsweise schreibt agiletesting.blogspot.nl :

In einem Pull-System kontaktieren Clients den Server unabhängig voneinander, sodass das gesamte System skalierbarer ist als ein Push-System

Auf der anderen Seite demonstriert Rackspace, dass sie 15K-Systeme mit einem Push-basierten Modell handhaben können .

infastructures.org schreibt:

Wir schwören auf eine Pull-Methode für die Wartung von Infrastrukturen, die ein Tool wie SUP, CVSup, einen Rsync-Server oder Cfengine verwendet. Anstatt Änderungen an Clients weiterzuleiten, muss jeder einzelne Client-Computer dafür verantwortlich sein, den Gold-Server beim Start abzufragen und anschließend regelmäßig seine eigene Revisionsstufe beizubehalten. Bevor wir diesen Standpunkt übernommen haben, haben wir umfangreiche push-basierte Skripte entwickelt, die auf ssh, rsh, rcp und rdist basieren. Das Problem, das wir bei den r-Befehlen (oder ssh) festgestellt haben, war folgendes: Wenn Sie ein r-befehlsbasiertes Skript ausführen, um eine Änderung auf Ihre Zielcomputer zu übertragen, besteht die Wahrscheinlichkeit, dass einer von ihnen über 30 Zielhosts verfügt zu einem bestimmten Zeitpunkt nicht erreichbar sein. Das Führen der Liste der in Betrieb genommenen Maschinen wird zum Albtraum. Während Sie Code schreiben, um dies zu korrigieren, müssen Sie sich mit dem folgenden Code auseinandersetzen: Timeouts von toten Hosts; Protokollierung und Wiederholung von toten Hosts; Parallele Jobs forken und ausführen, um zu versuchen, viele Hosts in angemessener Zeit zu treffen; und schließlich den Fall zu erkennen und zu verhindern, dass alle verfügbaren TCP-Sockets auf dem Quellcomputer mit allen ausgehenden rsh-Sitzungen belegt werden. Dann haben Sie immer noch das Problem, alles, was Sie gerade getan haben, in die Installationsimages für alle neuen Hosts zu übernehmen, die in Zukunft installiert werden sollen, und es für alle Hosts zu wiederholen, die nicht mehr funktionieren und morgen neu erstellt werden müssen. Nachdem wir uns die Mühe gemacht hatten, eine R-Command-basierte Replikation zu implementieren, fanden wir, dass es sich einfach nicht lohnt. Wir planen nicht, eine Infrastruktur wieder mit R-Befehlen oder einem anderen Push-Mechanismus zu verwalten. Sie skalieren nicht so gut wie Pull-basierte Methoden. Parallele Jobs forken und ausführen, um zu versuchen, viele Hosts in angemessener Zeit zu treffen; und schließlich den Fall zu erkennen und zu verhindern, dass alle verfügbaren TCP-Sockets auf dem Quellcomputer mit allen ausgehenden rsh-Sitzungen belegt werden. Dann haben Sie immer noch das Problem, alles, was Sie gerade getan haben, in die Installationsimages für alle neuen Hosts zu übernehmen, die in Zukunft installiert werden sollen, und es für alle Hosts zu wiederholen, die nicht mehr funktionieren und morgen neu erstellt werden müssen. Nachdem wir uns die Mühe gemacht hatten, eine R-Command-basierte Replikation zu implementieren, fanden wir, dass es sich einfach nicht lohnt. Wir planen nicht, eine Infrastruktur wieder mit R-Befehlen oder einem anderen Push-Mechanismus zu verwalten. Sie skalieren nicht so gut wie Pull-basierte Methoden. Parallele Jobs forken und ausführen, um zu versuchen, viele Hosts in angemessener Zeit zu treffen; und schließlich den Fall zu erkennen und zu verhindern, dass alle verfügbaren TCP-Sockets auf dem Quellcomputer mit allen ausgehenden rsh-Sitzungen belegt werden. Dann haben Sie immer noch das Problem, alles, was Sie gerade getan haben, in die Installationsimages für alle neuen Hosts zu übernehmen, die in Zukunft installiert werden sollen, und es für alle Hosts zu wiederholen, die nicht mehr funktionieren und morgen neu erstellt werden müssen. Nachdem wir uns die Mühe gemacht hatten, eine R-Command-basierte Replikation zu implementieren, fanden wir, dass es sich nicht lohnt. Wir planen nicht, eine Infrastruktur wieder mit R-Befehlen oder einem anderen Push-Mechanismus zu verwalten. Sie skalieren nicht so gut wie Pull-basierte Methoden. und schließlich den Fall zu erkennen und zu verhindern, dass alle verfügbaren TCP-Sockets auf dem Quellcomputer mit allen ausgehenden rsh-Sitzungen belegt werden. Dann haben Sie immer noch das Problem, alles, was Sie gerade getan haben, in die Installationsimages für alle neuen Hosts zu übernehmen, die in Zukunft installiert werden sollen, und es für alle Hosts zu wiederholen, die nicht mehr funktionieren und morgen neu erstellt werden müssen. Nachdem wir uns die Mühe gemacht hatten, eine R-Command-basierte Replikation zu implementieren, fanden wir, dass es sich einfach nicht lohnt. Wir planen nicht, eine Infrastruktur wieder mit R-Befehlen oder einem anderen Push-Mechanismus zu verwalten. Sie skalieren nicht so gut wie Pull-basierte Methoden. und schließlich den Fall zu erkennen und zu verhindern, dass alle verfügbaren TCP-Sockets auf dem Quellcomputer mit allen ausgehenden rsh-Sitzungen belegt werden. Dann haben Sie immer noch das Problem, alles, was Sie gerade getan haben, in die Installationsimages für alle neuen Hosts zu übernehmen, die in Zukunft installiert werden sollen, und es für alle Hosts zu wiederholen, die nicht mehr funktionieren und morgen neu erstellt werden müssen. Nachdem wir uns die Mühe gemacht hatten, eine R-Command-basierte Replikation zu implementieren, fanden wir, dass es sich einfach nicht lohnt. Wir planen nicht, eine Infrastruktur wieder mit R-Befehlen oder einem anderen Push-Mechanismus zu verwalten. Sie skalieren nicht so gut wie Pull-basierte Methoden. Dann haben Sie immer noch das Problem, alles, was Sie gerade getan haben, in die Installationsimages für alle neuen Hosts zu übernehmen, die in Zukunft installiert werden sollen, und es für alle Hosts zu wiederholen, die nicht mehr funktionieren und morgen neu erstellt werden müssen. Nachdem wir uns die Mühe gemacht hatten, eine R-Command-basierte Replikation zu implementieren, fanden wir, dass es sich einfach nicht lohnt. Wir planen nicht, eine Infrastruktur wieder mit R-Befehlen oder einem anderen Push-Mechanismus zu verwalten. Sie skalieren nicht so gut wie Pull-basierte Methoden. Dann haben Sie immer noch das Problem, alles, was Sie gerade getan haben, in die Installationsimages für alle neuen Hosts zu übernehmen, die in Zukunft installiert werden sollen, und es für alle Hosts zu wiederholen, die nicht mehr funktionieren und morgen neu erstellt werden müssen. Nachdem wir uns die Mühe gemacht hatten, eine R-Command-basierte Replikation zu implementieren, fanden wir, dass es sich einfach nicht lohnt. Wir planen nicht, eine Infrastruktur wieder mit R-Befehlen oder einem anderen Push-Mechanismus zu verwalten. Sie skalieren nicht so gut wie Pull-basierte Methoden. oder mit irgendeinem anderen Druckmechanismus. Sie skalieren nicht so gut wie Pull-basierte Methoden. oder mit irgendeinem anderen Druckmechanismus. Sie skalieren nicht so gut wie Pull-basierte Methoden.

Ist das nicht ein Implementierungsproblem statt eines architektonischen? Warum ist es schwieriger, einen Threaded-Push-Client zu schreiben als einen Threaded-Pull-Server?

Willem
quelle
4
Nur eine Anmerkung, Ansible kann auch über ziehen ansible-pull.
Ceejayoz
1
Ein großer Vorteil ist das Durchqueren von NATs und Firewalls. Dies ist oft keine Straßensperre, aber manchmal ein Game Changer.
Dan Garthwaite
SALT verwendet pub / sub ZeroMQ. Welches ist anders.
Dan Garthwaite
1
Im Thread Application Deployment vs. System Configuration auf der Mailingliste [devops-toolchain] [1] gab es eine ausführliche Debatte darüber . [1]: code.google.com/p/devops-toolchain
sciurus
1
btw - HP Server Automation ist Push-modelliert und kann Zehntausende von Geräten verwalten {Offenlegung - ich bin ein Automation Architect für einen HP Partner}
warren

Antworten:

8

Das Problem bei Push-basierten Systemen besteht darin, dass Sie ein vollständiges Modell der gesamten Architektur auf dem zentralen Push-Knoten haben müssen. Sie können nicht auf eine Maschine pushen, die Sie nicht kennen.

Es kann natürlich funktionieren, aber es erfordert viel Arbeit, um es synchron zu halten.

Mit Dingen wie Mcollective können Sie Puppet und andere CMs in ein Push-basiertes System umwandeln. Im Allgemeinen ist es trivial, ein Pull-System in ein Push-basiertes umzuwandeln, aber nicht immer einfach, den anderen Weg zu gehen.

Es gibt auch die Frage der Organisationspolitik. Ein Push-basiertes System gibt den zentralen Administratoren die Kontrolle. Es kann sehr schwierig sein, die Komplexität auf diese Weise zu verwalten. Ich denke, das Problem bei der Skalierung ist ein roter Hering. Beide Ansätze sind skalierbar, wenn man sich nur die Anzahl der Kunden ansieht. Push ist in vielerlei Hinsicht einfacher zu skalieren. Eine dynamische Konfiguration setzt jedoch mehr oder weniger voraus, dass Sie mindestens eine Pull-Version der Client-Registrierung haben.

Letztendlich geht es darum, welches System dem Workflow und der Eigentümerschaft in Ihrer Organisation entspricht. Pull-Systeme sind in der Regel flexibler.

Fred der Zauberwunderhund
quelle
2
Vielen Dank! Aber warum würde dynamische Konfiguration ziehen implizieren? Ansible verwendet zum Beispiel Dynamic Push. Es scheint also, dass die Tatsache, dass Puppet keinen dynamischen Push ausführen kann, eine Einschränkung der Implementierung und keine Einschränkung der Architektur ist, oder?
Willem
4
@Willem Eine wirklich "dynamische" Umgebung bedeutet, dass ein neuer Computer jederzeit und überall angezeigt werden kann und eine Konfiguration erfordert. Bei einem Push-basierten System müssen Sie dieses System auf dem zentralen Knoten konfigurieren. Ein Pull-basiertes System kann eine (generische) Konfiguration abrufen, ohne dass der Umgebungsadministrator etwas an den Konfigurationsservern tun muss.
Voretaq7
1
Zabbix erkennt Hosts, Ansible kann mithilfe eines dynamischen Inventars eine Pull-Konfiguration auf neu erkannte Hosts übertragen.
bbaassssiiee
Ja, ansible kann viele Quellen für sein dynamisches Inventar verwenden, zum Beispiel die ESX-API. Auf diese Weise wissen Sie über eine VM Bescheid, sobald sie erstellt wurde, und können Spiele mit einem Muster-Match ausführen.
JM Becker
11

Falls es für jemanden von Interesse ist, kann ich zumindest einen Bericht zur Benutzererfahrung abgeben, in dem ich die sofort einsatzbereiten Push-Funktionen von Ansible zum ersten Mal im Kontext der Patch-Verwaltung von Multi-Host-Setups unternehmenskritischer Systeme verwendet habe in der Amazonaswolke. Um meine Vorurteile oder Vorurteile zu verstehen, sollte ich erklären, dass ich Ruby auf der Ebene der Automatisierungsskripte bevorzuge und Projekte so eingerichtet habe, dass in der Vergangenheit die Master-Agent-Puppet-Konfiguration pro Projekt-Vpc verwendet wurde. Meine Erfahrung lässt also Vorurteile hinter sich, wenn es welche gäbe.

Meine jüngsten Erfahrungen waren sehr positiv für die dynamische Übertragung auf einen sich ändernden Stand von Dutzenden bis zu Hunderten von Servern, die vergrößert oder verkleinert, beendet und aktualisiert werden können. In meiner Situation reichte ein einfacher Ansible 1.7-Ad-hoc-Befehl aus, um den Patch zu erstellen. Angesichts der Effektivität, einen AnsibleController (auf einem t2.micro) pro Vpc für diesen Zweck einzurichten, beabsichtige ich, die Technik in Zukunft für komplexere Anforderungen zu erweitern.

Lassen Sie mich zu der in diesem Thread gestellten Frage zurückkehren: Für und Wider von Push in einem sich dynamisch verändernden Nachlass.

Die Annahmen für die Art des Server-Standorts, auf den ich abzielte, lauteten:

  • Keine Annahme, dass IP-Adressen oder von Amazon generierte lokale Hostnamen von langer Dauer sind - sie können beide kommen und gehen
  • Alle Instanzen wurden aus Maschinenabbildern erstellt, die bereits die Möglichkeit hatten, ssh-Zugriff von einem einzelnen privilegierten Administrator aus zu ermöglichen
  • Um Server zu individualisieren und potenziell in Gruppen zu unterteilen, je nach Funktion oder Entwicklungsstadium (z. B. Test oder Produkt), werden bestimmte Amazon-Tags mit vereinbarten konventionellen Namen gestartet
  • Dass ich Linux- und Windows-Server separat mit unterschiedlichen Ad-hoc-Befehlen patchen würde, um Linux-spezifischen Anmeldungen bei der Kontaktaufnahme mit einem Windows-Server zu scheitern, war vollkommen akzeptabel

Unter diesen Umständen ist es sehr einfach, ein Computer-Image eines AnsibleControllers zu erstellen, das in zahlreiche Vpcs abgelegt und (mit Anmeldeinformationen) in den vorhandenen Serverkonten vor Ort konfiguriert werden kann. Automatisiert wird innerhalb jeder Instanz, die aus dem Image erstellt wird

  1. Ein Cron-Job, mit dem der Patch in regelmäßigen Abständen auf ausgeführte Server übertragen wird, damit in regelmäßigen Abständen kontinuierlich auf den erforderlichen Nachlass zugegriffen werden kann
  2. Eine Methode zur Berechnung des Ansible-Inventars in jedem solchen Intervall.

Der zweite Gegenstand kann bei Bedarf relativ komplex gestaltet werden (über die Infostruktur des Ansible-Inventars). Wenn jedoch keine Raffinesse erforderlich ist, finden Sie hier ein sehr einfaches Beispiel für ein Skript, mit dem alle Amazon EC2-Instanzen in jedem Cron-Intervall berechnet und die Ergebnisse in eine entsprechende Inventardatei (z. B. / etc / ansible / hosts) geleitet werden.

#!/bin/bash
# Assumes aws-cli/1.3.4 Python/2.6.9 Linux/3.4.73-64.112.amzn1.x86_64 or greater
# http://aws.amazon.com/releasenotes/8906204440930658
# To check yum list aws-cli
# Assumes that server is equipped with AWS keys and is able to access some or all
# instances in the account within it is running.
# Provide a list of host IPs each on a separate line
# If an argument is passed then treat it as the filename, whether local or absolute 
# path, to which the list is written

function list-of-ips {
    /usr/bin/aws ec2 describe-instances --filters '[ {"Name": "instance-state-code", "Values": [ "16" ] } ]' | grep -w PrivateIpAddress | awk  '{x=$2; gsub("\"","", x); gsub(",","", x); if(x && FNR!=1){print x;}}' | uniq
 }

if [ -n "$1" ]; then
   list-of-ips > "$1"
else
   list-of-ips
fi

Die einzige Einschränkung für den Anwendungsfall ist, dass der Patch-Befehl idempotent sein sollte. Es ist wünschenswert, einen Vortest durchzuführen, um sicherzustellen, dass dies erfüllt ist, um sicherzustellen, dass der Patch genau das tut, was beabsichtigt ist.

Zusammenfassend habe ich einen Anwendungsfall dargestellt, in dem dynamischer Push gegen die von mir gesetzten Ziele wirkt. Es handelt sich um eine wiederholbare Lösung (in dem Sinne, dass sie in ein Image eingebettet ist, das in mehreren Konten und Regionen bereitgestellt werden kann). Nach meiner bisherigen Erfahrung ist es viel einfacher, die dynamische Push-Technik bereitzustellen - und in Aktion zu treten - als die Alternativen, die aus den momentan verfügbaren Toolsets zur Verfügung stehen.

Johnz
quelle
2
//, @jonz, dies ist die Art von Diskussion, für die meiner Meinung nach erfahrene Entwickler das Stack Exchange-Modell lieben gelernt haben. Mir gefallen besonders die von Ihnen gewählten Begriffe, und in dieser Antwort werden zunächst die Annahmen aufgeführt.
Nathan Basanese