Die heiße Kartoffel im Raum der containerisierten Lösungen sind persistente Dienste. Zustandslose Anwendungen sind einfach und trivial, aber die Bereitstellung eines persistenten Dienstes wie ElasticSearch ist eine ganz andere Sache. In diesem Blogbeitrag zeigen wir Ihnen, wie einfach es auf dieser Plattform ist, ElasticSearch-Cluster zu erstellen. Der Schlüssel dazu ist die Möglichkeit, die externen IP-Adressen und Portnummern aller Cluster-Mitglieder in Consul abzurufen und die wiederverwendbaren Vorlagen der CoreOS Unit File. Die vorgestellte Lösung ist eine gebrauchsfertige ElasticSearch-Komponente für Ihre Anwendung. Diese Lösung:
- verwendet Empheral Ports, so dass wir tatsächlich mehrere ElasticSearch-Knoten auf demselben Host betreiben können
- mountet persistenten Speicher unter jedem Knoten, um Datenverluste bei Serverabstürzen zu verhindern
- nutzt die Leistungsfähigkeit der CoreOS Unit-Vorlagendateien für die Bereitstellung neuer ElasticSearch-Cluster.
In den vorangegangenen Blog-Beiträgen haben wir unsere Hochverfügbare Docker-Container-Plattform mit CoreOS und Consul definiert und gezeigt , wie wir einem Docker-Container persistenten Speicher hinzufügen können. Sobald diese Plattform gebootet ist, müssen Sie nur noch die folgende Fleet-Unit-Systemvorlagendatei elasticsearch@.service einreichen und 3 oder mehr Instanzen starten, um einen ElasticSearch-Cluster einzusetzen.
Booten der Plattform
Um den ElasticSearch-Cluster in Aktion zu sehen, starten Sie zunächst unsere CoreOS-Plattform.
[bash]
git clone https://github.com/mvanholsteijn/coreos-container-platform-as-a-service
cd coreos-container-platform-as-a-service/vagrant
vagrant up
./is_platform_ready.sh
[/bash]
Starten eines ElasticSearch-Clusters
Sobald die Plattform gestartet ist, übermitteln Sie die elasticsearch Unit-Datei und starten drei Instanzen:
[bash]
export FLEETCTL_TUNNEL=127.0.0.1:2222
cd ../fleet-units/elasticsearch
fleetctl submit elasticsearch@.service
fleetctl start elasticsearch@{1..3}
[/bash]
Warten Sie nun, bis alle elasticsearch-Instanzen laufen, indem Sie den Status der Einheit überprüfen.
[bash]
fleetctl list-units
...
UNIT MACHINE ACTIVE SUB
elasticsearch@1.service f3337760.../172.17.8.102 active running
elasticsearch@2.service ed181b87.../172.17.8.103 active running
elasticsearch@3.service 9e37b320.../172.17.8.101 active running
mnt-data.mount 9e37b320.../172.17.8.101 active mounted
mnt-data.mount ed181b87.../172.17.8.103 active mounted
mnt-data.mount f3337760.../172.17.8.102 active mounted
[/bash]
Erstellen Sie einen ElasticSearch-Index
Jetzt, wo der ElasticSearch-Cluster läuft, können Sie einen Index zum Speichern von Daten erstellen.
[bash]
curl -XPUT https://elasticsearch.127.0.0.1.xip.io:8080/megacorp/ -d
'{ "settings" : { "index" : { "number_of_shards" : 3, "number_of_replicas" : 2 } } }'
[/bash]
Einige Dokumente einfügen
[bash]
curl -XPUT https://elasticsearch.127.0.0.1.xip.io:8080/megacorp/employee/1 -d@- <<!
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
!
curl -XPUT https://elasticsearch.127.0.0.1.xip.io:8080/megacorp/employee/2 -d@- <<!
{
"first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums",
"interests": [ "music" ]
}
!
curl -XPUT https://elasticsearch.127.0.0.1.xip.io:8080/megacorp/employee/3 -d@- <<!
{
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}
!
[/bash]
Und fragen Sie den Index ab
[bash]
curl -XGET https://elasticsearch.127.0.0.1.xip.io:8080/megacorp/employee/_search?q=last_name:Smith
...
{
"took": 50,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"hits": {
"total": 2,
...
}
[/bash]
Neustart des Clusters
Selbst wenn Sie den gesamten Cluster neu starten, bleiben Ihre Daten erhalten.
[bash]
fleetctl stop elasticsearch@{1..3}
fleetctl list-units
fleetctl start elasticsearch@{1..3}
fleetctl list-units
curl -XGET https://elasticsearch.127.0.0.1.xip.io:8080/megacorp/employee/_search?q=last_name:Smith
...
{
"took": 50,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0
},
"hits": {
"total": 2,
...
}
[/bash]
Öffnen Sie die Konsole
Schließlich können Sie die Server und die Verteilung des Index im Cluster sehen, indem Sie die Konsole elasticsearch.127.0.0.1.xip.io:8080/_plugin/head/ öffnen.
Andere ElasticSearch-Cluster bereitstellen
Die Änderung des Namens der Vorlagendatei ist das Einzige, was Sie brauchen, um einen anderen ElasticSearch-Cluster einzusetzen.
[bash]
cp elasticsearch@.service my-cluster@.service
fleetctl submit my-cluster@.service
fleetctl start my-cluster@{1..3}
curl my-cluster.127.0.0.1.xip.io:8080
[/bash]
Wie funktioniert das?
Das Starten eines Knotens in einem ElasticSearch-Cluster ist recht trivial, wie die unten stehende Befehlszeile zeigt:
[bash]
exec gosu elasticsearch elasticsearch
--discovery.zen.ping.multicast.enabled=false
--discovery.zen.ping.unicast.hosts=$HOST_LIST
--transport.publish_host=$PUBLISH_HOST
--transport.publish_port=$PUBLISH_PORT
$@
[/bash]
Wir verwenden das Unicast-Protokoll und geben unseren eigenen Veröffentlichungshost und Port sowie eine Liste der IP-Adressen und Portnummern aller anderen Knoten im Cluster an.
Suche nach den anderen Knoten im Cluster
Aber wie finden wir die anderen Knoten des Clusters? Das ist ganz einfach. Wir fragen die Consul REST API nach allen Einträgen mit demselben Servicenamen ab, die als "es-transport" gekennzeichnet sind. Dies ist der Dienst, der von ElasticSearch auf Port 9300 angeboten wird.
[bash]
curl -s https://consul:8500/v1/catalog/service/$SERVICE_NAME?tag=es-transport
...
[
{
"Node": "core-03",
"Address": "172.17.8.103",
"ServiceID": "elasticsearch-1",
"ServiceName": "elasticsearch",
"ServiceTags": [
"es-transport"
],
"ServiceAddress": "",
"ServicePort": 49170
},
{
"Node": "core-01",
"Address": "172.17.8.101",
"ServiceID": "elasticsearch-2",
"ServiceName": "elasticsearch",
"ServiceTags": [
"es-transport"
],
"ServiceAddress": "",
"ServicePort": 49169
},
{
"Node": "core-02",
"Address": "172.17.8.102",
"ServiceID": "elasticsearch-3",
"ServiceName": "elasticsearch",
"ServiceTags": [
"es-transport"
],
"ServiceAddress": "",
"ServicePort": 49169
}
]
[/bash]
Die Umwandlung in eine kommagetrennte Liste von Netzwerkendpunkten erfolgt mit dem folgenden jq-Befehl:
[bash]
curl -s https://consul:8500/v1/catalog/service/$SERVICE_NAME?tag=es-transport |
jq -r '[ .[] | [ .Address, .ServicePort | tostring ] | join(":") ] | join(",")'
[/bash]
Finden Sie Ihren eigenen Netzwerk-Endpunkt
Wie Sie in der obigen JSON-Ausgabe sehen können, hat jeder Serviceeintrag eine eindeutige ServiceID. Um unseren eigenen Endpunkt zu erhalten, verwenden wir den folgenden jq-Befehl:
[bash]
curl -s https://consul:8500/v1/catalog/service/$SERVICE_NAME?tag=es-transport |
jq -r ".[] | select(.ServiceID=="$SERVICE_9300_ID") | .Address, .ServicePort"
[/bash]
Ermitteln der Anzahl der Knoten im Cluster
Die vorgesehene Anzahl der Knoten im Cluster wird ermittelt, indem die Anzahl der Fleet-Unit-Instanzdateien in CoreOS beim Start gezählt und diese Zahl als Umgebungsvariable übergeben wird.
[bash]
TOTAL_NR_OF_SERVERS=$(fleetctl list-unit-files | grep '%p@[^.][^.]*.service' | wc -l)
[/bash]
Das %p bezieht sich auf den Teil der Fleet-Unit-Datei vor dem @-Zeichen.
Der Docker-Befehl run
Der Docker-Befehl zum Ausführen wird unten angezeigt. ElasticSearch stellt zwei Ports zur Verfügung: Port 9200 stellt eine REST-Api für die Clients zur Verfügung und Port 9300 wird als Transportprotokoll zwischen den Knoten im Cluster verwendet. Jeder Port ist ein Dienst und entsprechend gekennzeichnet.
[bash]
ExecStart=/bin/sh -c "/usr/bin/docker run --rm
--name %p-%i
--env SERVICE_NAME=%p
--env SERVICE_9200_TAGS=http
--env SERVICE_9300_ID=%p-%i
--env SERVICE_9300_TAGS=es-transport
--env TOTAL_NR_OF_SERVERS=$(fleetctl list-unit-files | grep '%p@[^.][^.]*.service' | wc -l)
-P
--dns $(ifconfig docker0 | grep 'inet ' | awk '{print $2}')
--dns-search=service.consul
cargonauts/consul-elasticsearch"
[/bash]
Die Optionen werden in der folgenden Tabelle erläutert:
| Option | Beschreibung |
| --env SERVICE_NAME=%p | Der Name dieses Dienstes, der in Consul bekannt gegeben werden soll, ergibt einen FQDN von %p.service.consul und wird als Clustername verwendet. %p bezieht sich auf den ersten Teil der Flotteneinheit-Vorlagendatei bis zum @. |
| --env SERVICE_9200_TAGS=www | Das Tag, das dem Dienst an Port 9200 zugewiesen ist. Dieser wird vom http-Router erfasst, so dass jeglicher http-Verkehr zum Host elasticsearch direkt zu diesem Port geleitet wird. |
| --env SERVICE_9300_ID=%p-%i | Die eindeutige ID dieses Dienstes in Consul. Sie wird vom Startskript verwendet, um den externen Port und die IP-Adresse des Dienstes in Consul zu finden und wird als Knotenname für den ES-Server verwendet. %p bezieht sich auf den ersten Teil der Fleet-Unit-Vorlagendatei bis zum @ %i bezieht sich auf den zweiten Teil der Fleet-Unit-Datei bis zur .service. |
| --env SERVICE_9300_TAGS=es-transport | Das Tag, das dem Dienst an Port 9300 zugewiesen wurde. Dies wird vom Startskript verwendet, um die anderen Server im Cluster zu finden. |
| --env TOTAL_NR_OF_SERVERS=$(...) | Die Anzahl der übermittelten Unit-Dateien wird gezählt und als Umgebungsvariable 'TOTAL_NR_OF_SERVERS' übergeben. Das Startskript wartet, bis diese Anzahl von Servern tatsächlich in Consul registriert ist, bevor es die ElasticSearch-Instanz startet. |
| --dns $(...) | Stellen Sie DNS so ein, dass es die Schnittstelle docker0 abfragt, wo Consul an Port 53 gebunden ist. (Die IP-Adresse der Schnittstelle docker0 wird nach dem Zufallsprinzip aus einem bestimmten Bereich ausgewählt). |
| -dns-search=service.consul | Die standardmäßige DNS-Suchdomäne. |
Quellen
Die Quellen für das ElasticSearch-Repository finden Sie auf github.
| Quelle | Beschreibung |
| start-elasticsearch-clustered.sh | komplettes Startskript von elasticsearch |
| elasticsearch | CoreOS-Flotten-Unit-Dateien für elasticsearch-Cluster |
| consul-elasticsearch | Quellen für das Consul ElasticSearch-Repository |
Fazit
CoreOS Fleet Template Unit Files sind eine leistungsstarke Methode, um gebrauchsfertige Komponenten für Ihre Plattform bereitzustellen. Wenn Sie clusterfähige Anwendungen einsetzen möchten, ist eine Service-Registry wie Consul unerlässlich.
Verfasst von

Mark van Holsteijn
Mark van Holsteijn is a senior software systems architect at Xebia Cloud-native solutions. He is passionate about removing waste in the software delivery process and keeping things clear and simple.
Unsere Ideen
Weitere Blogs
Contact



