Einführung in die Architektur der Fraktale

Einführung in die Architektur der Fraktale

Dieser Abschnitt stellt die Anwendungsarchitektur vor und erklärt, wie es entworfen wurde, um die Vorteile von Cloud-Features im Allgemeinen und OpenStack insbesondere zu nutzen. Es beschreibt auch einige Befehle im vorherigen Abschnitt.

Cloud-Anwendung Architektur Prinzipien

Cloud-Anwendungen teilen sich typischerweise mehrere Designprinzipien. Diese Grundsätze beeinflussten die Gestaltung der Fractals-Anwendung.

Modularität und Mikro-Dienste

Mikro-Dienste sind ein wichtiges Design-Muster, das hilft, die Modularität der Anwendung zu erreichen. Die Trennung von logischen Applikationsfunktionen in unabhängige Dienste vereinfacht die Wartung und Wiederverwendung. Entkopplungskomponenten erleichtern auch die selektive Skalierung einzelner Komponenten nach Bedarf. Weiterhin ist die Anwendungsmodularität ein notwendiges Merkmal von Anwendungen, die gut skalieren und fehlertolerant sind.

Skalierbarkeit

Cloud-Anwendungen verwenden oft viele kleine Instanzen eher als ein paar große Instanzen. Vorausgesetzt, dass eine Anwendung ausreichend modular ist, können Sie problemlos Mikrodienste über möglichst viele Fälle verteilen. Diese Architektur ermöglicht es einer Anwendung, an der Grenze vorbei zu gehen, die durch die maximale Größe einer Instanz auferlegt wird. Es ist wie das Versuchen, eine große Anzahl von Menschen von einem Ort zum anderen zu bewegen; Es gibt nur so viele Leute, die man in den größten Bus setzen kann, aber man kann eine unbegrenzte Anzahl von Bussen oder Kleinwagen benutzen, die nur die Kapazität bieten, die man braucht - und nicht mehr.

Fehlertoleranz

In der Cloud-Programmierung gibt es eine bekannte Analogie, die als ‚Vieh vs Haustiere‘ bekannt ist. Wenn Sie es noch nicht gehört haben, geht es so:

Wenn Sie mit Haustieren umgehen, benennen und pflegen Sie sie. Wenn sie krank werden, pflegt man sie wieder gesund, was schwierig und sehr zeitraubend sein kann. Wenn Sie mit Vieh umgehen, fügen Sie ein nummeriertes Etikett ans Ohr. Wenn sie krank werden, machen Sie sie weg und ziehen weiter.

Das ist, wie es geschieht, die neue Realität der Programmierung. Anwendungen und Systeme wurden auf großen, teuren Servern erstellt, die von Betriebs-Mitarbeitern betreut wurden, um sie gesund zu halten. Wenn etwas mit einem dieser Server schief gegangen wäre, war die Aufgabe des Mitarbeiters zu tun, was notwendig ist, um sie wieder ganz zu machen und den Server und die Anwendung wiederherzustellen.

Bei der Cloud-Programmierung ist es ganz anders. Anstatt große, teure Server, haben Sie virtuelle Maschinen, die Einweg sind; Wenn etwas schief geht, fahren Sie den Server herunter und erzeugen einen neuen. Es gibt immer noch Betriebs-Mitarbeiter, aber anstatt einzelne Server zu pflegen und zu betreuen, ist es ihre Aufgabe, die Gesundheit des Gesamtsystems zu überwachen.

Es gibt definitive Vorteile für diese Architektur. Es ist leicht, einen ‚neuen‘ Server zu bekommen, ohne irgendwelche Probleme, die unweigerlich entstehen, wenn ein Server seit Monaten läuft oder sogar Jahre alt ist.

