Skip to content
Arturo Rinaldi edited this page Dec 29, 2021 · 11 revisions

Introduzione

L'obiettivo della guida é descrivere come realizzare un un sistema completamente funzionante, tramite docker e docker-compose, dello stack Iotronic comprensivo di una macchina controller e di una o piú macchine wagent.

Vengono pertanto richieste almeno due macchine virtuali su cloud computing e l'installazione dello stack docker sulle stesse oltre che dei pacchetti base di produttivitá e compilazione dei sorgenti.

Prerequisiti

  • 2 VM OVH (od altro servizio cloud)
  • Una Certification Authority (CA) creata appositamente e certificati di sicurezza generati a partire dalla stessa.
  • Creazione dei domini dedicati per la macchina controller e la macchina wagent (uno o piú a seconda dell'infrastruttura). In questa guida sono stati scelti questi domini:
    • VM controller: demo-controller.smartme.io
    • VM wagent: demo-wagent.smartme.io

VM controller

La VM di tipo controller, basata su Ubuntu 20.04 LTS, ha un'istanza fisica di nginx e 5 istanze di container docker con relativi volumi dedicati:

  • nginx
  • s4t_mysql [oppure istanza remota OVH]
  • s4t_rabbitmq -> P[5672]
  • s4t_keystone -> P[5000 ]
  • s4t_iotronic_conductor -> P[8812 ]
  • s4t_iotronic_ui -> P[443/80]

Le instanze di tipo s4t_* sono legate alla macchina host tramite mapping delle porte interne (bridge di rete di docker) ed identificate nella lista sopra dalla nomenclatura P[<numero porta>].

VM wagent

La VM di tipo wagent, basata su Ubuntu 20.04 LTS, ha invece 3 istanze di container docker con relativi volumi dedicati:

  • s4t_iotronic_wstun -> P[8080]
  • s4t_iotronic_crossbar -> P[8181]
  • s4t_iotronic_wagent [contiene un istanza di NGINX] -> P[ 80 | 443 ]

Qui invece le instanze di tipo s4t_* agiscono direttamente sulle porte fisiche della macchina host e sono identificate nella lista sopra dalla nomenclatura P[<numero porta>].

s4t_iotronic_wagent contiene a sua volta un'istanza di nginx legata allo script di avvio di wagent, necessario per il suo corretto funzionamento.

PARTE CONTROLLER

  1. Installare NGINX

    A. installare nginx tramite package manager della distribuzione linux in uso. Nel nostro testbed le macchine virtuali sono state create con Ubuntu 20.04 LTS.

    $ apt update && apt install nginx
    

    B. Installare certbot con plugin dedicato per nginx

    Installare certbot e il plugin relativo di nginx per generare i certificati per esporre i servizi in https col seguente comando:

    & apt update && apt install certbot python3-certbot-nginx
    

    In modo tale da certificare il dominio relativo alla macchina controller (demo-controller.smartme.io in questo caso). La porta 80 effettuerá il t unnel proxy di default per la porta 8086 dedicata ad horizon (8086).

    Creare il file /etc/nginx/sites-available/demo-controller :

    vim /etc/nginx/sites-available/demo-controller
    

    ed incollare il seguente contenuto:

    server {
       server_name controller-demo.smartme.io;
       location /{
       proxy_pass http://localhost:8086/;
       proxy_redirect off;
       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Forwarded-Protocol $scheme;
       proxy_set_header X-Url-Scheme $scheme;
       }
       listen 80;
    }
    

    creare quindi il link simbolico a /etc/nginx/sites-enabled/

    ln -s /etc/nginx/sites-available/demo-controller /etc/nginx/sites-enabled/
    

    C. creazione dei certificati per nginx

    Effettuare la creazione dei certificati per registrare il dominio della macchina controller su nginx con il comando:

    certbot --nginx
    

    D. Configurare NGINX per esporre keystone (5001 locale - 5000 pubblica)

    creare il file:

    vim /etc/nginx/sites-available/keystone-demo-controller
    

    e copiarvi dentro il seguente contenuto:

    server {
        server_name demo-controller.smartme.io;
        location /{
        proxy_pass http://localhost:5001/;
        proxy_redirect off;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Url-Scheme $scheme;
        }
        listen 5000 ssl;
        ssl_certificate /etc/letsencrypt/live/demo-controller.smartme.io/fullchain;
        ssl_certificate_key /etc/letsencrypt/live/demo-controller.smartme.io/privkey.pem;
    }
    

    creare quindi il link simbolico a /etc/nginx/sites-enabled/ :

    $ ln -s /etc/nginx/sites-available/keystone-demo-controller  /etc/nginx/sites-enabled/
    

    E. Configurare NGINX per esporre iotronic (8813 locale - 8812 pubblica)

    creare il file:

    /etc/nginx/sites-available/iotronic-demo-controller
    

    e copiarvi il seguente contenuto:

    server {
        server_name demo-controller.smartme.io;
        location /{
        proxy_pass http://localhost:8813/;
        proxy_redirect off;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Protocol $scheme;
        proxy_set_header X-Url-Scheme $scheme;
        }
        listen 8812 ssl;
        ssl_certificate /etc/letsencrypt/live/demo-controller.smartme.io/fullchain;
        ssl_certificate_keym /etc/letsencrypt/live/demo-controller.smartme.io/privkey.pem;
    }
    

    creare quindi il link simbolico a /etc/nginx/sites-enabled/ :

    $ ln -s /etc/nginx/sites-available/iotronic-demo-controller /etc/nginx/sites-enabled/
    

    E. ricaricare le configurazioni di nginx con:

    $ nginx -s reload
    
  2. Certification Authority

    Creare la Certification Autorithy (CA) ed i relativi certificati di sicurezza con i seguenti comandi:

    A. navigare nella cartella 0-CA e lanciare lo script ./ca_create:

    $ cd 0-CA/
    $ ./ca_create
    

    Verrá creata la directory CA con la chiave di sicurezza:

    .
    ├── CA
    │   ├── SmartME_CA.key
    │   ├── SmartME_CA.pem
    │   └── SmartME_CA.srl
    

    B. creare i corrispondenti certificati di sicurezza lanciando lo script:

    ./client_cert
    

    Verrá creata la cartella client_iotronic con all’interno i certificati e la Certification Authority stessa:

    .
    └── client_iotronic
        ├── CA.pem
        ├── iotronic.csr
        ├── iotronic.key
        └── iotronic.pem
    

    C. copiare tutto il contenuto della cartella nel percorso:

    /etc/ssl/iotronic
    

    con i comandi :

    $ mkdir -p /etc/ssl/iotronic
    $ cp -r CA/ client_iotronic/ /etc/ssl/iotronic/
    

    trasferire i certificati (tutto il contenuto delle cartelle CA e client_iotronic) sulle macchine WAGENT e ripetere la copia dei certificati di cui al punto sopra sempre nello stesso percorso di destinazione.

    D. la struttura finale della directory, con CA e certificati generati, dovrá rispecchiare questa alberatura:

    .
    ├── CA
    │   ├── SmartME_CA.key
    │   ├── SmartME_CA.pem
    │   └── SmartME_CA.srl
    ├── ca_create
    ├── client_cert
    └── client_iotronic
        ├── CA.pem
        ├── iotronic.csr
        ├── iotronic.key
        └── iotronic.pem
    
  3. Configurazione del database MySql

    In questo step si deve effettuare la creazione dell’immagine personalizzata basata sul layer docker: mariadb:focal che viene scaricato col comando: $ docker pull mariadb:focal

    A. navigare nella cartella 1-mysql:

     $ cd 1-mysql/
    

    B. le utenze e le password del database possono essere definite nel template initfile.sql all’interno della cartella stessa.

    CREATE USER IF NOT EXISTS s4t_keystone@localhost IDENTIFIED BY '<IOTRONIC_DBPASS>';
    SET PASSWORD FOR s4t_keystone@localhost = PASSWORD('<IOTRONIC_DBPASS>');
    
    CREATE USER IF NOT EXISTS s4t_iotronic@localhost IDENTIFIED BY '<IOTRONIC_DBPASS>';
    SET PASSWORD FOR s4t_iotronic@localhost = PASSWORD('<IOTRONIC_DBPASS>');
    
    CREATE DATABASE s4t_keystone;
    GRANT ALL PRIVILEGES ON s4t_keystone.* TO 's4t_keystone'@'localhost' IDENTIFIED BY '<IOTRONIC_DBPASS>';
    GRANT ALL PRIVILEGES ON s4t_keystone.* TO 's4t_keystone'@'%' IDENTIFIED BY '<IOTRONIC_DBPASS>';
    
    CREATE DATABASE s4t_iotronic;
    GRANT ALL PRIVILEGES ON s4t_iotronic.* TO 's4t_iotronic'@'localhost' IDENTIFIED BY '<IOTRONIC_DBPASS>';
    GRANT ALL PRIVILEGES ON s4t_iotronic.* TO 's4t_iotronic'@'%' IDENTIFIED BY '<IOTRONIC_DBPASS>';
    

    come si puó vedere dal file di configurazione iniziale, sono stati creati i due utenti e relativi database:

    • s4t_keystone
    • s4t_iotronic

    con password di default <IOTRONIC_DBPASS> che nel nostro caso ha come valore di default sm3d3m0n

    C. Una volta definite le utenze/password, lanciare lo script:

    $ ./build
    

    per generare l’immagine docker finale con le voci del database di default che sono state definite nel file di inizializzazione.

  4. RabbitMQ

    Procedimento simile viene fatto per questo step. L’immagine personalizzata basata sul layer docker:

    rabbitmq:3.9.8
    

    A. navigare da shell nella cartella 1-rabbitmq:

    $ cd 1-rabbitmq
    

    B. impostare la password RABBIT_PASS per rabbitmq in scripts/rabbitmq-setup.sh. Il valore predefinito é smartme:

    #!/bin/bash
    
    #if [ "$EUID" -ne 0 ]
    #  then echo "Please run as root"
    #  exit
    #cfi
    
    if [ ! -f ${HOME}/.rabbitmq_setup_completed ]
    then
            RABBIT_PASS="smartme"
    
            rabbitmqctl add_user openstack $RABBIT_PASS
            rabbitmqctl set_permissions openstack ".*" ".*" ".*"
    
            touch ${HOME}/.rabbitmq_setup_completed
    
            echo -e "\e[32mCompleted \e[0m"
    else
            echo "no need to setup rabbitmq !"
    fi
    

    C. lanciare lo script:

    $ ./build
    

    per generare l’immagine docker final.

    D. l’immagine include lo script rabbitmq-setup.sh sotto il percorso /usr/bin/rabbitmq-setup che si occuperá del breve setup del server rabbit una volta che il container é attivo.

  5. Keystone

    A. Navigare da shell nella cartella 2-keystone/build con il comando:

    cd 2-keystone/build
    

    B. modificare il file conf/keystone.conf in base alla definizione del database SQL che é stato creato nello step precendente:

    [database]
    connection =  mysql+pymysql://s4t_keystone:<IOTRONIC_DBPASS>@s4t_iotronic_db/s4t_keystone
    

    dove s4t_iotronic_db é uno dei database creato in ascolto sulla porta 3306. Il container di keystone va a cercare il DNS del container MySql di docker stesso.

    La password <IOTRONIC_DBPASS> ha come valore di default sm3d3m0n.

    C. Modificare il file scripts/keystone-setup.sh con le utenze scelte e l’endpoint di keystone:

    HOST="demo-controller.smartme.io"
    ADMIN_PASS="smartme"
    HTTPS=true
    

    D. modificare il file conf/adminrcin base al dominio scelto per la macchina relativa al sistema controller. Nel nostro caso abbiamo:

    OS_PROJECT_DOMAIN_NAME=Default
    OS_USER_DOMAIN_NAME=Default
    OS_PROJECT_NAME=admin
    OS_USERNAME=admin
    OS_PASSWORD=smartme
    OS_AUTH_URL=https://demo-controller.smartme.io:5000/v3
    OS_IDENTITY_API_VERSION=3
    OS_IMAGE_API_VERSION=2
    

    E. Lanciare lo script di build dell’immagine col comando:

    ./build
    

    F. nell’immagine verrá inserito lo script keystone-setup.sh, sotto il percorso /usr/bin/keystone-setup, che si occuperá del setup automatico del container del servizio Keystone una volta avviato.

  6. Conductor

    A. Navigare da shell nella cartella 3-conductor/build:

    $ cd 3-conductor/build
    

    B. modificare il file conf/iotronic.conf in base ai cambiamenti effettuati negli step precedenti. In particolare:

    # rabbitmq
    transport_url=rabbit://openstack:<RABBIT_PASS>@s4t_rabbitmq:5672/
    
    # RANGE porte servizi
    [conductor]
    service_port_min=50000
    service_port_max=50100
    
    # MYSQL
    [database]
    connection =  mysql+pymysql://s4t_iotronic:<IOTRONIC_DBPASS>@s4t_iotronic_db/s4t_iotronic
    
    # KEYSTONE
    [keystone_authtoken]
    www_authenticate_uri = https://demo-controller.smartme.io:5000
    auth_url = https://demo-controller.smartme.io:5000
    

    C. modificare il file scripts/openstack-setup.sh in questo modo:

    IP_IOTRONIC="demo-controller.smartme.io"
    IOTRONIC_PASS="smartme"
    HTTPS=true
    

    D. lanciare lo script di build della nuovo layer docker con il comando:

    ./build
    

    E. una volta che il container é avviato, lanciare lo script openstack-setup per fare compiere al container del conductor il setup automatico e registrare il dominio grazie all’interazione con i container di keystone, rabbitmq e mysql.

  7. Iotronic-UI

    A. Navigare da shell nella cartella 6-ui/build:

    $ cd 6-ui/build
    

    B. modificare il file conf/local_settings.py (controllando HTTPS) in base al dominio scelto per la macchina controller:

    OPENSTACK_HOST = "demo-controller.smartme.io"
    OPENSTACK_KEYSTONE_URL = "https://%s:5000/v3" % OPENSTACK_HOST
    OPENSTACK_KEYSTONE_DEFAULT_ROLE = "member"
    

    C. lanciare la build dell’immagine con il comando:

    ./build
    

PARTE AGENT

  1. Crossbar

    A. Navigare nella cartella 4-iotronic-crossbar:

    $ cd 4-iotronic-crossbar/
    

    B. lanciare la build dell’immagine con il comando:

    ./build
    
  2. WSTun

    A. Navigare da shell nella cartella 4-iotronic-wstun:

    $ cd 4-iotronic-wstun/
    

    lanciare la build dell’immagine con il comando:

    ./build
    

    B. il container dovrá poi prevedere dei volumi montati nei seguenti percorsi:

    CERT_PATH : "/etc/ssl/iotronic/client_iotronic/:/var/lib/iotronic/ssl/:ro"
    ALLOW_PATH :"s4t_iotronic_wagent_wstun:/var/lib/wstun:ro”
    

    in particolare il percorso ALLOW_PATH andrá montato nel volume s4t_iotronic_wagent_wstun a cavallo dei container di wstun e wagent (descritto nella sezione successiva) in modo tale da avere in comune il file JSON degli host abilitati /var/lib/wstun/allowlist che verrá scritto di volta in volta dal servizio iotronic.

    C. il container viene lanciato con questo ENTRYPOINT:

    ENTRYPOINT ["wstun", "-r", "-s", "8080", "--ssl=true", "--key=/var/lib/iotronic/ssl/iotronic.key", "--cert=/var/lib/iotronic/ssl/iotronic.pem","-a/var/lib/wstun/allowlist"]
    
  3. WAgent

    A. La macchina deve risiedere su un server le cui porte sono raggiungibili dall’esterno in particolare la 8181 (crossbar) e la 8080 (wstun)

    B. il container viene lanciato col volume condiviso s4t_iotronic_wagent_wstun insieme al container di wstun.

    C. Navigare da shell nella cartella 5-wagent/:

    $ cd 5-wagent/
    

    e modificare il file conf/iotronic.conf in base al dominio scelto per le macchine di controller / wagent :

    # rabbitmq
    transport_url=rabbit://openstack:<RABBIT_PASS>@s4t_rabbitmq:5672/
    
    # Wamp-agent
    wamp_transport_url=wss://demo-wagent.smartme.io:8181/
    
    # MYSQL
    [database]
    connection =  mysql+pymysql://s4t_iotronic:<IOTRONIC_DBPASS>@s4t_iotronic_db/s4t_iotronic
    
    # KEYSTONE
    [keystone_authtoken]
    www_authenticate_uri = https://demo-controller.smartme.io:5000
    auth_url = https://demo-controller.smartme.io:5000
    

PARTE DOCKER COMPOSE

Per automatizzare la creazione dei sistemi CONTROLLER e WAGENT, dopo avere creato in ogni caso le immagini docker sulle rispettive macchine, sono stati creati due file YAML di docker-compose:

  • docker-compose-controller.yml
  • docker-compose-wagent.yml

PARTE CONTROLLER

modificare il docker-compose-controller.yml impostando le variabili di environment secondo quanto riportato precedentemente nella fase di configurazione di controller. Nel microservizio del database SQL impostare la propria password di root tramite la variabile di ambiente MARIADB_ROOT_PASSWORD:

MARIADB_ROOT_PASSWORD: <MARIADB_ROOT_PASSWORD>

in questo caso il valore di default é smartme. Lo stesso vale per il servizio rabbitmq:

RABBIT_PASS="<RABBIT_PASS>"

anche qui di default impostata al valore smartme. I servizi keystone e conductor hanno in comune i seguenti valori di default come variabili di ambiente:

OS_PROJECT_DOMAIN_NAME=Default
OS_USER_DOMAIN_NAME=Default
OS_PROJECT_NAME=admin
OS_USERNAME=admin
OS_PASSWORD=smartme
OS_AUTH_URL=https://demo-controller.smartme.io:5000/v3
OS_IDENTITY_API_VERSION=3
OS_IMAGE_API_VERSION=2
HOST="demo-controller.smartme.io"
ADMIN_PASS="smartme"

il servizio conductor ha anche come variabile di ambiante IOTRONIC_PASS che ha come valore di default smartme:

IOTRONIC_PASS=<IOTRONIC_PASS>

Una volta apportate le modifiche (se necessarie), dalla directory dei sorgenti lanciare il comando:

$ docker-compose -f docker-compose-controller.yml up -d

verranno creati, nel seguente ordine, questi servizi:

  • mariadb
  • rabbitmq
  • keystone (dipendente da mariadb, rabbitmq)
  • conductor (dipendente da mariadb, rabbitmq, keystone)
  • ui (dipendente da conductor)

una volta che il processo di creazione dei container in background é terminato, bisogna compiere delle operazioni manuali per terminare il setup e registrare gli endpoint che entrano in comunicazione tra loro:

1. Entrare da shell nel container s4t_rabbitmq con:

$ docker exec -ti s4t_rabbitmq bash

e lanciare il comando:

$ rabbitmq-setup

per inizializzare il server rabbit con i giusti parametri. In alternativa é possibile usare il comando unico:

$ docker exec -ti s4t_rabbitmq rabbitmq-setup

2. Entrare da shell nel container s4t_keystone con:

$ docker exec -ti s4t_keystone bash

e lanciare il comando:

$ keystone-setup

per sincronizzare keystone con il database creato e creare il progetto openstack. In alternativa é possibile usare il comando unico:

$ docker exec -ti s4t_keystone keystone-setup

3. Entrare da shell nel container s4t_conductor con:

$ docker exec -ti s4t_conductor bash

e lanciare il comando:

$ openstack-setup

per registrare gli Endpoint finali di openstack. In alternativa é possibile usare il comando unico:

$ docker exec -ti s4t_conductor openstack-setup

4. Test di verifica del funzionamento:

PARTE WAGENT

dalla directory dei sorgenti, lanciare il comando:

$ docker-compose -f docker-wagent-controller.yml up -d

verranno creati, nel seguente ordine, questi servizi:

  • crossbario
  • wstun
  • wagent

se la parte controller é stata impostata in modo corretto, non sará necessario lanciare alcun comando aggiuntivo all’interno dei container della macchina WAGENT. Il sistema infatti si integrerá senza soluzione di continuitá con la parte CONTROLLER.

1. L’unica differenza, rispetto al sistema CONTROLLER, é che le porte dei container non usano il bridge di docker per la comunicazione col sistema fisico. Viene infatti usata la modalitá host:

https://docs.docker.com/network/host/

che usa le porte fisiche del sistema Linux anziché la proiezione di quelle del container stesso. Nel file di compose viene attivata definendo la voce:

network_mode: host

all'interno della definizione di ogni microservizio. Qui l'esempio per wstun:

wstun:
  container_name: s4t_iotronic_wstun
  restart: unless-stopped
  image: smartmeio/s4t_iotronic_wstun:1.1.0
  volumes:
    - '/etc/ssl/iotronic/client_iotronic:/var/lib/iotronic/ssl/:ro'
    - 's4t_iotronic_wagent_wstun:/var/lib/wstun:ro'
  network_mode: host

2. Test di verifica del funzionamento:

sul container s4t_conductor della macchina CONTROLLER verificare che il nuovo wagent sia stato rilevato.

Clone this wiki locally