# Load Balancing

Der Load Balancer nimmt die Anfragen der Clients entgegen und leitet diese an den am besten geeigneten Server weiter. Somit stellen Sie sicher, dass Enginsight auch bei einer Vielzahl eingehender Anfragen optimal läuft.

<figure><img src="https://3532046264-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LTMe1v0eboWCAUTQHbT-3758922206%2Fuploads%2FOfCl7PtEza66PIdGxCpe%2FLoadBalancing.webp?alt=media&#x26;token=d72774b2-6603-4e3d-a262-8492be91d134" alt=""><figcaption><p>Mittels 2. App-Server und der Auslagerung der Services auf eine separate VM werden Anfragen nun gleichmäßig verteilt und die Performance gesteigert.</p></figcaption></figure>

{% hint style="info" %}
Wir empfehlen die Nutzung des Load Balancers spätestens ab 500 zu betreuenden Hosts.
{% endhint %}

Zur Nutzung des Load Balancing müssen 3 zusätzliche virtuelle Maschinen bereitgestellt werden:

1. VM für den Load Balancer
2. VM für die Services
3. VM für den 2. App-Server

{% hint style="info" %}
Für einen flüssigen Betrieb empfehlen wir Ihnen Nginx als Reverse Proxys zu nutzen.
{% endhint %}

## Vorbereitung der Virtuellen Maschinen

### Load Balancer VM

Bereiten Sie im ersten Schritt die VM für den Load Balancer vor. Dieser dient der Zertifikatsbehandlung und Weiterleitung Ihrer Anfragen.

{% hint style="warning" %}
Es gilt zu beachten, dass auf der VM, auf der der Nginx läuft **kein Docker** installiert wird. Nur so können Sie einen reibungslosen Ablauf sicherstellen.
{% endhint %}

1. Stellen Sie eine VM für den Load Balancer bereit.
2. Installieren Sie den Nginx mittels `sudo apt install nginx`.&#x20;
3. Übernehmen Sie hierfür ganz einfach die Konfiguration und passen Sie diese entsprechend an.\
   Öffnen Sie die Konfiguration mit folgendem Befehl:\
   `sudo nano /etc/nginx/sites-available/ngs.conf`

   Sollten Sie unsere ISO nicht nutzen, kann die Standardkonfiguration auch unter\
   `sudo nano /etc/nginx/sites-available/default`\
   angepasst werden.

   ```
    map $http_upgrade $connection_upgrade {
       default upgrade;
       ''      close;
   }
    
   upstream apiServers {
       server <IP_API_SERVER1>:8080;
       server <IP_API_SERVER2>:8080;
   }
    
   upstream appServers {
       server <IP_API_SERVER1>:80;
       server <IP_API_SERVER2>:80;
   }
    
    
     server {
       listen 443 ssl http2;
       listen [::]:443 ssl http2;
    
       ssl_stapling on;
       ssl_stapling_verify on;
       server_name ...;
    
       ssl_protocols TLSv1.2;
       ssl_prefer_server_ciphers on;
       ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384";
       ssl_ecdh_curve secp384r1;
       ssl_session_cache shared:SSL:10m;
       ssl_session_tickets off;
       resolver 8.8.8.8 8.8.4.4 valid=300s;
       resolver_timeout 5s;
    
       ssl_dhparam /etc/nginx/dhparam.pem;
       ssl_certificate /etc/letsencrypt/live/.../fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/.../privkey.pem;
    
       client_max_body_size 200m;
    
       location / {
           proxy_pass http://apiServers;
           proxy_set_header Host $host;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-Proto "https";
           proxy_set_header X-Forwarded-Ssl "on";
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection $connection_upgrade;
       }
   }
    
    
   server {
       listen 443 ssl http2;
       listen [::]:443 ssl http2;
    
       ssl_stapling on;
       ssl_stapling_verify on;
       server_name ...;
    
       ssl_protocols TLSv1.2;
       ssl_prefer_server_ciphers on;
       ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384";
       ssl_ecdh_curve secp384r1;
       ssl_session_cache shared:SSL:10m;
       ssl_session_tickets off;
       resolver 8.8.8.8 8.8.4.4 valid=300s;
       resolver_timeout 5s;
    
       ssl_dhparam /etc/nginx/dhparam.pem;
       ssl_certificate /etc/letsencrypt/live/.../fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/.../privkey.pem;
    
       client_max_body_size 200m;
    
       location / {
           proxy_pass http://appServers;
           proxy_set_header Host $host;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-Proto "https";
           proxy_set_header X-Forwarded-Ssl "on";
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection $connection_upgrade;
       }
   }
   ```