Wie bei der klassischen Infrastruktur sind Ausfälle der zugrunde liegenden Cloud-Infrastruktur (Hardware, Netzwerke und Software) unvermeidbar. Wenn Sie Ihre Cloud entwerfen, ist es entscheidend, dass Ihre Anwendung für eine Umgebung entworfen ist, in der Ausfälle jederzeit passieren können. Das klingt wie eine Drohung, aber es ist nicht; Durch die Gestaltung Ihrer Anwendung mit einem hohen Maß an Fehlertoleranz, machen Sie es auch belastbar und anpassungsfähiger, angesichts der Veränderung.

Fehlertoleranz ist für die Cloud-basierte Anwendung unerlässlich.

Automatisierung

Wenn eine Anwendung dazu gedacht ist, automatisch zu skalieren, um die Nachfrage zu erfüllen, ist es nicht möglich, manuelle Schritte in den Prozess der Bereitstellung einer Komponente anzuwenden. Automatisierung verringert auch die Zeit für die Wiederherstellung für Ihre Anwendung bei Komponentenausfällen, erhöht die Fehlertoleranz und die Widerstandsfähigkeit.

Programmatische Schnittstellen (APIs)

Wie viele Cloud-Anwendungen hat die Fractals-Anwendung eine ‚RESTful API‘ <http://en.wikipedia.org/wiki/Representational_state_transfer> `_. Sie können sich direkt mit ihr verbinden und Fraktale erzeugen, oder Sie können sie als Bestandteil einer größeren Anwendung integrieren. Jedes Mal, wenn eine Standardschnittstelle wie eine API verfügbar ist, wird automatisiertes Testen viel mehr machbar, wodurch die Softwarequalität erhöht wird.

Fraktale Anwendungsarchitektur

Die Fractals-Anwendung wurde mit den Prinzipien des vorherigen Unterabschnitts entworfen. Sie werden feststellen, dass in :doc: getting_started, wir die Anwendung in einem All-in-One-Stil, auf einer einzigen virtuellen Maschine einsetzen. Dies ist keine gute Praxis, aber weil die Anwendung Mikrodienste verwendet, um logische Anwendungsfunktionen zu entkoppeln, können wir dies leicht ändern.

digraph {
  API -> Database [color=green];
  API -> Database [color=orange];
  Database -> API [color=red];
  API -> Webinterface [color=red];
  API -> "Queue Service" [color=orange];
  "Queue Service" -> Worker [color=orange];
  Worker -> API [color=green];
}

Message-Warteschlangen werden verwendet, um die Kommunikation zwischen den Fractal-Anwendungsdiensten zu erleichtern. Die Fractal-Anwendung verwendet eine ‚Warteschlange‘ <https://www.rabbitmq.com/tutorials/tutorial-two-python.html> `_ (oder Task-Warteschlange), um Aufgaben an die Worker-Services zu verteilen.

Message-Warteschlangen arbeiten ähnlich wie eine Warteschlange (oder eine Reihe, für diejenigen von uns auf der anderen Seite des Ozeans) in einer Bank, die von mehreren Angestellten bedient wird. Die Meldungswarteschlange in unserer Anwendung bietet einen Feed von Arbeitsanfragen, die von den Arbeitnehmerdiensten ein-zu-Zeit genommen werden können, ob es einen einzelnen Workerservice oder Hunderte von ihnen gibt.

Dies ist ein ‚nützliches Muster‘ <https://msdn.microsoft.com/en-us/library/dn568101.aspx> `_ für viele Cloud-Anwendungen, die lange Listen von Anfragen bekommen und ein Pool von Ressourcen, von denen sie zu bedienen haben. Dies bedeutet auch, dass ein Arbeiter abstürzen kann und die Aufgaben von anderen Workern verarbeitet werden.

Bemerkung

Das ‚RabbitMQ Start Tutorial <https://www.rabbitmq.com/getstarted.html> `_ bietet eine gute Einführung in die Nachrichtenwarteschlangen.

digraph {
  rankdir=LR;
  Queue [shape="doublecircle"];
  API -> Queue;
  Queue -> "Worker 1";
  Queue -> "Worker 2";
}

