Il monitoraggio è una preoccupazione per i container, poiché l'infrastruttura è dinamica. I contenitori possono essere creati e distrutti di routine e sono effimeri. Quindi, come tieni traccia delle tue istanze MySQL in esecuzione su Docker?
Come con qualsiasi componente software, ci sono molte opzioni disponibili che possono essere utilizzate. Considereremo Prometheus come una soluzione creata per l'infrastruttura distribuita e funziona molto bene con Docker.
Questo è un blog in due parti. In questo blog, parte 1, tratteremo l'aspetto della distribuzione dei nostri container MySQL con Prometheus e i suoi componenti, in esecuzione come container Docker autonomi e servizi Docker Swarm. Nella parte 2, esamineremo le metriche importanti da monitorare dai nostri container MySQL, nonché l'integrazione con i sistemi di paging e notifica.
Introduzione a Prometeo
Prometheus è un sistema completo di monitoraggio e trend che include scraping integrato e attivo, archiviazione, query, rappresentazione grafica e avvisi basati su dati di serie temporali. Prometheus raccoglie le metriche tramite il meccanismo di pull da target configurati a determinati intervalli, valuta le espressioni delle regole, visualizza i risultati e può attivare avvisi se si osserva che alcune condizioni sono vere. Supporta tutte le metriche di destinazione che vogliamo misurare se si desidera eseguire MySQL come contenitori Docker. Tali metriche includono le metriche degli host fisici, le metriche dei container Docker e le metriche del server MySQL.
Dai un'occhiata al diagramma seguente che illustra l'architettura di Prometheus (tratto dalla documentazione ufficiale di Prometheus):
Stiamo per distribuire alcuni contenitori MySQL (standalone e Docker Swarm) completi di un server Prometheus, MySQL exporter (ovvero un agente Prometheus per esporre le metriche MySQL, che possono quindi essere raschiate dal server Prometheus) e anche Alertmanager per gestire gli avvisi basati sulle metriche raccolte.
Per maggiori dettagli consulta la documentazione di Prometheus. In questo esempio, utilizzeremo le immagini Docker ufficiali fornite dal team di Prometheus.
Docker autonomo
Distribuzione di contenitori MySQL
Eseguiamo due server MySQL autonomi su Docker per semplificare la nostra procedura dettagliata di distribuzione. Un container utilizzerà l'ultimo MySQL 8.0 e l'altro MySQL 5.7. Entrambi i container si trovano nella stessa rete Docker denominata "db_network":
$ docker network create db_network
$ docker run -d \
--name mysql80 \
--publish 3306 \
--network db_network \
--restart unless-stopped \
--env MYSQL_ROOT_PASSWORD=mypassword \
--volume mysql80-datadir:/var/lib/mysql \
mysql:8 \
--default-authentication-plugin=mysql_native_password
MySQL 8 utilizza per impostazione predefinita un nuovo plug-in di autenticazione chiamato caching_sha2_password . Per la compatibilità con il contenitore di esportazione MySQL di Prometheus, utilizziamo il ampiamente utilizzato mysql_native_password plugin ogni volta che creiamo un nuovo utente MySQL su questo server.
Per il secondo contenitore MySQL in esecuzione 5.7, eseguiamo quanto segue:
$ docker run -d \
--name mysql57 \
--publish 3306 \
--network db_network \
--restart unless-stopped \
--env MYSQL_ROOT_PASSWORD=mypassword \
--volume mysql57-datadir:/var/lib/mysql \
mysql:5.7
Verifica se i nostri server MySQL funzionano correttamente:
[[email protected] mysql]# docker ps | grep mysql
cc3cd3c4022a mysql:5.7 "docker-entrypoint.s…" 12 minutes ago Up 12 minutes 0.0.0.0:32770->3306/tcp mysql57
9b7857c5b6a1 mysql:8 "docker-entrypoint.s…" 14 minutes ago Up 14 minutes 0.0.0.0:32769->3306/tcp mysql80
A questo punto, la nostra architettura è simile a questa:
Iniziamo a monitorarli.
Esposizione delle metriche Docker a Prometheus
Docker ha un supporto integrato come target Prometheus, che possiamo utilizzare per monitorare le statistiche del motore Docker. Possiamo semplicemente abilitarlo creando un file di testo chiamato "daemon.json" all'interno dell'host Docker:
$ vim /etc/docker/daemon.json
E aggiungi le seguenti righe:
{
"metrics-addr" : "12.168.55.161:9323",
"experimental" : true
}
Dove 192.168.55.161 è l'indirizzo IP principale dell'host Docker. Quindi, riavvia il demone Docker per caricare la modifica:
$ systemctl restart docker
Poiché abbiamo definito --restart=unless-stoppato nel comando di esecuzione dei nostri contenitori MySQL, i contenitori verranno avviati automaticamente dopo l'esecuzione di Docker.
Distribuzione di MySQL Exporter
Prima di andare oltre, l'esportatore mysqld richiede che un utente MySQL venga utilizzato per scopi di monitoraggio. Nei nostri container MySQL, crea l'utente di monitoraggio:
$ docker exec -it mysql80 mysql -uroot -p
Enter password:
mysql> CREATE USER 'exporter'@'%' IDENTIFIED BY 'exporterpassword' WITH MAX_USER_CONNECTIONS 3;
mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';
Tieni presente che si consiglia di impostare un limite massimo di connessione per l'utente per evitare di sovraccaricare il server con il monitoraggio di scraping sotto carico pesante. Ripeti le affermazioni precedenti sul secondo contenitore, mysql57:
$ docker exec -it mysql57 mysql -uroot -p
Enter password:
mysql> CREATE USER 'exporter'@'%' IDENTIFIED BY 'exporterpassword' WITH MAX_USER_CONNECTIONS 3;
mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';
Eseguiamo il contenitore mysqld exporter chiamato "mysql8-exporter" per esporre le metriche per la nostra istanza MySQL 8.0 come di seguito:
$ docker run -d \
--name mysql80-exporter \
--publish 9104 \
--network db_network \
--restart always \
--env DATA_SOURCE_NAME="exporter:[email protected](mysql80:3306)/" \
prom/mysqld-exporter:latest \
--collect.info_schema.processlist \
--collect.info_schema.innodb_metrics \
--collect.info_schema.tablestats \
--collect.info_schema.tables \
--collect.info_schema.userstats \
--collect.engine_innodb_status
E anche un altro contenitore di esportazione per la nostra istanza MySQL 5.7:
$ docker run -d \
--name mysql57-exporter \
--publish 9104 \
--network db_network \
--restart always \
-e DATA_SOURCE_NAME="exporter:[email protected](mysql57:3306)/" \
prom/mysqld-exporter:latest \
--collect.info_schema.processlist \
--collect.info_schema.innodb_metrics \
--collect.info_schema.tablestats \
--collect.info_schema.tables \
--collect.info_schema.userstats \
--collect.engine_innodb_status
Abbiamo abilitato un gruppo di flag di raccolta per il contenitore per esporre le metriche MySQL. Puoi anche abilitare --collect.slave_status, --collect.slave_hosts se hai una replica MySQL in esecuzione su container.
Dovremmo essere in grado di recuperare le metriche MySQL tramite curl dall'host Docker direttamente (la porta 32771 è la porta pubblicata assegnata automaticamente da Docker per il contenitore mysql80-exporter):
$ curl 127.0.0.1:32771/metrics
...
mysql_info_schema_threads_seconds{state="waiting for lock"} 0
mysql_info_schema_threads_seconds{state="waiting for table flush"} 0
mysql_info_schema_threads_seconds{state="waiting for tables"} 0
mysql_info_schema_threads_seconds{state="waiting on cond"} 0
mysql_info_schema_threads_seconds{state="writing to net"} 0
...
process_virtual_memory_bytes 1.9390464e+07
A questo punto, la nostra architettura è simile a questa:
Ora possiamo configurare il server Prometheus.
Distribuzione del server Prometheus
Innanzitutto, crea il file di configurazione di Prometheus in ~/prometheus.yml e aggiungi le seguenti righe:
$ vim ~/prometheus.yml
global:
scrape_interval: 5s
scrape_timeout: 3s
evaluation_interval: 5s
# Our alerting rule files
rule_files:
- "alert.rules"
# Scrape endpoints
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'mysql'
static_configs:
- targets: ['mysql57-exporter:9104','mysql80-exporter:9104']
- job_name: 'docker'
static_configs:
- targets: ['192.168.55.161:9323']
Dal file di configurazione di Prometheus, abbiamo definito tre lavori:"prometheus", "mysql" e "docker". Il primo è il compito di monitorare il server Prometheus stesso. Il prossimo è il lavoro per monitorare i nostri contenitori MySQL chiamati "mysql". Definiamo gli endpoint sui nostri esportatori MySQL sulla porta 9104, che ha esposto le metriche compatibili con Prometheus rispettivamente dalle istanze MySQL 8.0 e 5.7. "alert.rules" è il file delle regole che includeremo più avanti nel prossimo post del blog a scopo di avviso.
Possiamo quindi mappare la configurazione con il container Prometheus. Dobbiamo anche creare un volume Docker per i dati Prometheus per la persistenza e anche esporre pubblicamente la porta 9090:
$ docker run -d \
--name prometheus-server \
--publish 9090:9090 \
--network db_network \
--restart unless-stopped \
--mount type=volume,src=prometheus-data,target=/prometheus \
--mount type=bind,src="$(pwd)"/prometheus.yml,target=/etc/prometheus/prometheus.yml \
--mount type=bind,src="$(pwd)
prom/prometheus
Ora il nostro server Prometheus è già in esecuzione ed è possibile accedervi direttamente sulla porta 9090 dell'host Docker. Apri un browser web e vai a http://192.168.55.161:9090/ per accedere all'interfaccia utente web di Prometheus. Verifica lo stato del target in Stato -> Target e assicurati che siano tutti verdi:
A questo punto, la nostra architettura di container è simile a questa:
Il nostro sistema di monitoraggio Prometheus per i nostri container MySQL standalone è ora distribuito.
Sciame Docker
Distribuzione di un cluster Galera a 3 nodi
Supponendo di voler distribuire un cluster Galera a tre nodi in Docker Swarm, dovremmo creare 3 servizi diversi, ognuno dei quali rappresenta un nodo Galera. Utilizzando questo approccio, possiamo mantenere un nome host risolvibile statico per il nostro contenitore Galera, insieme ai contenitori di esportazione MySQL che accompagneranno ciascuno di essi. Utilizzeremo l'immagine MariaDB 10.2 gestita dal team Docker per eseguire il nostro cluster Galera.
Per prima cosa, crea un file di configurazione MySQL da utilizzare per il nostro servizio Swarm:
$ vim ~/my.cnf
[mysqld]
default_storage_engine = InnoDB
binlog_format = ROW
innodb_flush_log_at_trx_commit = 0
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
innodb_autoinc_lock_mode = 2
innodb_lock_schedule_algorithm = FCFS # MariaDB >10.1.19 and >10.2.3 only
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
wsrep_sst_method = mariabackup
Crea una rete di database dedicata nel nostro Swarm chiamata "db_swarm":
$ docker network create --driver overlay db_swarm
Importa il nostro file di configurazione MySQL nella configurazione Docker in modo da poterlo caricare nel nostro servizio Swarm quando lo creeremo in seguito:
$ cat ~/my.cnf | docker config create my-cnf -
Crea il primo servizio bootstrap Galera, con "gcomm://" come indirizzo del cluster chiamato "galera0". Questo è un servizio transitorio solo per il processo di bootstrap. Elimineremo questo servizio una volta che avremo altri 3 servizi Galera in esecuzione:
$ docker service create \
--name galera0 \
--replicas 1 \
--hostname galera0 \
--network db_swarm \
--publish 3306 \
--publish 4444 \
--publish 4567 \
--publish 4568 \
--config src=my-cnf,target=/etc/mysql/mariadb.conf.d/my.cnf \
--env MYSQL_ROOT_PASSWORD=mypassword \
--mount type=volume,src=galera0-datadir,dst=/var/lib/mysql \
mariadb:10.2 \
--wsrep_cluster_address=gcomm:// \
--wsrep_sst_auth="root:mypassword" \
--wsrep_node_address=galera0
A questo punto, la nostra architettura del database può essere illustrata come segue:
Quindi, ripeti il seguente comando per 3 volte per creare 3 diversi servizi Galera. Sostituisci {name} rispettivamente con galera1, galera2 e galera3:
$ docker service create \
--name {name} \
--replicas 1 \
--hostname {name} \
--network db_swarm \
--publish 3306 \
--publish 4444 \
--publish 4567 \
--publish 4568 \
--config src=my-cnf,target=/etc/mysql/mariadb.conf.d/my.cnf \
--env MYSQL_ROOT_PASSWORD=mypassword \
--mount type=volume,src={name}-datadir,dst=/var/lib/mysql \
mariadb:10.2 \
--wsrep_cluster_address=gcomm://galera0,galera1,galera2,galera3 \
--wsrep_sst_auth="root:mypassword" \
--wsrep_node_address={name}
Verifica i nostri attuali servizi Docker:
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
wpcxye3c4e9d galera0 replicated 1/1 mariadb:10.2 *:30022->3306/tcp, *:30023->4444/tcp, *:30024-30025->4567-4568/tcp
jsamvxw9tqpw galera1 replicated 1/1 mariadb:10.2 *:30026->3306/tcp, *:30027->4444/tcp, *:30028-30029->4567-4568/tcp
otbwnb3ridg0 galera2 replicated 1/1 mariadb:10.2 *:30030->3306/tcp, *:30031->4444/tcp, *:30032-30033->4567-4568/tcp
5jp9dpv5twy3 galera3 replicated 1/1 mariadb:10.2 *:30034->3306/tcp, *:30035->4444/tcp, *:30036-30037->4567-4568/tcp
La nostra architettura ora ha un aspetto simile a questo:
È necessario rimuovere il servizio Swarm bootstrap di Galera, galera0, per interromperne l'esecuzione perché se il contenitore viene riprogrammato da Docker Swarm, verrà avviata una nuova replica con un nuovo volume nuovo. Corriamo il rischio di perdita di dati perché --wsrep_cluster_address contiene "galera0" negli altri nodi Galera (o servizi Swarm). Quindi, rimuoviamolo:
$ docker service rm galera0
A questo punto, abbiamo il nostro Cluster Galera a tre nodi:
Ora siamo pronti per implementare il nostro esportatore MySQL e il server Prometheus.
Servizio Swarm di MySQL Exporter
Accedi a uno dei nodi Galera e crea l'utente esportatore con i privilegi appropriati:
$ docker exec -it {galera1} mysql -uroot -p
Enter password:
mysql> CREATE USER 'exporter'@'%' IDENTIFIED BY 'exporterpassword' WITH MAX_USER_CONNECTIONS 3;
mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%';
Quindi, crea il servizio di esportazione per ciascuno dei servizi Galera (sostituisci {name} rispettivamente con galera1, galera2 e galera3):
$ docker service create \
--name {name}-exporter \
--network db_swarm \
--replicas 1 \
-p 9104 \
-e DATA_SOURCE_NAME="exporter:[email protected]({name}:3306)/" \
prom/mysqld-exporter:latest \
--collect.info_schema.processlist \
--collect.info_schema.innodb_metrics \
--collect.info_schema.tablestats \
--collect.info_schema.tables \
--collect.info_schema.userstats \
--collect.engine_innodb_status
A questo punto, la nostra architettura è simile a questa con i servizi di esportazione nella foto:
Servizio Prometheus Server Swarm
Infine, distribuiamo il nostro server Prometheus. Simile alla distribuzione di Galera, dobbiamo preparare il file di configurazione di Prometheus prima di importarlo in Swarm usando il comando Docker config:
$ vim ~/prometheus.yml
global:
scrape_interval: 5s
scrape_timeout: 3s
evaluation_interval: 5s
# Our alerting rule files
rule_files:
- "alert.rules"
# Scrape endpoints
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'galera'
static_configs:
- targets: ['galera1-exporter:9104','galera2-exporter:9104', 'galera3-exporter:9104']
Dal file di configurazione di Prometheus, abbiamo definito tre lavori:"prometheus" e "galera". Il primo è il compito di monitorare il server Prometheus stesso. Il prossimo è il lavoro per monitorare i nostri contenitori MySQL chiamati "galera". Definiamo gli endpoint sui nostri esportatori MySQL sulla porta 9104, che espongono le metriche compatibili con Prometheus rispettivamente dai tre nodi Galera. "alert.rules" è il file delle regole che includeremo più avanti nel prossimo post del blog a scopo di avviso.
Importa il file di configurazione nella configurazione Docker da utilizzare con il contenitore Prometheus in seguito:
$ cat ~/prometheus.yml | docker config create prometheus-yml -
Eseguiamo il container del server Prometheus e pubblichiamo la porta 9090 di tutti gli host Docker per il servizio dell'interfaccia utente Web di Prometheus:
$ docker service create \
--name prometheus-server \
--publish 9090:9090 \
--network db_swarm \
--replicas 1 \
--config src=prometheus-yml,target=/etc/prometheus/prometheus.yml \
--mount type=volume,src=prometheus-data,dst=/prometheus \
prom/prometheus
Verifica con il comando del servizio Docker di avere 3 servizi Galera, 3 servizi di esportazione e 1 servizio Prometheus:
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
jsamvxw9tqpw galera1 replicated 1/1 mariadb:10.2 *:30026->3306/tcp, *:30027->4444/tcp, *:30028-30029->4567-4568/tcp
hbh1dtljn535 galera1-exporter replicated 1/1 prom/mysqld-exporter:latest *:30038->9104/tcp
otbwnb3ridg0 galera2 replicated 1/1 mariadb:10.2 *:30030->3306/tcp, *:30031->4444/tcp, *:30032-30033->4567-4568/tcp
jq8i77ch5oi3 galera2-exporter replicated 1/1 prom/mysqld-exporter:latest *:30039->9104/tcp
5jp9dpv5twy3 galera3 replicated 1/1 mariadb:10.2 *:30034->3306/tcp, *:30035->4444/tcp, *:30036-30037->4567-4568/tcp
10gdkm1ypkav galera3-exporter replicated 1/1 prom/mysqld-exporter:latest *:30040->9104/tcp
gv9llxrig30e prometheus-server replicated 1/1 prom/prometheus:latest *:9090->9090/tcp
Ora il nostro server Prometheus è già in esecuzione ed è possibile accedervi direttamente sulla porta 9090 da qualsiasi nodo Docker. Apri un browser web e vai a http://192.168.55.161:9090/ per accedere all'interfaccia utente web di Prometheus. Verifica lo stato del target in Stato -> Target e assicurati che siano tutti verdi:
A questo punto, la nostra architettura Swarm è simile a questa:
Continua..
Ora abbiamo il nostro database e lo stack di monitoraggio distribuito su Docker. Nella parte 2 del blog, esamineremo le diverse metriche MySQL da tenere d'occhio. Vedremo anche come configurare gli avvisi con Prometheus.