An sich klingt es recht einleuchtend: Das Ziel des Aufbaus einer Daten-Analyse-Plattform ist es, eine Plattform zur Analyse von Daten zur Verfügung zustellen.
Hier stellt sich natürlich direkt die erste Frage: Welche Daten sind vorhanden und auf welche Art sollen diese analysiert werden? Beide Teilaspekte sind ausschlaggebend für die Auswahl der Hard- und Softwarekomponenten.
Als kurzer Reminder: Bitte bedenken Sie, dass es sich nicht lohnt, eine Big Data Plattform aufzubauen, wenn Sie keine Big Data haben. Ja, natürlich klingt es gut zu sagen, dass man einen Hadoop-Cluster betreibt. Aber:
Aber nun wollen wollen wir uns um den Aufbau der Appliance kümmern, denn unsere Daten sind enorm groß und enorm volatil. Die Details der Daten werden wir uns in einem späteren Blog anschauen.
Zu Beginn sollten wir uns Gedanken gemacht haben, ob wir lieber einzelne, kleinere Systeme (z.B. Intel NUCs) erwerben oder ein großes System zur Verwaltung von virtuellen Maschinen nutzen möchten. Die Nutzung einer Cloud kommt für uns erst ein Mal nicht in Frage, da wir uns dem Thema Aufbau einer Appliance von allen Seiten aus nähern möchten.
Einzelne, kleinere Systeme haben den Vorteil, dass man mit wenigen starten und diese nach und nach erweitern kann. Da wir allerdings neben dem Hadoop-Cluster auch Systeme für die Datenflüsse und die Daten-Analyse benötigen, müssten wir gleich zu Beginn wenigstens 6 erwerben (1 Hadoop-Cluster-Master, 3 Hadoop-Cluster-Member, 1 Data-Flow- und 1 Data-Analytics-System). Die Gesamtkosten dieser Systeme kommen allerdings schon sehr an die Kosten für ein leistungsfähiges Multi-Core-System, so dass wir uns hier für letzteres entscheiden, auch und vor allem um verschiedene Konfigurationen (CPU, RAM, DISK) ausprobieren zu können. Hier eine mögliche Konfiguration:
Auf weitere Komponenten des Systems, wie beispielsweise Mainboard und Kühlung, gehen wir hier im Detail nicht näher ein, da es für den Aufbau der Appliance nicht relevant ist.
Ein Hadoop-Cluster im Stand-Alone-Modus auf einer/dieser leistungsfähigen Hardware zu betreiben, ist wenig sinnvoll, daher bauen wir nun die einzelnen Cluster-Member virtuell auf und haben dabei die Möglichkeit, einzelne Systeme später mit mehr oder weniger CPUs und Speicher auszustatten, um zu den verschiedenen Konfigurationen Erfahrungen zu sammeln.
Zur Virtualisierung stehen uns unterschiedliche Software-Komponenten zur Verfügung, die je nach Host-Betriebssystem ihre Stärken ausspielen. Um hier das Host-System für die virtuellen Umgebungen ein wenig in den Hintergrund zu drängen, wählen wir eine Software, die für viele Betriebssysteme zur Verfügung steht und sich zusätzlich sehr gut über die Kommandozeile konfigurieren läßt: Virtualbox von Oracle. Somit kann die Appliance sehr gut unter Microsoft Windows oder auch Linux als Host aufgebaut werden. Wichtig bei der Auswahl des Host-Betriebssystems ist nur die Unterstützung der NVIDIA Grafikkarte von MSI, da wir zur Datenanalyse später ggf. die vielen Rechenkerne der Grafikkarte verwenden möchten. Das wiederum schränkt das Betriebssystem des Hosts mehr ein als die Auswahl der Virtualisierungssoftware, denn eine einfache Nutzung der NVIDIA-CUDA-Software ist aktuell eher für Ubuntu-Linux (16.04 LTS) und Microsoft Windows 10, als für CentOS oder andere Linux-Derivate verfügbar.
Da die virtuellen Umgebungen, wie auch die Virtualisierungssoftware, betriebssystemunabhängig sind, ist es sogar möglich, die Appliance mit mehreren Host-Betriebssystemen aufzubauen und je nach Anforderung (oder Zeit und Lust) entsprechend umzuschalten.
Hinweis: Die Virtualisierung hätte auch mit Docker durchgeführt werden können. Ich habe mich für Virtualbox entschieden, da ich im Besonderen auf die Konfiguration und Verteilung der Software unter einem realen Betriebssystem eingehen wollte, so wie wir es, wenn Sie keine Appliance verwenden möchten, auch mit normalen PC-Systemen durchführen würden.
Für die einzelnen Cluster-Member müssen wir uns nun überlegen, wie wir diese (vorerst) konfigurieren, um die Speicherung der Daten und die darauf aufbauenden Analysen sinnvoll zu verteilen.
Als Best Practice für einen kleinen Cluster hat sich folgender Aufbau als sinnvoll erwiesen:
Somit kommen wir in Summe, für das erste Setup, auf insgesamt 6 Systeme mit 22 CPU-Cores, 48 GB RAM und 532 GB Disk. Da uns in der Appliance 16 CPU-Cores mit 32 Threads, 64 GB RAM und 3GB (1GB SSD + 2GB HDD) Disk zur Verfügung stehen, haben wir noch ein wenig Luft für Erweiterungen. Die Nutzung des Clusters wird uns später zeigen, ob die Konfiguration so hinreichend gewählt ist.
Um die einzelnen Cluster-Member nun als virtuelles System bereitzustellen, ist es erst ein mal notwendig, sich für eine Betriebssystem zu entscheiden. Die gute Nachricht zu Beginn: Aus der Liste der etablierten Linux-Distributionen (und Linux muss es schon sein) können wir frei wählen, da die Software, die wir verwenden, zum großen Teil “nur” auf einer lauffähigen JAVA-Umgebung aussetzt. Wir müssen somit nicht erst prüfen, ob der Paketmanager der Distribution die korrekte = aktuelle Version unserer Software bereitstellt.
Nun leider die schlechte Nachricht: Es gibt soooo viele etablierte Linux-Distributionen. Und eben so viele Vorlieben und gute Gründe, die eine Distribution der anderen vorzuziehen.
Meine Schwerpunkte bei der Auswahl für die Cluster-Member lagen allerdings im offiziellen Support der Distribution bei großen Hardware-Anbietern (um ggf. später die Umgebungen problemlos übertragen zu können) und in der Langzeit-Unterstützung der Distribution bei Software-Upates. Sehr bekannt ist die bereits zuvor genannte Distribution Ubuntu in der Version 16.04 LTS, sowie CentOS als freier Klon der Red-Hat-Distritution und Debian, die als Basis für Ubuntu & Co. dient. Da ich Debian bereits auf einen anderen Cluster verwende und Ubuntu 16.04 LTS als Host für die Appliance zum Einsatz kommt, habe ich CentOS verwendet, um möglichst viel beim Aufbau der Appliance lernen zu können.
Die Installation von CentOS als virtueller Maschine unter VirtualBox ist hinreichend unspektakulär und wurde bereits ausreichend in anderen Blogs und Videos beschrieben. Suchen Sie in der Internet-Suchmaschine Ihrer Wahl einfach nach install centos 7 on virtualbox und Sie werden sogar Video-Anleitungen hierzu finden. Die einzig wichtigen Punkte nach der Installation des Betriebssystems sind die korrekte Vergabe einer IP-Adresse und die Zuweisung des gewünschten Hostnames. Damit die virtuelle Maschine als eigenständige Umgebung im Netzwerk identifiziert wird, konfigurieren wir den Netzwerk Adapter (network adapter) als Bridged Adapter (attached to: Bridged Adapter) und wählen als Basis für diesen Adapter die Netzwerkkarte des Hosts.
Die Vergabe einer IP-Adresse geschieht in meinem Netzwerk über einen DHCP-Server, der glücklicherweise auch gleich bei Zuordnung der MAC-Adressse einen DNS-Eintrag vorhält.
Der Hostname bei CentOS wird nach erfolgreicher Anmeldung wie folgt gesetzt:
sudo hostnamectl set-hostname "meinHostname" --static
Die erste Maschine nutzen wir als Vorlage - ich habe sie analyticsTemplate genannt, um aus dieser die verschiedenen Cluster-Member zu erzeugen. In VirtualBox geht das über die Auswahl der VM, einem Klick mit der rechten Maustaste bei Auswahl Clone. Die Tastenkombination zur Ausführung dieser Funktion ist ctrl + o. Bitte wählen Sie in dem angezeigten Dialog auch Reinitialize the MAC address of all network cards aus, damit der DHCP-Server durch die neue MAC-Adresse eine neue Zuordnung zu einer IP-Adresse und ggf. des internen DNS-Eintrags vornehmen kann.
Auf diesem Wege legen wir dann folgende virtuellen Maschinen an:
Um gleich zu Beginn eine gute Basis für einen kontrolliert lauffähigen Cluster zu haben, binden wir die neuen Cluster-Member direkt in das System-Monitoring unserer Netzwerk-Infrastruktur ein.
Sie haben sich bisher mit dem Thema Monitoring noch nicht beschäftigt? Dann möchte ich Ihnen zumindest diese vier Systeme zur weiteren Berücksichtigung nennen.
Nagios ist sicherlich der Urvater des System-Monitoring in neueren (also nicht Mainframe-) Umgebungen. Viele andere Systeme orientieren sich daran. Ich habe mich allerdings für Zabbix entschieden, da mir auf der einen Seite ein schlanker Agent auf den Systemen wichtig war (da ich auch weniger leistungsfähige Systeme überwachen möchte, wie beispielsweise einen Raspberry Pi) und auf der anderen Seite eine einfache Abfrage beliebiger Metriken auf dem Monitoring-Client im Fokus stand. Der Zabbix-Agent benötigt kaum Arbeitsspeicher und erzeugt wenig Systemlast. Und er lässt sich einfach über die Agent-Konfiguration um eigene Skripte erweitern. Hinzu kommt eine sehr gute JMX-Überwachung, was im Hadoop-Umfeld sehr hilfreich ist, da die meisten Hadoop-Komponenten auf JAVA aufsetzen.
Die beiden Themen Big Data und Cloud gehören nicht zwingend zusammen, werden aber doch häufig gemeinsam genannt. Wird eine Anwendung als Cloud-Lösung konzipiert, so ist es nicht nur sehr wichtig, dass die einzelnen Systeme effizient miteinander kommunizieren. Es muss auch kurzfristig möglich sein, bestehende Cloud-Instanzen zu erweitern oder zu reduzieren.
Um dieses wiederum effizient durchführen zu können, wurde sehr schnell der Begriff Infrastructure as Code erzeugt, der bedeutet, dass die Bereitstellung einer Laufzeit-Umgebung nicht mehr aufwändig per Hand, sondern automatisiert über Konfigurationsdateien stattfindet, die man dann sogar in einem Versionierungssystem (wie beispielsweise GIT oder Mercurial) verwalten kann.
Unsere virtuellen Maschinen in der Appliance sind, mit etwas Abstand betrachtet, auch nichts anderes als Laufzeit-Umgebungen eines Cloud-Anbieters: Unsere Appliance ist quasi eine Cloud. Was uns als Übergang zur Softwareverteilung dienen soll.
Wie bereits erwähnt, basieren viele Hadoop-Komponenten auf JAVA und sind somit nach Bereitstellung einer JAVA-Runtime theoretisch lauffähig. Theoretisch lauffähig, da für den einwandfreien Betrieb der Komponente noch einige (wenige) Konfigurationen vorgenommen werden müssen.
Da wir nun bereits 6 Cluster-Member (und eine Template VM) haben, würde es bedeuten, wir müssten auf den 6 virtuellen Maschinen JAVA installieren. Sie könnten einwenden, dass wir JAVA auch zuvor in der Template VM hätten installieren können, was uns somit von der Installation auf 6 Maschinen befreit hätte. Das ist korrekt, verlagert das “Problem” allerdings nur ein wenig im Ablauf.
Wenn wir uns nun vorstellen, dass wir nicht mit 6, sondern mit 100 virtuellen Maschinen arbeiten, ist jedem gleich klar, dass wir eine andere Lösung benötigen.
Und diese Lösung heißt rsync und/mit ansible und funktioniert folgendermaßen: Um unabhängig vom Host der bisher 6 virtuellen Umgebungen zu sein, bauen wir uns eine 7. Umgebung als analyticsDevelopment auf und konfigurieren diese ebenso wie die 6 VMs zuvor (Network Adapter, IP, Hostname). Hint: Sie können natürlich auch eine neue VM mit einem weiteren Betriebssystem aufbauen. Die neue Umgebung hat ja einen anderen Anspruch an Stabilität als die Cluster-Member.
Da der Aufbau der Appliance auch den Zweck des Wissensaufbaus hat, habe ich als Betriebssystem für die analyticsDevelopment VM Fedora gewählt.
Folgende Schritte zur Verteilung (und Konfiguration) der Software sind nun notwendig:
Zur generellen Konfiguration im Cluster-Member, aber auch zur Ausführung von Ansible Skripten und Playbooks (siehe nachfolgende Beschreibungen), nutzen wir das Netzwerkprotokoll SSH (Secure Shell). Per SSH ist es möglich, sich direkt von seiner lokalen auf die Remote Maschine zu verbinden. Auch unterstützt SSH das Übertragen von Daten per SCP (Secure Copy), so dass wir auch in der Lage sind, Daten von A (lokal) nach B (remote) oder anders herum zu übertragen.
Um SSH nutzen zu können, benötigen wir einen SSH Client und einen SSH Server. Bei den bisher ausgewählten virtuellen Betriebssystemens der Appliance sind diese Voraussetzungen bereits gegeben.
Somit haben wir den:
Zur Überprüfung melden wir uns direkt an den virtuelen Maschinen an: Nach dem Start der VM via Virtualbox Überfläche können wir unseren Benutzernamen und das Passwort eintragen und befinden uns somit direkt in der entsprechenden Umgebung. Starten wir mit analyticsDevelopment.
Mit folgender Eingabe prüfen wir die Verfügbarkeit der SSH Client Binaries:
which ssh
> Ergebnis: /usr/bin/ssh
Hier prüfen wir, ob der SSH Server vorhanden (1) und geladen ist:
systemctl | grep sshd.service
> Ergebnis: sshd.service -> loaded active running -> OpenSSH server daemon
Sollte der Service vorhanden, aber nicht geladen sein, so würden wir als Ergebnis erhalten:
> Ergebnis: sshd.service -> loaded inactive (dead) -> OpenSSH server daemon
In diesem Fall können wir den Service wie folgt starten:
sudo systemctl start sshd.service
Eine umfangreichere Information zum Service erhalten wir durch:
sudo systemctl start sshd.service
Sollte der Service nicht installiert sein, so können wir diesen in einer aktuellen Fedora-Umgebung nachinstallieren:
sudo dnf install openssh-server
Hinweis: Mit Fedora 22 (Auslieferung im Mai 2015) wurde der neue Package Manager DNF (Dandified) für rpm-basierte Linux-Distributionen eingeführt. In centOS 7 wird weiterhin YUM (Yellowdog Updater, Modified) genutzt, da zur Zeit der Bereitstellung der Distribution (im Juli 2014) DNF in Fedora (damals noch Fedora 20 vom Dezember 2013) noch nicht verfügbar war.
Damit wir bei der späteren Verwendung, also der Anmeldung per SSH, an einem unseren Cluster-Member, nicht immer wieder nach einem Passwort gefragt werden, erzeugen wir einen SSH Schlüssel und übertragen diesen auf die einzelnen Umgebungen.
Zuerst erzeugen wir einen Schlüssel mit der RSA-Methode und einer Länge (vielleicht etwas übertrieben) 4096 und übertragen diesen anschliessend von unserer aktuellen Umgebung auf einen Cluster-Member (hier: analyticsMaster):
ssh-keygen -t rsa -b 4096
ssh-copy-id username@analyticsMaster
Hinweis: Bitte ersetzen Sie username durch den Namen, den Sie bei der Installation der virtuellen Umgebungen verwendet haben.
Nach der Übertragung des Schlüssels können wir uns nun ohne Eingabe des Passwortes auf dem Remote-System per SSH anmelden:
ssh username@analyticsMaster
Danach sieht es dann so aus, als ob wir uns direkt auf der Umgebung befinden würden.
Da wir in einem Cluster (oder sogar in einem Data Center) eine recht große Anzahl von Maschinen zu verwalten haben, ist es natürlich ratsam, diese nicht manuell zu verwalten bzw. zu konfigurieren. Zu diesem Zweck verwenden wir ansible.
ansible hat den Vorteil, dass es nur auf einer Maschine installiert werden muss und nur eine SSH Verbindung zu den zu verwaltenden Maschinen benötigt.
ansible verwenden wir auf analyticsDevelopment und können es wie folgt installieren:
sudo dnf install ansible
Von nun an können wir ansible durch den einfachen Aufruf des gleichgenannten Binaries verwenden und Systeme über die (bash-)Console verwalten:
ansible --help
ansible kennt allerdings auch sogenannte Strategiebücher (playbooks), um vollständige Abläufe zu automatisieren, wie beispielsweise:
Wie wir ansible konfigurieren und verwenden, sehen wir im nachfolgenden Punkt. Um die Arbeit mit den Playbooks allerdings ein wenig zu vereinfachen, legen wir zu Beginn einen Alias für den Aufruf des ansible-playbook-Binaries an:
alias ap='/usr/bin/ansible-playbook'
Für die Verteilung unserer Hadoop-Software-Komponenten könnten wir auch ansible verwenden, da dieses auch die Übertragung von Dateien von A nach B durch ein entsprechendes Modul erlaubt. Ich habe mir allerdings angewöhnt einige zentrale Funktionen zur Reduzierung der Komplexität zu trennen und nutze somit zur Übertragung von Daten (Synchronisation von Verzeichnisstrukturen) rsync.
Damit wir rsync allerdings verwenden können, muss es auf allen Maschinen installiert sein. Und genau das wollen wir nun exemplarisch mit ansible durchführen.
Hinweis: Wir werden später sehen, dass wir durch die Trennung der Funktionen (Synchronisation und Konfiguration) mittels rsync und ansible einen gewissen Mehraufwand haben. Wenn Ihnen das nicht zusagt, sollten Sie sich das zuvor genannte rsync-Modul von ansible im Nachgang mal anschauen.
Zur einfachen Verwendung von ansible setzt diese Komponente auf zwei Konfigurationsdateien:
Die hosts-Datei finden wir in folgendem Ordner:
/etc/ansible
Da es sich um einen System-Ordner handelt, können wir den Inhalt nur wie folgt verändern:
sudo vi /etc/ansible/hosts
.
[analytics:children]
analyticsDevelopmentGroup
analyticsMasterGroup
analyticsWorkerGroup
analyticsBrokerGroup
analyticsDataflowGroup
[analyticsDevelopmentGroup]
analyticsDevelopment
[analyticsMasterGroup]
analyticsMaster
[analyticsWorkerGroup]
analyticsWorker1
analyticsWorker2
analyticsWorker3
[analyticsBrokerGroup]
analyticsBroker1 anyVar=100
[analyticsDataflowGroup]
analyticsDataflow1
Was sehen wir hier? Erst einmal folgt der Aufbau der hosts-Datei einer INI-Datei, in welcher die Sektionen, wie beispielsweise analyticsDevelopmentGroup, über eckige Klammern definiert werden. In den Sektionen finden wir dann die relevanten Einträge (also die Namen der virtuellen Maschinen, die wir zuvor konfiguriert hatten (siehe oben)), die allerdings auch auf andere Sektoren verweisen können (Hierarchie), wie bei analytics:children.
Jeder (!) Eintrag der ansible-hosts-Datei kann später in den Playbooks referenziert werden. Einen besonderen Eintrag finden wir bei analyticsBroker1 und zwar anyVar=100. Auch diesen Eintrag, hier eine zu einer Maschine definierten Variablen (auf die wir hier aber nicht weiter eingehen werden) können wir verwenden, natürich nicht als Host-Referenz, aber als variablen Wert des speziellen Hosts.
Kommen wir nun zu den ansible-playbooks: Um die zugehörigen Dateien einfacher zu handhaben, legen wir in unserem home-Ordner (Hint: wir sind weiterhin in der VM analyticsDevelopment) nun einen entsprechenden Ordner an:
cd; mkdir Ansible
Die Playbooks sind in der YAML Syntax ausgedrückt und unser spezielles Playbook (hier: analytics-yum-install-rsync.yml) zur Installation von rsync auf allen (!) Cluster-Membern sieht wie folgt aus:
vi ~/Ansible/analytics-yum-install-rsync.yml
\
- hosts: analytics
become: yes
tasks:
- name: install rsync
yum:
name: rsync
state: latest
Die erste Zeile (hosts:) definiert die Inventur-Teilnehmer, bei denen die nachfolgenden Tätigkeiten (tasks) ausgeführt werden sollen. Wie zuvor erwähnt können wir alle Einträge der ansible-hosts verwenden. Wir könnten somit rsync anstatt auf allen Umgebungen nur auf einzelnen (z.B. analyticsWorker2) oder einzelnen Gruppen (z.B analyticsMasterGroup) oder auf eine Liste von Umgebungen (z.B. analyticsWorker1, analyticsWorker2, analyticsWorker3, analyticsMasterGroup) installieren. Zur Installation der Software verwenden wir wiederum ein ansible-Modul (hier: yum), welches den Namen (name:) der Software und die Version (state:) erwartet.
Da wir zuvor einen Alias für die Ausführung der ansible-playbooks angelegt hatten, können wir nun das erste Playbook zur Installation von rsync ausführen:
ap ~/Ansible/analytics-yum-install-rsync.yml
Folgende Informationen erhalten wir während der Ausführung:
PLAY [analytics] *******************
TASK [Gathering Facts] *************
ok: [analyticsWorker1]
ok: [analyticsMaster]
ok: [analyticsDevelopment]
ok: [analyticsWorker3]
ok: [analyticsBroker1]
ok: [analyticsWorker2]
ok: [analyticsDataflow1]
TASK [install rsync] ***************
ok: [analyticsDevelopment]
ok: [analyticsMaster]
ok: [analyticsWorker1]
ok: [analyticsWorker2]
ok: [analyticsDataflow1]
ok: [analyticsWorker3]
ok: [analyticsBroker1]
PLAY RECAP *************************
analyticsBroker1 : ok=2 changed=1 unreachable=0 failed=0
analyticsDataflow1 : ok=2 changed=1 unreachable=0 failed=0
analyticsDevelopment : ok=2 changed=1 unreachable=0 failed=0
analyticsMaster : ok=2 changed=1 unreachable=0 failed=0
analyticsWorker1 : ok=2 changed=1 unreachable=0 failed=0
analyticsWorker2 : ok=2 changed=1 unreachable=0 failed=0
analyticsWorker3 : ok=2 changed=1 unreachable=0 failed=0
Die Ausgabe startet mit der Angabe der Inventur-Teilnehmer (analytics) und der Einreichbarkeit dieser (Gathering Facts). Sollte ein Teilnehmer nicht erreichbar sein, so würde dieses in diesem Bereich aufgeführt und farblich von dem erreichten Teilnehmer (eigentlich in grün dargestellt) gekennzeichnet. Darauf folgt die Auslistung der im playbook definierten Tasks, hier install rsync. Die Teilnehmer, für die die Software installiert wurde, sind gelb gekennzeichnet.
Die Summe der in den Tasks gelb gekennzeichneten Ausführungen (im Blog leider nicht erkennbar) werden in PLAY RECAP unter changed aufsummiert. Da wir hier nur einen Tasks ausgeführt und, innerhalb dessen, keine Fehler erzeugt haben, sind alle Teilnehmer mit changed=1 gekennzeichnet.
Gerne können Sie sich nun an den einzelnen Maschinen anmelden und prüfen, ob Sie dort rsync vorfinden.
rsync --version
Da wir uns zuvor mit den Playbooks von ansible vertraut gemacht haben, geht von nun an alles ganz schnell und einfach.
Denn die Installation folgt nun einem einfacher Muster: Entweder wir übertragen Komponenten per rsync und konfigurieren diese im Anschluss mit ansible oder wir installieren und konfigurieren die notwendige Komponente direkt mit ansible.
Für JAVA nutzen wir nun das erste Vorgehen und müssen zu Beginn die gewünschte JAVA Version von der Webseite von Oracle herunterladen. Da wir (erst einmal) keinen JAVA-Code entwickeln wollen, würde uns sogar die Server JRE reichen.
Hinweis: wir befinden uns nach wie vor auf dem analyticsDevelopment.
Damit wir eine allgemein gültige und gut nachvollziehbare Ordnerstruktur haben, legen wir unsere nun folgenden Ordner unter /opt an. Und damit wir das nicht auf alle Maschinen immer und immer wieder tun müssen, nutzen wir hier natürlich ein ansible-playbook, das wie folgt aussieht und das wir nun nach und nach erweitern:
- hosts: analytics
tasks:
- name: create oracle folder javap
become: true
file:
path: /opt/oracle-java
state: directory
owner: username
group: usergroup
mode: 0775
Bitte ersetzen Sie username und usergroup durch die für Sie passenden Werte.
Nach dem Download des Packets entpacken wir dieses nun unter /opt/oracle-java:
tar xzf server-jre-8u152-linux-x64.tar.gz --directory /opt/oracle-java
Da Oracle seine Dateien in Ordnerstrukturen vorhält, die den Versionsnummern der JRE folgen, erhalten wir nach dem entpacken in /opt/oracle-java einen Unterordner mit der Bezeichnung: jdk1.8.0_152
Um nicht immer wieder die Skripte anpassen zu müssen, falls wir eine neue JAVA-Version verwenden, legen wir einen symbolischen Link zu diesem Ordner mit dem Namen jdk8 an und verweisen fortan auf diesen Link:
ln -s /opt/oracle-java/jdk1.8.0_152 /opt/oracle-java/jdk8
Zur Verteilung der JRE nutzen wir nun rsync und können mit nachfolgendem bash-Skript, welches wir in /opt/oracle-java als rsyncAnalytics.sh speichern, die erste Komponente auf die Umgebungen verteilen:
currentdir=`pwd`
rsync -avxP --delete-after $currentdir/ username@analyticsMaster:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsWorker1:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsWorker2:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsWorker3:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsBroker1:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsDataflow1:$currentdir/
Was passiert hier? Wir synchrosieren und validieren die Synchronisation (Parameter v) den aktuellen Ordner (currentdir=`pwd`) mit dem Remote-Ordner im archiv-Modus (Parameter a) und stellen sicher, dass die File-Systeme der beiden Umgebungen kompatibel sind (Parameter x). Nach der Übertragung werden im Ziel alle Dateien gelöscht, die nicht in der Quelle sind (Parameter –delete-after), so dass wir im Ziel immer eine saubere “Installation” haben.
Achtung: Das bedeutet natürlich im Umkehrschluss, dass wir somit auch alle Daten löschen würden, die sich im Ziel-Ordner befinden. Daher müssen wir bei der Konfiguration immer darauf achten, dass ausführbare Dateien und Daten immer getrennt gespeichert werden. Das klingt selbstverständlich, ist es aber leider nicht immer.
Um JAVA nun auf den Umgebungen nutzen zu können, müssen wir es dort nur noch bekannt geben. Und das geht wieder einfach und per ansible (analytics-set-java.yml):
- hosts: analytics
tasks:
- name: check/insert JAVA_HOME
blockinfile:
dest: "{{ ansible_env.HOME }}/.bashrc"
marker: "# {mark} ANSIBLE MANAGED BLOCK -- JAVA"
block: |
export JAVA_HOME=/opt/oracle-java/jdk8
export PATH=$PATH:$JAVA_HOME/bin
create: yes
- name: update-alternative install java
become: true
alternatives:
name: java
link: /usr/bin/java
path: /opt/oracle-java/jdk8/bin/java
Wenn Sie mögen, können Sie auch für javac und javaws diese Alternativen nach demselben Schema setzen.
Zur Kontrolle, ob alles geklappt hat, melden wir uns kurz an einer der virtuellen Umgebungen an und prüfen die Verfügbarkeit und Version von JAVA:
ssh username@@analyticsWorker3
java --version
Zur Installation von Zabbix nutzen wir wie schon zuvor das yum-Modul von ansible. Hierbei fügen wir zu Beginn das entsprechende Repository von Zabbix ein und führen dann die Installation aus (analytics-yum-install-zabbix-repo-agent.yml):
- hosts: analytics
become: yes
tasks:
- name: install the zabbix 3.2 rpm from a remote repo
yum:
name: http://repo.zabbix.com/zabbix/3.2/rhel/7/x86_64/zabbix-release-3.2-1.el7.noarch.rpm
state: present
- name: install zabbix-agent
yum:
name: zabbix-agent
state: latest
Hinweis: Da mein Zabbix-Server noch auf Version 3.2 beruht, nutzen ich hier auch das Repository von 3.2 für den Agent. Bitte passen Sie diese Version Ihren Anforderungen nach an.
Der Agent muss nicht sonderlich aufwendig konfiguriert werden. Er benötigt nur drei Angaben zur Kommunikation mit dem Zabbix-Server.
- hosts: analytics
tasks:
- name: Find and replace values from names in zabbix_agentd.conf
become: true
lineinfile:
create: no
dest: /etc/zabbix/zabbix_agentd.conf
regexp: "^{{ item.name }}"
line: "{{ item.name }}{{ item.value }}"
backrefs: yes # (uncommented because of 'create: no')
state: present
with_items:
- { name: 'Server=', value: '192.168.n.m' }
- { name: 'ServerActive=', value: '192.168.n.m' }
- { name: 'Hostname=', value: 'HostNameZabbixServer' }
- name: enable zabbit-agent service
become: true
service:
name: zabbix-agent
state: started
Um jedoch nicht mehrfach denselben Task in das Skript aufzunehmen, besteht in ansible die Möglichkeit, über eine Liste von Einträge zu iterieren. Genau das passiert hier mit with_items.
Der darüber stehende Task wird dreimal ausgeführt und ergänzt in der Konfigurationsdatei /etc/zabbix/zabbix_agentd.conf den Eintrag Server, ServerActive und Hostname mit den mit value vorgegeben Werten, die Sie natürlich Ihrer Umgebung nach entsprechend anpassen müssen.
Nachdem der Tasks erolgreich durchgelaufen ist, wird der Agent mit einem zweiten Task (mit dem service-Modul) gestartet.
Da wir uns erst in einem späteren Tutorial um die Daten und Datenstrukturen kümmern, können wir hier und jetzt noch nicht entscheiden, welche Komponenten aus dem Hadoop-Öko-System die für unsere Anforderungen Richtigen sind.
Wo wir uns aber sicher sind, ist, dass wir ein HDFS, Hadoop Distributed File System, benötigen werden. Also starten wir damit.
Das vorgehen ist dem der Installation von JAVA sehr ähnlich:
Konkret sieht das dann wie folgt aus:
wget http://ftp.halifax.rwth-aachen.de/apache/hadoop/common/hadoop-2.8.2/hadoop-2.8.2.tar.gz
.
# Dateiname: analytics-create-apache-opt.yml
- hosts: analytics
tasks:
- name: create apache folder hadoop
become: true
file:
path: /opt/apache-hadoop
state: directory
owner: username
group: usergroup
mode: 0775
.
ap analytics-create-apache-opt.yml
tar xzf hadoop-2.8.2.tar.gz --directory /opt/apache-hadoop
ln -s /opt/apache-hadoop/hadoop-2.8.2 /opt/apache-hadoop/hadoop
(hier passiert ein kleines Wunder; Erläuterung etwas weiter unten)
# Dateiname: rsyncAnalytics.sh
currentdir=`pwd`
rsync -avxP --delete-after $currentdir/ username@analyticsMaster:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsWorker1:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsWorker2:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsWorker3:$currentdir/
rsync -avxP --delete-after $currentdir/ username@analyticsDataflow1:$currentdir/
ssh username@analyticsWorker1 rm $currentdir/hadoop/etc/hadoop/slaves
ssh username@analyticsWorker2 rm $currentdir/hadoop/etc/hadoop/slaves
ssh username@analyticsWorker3 rm $currentdir/hadoop/etc/hadoop/slaves
ssh username@analyticsDataflow1 rm $currentdir/hadoop/etc/hadoop/slaves
.
sh /opt/apache-hadoop/rsyncAnalytics.sh
.
# Dateiname: analytics-set-hadoop.yml
- hosts: analytics
tasks:
- name: check/insert HADOOP_HOME
blockinfile:
dest: "{{ ansible_env.HOME }}/.bashrc"
marker: "# {mark} ANSIBLE MANAGED BLOCK -- HADOOP"
block: |
export HADOOP_HOME=/opt/apache-hadoop/hadoop
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export PATH=$PATH:$HADOOP_HOME/bin
create: yes
- hosts: analyticsMasterGroup
tasks:
- name: create apache folder haddop namenode
become: true
file:
path: /analyticsData/data/hadoop/hdfs/namenode
state: directory
owner: username
group: usergroup
mode: 0750
- hosts: analyticsWorkerGroup
tasks:
- name: create apache folder haddop datanode
become: true
file:
path: /analyticsData/data/hadoop/hdfs/datanode
state: directory
owner: username
group: usergroup
mode: 0750
.
ap analytics-set-hadoop.yml
Nach der Anlage des symbolischen Links ist ein kleines Wunder passiert. Und zwar das Wunder der Konfiguration des HDFS-Clusters. Dieser Blog dient uns zum Verständnis des Aufbaus einer Data Analytics Plattform. Keine Sorge, ich bleibe Ihnen die Konfiguration von HDFS nicht schuldig. Ich wollte nur diese ohnehin schon sehr umfangreich Seite nicht mit noch umfangreicheren ansible-playbook-Skripten oder HDFS-Konfigurationsdateien füllen. Daher finden Sie hier die notwendigen Konfigurationsdateien unseres HDFS-Clusters.
Der letzte Schritt zum Bereitstellen des Hadoop Distributed File Systems ist die Formatierung dessen. Das klingt beängstigend. Aber machen Sie sich keine Sorge, denn erstens haben wir oben schon etwas vorgesorgt und zweitens ist der Vorgang jederzeit reproduzierbar.
Warum haben wir vorgesorgt? Nun, in dem Strategiebuch analytics-set-hadoop.yml haben wir für den analyticsMaster und für die einzelnen Worker (analyticsWorker1, analyticsWorker2, analyticsWorker3) einen besonderen Ordner (namenode bzw. datanode) angelegt. Wie Sie sehen befinden sich beide Ordner ausserhalb der ausführbaren Apache Hadoop Dateien (/opt/apache-hadoop).
In diesen beiden Ordner befindet sich nach der Formatierung sozusagen das HDFS, denn an sich wird dieses nur über eine gewisse Anzahl von Dateien repräsentiert, die von Namenode des HDFS-Master verwaltet werden.
Sollten wir somit nach der Formatierung des HDFS feststellen, dass uns das gar nicht gefällt, was wir gemacht haben, so löschen wir einfach die Inhalte der beiden Ordner und starten neu. That’s it.
Zur Bereitstellung des HDFS verbinden wir uns nun mit dem analyticsMaster und formatieren den HDFS-Cluster:
ssh username@analyticsMaster
hdfs namenode -format
Zum Schluss müssen wir “nur noch” den HDFS-Cluster starten und können uns dann mit der WebUI, welches standardmäßig über Port 50070 erreichbar ist, verbinden:
/opt/apache-hadoop/hadoop/sbin/start-dfs.sh