Der Workerservice konsumiert Nachrichten aus der Arbeitswarteschlange und verarbeitet sie dann, um die entsprechende Fraktalbilddatei zu erstellen.

Natürlich gibt es auch eine Web-Schnittstelle, die eine menschlichere Art und Weise des Zugriffs auf die API bietet, um die erzeugten Fraktalbilder und eine einfache Befehlszeilenschnittstelle anzuzeigen.

screenshot of the webinterface

Es gibt auch mehrere Speicher-Backends (um die erzeugten Fraktalbilder zu speichern) und eine Datenbankkomponente (um den Status der Aufgaben zu speichern), aber wir sprechen über die in Mach es haltbar und Blockieren Sie Speicherplatz.

Wie die Fractals-Anwendung mit OpenStack interagiert

Die Magie entzaubert

Also, was genau war die Frage am Ende des vorherigen Abschnitts? Lassen Sie uns es noch einmal anschauen. In diesem Unterabschnitt erklären wir nur, was Sie bereits im vorigen Abschnitt gemacht haben. Sie müssen diese Befehle nicht mehr ausführen.

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i faafo -i messaging -r api -r worker -r demo
'''

instance_name = 'all-in-one'
testing_instance = conn.create_node(name=instance_name,
                                   image=image,
                                   size=flavor,
                                   ex_keyname=keypair_name,
                                   ex_userdata=userdata,
                                   ex_security_groups=[all_in_one_security_group])

Wir erklärten das Abbild und die Variante in get_started, also in den folgenden Abschnitten werden wir die anderen Parameter im Detail erklären, darunter ex_userdata (cloud-init) und ex_keyname (Schlüsselpaare ).

Einführung in cloud-init

cloud-init <https://cloudinit.readthedocs.org/en/latest/> `_ ist ein Tool, das Instanz-Konfigurationsaufgaben während des Bootens einer Cloud-Instanz ausführt und auf den meisten Cloud-Abbildern installiert wird. :code:`ex_userdata, der an create_node übergeben wurde, sind die an cloud-init übergebenen Konfigurationsdaten.

In diesem Fall präsentieren wir ein Shell-Skript als userdata <https://cloudinit.readthedocs.org/en/latest/topics/format.html#user-data-script> `_. Wenn :code:`create_node die Instanz erstellt, wird cloud-init als Shell-Skript in der Variable userdata ausgeführt.

Wenn während der Instanzerstellung ein SSH-Public-Key zur Verfügung gestellt wird, installiert cloud-init diesen Schlüssel auf einem Benutzerkonto. (Der Benutzername variiert zwischen Cloud-Abbildern.) Siehe ‚Erhalten von Abbildern <https://docs.openstack.org/image-guide/obtain-images.html> `_ Abschnitt der Abbildanleitung zur Anleitung, welche Benutzernamen Sie verwenden sollten, wenn SSHen. Wenn Sie noch Probleme beim Anmelden haben, fragen Sie Ihren Cloud-Anbieter, um den Benutzernamen zu bestätigen.

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i messaging -i faafo -r api -r worker -r demo
'''

Nachdem die Instanz erstellt wurde, lädt Cloud-init ein Skript namens install.sh herunter und führt es aus. Dieses Skript installiert die Fractals-Anwendung. Cloud-init kann Bash-Scripts und eine Reihe von verschiedenen Arten von Daten verarbeiten. Sie können sogar mehrere Arten von Daten bereitstellen. Weitere Informationen über cloud-init finden Sie in der offiziellen Dokumentation <https://cloudinit.readthedocs.org/en/latest/> `_.

Einführung in Schlüsselpaare

Sicherheit ist wichtig, wenn es um Ihre Instanzen geht; es kann nicht jeder auf sie zugreifen. Um die Anmeldung in einer Instanz zu aktivieren, müssen Sie während der Instanzerstellung den öffentlichen Schlüssel eines SSH-Schlüsselpaars angeben. Im Abschnitt Eins haben Sie ein Schlüsselpaar zu OpenStack erstellt und hochgeladen und Cloud-init für das Benutzerkonto installiert.