4. Fügen Sie nun die Zertifikate hinzu und passen Sie die Pfade entsprechend in der Konfiguration an. Bsp.: \
   Ablageort der Zertifikate: `/etc/nginx/ssl` \
   \
   Anpassung in der Konfiguration: \
   `ssl_certificate /etc/nginx/ssl/fullchain.pem;`\
   und \
   `ssl_certificate_key /etc/nginx/privkey.pem;`<br>

{% hint style="warning" %}
Sollten Sie Ihre Zertifikate auf IP Adressen ausgestellt haben, stellen Sie sicher, dass die jeweiligen Zertifikate auch auf die korrekten IP-Adressen ausgestellt sind. &#x20;
{% endhint %}

### Services VM

Diese VM ist ausschließlich für die Ausführung der folgenden Services bereit zustellen:

| Service       | Funktion                                                                                                    |
| ------------- | ----------------------------------------------------------------------------------------------------------- |
| sentinel-m3   | Regelt Alarme und verwaltet zugeordnete Benachrichtigungen.                                                 |
| reporter-m4   | Versorgt die Enginsight-Plattform mit aktuellen Vulnerabilitätsdaten (CVEs) und verteilt sie an die Module. |
| profiler-m22  | Sorgt für die Berechnung des Normalverlaufs der Machine Learning Metriken.                                  |
| anomalies-m28 | Gleicht Normalverlauf der Machine Learning Metriken mit den gemessenen Daten ab, um Anomalien zu erkennen.  |
| scheduler-m29 | Löst geplante, automatisierte Aktionen aus, zum Beispiel Plugins oder Audits.                               |
| updater-m34   | Managed und aktualisiert die Konfigurationschecklisten.                                                     |
| generator-m35 | Erzeugt PDF-Berichte, z.B. für Hosts, Endpunkte und Penetrationstests.                                      |
| historian-m38 | Fasst gemessene Daten zusammen, um sie im zeitlichen Verlauf darzustellen.                                  |
| themis-m43    | Fungiert als Integritäts-Manager und überprüft Daten auf Korrektheit sowie Aktualität.                      |

{% hint style="warning" %}
Beachten Sie unbedingt, dass die Services nun auf einer separaten VM ausgeführt werden und berücksichtigen Sie dies bei der Konfiguration Ihrer App Server.
{% endhint %}

