
Abbiamo già parlato di , che consente di sviluppare applicazioni distribuite e confezionarle. Ora rimane solo un passo: imparare a distribuire queste applicazioni e gestirle. Non preoccupatevi, abbiamo coperto tutto! Abbiamo raccolto tutte le best practices per lavorare con Tarantool Cartridge e scritto , che installerà il pacchetto sui server, avvierà le istanze, le unirà in un cluster, configurerà l'autenticazione, bootstrapperà vshard, abiliterà il failover automatico e aggiornerà la configurazione del cluster.
Interessati? Allora venite a scoprire di più, vi racconteremo e mostreremo tutto.
Iniziamo con un esempio
Considereremo solo una parte delle funzionalità del nostro ruolo. La descrizione completa di tutte le sue capacità e dei parametri di ingresso è sempre disponibile in . Ma è meglio provare una volta piuttosto che vedere cento volte, quindi mettiamo in funzione una piccola applicazione.
Con Tarantool Cartridge ci sono un modo per creare una piccola applicazione Cartridge che memorizza informazioni sui clienti di una banca e sui loro conti, e offre un'API per gestire i dati tramite HTTP. Per fare questo, nell'applicazione vengono descritte due possibili ruoli: api e storage, che possono essere assegnati alle istanze.
Il Cartridge in sé non dice nulla su come avviare i processi, fornisce solo la possibilità di configurare le istanze già avviate. Il resto deve essere fatto dall'utente: distribuire i file di configurazione, avviare i servizi e configurare la topologia. Ma non ci occupiamo noi di questo, lo farà Ansible per noi.
Passiamo ai fatti
Quindi, distribuiamo la nostra applicazione su due macchine virtuali e configuriamo una semplice topologia:
- ReplicaSet
app-1implementerà il ruoloapi, che include il ruolovshard-router. Qui ci sarà solo un'istanza. - ReplicaSet
storage-1implementa il ruolostorage(e contemporaneamentevshard-storage), qui aggiungeremo due istanze da macchine diverse.

Per avviare l'esempio avremo bisogno di e (versioni 2.8 o superiori).
Il ruolo stesso si trova in . Questo è un repository che consente di condividere le proprie esperienze e utilizzare ruoli già pronti.
Cloniamo il repository con l'esempio:
$ git clone https://github.com/dokshina/deploy-tarantool-cartridge-app.git
$ cd deploy-tarantool-cartridge-app && git checkout 1.0.0Alziamo le macchine virtuali:
$ vagrant upInstalliamo il ruolo ansible Tarantool Cartridge:
$ ansible-galaxy install tarantool.cartridge,1.0.1Eseguiamo il ruolo installato:
$ ansible-playbook -i hosts.yml playbook.ymlAspettiamo il termine dell'esecuzione del playbook, poi passiamo a e godiamo il risultato:

È possibile trasferire i dati. È fantastico, vero?
Ora vediamo come lavorare su questo e aggiungiamo un altro replicaset alla topologia.
Iniziamo a capire
Quindi, cosa è successo?
Abbiamo avviato due macchine virtuali e lanciato un playbook Ansible che ha configurato il nostro cluster. Diamo un'occhiata al contenuto del file playbook.yml:
---
- name: Deploy my Tarantool Cartridge app
hosts: all
become: true
become_user: root
tasks:
- name: Import Tarantool Cartridge role
import_role:
name: tarantool.cartridgeQui non succede niente di interessante, lanciamo il ruolo Ansible chiamato tarantool.cartridge.
Tutto ciò che è importante (cioè la configurazione del cluster) si trova nel -file hosts.yml:
---
all:
vars:
# common cluster variables
cartridge_app_name: getting-started-app
cartridge_package_path: .\/getting-started-app-1.0.0-0.rpm # path to package
cartridge_cluster_cookie: app-default-cookie # cluster cookie
# common ssh options
ansible_ssh_private_key_file: ~\/vagrant.d\/insecure_private_key
ansible_ssh_common_args: '-o IdentitiesOnly=yes -o UserKnownHostsFile=\/dev\/null -o StrictHostKeyChecking=no'
# INSTANCES
hosts:
storage-1:
config:
advertise_uri: '172.19.0.2:3301'
http_port: 8181
app-1:
config:
advertise_uri: '172.19.0.3:3301'
http_port: 8182
storage-1-replica:
config:
advertise_uri: '172.19.0.3:3302'
http_port: 8183
children:
# GROUP INSTANCES BY MACHINES
host1:
vars:
# first machine connection options
ansible_host: 172.19.0.2
ansible_user: vagrant
hosts: # instances to be started on the first machine
storage-1:
host2:
vars:
# second machine connection options
ansible_host: 172.19.0.3
ansible_user: vagrant
hosts: # instances to be started on the second machine
app-1:
storage-1-replica:
# GROUP INSTANCES BY REPLICA SETS
replicaset_app_1:
vars: # replica set configuration
replicaset_alias: app-1
failover_priority:
- app-1 # leader
roles:
- 'api'
hosts: # replica set instances
app-1:
replicaset_storage_1:
vars: # replica set configuration
replicaset_alias: storage-1
weight: 3
failover_priority:
- storage-1 # leader
- storage-1-replica
roles:
- 'storage'
hosts: # replica set instances
storage-1:
storage-1-replica:Tutto ciò di cui abbiamo bisogno è imparare a gestire le istanze e i replicaset, modificando il contenuto di questo file. In seguito aggiungeremo nuove sezioni. Per non confonderci su dove aggiungerle, puoi dare un'occhiata alla versione finale di questo file, hosts.updated.yml, che si trova nel repository di esempio.
Gestione delle istanze
In termini di Ansible, ogni istanza è un host (da non confondere con un server fisico), cioè un nodo dell'infrastruttura che Ansible gestirà. Per ogni host possiamo specificare le opzioni di connessione (come ad esempio ansible_host e ansible_user), e la configurazione dell'istanza. La descrizione delle istanze si trova nella sezione hosts.
Esaminiamo la configurazione dell'istanza storage-1:
all:
vars:
...
# ISTANZE
hosts:
storage-1:
config:
advertise_uri: '172.19.0.2:3301'
http_port: 8181
...Nella variabile config abbiamo specificato i parametri dell'istanza — advertise URI e porta HTTP.
Di seguito sono riportati i parametri delle istanze app-1 e storage-1-replica.
Dobbiamo comunicare ad Ansible i parametri di connessione per ogni istanza. È logico raggruppare le istanze in base alle macchine virtuali. Per questo, le istanze sono state raggruppate in gruppi host1 e host2, e in ogni gruppo nella sezione vars sono indicati i valori ansible_host e ansible_user per una virtual machine. E nella sezione hosts — i host (che sono anche istanze), che fanno parte di questo gruppo:
all:
vars:
...
hosts:
...
children:
# GRUPPA ISTANZE PER MACCHINE
host1:
vars:
# opzioni di connessione della prima macchina
ansible_host: 172.19.0.2
ansible_user: vagrant
hosts: # istanze da avviare sulla prima macchina
storage-1:
host2:
vars:
# opzioni di connessione della seconda macchina
ansible_host: 172.19.0.3
ansible_user: vagrant
hosts: # istanze da avviare sulla seconda macchina
app-1:
storage-1-replica:Iniziamo a modificare hosts.yml. Aggiungiamo altre due istanze, storage-2-replica sulla prima macchina virtuale e storage-2 sulla seconda:
all:
vars:
...
# ISTANZE
hosts:
...
storage-2: # <==
config:
advertise_uri: '172.19.0.3:3303'
http_port: 8184
storage-2-replica: # <==
config:
advertise_uri: '172.19.0.2:3302'
http_port: 8185
children:
# GRUPPA ISTANZE PER MACCHINE
host1:
vars:
...
hosts: # istanze da avviare sulla prima macchina
storage-1:
storage-2-replica: # <==
host2:
vars:
...
hosts: # istanze da avviare sulla seconda macchina
app-1:
storage-1-replica:
storage-2: # <==
...Avviamo il playbook di ansible:
$ ansible-playbook -i hosts.yml
--limit storage-2,storage-2-replica
playbook.ymlSi noti l'opzione --limit. Poiché ogni istanza del cluster è un host in termini di Ansible, possiamo specificare esplicitamente quali istanze devono essere configurate durante l'esecuzione del playbook.
Rientriamo nell'interfaccia Web e vediamo le nostre nuove istanze:

Non ci fermeremo qui e impariamo a gestire la topologia.
Gestione della topologia
Uniamo le nostre nuove istanze in un replicaset storage-2. Aggiungiamo un nuovo gruppo replicaset_storage_2 e descriviamo nelle sue variabili i parametri del replicaset analogamente a replicaset_storage_1. Nella sezione hosts specificheremo quali istanze faranno parte di questo gruppo (cioè il nostro replicaset):
---
all:
vars:
...
hosts:
...
children:
...
# GRUPPARE LE ISTANZE PER SET DI REPLICA
...
replicaset_storage_2: # <==
vars: # configurazione del replicaset
replicaset_alias: storage-2
weight: 2
failover_priority:
- storage-2
- storage-2-replica
roles:
- 'storage'
hosts: # istanze del replicaset
storage-2:
storage-2-replica:Riavviamo il playbook:
$ ansible-playbook -i hosts.yml
--limit replicaset_storage_2
--tags cartridge-replicasets
playbook.ymlNel parametro --limit stavolta abbiamo passato il nome del gruppo, che corrisponde al nostro replicaset.
Consideriamo l'opzione tags.
Il nostro ruolo esegue sequenzialmente diverse attività, contrassegnate dai seguenti tag:
cartridge-instances: gestione delle istanze (configurazione, connessione al membership);cartridge-replicasets: gestione della topologia (gestire i replicaset e rimuovere in modo irrevocabile (expel) le istanze dal cluster);cartridge-config: gestione degli altri parametri del cluster (vshard bootstrapping, modalità di failover automatico, parametri di autorizzazione e configurazione dell'applicazione).
Possiamo specificare chiaramente quale parte del lavoro vogliamo eseguire, quindi il ruolo salterà l'esecuzione delle altre attività. Nel nostro caso vogliamo lavorare solo con la topologia, quindi abbiamo specificato cartridge-replicasets.
Valutiamo il risultato dei nostri sforzi. Troviamo il nuovo replicaset su .

Evviva!
Sperimentate con la modifica della configurazione delle istanze e dei replicaset e osservate come cambia la topologia del cluster. Potete provare diversi scenari operativi, come ad esempio o l'aumento di memtx_memory. Il ruolo cercherà di farlo senza riavviare l'istanza, per ridurre il possibile downtime della vostra applicazione.
Non dimenticate di eseguire vagrant halt, per fermare le macchine virtuali quando avete finito di lavorare con esse.
E cosa c'è sotto il cofano?
Qui parlerò più dettagliatamente di cosa è accaduto sotto il cofano del ruolo ansible durante i nostri esperimenti.
Esaminiamo passo dopo passo il deploy dell'applicazione Cartridge.
Installazione del pacchetto e avvio delle istanze
Prima di tutto, è necessario trasferire il pacchetto sul server e installarlo. Ora il ruolo può lavorare con pacchetti RPM e DEB.
Successivamente, avviamo le istanze. Qui tutto è molto semplice: ogni istanza è un singolo systemd-servizio. Lo spiego con un esempio:
$ systemctl start myapp@storage-1Questo comando avvierà l'istanza storage-1 dell'applicazione myapp. L'istanza avviata cercherà il suo in /etc/tarantool/conf.d/. I log dell'istanza possono essere visualizzati usando journald.
Il file Unit /etc/systemd/system/myapp@.sevice per il servizio systemd sarà fornito insieme al pacchetto.
In Ansible, ci sono moduli integrati per l'installazione di pacchetti e la gestione dei servizi systemd, non abbiamo inventato nulla di nuovo.
Configurazione della topologia del cluster
Ma qui inizia la parte più interessante. Sarebbe strano dedicarsi a un ruolo ansible speciale per installare pacchetti e avviare systemd-servizi.
Il cluster può essere configurato manualmente:
- Primo metodo: apriamo l'interfaccia Web e facciamo clic sui pulsanti. Per avviare un paio di istanze basta.
- Secondo metodo: possiamo utilizzare l'API GraphQl. Qui è possibile automatizzare qualcosa, ad esempio scrivere uno script in Python.
- Terzo metodo (per i più decisi): accediamo al server e ci connettiamo a una delle istanze tramite
tarantoolctl connected effettuare tutte le manipolazioni necessarie con il modulo Luacartridge.
L'obiettivo principale della nostra invenzione è fare proprio questa parte, la più complessa del lavoro.
Ansible consente di scrivere il proprio modulo e utilizzarlo in un ruolo. Il nostro ruolo utilizza moduli di questo tipo per gestire vari componenti del cluster.
Come funziona? Descrivi lo stato desiderato del cluster in una configurazione dichiarativa, e il ruolo fornisce a ciascun modulo la sua sezione di configurazione. Il modulo riceve lo stato corrente del cluster e lo confronta con quello che ha ricevuto in ingresso. Dopodiché, attraverso il socket di una delle istanze, viene eseguito un codice che porta il cluster allo stato desiderato.
Conclusioni
Oggi abbiamo raccontato e mostrato come distribuire la vostra applicazione su Tarantool Cartridge e configurare una semplice topologia. Per questo abbiamo utilizzato Ansible, uno strumento potente, caratterizzato da un uso semplice e che consente di configurare contemporaneamente molti nodi dell'infrastruttura (nel nostro caso, queste sono istanze del cluster).
In precedenza abbiamo esaminato uno dei numerosi modi per descrivere la configurazione del cluster attraverso Ansible. Non appena capirete di essere pronti per avanzare, approfondite per la scrittura di playbook. Potrebbe esservi più comodo gestire la topologia utilizzando group_vars e host_vars.
Presto parleremo di come espellere definitivamente le istanze dalla topologia, bootstrap vshard, gestire la modalità di failover automatico, configurare l'autenticazione e patchare la configurazione del cluster. Nel frattempo, potete esplorare autonomamente. e sperimentare con le impostazioni del cluster.
Se qualcosa non funziona, assicurati di il problema. Risolveremo tutto rapidamente!
Fonte: habr.com