Sogar mit einem installierten Schlüssel, müssen Sie jedoch die entsprechenden Sicherheitsgruppenregeln aktiviert haben, um auf Ihre Instanz zuzugreifen.

Einführung in Sicherheitsgruppen

Sicherheitsgruppen sind Sätze von Netzwerkzugriffsregeln, die auf die Vernetzung einer Instanz angewendet werden. Standardmäßig ist nur Austritt (ausgehender) Verkehr erlaubt. Sie müssen explizit den Eintritt (Eingang) des Netzwerkzugriffs aktivieren, indem Sie eine Sicherheitsgruppenregel erstellen.

Warnung

Das Entfernen der von OpenStack erstellten Ausstiegsregel wird dazu führen, dass Ihre Instanz-Netzwerke zusammenbrechen.

Beginnen Sie mit dem Erstellen einer Sicherheitsgruppe für die All-in-One-Instanz und Hinzufügen der entsprechenden Regeln wie HTTP (TCP-Port 80) und SSH (TCP-Port 22):

all_in_one_security_group = conn.ex_create_security_group('all-in-one', 'network access for all-in-one application.')
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 80, 80)
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 22, 22)

Bemerkung

ex_create_security_group_rule () nimmt Bereiche von Ports als Eingabe. Aus diesem Grund sind die Anschlüsse 80 und 22 zweimal angegeben.

Sie können verfügbare Sicherheitsgruppen mit:

conn.ex_list_security_groups()

Sobald Sie eine Regel oder Gruppe erstellt haben, können Sie sie auch löschen:

conn.ex_delete_security_group_rule(rule)
conn.ex_delete_security_group(security_group)

Um zu sehen, welche Sicherheitsgruppen für eine Instanz gelten, können Sie:

conn.ex_get_node_security_groups(testing_instance)

Sobald Sie Berechtigungen konfiguriert haben, müssen Sie wissen, wo Sie auf die Anwendung zugreifen können.

Einführung in Floating-IPs

Wie in der traditionellen IT werden Cloud-Instanzen über IP-Adressen angesprochen, die OpenStack zuweist. Wie dies tatsächlich geschieht, hängt vom Netzwerk-Setup für Ihre Cloud ab. In einigen Fällen erhalten Sie einfach eine Internet-Router-fähige IP-Adresse, die direkt Ihrer Instanz zugewiesen wurde.

Der häufigste Weg für OpenStack-Clouds, um Internet-Router-fähige IP-Adressen zu Instanzen zuzuordnen, ist jedoch durch die Verwendung von Floating-IPs. Eine Floating-IP ist eine Adresse, die als Entität für sich selbst existiert und einer bestimmten Instanznetzwerkschnittstelle zugeordnet werden kann. Wenn eine Floating-IP-Adresse einer Instanznetzwerkschnittstelle zugeordnet ist, leitet OpenStack den für diese Adresse verknüpften Verkehr an die Adresse der internen Netzwerkschnittstellenadresse der Instanz zurück. Ihr Cloud-Anbieter bietet in der Regel Pools von Floating-IPs für Ihren Einsatz.

Um eine Floating-IP zu verwenden, müssen Sie zuerst Ihr Projekt eine IP zuordnen und sie dann der Netzwerkschnittstelle Ihrer Instanz zuordnen.

Bemerkung

Das Zuweisen einer Floating-IP-Adresse zu einer Instanz ändert nicht die IP-Adresse der Instanz, es bewirkt, dass OpenStack die Netzwerkübersetzungsregeln festlegt, um eine *zusätzliche IP-Adresse zuzulassen.

unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        print("Found an unused Floating IP: %s" % floating_ip)
        break