1. [Installieren Sie Docker](https://docs.docker.com/engine/install/) und laden Sie das Enginsight Repo auf Ihre Services VM ([Installation Appserver ](https://docs.enginsight.com/docs/on-premises/manuelle-installation#applikationsserver-enginsight-installieren)Schritt 1-4).
2. Passen Sie nun die `docker-compose.yml` unter `/opt/enginsight/enterprise` gemäß den Anweisungen an.

   ```
   version: "3"
   services:
     mongodb-cves:
       image: mongo:4
       networks:
       - mongodb-cves
       restart: always
       volumes:
       - mongodb-cves-volume:/data/db

     sentinel-m3:
       image: registry.enginsight.com/enginsight/sentinel-m3:2.22.37
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/sentinel-m3/config.json"

     reporter-m4:
       image: registry.enginsight.com/enginsight/reporter-m4:2.4.47
       networks:
       - mongodb-cves
       depends_on:
       - mongodb-cves
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/reporter-m4/config.json"

     profiler-m22:
       image: registry.enginsight.com/enginsight/profiler-m22:2.2.9
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/profiler-m22/config.json"

     anomalies-m28:
       image: registry.enginsight.com/enginsight/anomalies-m28:2.2.2
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/anomalies-m28/config.json"

     scheduler-m29:
       image: registry.enginsight.com/enginsight/scheduler-m29:1.8.76
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/scheduler-m29/config.json"

     updater-m34:
       image: registry.enginsight.com/enginsight/updater-m34:2.0.4
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/updater-m34/config.json"

     generator-m35:
       image: registry.enginsight.com/enginsight/generator-m35:1.14.2
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/generator-m35/config.json"

     historian-m38:
       image: registry.enginsight.com/enginsight/historian-m38:2.1.58
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/historian-m38/config.json"

     themis-m43:
       image: registry.enginsight.com/enginsight/themis-m43:1.18.20
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/themis-m43/config.json"

   networks:
     mongodb-cves:

   volumes:
     mongodb-cves-volume:
   ```

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Stellen Sie sicher, dass immer die aktuellen Versionsendungen genutzt werden.</p></div>
3. Hinterlegen Sie eine [Mail-Server-Konfiguration](https://docs.enginsight.com/docs/on-premises/konfiguration/mailserver) und stellen Sie sicher, dass die Mail-Server-Konfiguration identisch mit jener auf den App-Servern ist.

### Datenbank VM

1. Sichern Sie Ihre Datenbank mit `iptables` ab.

   <div data-gb-custom-block data-tag="hint" data-style="danger" class="hint hint-danger"><p>Passen Sie die <code>iptables</code> so an, dass jegliche Verbindungen von außerhalb zur Datenbank blockiert werden. Dieser Schritt führt dazu, dass <strong>nur</strong> die Applikation auf die MongoDB zugreifen kann und unberechtigte Zugriffe verhindert werden.</p></div>
2. Fügen Sie neue Regeln für den 2. App Server sowie den Server hinzu, auf dem die Services ausgeführt werden. Rufen Sie hierfür die `iptables` auf.&#x20;

   ```
   sudo nano /etc/iptables/rules.v4 
   ```
3. Fügen Sie, wie unten abgebildet, Regeln für den Redis hinzu.

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Ersetzen Sie <code>&#x3C;APP IP></code> durch die von der Datenbank erreichbare IP des Applikationsservers. Ersetzen Sie <code>&#x3C;DB IP></code> durch die von der Applikation erreichbare IP des Datenbankservers </p></div>

   ```
    -A INPUT -p tcp -m tcp --dport 27017 -s 127.0.0.1 -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 27017 -s <APP IP> -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 6379 -s <APP IP> -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 27017 -s <APP2 IP> -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 6379 -s <APP2 IP> -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 27017 -s <Services IP> -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 6379 -s <Services IP> -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 27017 -s <DB IP> -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 27017 -j DROP
    -A INPUT -p tcp -m tcp --dport 6379 -j DROP
   ```
4. Sobald alle Änderungen vorgenommen sind speichern Sie Ihre Einstellungen persistent.

   ```
   sudo iptables-restore < /etc/iptables/rules.v4
   sudo apt-get install -y iptables-persistent
   ```
5. Fügen Sie nun Redis hinzu, indem Sie den Redis-Server installieren.

   ```
   sudo apt install redis-server
   ```
6. Passen Sie die Konfiguration an.

   ```
   sudo nano /etc/redis/redis.conf
   bind 0.0.0.0 
   ```
7. Speichern und starten Sie die Anwendung anschließend neu.

   ```
   sudo service redis restart
   ```

{% hint style="info" %}
**Empfehlung für größere Installationen**

Ab einer Systemgröße von **mehr als 1.000 Assets** empfehlen wir den Einsatz eines **MongoDB-Clusters**.\
Durch Replikation und Lastverteilung innerhalb des Clusters wird die Datenbankperformance und Ausfallsicherheit erheblich verbessert.
{% endhint %}

### App-Server VMs

Bereiten Sie zwei Virtuelle Maschinen für die App-Server vor. Diese VMs gewährleistet, dass die Benutzeroberfläche von allen Servern aus erreichbar ist und die Services parallel ausgeführt werden können.

{% hint style="info" %}
Falls Sie Enginsight zuvor ohne Load Balancer genutzt haben, können Sie den bisher genutzten App-Server als eine der 2 benötigten App-Server VMs verwenden!

Dies erleichtert die Einrichtung des Load Balancers erheblich und ermöglicht es Ihnen, schnell mit der Implementierung fortzufahren.
{% endhint %}

1. [Installieren Sie Docker](https://docs.docker.com/engine/install/) und laden Sie das Enginsight Repo auf Ihre Services VM ([Installation Appserver ](https://docs.enginsight.com/docs/on-premises/manuelle-installation#applikationsserver-enginsight-installieren)Schritt 1-4).

   <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Um Zeit und Mühe zu sparen, empfehlen wir Ihnen, entweder unsere ISO-Datei zu nutzen oder den ersten App-Server zu klonen, um die zweite VM für den App-Server zu erstellen. </p></div>
2. Passen Sie die [docker-compose.yml](https://docs.enginsight.com/docs/konfiguration/https#interne-ports-definieren) , wie nachfolgend angegeben an.

   ```
   version: "3"
   services:
     ui-m1:
       image: registry.enginsight.com/enginsight/ui-m1:3.5.10
       ports:
       - "80:80"
       restart: always
       volumes:
       - "./conf/ui-m1/environment.js.production:/opt/enginsight/ui-m1/config/environment.js"

     server-m2:
       image: registry.enginsight.com/enginsight/server-m2:3.5.426
       ports:
       - "8080:8080"
       restart: always
       volumes:
       - "./conf/services/config.json.production:/etc/enginsight/server-m2/config.json"

   ```

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Beachten Sie auch hier, dass am Ende stets die aktuellen Versionen stehen. <br>Passen Sie hierfür entweder die .xml an und löschen Sie alle nicht benötigten Einträge <strong>oder</strong> passen Sie die Versionen selbstständig an.</p></div>
3. Hinterlegen Sie, falls noch nicht vorhanden, die [Mail-Server-Konfiguration](https://docs.enginsight.com/docs/on-premises/konfiguration/mailserver) und stellen Sie sicher, dass die Mail-Server-Konfiguration identisch mit jener auf der Services-VM ist.
4. Sollten Sie den App Server geklont haben, so deaktivieren Sie den nginx auf beiden App Servern mit dem Befehl: `sudo systemctl stopp nginx` und `sudo systemctl disable nginx`
5. Kopieren Sie den Inhalt der Datei `DEFAULT_JWT_SECRET.conf` unter `/opt/enginsight/enterprise/conf` und fügen Sie diese auf dem 2. App Server in die selbe Datei ein. So stellen Sie sicher, dass beide Dateien identisch auf beiden Servern hinterlegt sind.
6. Prüfen Sie nun die Connection zu Redis. Loggen Sie sich hierfür in den Container ein und stellen Sie eine Verbindung her:
   * Redis Connection prüfen
     1. `sudo docker ps`
     2. `sudo docker exec -it <ID von server-m2> /bin/sh`
     3. `apk add redis` &#x20;
     4. `redis-cli -h <IPDB>`
7. Überprüfen Sie nun anhand der Docker Logs von server m-2, ob eine Connection von der Datenbank zu Redis besteht.

## Load Balancing starten

1. Ändern Sie den DNS Eintrag.

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Beachten Sie hierbei, dass die URL der APP und der API auf den Loadbalancer ausgerichtet sind und nicht mehr auf den APP Server.</p></div>
2. Sobald Sie alle VMs vorbereitet haben, können Sie die `setup.sh` ausführen.

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Beachten Sie, dass die Redis URL in <code>redis://&#x3C;IPDB>:6379</code> abgeändert werden muss</p></div>

Jetzt ist es an der Zeit zu überprüfen, ob Ihre Anwendung auch im Falle eines einzelnen Serverausfalls weiterhin problemlos funktioniert.

3. Führen Sie hierfür `sudo docker-compose down` auf dem APP Server 1 aus und überprüfen Sie, ob der APP Server 2 weiterhin Daten empfängt und alle Hosts weiterhin aktiv sind.
4. Fahren Sie alle Docker Container mit `sudo docker-compose up -d` wieder hoch&#x20;
5. Führen Sie die Unterpunkte 1 und 2 nocheinmal für App Server 2 durch.

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p>Beachten Sie, dass das Update-Script nun immer auf allen drei Servern ausgeführt werden muss, um sicherzustellen, dass alle Server auf dem neuesten Stand sind und keine Inkompatibilitäten auftreten.</p></div>
