La surveillance est une préoccupation pour les conteneurs, car l'infrastructure est dynamique. Les conteneurs peuvent être créés et détruits de manière routinière et sont éphémères. Alors, comment suivre l'exécution de vos instances MySQL sur Docker ?
Comme pour tout composant logiciel, de nombreuses options peuvent être utilisées. Nous considérerons Prometheus comme une solution conçue pour une infrastructure distribuée et fonctionne très bien avec Docker.
Ceci est un blog en deux parties. Dans cette partie 1 du blog, nous allons couvrir l'aspect déploiement de nos conteneurs MySQL avec Prometheus et ses composants, fonctionnant en tant que conteneurs Docker autonomes et services Docker Swarm. Dans la partie 2, nous examinerons les métriques importantes à surveiller à partir de nos conteneurs MySQL, ainsi que l'intégration avec les systèmes de pagination et de notification.
Introduction à Prométhée
Prometheus est un système complet de surveillance et de tendances qui comprend le grattage, le stockage, l'interrogation, la représentation graphique et l'alerte intégrés et actifs basés sur des données de séries chronologiques. Prometheus collecte des métriques via un mécanisme d'extraction à partir de cibles configurées à des intervalles donnés, évalue les expressions de règle, affiche les résultats et peut déclencher des alertes si certaines conditions s'avèrent vraies. Il prend en charge toutes les métriques cibles que nous voulons mesurer si l'on souhaite exécuter MySQL en tant que conteneurs Docker. Ces métriques incluent des métriques d'hôtes physiques, des métriques de conteneur Docker et des métriques de serveur MySQL.
Jetez un œil au schéma suivant qui illustre l'architecture de Prometheus (extrait de la documentation officielle de Prometheus) :
Nous allons déployer des conteneurs MySQL (autonomes et Docker Swarm) complets avec un serveur Prometheus, un exportateur MySQL (c'est-à-dire un agent Prometheus pour exposer les métriques MySQL, qui peuvent ensuite être récupérées par le serveur Prometheus) et également Alertmanager pour gérer les alertes basées sur sur les métriques collectées.
Pour plus de détails, consultez la documentation de Prometheus. Dans cet exemple, nous allons utiliser les images Docker officielles fournies par l'équipe Prometheus.
Docker autonome
Déployer des conteneurs MySQL
Exécutons deux serveurs MySQL autonomes sur Docker pour simplifier notre procédure pas à pas de déploiement. Un conteneur utilisera la dernière version de MySQL 8.0 et l'autre MySQL 5.7. Les deux conteneurs sont dans le même réseau Docker appelé "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 utilise par défaut un nouveau plugin d'authentification appelé caching_sha2_password . Pour la compatibilité avec le conteneur d'exportation Prometheus MySQL, utilisons le très utilisé mysql_native_password plugin chaque fois que nous créons un nouvel utilisateur MySQL sur ce serveur.
Pour le deuxième conteneur MySQL exécutant la version 5.7, nous exécutons ce qui suit :
$ 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
Vérifiez si nos serveurs MySQL fonctionnent correctement :
[[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
À ce stade, notre architecture ressemble à ceci :
Commençons à les surveiller.
Exposer les métriques Docker à Prometheus
Docker a un support intégré en tant que cible Prometheus, où nous pouvons utiliser pour surveiller les statistiques du moteur Docker. Nous pouvons simplement l'activer en créant un fichier texte appelé "daemon.json" à l'intérieur de l'hôte Docker :
$ vim /etc/docker/daemon.json
Et ajoutez les lignes suivantes :
{
"metrics-addr" : "12.168.55.161:9323",
"experimental" : true
}
Où 192.168.55.161 est l'adresse IP principale de l'hôte Docker. Ensuite, redémarrez le démon Docker pour charger le changement :
$ systemctl restart docker
Puisque nous avons défini --restart=unless-stopped dans la commande d'exécution de nos conteneurs MySQL, les conteneurs seront automatiquement démarrés après l'exécution de Docker.
Déploiement de l'exportateur MySQL
Avant d'aller plus loin, l'exportateur mysqld nécessite l'utilisation d'un utilisateur MySQL à des fins de surveillance. Sur nos conteneurs MySQL, créez l'utilisateur de surveillance :
$ 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'@'%';
Notez qu'il est recommandé de définir une limite de connexion maximale pour l'utilisateur afin d'éviter de surcharger le serveur avec des scraps de surveillance sous une charge importante. Répétez les instructions ci-dessus sur le deuxième conteneur, 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'@'%';
Lançons le conteneur d'exportation mysqld appelé "mysql8-exporter" pour exposer les métriques de notre instance MySQL 8.0 comme ci-dessous :
$ 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
Et aussi un autre conteneur d'exportation pour notre instance 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
Nous avons activé un tas d'indicateurs de collecteur pour le conteneur afin d'exposer les métriques MySQL. Vous pouvez également activer --collect.slave_status, --collect.slave_hosts si vous avez une réplication MySQL en cours d'exécution sur des conteneurs.
Nous devrions pouvoir récupérer les métriques MySQL via curl directement depuis l'hôte Docker (le port 32771 est le port publié attribué automatiquement par Docker pour le conteneur 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
À ce stade, notre architecture ressemble à ceci :
Nous sommes maintenant prêts à configurer le serveur Prometheus.
Déploiement du serveur Prometheus
Tout d'abord, créez le fichier de configuration Prometheus dans ~/prometheus.yml et ajoutez les lignes suivantes :
$ 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']
A partir du fichier de configuration de Prometheus, nous avons défini trois jobs - "prometheus", "mysql" et "docker". Le premier est le travail de surveillance du serveur Prometheus lui-même. Le prochain est le travail de surveillance de nos conteneurs MySQL nommés "mysql". Nous définissons les points de terminaison sur nos exportateurs MySQL sur le port 9104, qui exposent les métriques compatibles Prometheus des instances MySQL 8.0 et 5.7 respectivement. Le "alert.rules" est le fichier de règles que nous inclurons plus tard dans le prochain article de blog à des fins d'alerte.
Nous pouvons ensuite mapper la configuration avec le conteneur Prometheus. Nous devons également créer un volume Docker pour les données Prometheus à des fins de persistance et également exposer publiquement le port 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
Maintenant, notre serveur Prometheus est déjà en cours d'exécution et est accessible directement sur le port 9090 de l'hôte Docker. Ouvrez un navigateur Web et accédez à http://192.168.55.161:9090/ pour accéder à l'interface utilisateur Web Prometheus. Vérifiez le statut de la cible sous Statut -> Cibles et assurez-vous qu'elles sont toutes vertes :
À ce stade, notre architecture de conteneur ressemble à ceci :
Notre système de surveillance Prometheus pour nos conteneurs MySQL autonomes est maintenant déployé.
Essaim Docker
Déploiement d'un cluster Galera à 3 nœuds
Supposons que nous voulions déployer un cluster Galera à trois nœuds dans Docker Swarm, nous devrions créer 3 services différents, chaque service représentant un nœud Galera. En utilisant cette approche, nous pouvons conserver un nom d'hôte résoluble statique pour notre conteneur Galera, ainsi que les conteneurs d'exportation MySQL qui accompagneront chacun d'eux. Nous utiliserons l'image MariaDB 10.2 gérée par l'équipe Docker pour exécuter notre cluster Galera.
Tout d'abord, créez un fichier de configuration MySQL à utiliser par notre service 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
Créez un réseau de base de données dédié dans notre Swarm appelé "db_swarm":
$ docker network create --driver overlay db_swarm
Importez notre fichier de configuration MySQL dans la configuration Docker afin que nous puissions le charger dans notre service Swarm lorsque nous le créerons plus tard :
$ cat ~/my.cnf | docker config create my-cnf -
Créez le premier service d'amorçage Galera, avec "gcomm://" comme adresse de cluster appelée "galera0". Il s'agit d'un service transitoire pour le processus d'amorçage uniquement. Nous supprimerons ce service une fois que nous aurons activé 3 autres services Galera :
$ 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
À ce stade, notre architecture de base de données peut être illustrée comme suit :
Ensuite, répétez la commande suivante 3 fois pour créer 3 services Galera différents. Remplacez {name} par galera1, galera2 et galera3 respectivement :
$ 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}
Vérifiez nos services Docker actuels :
$ 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
Notre architecture ressemble maintenant à ceci :
Nous devons supprimer le service Galera bootstrap Swarm, galera0, pour l'empêcher de s'exécuter, car si le conteneur est reprogrammé par Docker Swarm, une nouvelle réplique sera démarrée avec un nouveau volume frais. Nous courons le risque de perdre des données car --wsrep_cluster_address contient "galera0" dans les autres nœuds Galera (ou services Swarm). Alors, supprimons-le :
$ docker service rm galera0
À ce stade, nous avons notre cluster Galera à trois nœuds :
Nous sommes maintenant prêts à déployer notre exportateur MySQL et notre serveur Prometheus.
Service Swarm d'exportation MySQL
Connectez-vous à l'un des nœuds Galera et créez l'utilisateur exportateur avec les privilèges appropriés :
$ 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'@'%';
Ensuite, créez le service d'exportation pour chacun des services Galera (remplacez {name} par galera1, galera2 et galera3 respectivement) :
$ 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
À ce stade, notre architecture ressemble à ceci avec les services d'exportation dans l'image :
Service Swarm du serveur Prometheus
Enfin, déployons notre serveur Prometheus. Comme pour le déploiement Galera, nous devons d'abord préparer le fichier de configuration Prometheus avant de l'importer dans Swarm à l'aide de la commande 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']
À partir du fichier de configuration de Prometheus, nous avons défini trois tâches - "prometheus" et "galera". Le premier est le travail de surveillance du serveur Prometheus lui-même. Le prochain est le travail de surveillance de nos conteneurs MySQL nommés "galera". Nous définissons les points de terminaison sur nos exportateurs MySQL sur le port 9104, qui exposent les métriques compatibles Prometheus des trois nœuds Galera respectivement. Le "alert.rules" est le fichier de règles que nous inclurons plus tard dans le prochain article de blog à des fins d'alerte.
Importez le fichier de configuration dans la configuration Docker pour l'utiliser ultérieurement avec le conteneur Prometheus :
$ cat ~/prometheus.yml | docker config create prometheus-yml -
Exécutons le conteneur du serveur Prometheus et publions le port 9090 de tous les hôtes Docker pour le service d'interface utilisateur Web 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
Vérifiez avec la commande du service Docker que nous avons 3 services Galera, 3 services exportateur et 1 service 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
Maintenant, notre serveur Prometheus est déjà en cours d'exécution et est accessible directement sur le port 9090 à partir de n'importe quel nœud Docker. Ouvrez un navigateur Web et accédez à http://192.168.55.161:9090/ pour accéder à l'interface utilisateur Web Prometheus. Vérifiez le statut de la cible sous Statut -> Cibles et assurez-vous qu'elles sont toutes vertes :
À ce stade, notre architecture Swarm ressemble à ceci :
A suivre..
Nous avons maintenant notre base de données et notre pile de surveillance déployées sur Docker. Dans la partie 2 du blog, nous examinerons les différentes métriques MySQL à surveiller. Nous verrons également comment configurer les alertes avec Prometheus.