Wenn Sie keine frei Floating-IPs haben, die zuvor für Ihr Projekt reserviert wurden, wählen Sie zunächst einen Floating IP Pool, der von Ihrem Provider angeboten wird. In diesem Beispiel haben wir das erste ausgewählt und sind davon ausgegangen, dass es über IP-Adressen verfügt.

pool = conn.ex_list_floating_ip_pools()[0]

Bitte fordern Sie an, dass eine Adresse aus diesem Pool Ihrem Projekt zugewiesen wird.

unused_floating_ip = pool.create_floating_ip()

Nun, da Sie eine unbenutzte Floating-IP-Adresse für Ihr Projekt zugeordnet haben, fügen Sie es an eine Instanz.

conn.ex_attach_floating_ip_to_node(instance, unused_floating_ip)

Das bringt uns dahin, wo wir am Ende von / getting_started enden. Aber wohin gehen wir von hier

Aufteilung von Diensten über mehrere Instanzen hinweg

Wir haben über die Trennung von Funktionen in verschiedene Mikro-Dienste gesprochen und wie das uns ermöglicht, die Cloud-Architektur zu nutzen. Nun lassen Sie uns das in Aktion sehen.

Der Rest dieses Tutorials bezieht sich nicht auf die All-in-One-Instanz, die Sie in Abschnitt eins erstellt haben. Nehmen Sie sich einen Moment Zeit, um diese Instanz zu löschen.

Es ist einfach, Dienste in mehrere Instanzen aufzuteilen. Wir erstellen eine Controller-Instanz namens app-controller, die die API-, Datenbank- und Messaging-Dienste hostet. Wir werden auch eine Worker-Instanz namens app-worker-1 erstellen, die nur Fraktale erzeugt.

Der erste Schritt ist, die Controller-Instanz zu starten. Die Instanz verfügt über den API-Dienst, die Datenbank und den Messaging-Dienst, wie Sie aus den an das Installationsskript übergebenen Parametern sehen können.

Parameter

Beschreibung

Werte

-i

Installiere eines Dienstes

messaging (installiere RabbitMQ) und faafo (installiere die Faafo app).

-r

Aktivieren/Starten von etwas

api (Aktivieren und Starten des API-Dienstes) worker (Aktivieren und Starten des Worker Service) und demo (den Demo-Modus ausführen, um zufällige Fraktale anzufordern).

worker_group = conn.ex_create_security_group('worker', 'for services that run on a worker node')
conn.ex_create_security_group_rule(worker_group, 'TCP', 22, 22)

controller_group = conn.ex_create_security_group('control', 'for services that run on a control node')
conn.ex_create_security_group_rule(controller_group, 'TCP', 22, 22)
conn.ex_create_security_group_rule(controller_group, 'TCP', 80, 80)
conn.ex_create_security_group_rule(controller_group, 'TCP', 5672, 5672, source_security_group=worker_group)

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i messaging -i faafo -r api
'''

instance_controller_1 = conn.create_node(name='app-controller',
                                         image=image,
                                         size=flavor,
                                         ex_keyname='demokey',
                                         ex_userdata=userdata,
                                         ex_security_groups=[controller_group])

conn.wait_until_running([instance_controller_1])
print('Checking for unused Floating IP...')
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        break


if not unused_floating_ip:
    pool = conn.ex_list_floating_ip_pools()[0]
    print('Allocating new Floating IP from pool: {}'.format(pool))
    unused_floating_ip = pool.create_floating_ip()


conn.ex_attach_floating_ip_to_node(instance_controller_1, unused_floating_ip)
print('Application will be deployed to http://%s' % unused_floating_ip.ip_address)

Beachten Sie, dass dieses Mal, wenn Sie eine Sicherheitsgruppe erstellen, eine Regel enthält, die nur für Instanzen gilt, die Teil der Worker-Gruppe sind.

Als nächstes starten Sie eine zweite Instanz, die die Worker-Instanz sein wird:

instance_controller_1 = conn.ex_get_node_details(instance_controller_1.id)
if instance_controller_1.public_ips:
    ip_controller = instance_controller_1.private_ips[0]
else:
    ip_controller = instance_controller_1.public_ips[0]

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i faafo -r worker -e 'http://%(ip_controller)s' -m 'amqp://guest:guest@%(ip_controller)s:5672/'
''' % {'ip_controller': ip_controller}
instance_worker_1 = conn.create_node(name='app-worker-1',
                                        image=image,
                                        size=flavor,
                                        ex_keyname='demokey',
                                        ex_userdata=userdata,
                                        ex_security_groups=[worker_group])

conn.wait_until_running([instance_worker_1])
print('Checking for unused Floating IP...')
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        break


if not unused_floating_ip:
    pool = conn.ex_list_floating_ip_pools()[0]
    print('Allocating new Floating IP from pool: {}'.format(pool))
    unused_floating_ip = pool.create_floating_ip()


conn.ex_attach_floating_ip_to_node(instance_worker_1, unused_floating_ip)
print('The worker will be available for SSH at %s' % unused_floating_ip.ip_address)


Beachten Sie, dass Sie diese Instanz der worker_group hinzugefügt haben, damit sie auf den Controller zugreifen kann.

Wie Sie aus den an das Installationsskript übergebenen Parametern sehen können, definieren Sie diese Instanz als Worker-Instanz. Aber Sie übergeben auch die Adresse der API-Instanz und die Nachrichtenwarteschlange, damit der Worker Anfragen abholen kann. Das Installationsskript der Fractals-Anwendung akzeptiert mehrere Parameter.

Parameter

Beschreibung

Beispiel

-e

Die Endpunkt-URL des API-Dienstes.

http://localhost/

-m

Die Transport-URL des Messaging-Dienstes.

amqp://guest:guest@localhost:5672/

-d

Die Verbindungs-URL für die Datenbank (hier nicht verwendet).

sqlite:////tmp/sqlite.db

Nun, wenn Sie eine Anfrage für ein neues Fraktal machen, verbinden Sie sich mit der Controller-Instanz App-Controller, aber die Arbeit wird tatsächlich von einer separaten Worker-Instanz durchgeführt - :code:` app-worker-1` .

Melden Sie sich mit SSH an und nutzen Sie die Fractal App

Melden Sie sich mit SSH bei der Worker-Instanz an app-worker-1, unter Verwendung des vorherigen SSH-Schlüsselpaars ‚demokey‘. Beginnen Sie mit der IP-Adresse des Workers:

ip_instance_worker_1 = instance_worker_1.private_ips[0]
print(ip_instance_worker_1)

Jetzt können Sie mit SSH in die Instanz:

$ ssh -i ~/.ssh/id_rsa USERNAME@IP_WORKER_1

Bemerkung

Ersetzen Sie IP_WORKER_1 mit der IP-Adresse der Workerinstanz und USERNAME mit den entsprechenden Benutzernamen.

Sobald Sie angemeldet sind, überprüfen Sie, ob der Worker-Service-Prozess wie erwartet ausgeführt wird. Sie finden die Protokolle des Worker Service im Verzeichnis /var/log/supervisor/.

worker # ps ax | grep faafo-worker
17210 ?        R      7:09 /usr/bin/python /usr/local/bin/faafo-worker

Starten Sie top zur Überwachung der CPU-Nutzung des faafo-worker process.

Melden Sie sich jetzt bei der Controller-Instanz an app-controller, auch mit SSH, mit dem zuvor hinzugefügten SSH-Schlüsselpaar‘ demokey ‚ an .

$ ssh -i ~/.ssh/id_rsa USERNAME@IP_CONTROLLER

Bemerkung

Ersetzen Sie IP_CONTROLLER mit der IP-Adresse der Controller-Instanz und USERNAME an den entsprechenden Benutzernamen.

Überprüfen Sie, ob der API-Serviceprozess wie erwartet ausgeführt wird. Sie finden die Protokolle für den API-Dienst im Verzeichnis /var/log/supervisor/.

controller # ps ax | grep faafo-api
17209 ?        Sl     0:19 /usr/bin/python /usr/local/bin/faafo-api

Rufen Sie nun die Befehlszeilenschnittstelle der Fractal-Anwendung an (faafo), um ein paar neue Fraktale anzufordern. Der folgende Befehl fordert einige Fraktale mit zufälligen Parametern an:

controller # faafo --endpoint-url http://localhost --verbose create
2015-04-02 03:55:02.708 19029 INFO faafo.client [-] generating 6 task(s)

Überwachen Sie top auf der Worker-Instanz. Nach dem Aufruf faafo sollte der Prozess :code:` faafo-worker` beginnen, eine Menge von CPU-Zyklen zu verbrauchen.

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
17210 root      20   0  157216  39312   5716 R 98.8  3.9  12:02.15 faafo-worker

Um die Details eines bestimmten Fraktals zu zeigen, verwenden Sie den Unterbefehl show der Faafo CLI.

controller # faafo show 154c7b41-108e-4696-a059-1bde9bf03d0a
+------------+------------------------------------------------------------------+
| Parameter  | Value                                                            |
+------------+------------------------------------------------------------------+
| uuid       | 154c7b41-108e-4696-a059-1bde9bf03d0a                             |
| duration   | 4.163147 seconds                                                 |
| dimensions | 649 x 869 pixels                                                 |
| iterations | 362                                                              |
| xa         | -1.77488588389                                                   |
| xb         | 3.08249829401                                                    |
| ya         | -1.31213919301                                                   |
| yb         | 1.95281690897                                                    |
| size       | 71585 bytes                                                      |
| checksum   | 103c056f709b86f5487a24dd977d3ab88fe093791f4f6b6d1c8924d122031902 |
+------------+------------------------------------------------------------------+

Es stehen mehr Befehle zur Verfügung; erfahren Sie mehr über sie mit :code: faafo get –help, faafo list --help und faafo delete --help.

Bemerkung

Die Anwendung speichert die erzeugten Fraktalbilder direkt in der Datenbank, die von der API-Dienstinstanz verwendet wird. Das Speichern von Bilddateien in einer Datenbank ist nicht gut. Wir machen es hier als Beispiel nur als eine einfache Möglichkeit, mehreren Instanzen zu ermöglichen, Zugriff auf die Daten zu haben. Für die bewährte Praxis empfehlen wir die Speicherung von Objekten in Object Storage, die in Mach es haltbar abgedeckt ist.

Nächste Schritte

Sie sollten nun ein grundlegendes Verständnis der Architektur von Cloud-basierten Anwendungen haben. Darüber hinaus haben Sie Praxis, neue Instanzen zu starten, automatisch konfigurieren sie beim Booten, und sogar modularisieren eine Anwendung, so dass Sie mehrere Instanzen verwenden können, um sie auszuführen. Dies sind die grundlegenden Schritte zum Anfordern und Verwenden von Compute-Ressourcen, um Ihre Anwendung auf einer OpenStack-Cloud auszuführen.

Von hier aus gehen Sie zu Skalieren, um zu erfahren, wie Sie Ihre Anwendung weiter skalieren können. Oder versuchen Sie einen dieser Schritte im Tutorial:

Komplettes Codebeispiel

Die folgende Datei enthält den gesamten Code aus diesem Abschnitt des Tutorials. Mit diesem umfassenden Code-Beispiel können Sie den Code als einzelnes Skript anzeigen und ausführen.

Bevor Sie dieses Skript ausführen, bestätigen Sie, dass Sie Ihre Authentifizierungsinformationen, die Varianten-ID und die Image-ID festgelegt haben.

# step-1
userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i faafo -i messaging -r api -r worker -r demo
'''

instance_name = 'all-in-one'
testing_instance = conn.create_node(name=instance_name,
                                   image=image,
                                   size=flavor,
                                   ex_keyname=keypair_name,
                                   ex_userdata=userdata,
                                   ex_security_groups=[all_in_one_security_group])

# step-2
userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i messaging -i faafo -r api -r worker -r demo
'''

# step-3
all_in_one_security_group = conn.ex_create_security_group('all-in-one', 'network access for all-in-one application.')
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 80, 80)
conn.ex_create_security_group_rule(all_in_one_security_group, 'TCP', 22, 22)

# step-4
conn.ex_list_security_groups()

# step-5
conn.ex_delete_security_group_rule(rule)
conn.ex_delete_security_group(security_group)

# step-6
conn.ex_get_node_security_groups(testing_instance)

# step-7
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        print("Found an unused Floating IP: %s" % floating_ip)
        break

# step-8
pool = conn.ex_list_floating_ip_pools()[0]

# step-9
unused_floating_ip = pool.create_floating_ip()

# step-10
conn.ex_attach_floating_ip_to_node(instance, unused_floating_ip)

# step-11
worker_group = conn.ex_create_security_group('worker', 'for services that run on a worker node')
conn.ex_create_security_group_rule(worker_group, 'TCP', 22, 22)

controller_group = conn.ex_create_security_group('control', 'for services that run on a control node')
conn.ex_create_security_group_rule(controller_group, 'TCP', 22, 22)
conn.ex_create_security_group_rule(controller_group, 'TCP', 80, 80)
conn.ex_create_security_group_rule(controller_group, 'TCP', 5672, 5672, source_security_group=worker_group)

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i messaging -i faafo -r api
'''

instance_controller_1 = conn.create_node(name='app-controller',
                                         image=image,
                                         size=flavor,
                                         ex_keyname='demokey',
                                         ex_userdata=userdata,
                                         ex_security_groups=[controller_group])

conn.wait_until_running([instance_controller_1])
print('Checking for unused Floating IP...')
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        break


if not unused_floating_ip:
    pool = conn.ex_list_floating_ip_pools()[0]
    print('Allocating new Floating IP from pool: {}'.format(pool))
    unused_floating_ip = pool.create_floating_ip()


conn.ex_attach_floating_ip_to_node(instance_controller_1, unused_floating_ip)
print('Application will be deployed to http://%s' % unused_floating_ip.ip_address)

# step-12
instance_controller_1 = conn.ex_get_node_details(instance_controller_1.id)
if instance_controller_1.public_ips:
    ip_controller = instance_controller_1.private_ips[0]
else:
    ip_controller = instance_controller_1.public_ips[0]

userdata = '''#!/usr/bin/env bash
curl -L -s https://opendev.org/openstack/faafo/raw/contrib/install.sh | bash -s -- \
    -i faafo -r worker -e 'http://%(ip_controller)s' -m 'amqp://guest:guest@%(ip_controller)s:5672/'
''' % {'ip_controller': ip_controller}
instance_worker_1 = conn.create_node(name='app-worker-1',
                                        image=image,
                                        size=flavor,
                                        ex_keyname='demokey',
                                        ex_userdata=userdata,
                                        ex_security_groups=[worker_group])

conn.wait_until_running([instance_worker_1])
print('Checking for unused Floating IP...')
unused_floating_ip = None
for floating_ip in conn.ex_list_floating_ips():
    if not floating_ip.node_id:
        unused_floating_ip = floating_ip
        break


if not unused_floating_ip:
    pool = conn.ex_list_floating_ip_pools()[0]
    print('Allocating new Floating IP from pool: {}'.format(pool))
    unused_floating_ip = pool.create_floating_ip()


conn.ex_attach_floating_ip_to_node(instance_worker_1, unused_floating_ip)
print('The worker will be available for SSH at %s' % unused_floating_ip.ip_address)


# step-13
ip_instance_worker_1 = instance_worker_1.private_ips[0]
print(ip_instance_worker_1)

# step-14
Creative Commons Attribution 3.0 License

Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.