Mai 16 2021

MySQL / PostgreSQL sur Disques iSCSI ne Démarre pas au Boot

Publié par sous Linux,Mysql,Postgresql

Vous hébergez les répertoires de données Mysql ou PostgreSQL sur des disques iSCSI mais le service ne démarre pas au boot du serveur. Le service ne trouve pas le répertoire. Pourtant, le service se lance manuellement après s’être loggué en SSH dès qu’il est disponible.

Mysql / PostgreSQL surr iSCSI ne démarre pas

Voici les logs de Mariadb mais ils seraient similaires pour Mysql:

mariadbd[795]: 0 [Note] /usr/sbin/mysqld (mysqld 10.5.9-MariaDB-1:10.5.9+maria~buster-log) starting as process 795 ...
mariadbd[795]: 0 [Warning] Can't create test file /opt/db/data/database_server.lower-test
mariadbd[795]: #007/usr/sbin/mysqld: Cannot change dir to '/var/lib/mysql/data/' (Errcode: 2 "No such file or directory")
mariadbd[795]: 0 [ERROR] Aborting
systemd[1]: mariadb.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: mariadb.service: Failed with result 'exit-code'.
systemd[1]: Failed to start MariaDB 10.5.9 database server.


Vous auriez des logs similaires pour PostgreSQL. J’ai stocké les données PostgreSQL sur une partition XFS, elle-même rrésidant sur LVM pour une gestion de l’espace disque plus flexible, comme l’ajout d’espace pendant que le système de fichiers est monté. C’est probablement la raison principale qui fait que les disques iSCSI sont populaires.

systemd: mounting /var/lib/pgsql
starting PostgreSQL database server
sd 2:0:0:0: [sdb] attached SCSI disk
xfs (dm-4): Mounting V4 Filesystem
postgresql-check-db-dir: "/var/lib/pgsql/data" is missing or empty
postgresql.service: control process exited, code=exited status=1
Failed to start PostgreSQL database server.


La base de données qui démarre manuellement après le boot indique certainement un problème d’ordre de démarrage des services. Les bases de données doivent démarrer après que les disques iscsi sont disponibles. Cela peut être résolu en ajoutant « After=remote-fs.target » dans le fichier systemd du service comme /usr/lib/systemd/system/postgresql-9.5.service pour PosgreSQL par exemple. C’est un moyen de gérer la précédence et les dépendances des services.

Notez que vous pourriez perdre ces changement la prochaine fois que le paquet est mis à jour. Systemd permet de créer un fichier supplémentaire où vous pouvez définir vos propres paramètres. Il ne sera jamais écrasé puisque c’est votre fichier, indépendant du paquet.
Créez simplement /etc/systemd/system/mariadb.service.d/override.conf comme ceci pour Mariadb, c’est la même procédure pour Mysql ou PostgreSQL:

[Service]
Environment="UMASK_DIR=0750"

[Unit]
After=remote-fs.target


Dans ce fichier, j’ai aussi changé les droits par défaut du répertoire de données pour que les utilisateurs appartenant au groupe Mysql puissent le parcourir.
Exécutez systemctl daemon-reload pour que les nouveaux changements soient pris en compte et redémarrez le serveur. La base de données devrait maintenant démarrer.

 

Aucune Réponse

Avr 13 2021

Rendez Ansible 6X Plus Rapide avec ces 3 Astuces

Publié par sous Ansible

Ansible est généralement lent car il se connecte à l’hôte distant pour chaque tâche qu’il exécute. Faisons quelques tests sur un petit rôle qui récupère la dernière version de kubectl (client Kubernetes) depuis une URL, et installe le binaire.
Voyons 3 façons simples d’accélérer Ansible et d’obtenir des meilleurs temps d’exécution.

- name: Récupération de la dernière version
   uri:
     url: "{{kubectl_url}}/stable.txt"
     return_content: yes
     status_code: 200
   register: kubectl_latest_version
 

 - name: Téléchargement du binaire kubectl
   get_url:
     url: "{{kubectl_url}}/v{{ kubectl_version |
       default(kubectl_latest_version.content | 
       regex_replace('^v', '')) }}/bin/{{kubectl_os}}/{{kubectl_arch}}/kubectl"
     dest: "/usr/local/bin"
     mode: '755'
     owner: "{{ kubectl_owner }}"
     group: "{{ kubectl_group }}"


Temps d’exécution avec les paramètres par défaut: 32,2s

Accélérer Ansible


Cache des Facts Ansible

Récupérer les facts est la première tâche qu’Ansible exécute lorsqu’il se connecte à un hôte et le moins que l’on puisse dire est que c’est lent. Très lent. La performance est aussi un problème lorsqu’on écrit un playbook que l’on teste maintes fois.

Heureusement, il est possible de faire des ajustements pour économiser du temps en ajoutant ces quelques lignes dans ansible.cfg:

# implémentation du cache et paramétrage des facts 
# pour une performance améliorée

gathering = smart
gather_subset = !hardware,!facter,!ohai

fact_caching_connection = /tmp/ansible_fact_cache
fact_caching = jsonfile

# expire le cache après 2 heures
fact_caching_timeout = 7200

Selon le fichier exemple ansible.cfg disponible en ligne, smart gathering « récupère par défaut, mais seulement si ce n’est pas déjà fait ».

Les facts hardware sont les plus longs à collecter, mais vous pourriez en avoir besoin surtout si vos rôles reposent sur les interfaces réseau. Vous pourriez recevoir une erreur « ansible_eth0 is undefined » par exemple.
Facter et ohai sont liés aux clients Puppet et Chef.

Et le plus efficace est le cache bien sûr qui stocke les informations dans un fichier JSON. Mais ca pourrait aussi l’être en mémoire, ou même dans une base partagée Redis.

On peut aussi désactiver les facts dans un playbook si on n’en a pas besoin. C’est un gain potentiellement significatif mais qui ne peut pas être utilisé souvent, la plupart des playbooks ont besoin des facts.

- name: mon_playbook
    hosts: *
    gather_facts: no
    tasks:


Temps d’exécution: 19,2s


Accélérer SSH avec le Pipelining

Activer le pipelining réduit le nombre d’opérations SSH requises pour exécuter un module sur le serveur distant. Ceci améliore la performance mais il faut d’abord désactiver ‘requiretty’ dans /etc/sudoers sur tous les hôtes gérés. Raison pour laquelle le pipelining est désactivé par défaut. Ajoutez dans ansible.cfg:

[ssh_connection]
pipelining = True

Si requiretty est paramétré, sudo ne fonctionnera que si l’utilisateur est loggué sur un tty réel.  Dans ce cas, sudo ne se lancera que dans une session de login et non dans un script cron ou cgi-bin. En revanche, ce paramètre est désactivé par défaut d’après la page de man, sur Debian et Ubuntu en tout cas.
On peut donc envisager d’utiliser le pipelining dans ce cas. Vérifiez la page de man de votre distribution Linux.


Temps d’exécution: 11,6s

Delegate_to localhost

La plupart des améliorations dépendent de la façon dont vous écrivez vos tâches Ansible. Dans ce rôle, vous pourriez vous connecter à l’URL depuis n’importe quel hôte – localhost? – et économiser une connexion SSH.
C’est le but de delegate_to qui est souvent pointé sur localhost. La première tâche devient:

- name: get kubectl last version
   delegate_to: localhost
   become: false
   uri:
     url: "{{kubectl_url}}/stable.txt"
     return_content: yes
     status_code: 200
   register: kubectl_latest_version


C’est une optimisation non négligeable que vous pouvez utiliser dès que la tâche peut s’exécuter n’importe où.

Il est préférable d’ajouter become: false ou vous pourriez avoir ce message d’erreur si Ansible essaye de faire un sudo root sur votre machine locale:

fatal: [backup]: FAILED! => {"changed": false, "module_stderr": "sudo: a password is required\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}


Temps d’exécution: 4,7s


Le temps d’exécution est le temps moyen de 10 exécutions à la suite, et les tests ont été réalisés sur un lien VPN loin d’être optimum.

Bien sûr les résultats ne sont pas linéaires, tous les playbooks ne s’exécuteront pas 6 fois plus rapidement mais cela donne une idée. Le cache permet d’économiser quelques secondes au lancement du playbook alors que la délégation à localhost est seulement applicable à quelques cas. Mais n’empêche.

Il existe d’autres améliorations possibles pour accélérer Ansible comme les tâches async pour lancer une tâche et passer immédiatement à la suite. Mais votre meilleur atout est d’exécuter Ansible sur une machine aussi proche que possible des hôtes ciblées.

 

Aucune Réponse

Avr 01 2021

Inventaire Ansible Dynamique des Serveurs IBM Cloud

Publié par sous Ansible,Python

IBM Cloud repose sur l’API Softlayer – aussi appelée IBM Classic Infrastructure – pour automatiser les actions. L’API est disponible en différents langages comme Python, Go, Java ou PHP et nous permettra de générer un inventaire Ansible.


Je vais générer un inventaire dynamique des serveurs récupérés sur mon compte IBM Cloud directement utilisable par Ansible. Je vais aussi générer des groupes correspondants aux datacenters. Vous aimeriez aussi regrouper les serveurs dans toutes sortes de catégories comme Databases, Mysql, Linux, Web, etc… Pas d’inquiétude, on peut aussi faire ca de façon très simple.
On peut y parvenir en ajoutant des tags aux hosts dans le portail IBM Cloud et un host peut avoir plusieurs tags évidemment et appartenir aux groupes Ansible correspondants à ces tags/étiquettes.

Une fois que ces groupes ont été déclarés dans le fichier inventory, vous pouvez lancer les playbooks Ansible comme l’installation des paquets Apache sur les serveurs appartenant au groupe « Web » par exemple.


Vous devez d’abord ajouter votre API key dans un fichier shell à exécuter avant de lancer le script. Ca pourrait faire partie du script, mais cella permet à chaque utilisateur d’utiliser sa propre clé. La clé d’API peut être générée ou trouvée sur le portail IBM Cloud.

export SL_USERNAME=nom_utilisateur
export SL_API_KEY=a1b2c3[...]3456


Lancez . ./IBM_SL_env.sh tout d’abord pour ajouter le username et l’API key dans des variables d’environnement qui seront lues par le script Python ci-dessous.

#!/usr/bin/env python3  
import os
import SoftLayer
 
HOST_VARS_DIR  = "host_vars"
INVENTORY_FILE = "inventory"
 
class Inventory:
   def __init__(self):
      # Variables
      self.categories = {}
      self.datacenter = {}
      self.servers = {}
 
      # Create Softlayer connection
      self.client = SoftLayer.create_client_from_env()
 
      # Init Methods
      self.get_server_list()
      self.write_inventory()
 

   def short_host_name(self, host):
      return host['fullyQualifiedDomainName'][:host['fullyQualifiedDomainName'].find('.mydomain.')]
 

   def add_host_to_cat(self, host, cat):
      if cat == "ibm-kubernetes-service": cat = "kube"
      if cat not in self.categories:
         self.categories[cat] = [host]
      else:
         self.categories[cat].append(host)
 

   def add_server_to_list(self, host):
      try:
         host["primaryBackendIpAddress"]
      except KeyError:
         pass
      else:
         host["ShortHostname"] = self.short_host_name(host)
             
         # Build server Categories list
         if host["tagReferences"] != []:
            for tagRef in host["tagReferences"]:
               self.add_host_to_cat(host["ShortHostname"], tagRef["tag"]["name"].strip())
             
         # Build datacenter lists
         if host["datacenter"]["name"] not in self.datacenter:
            self.datacenter[host["datacenter"]["name"]] = [host["ShortHostname"]]
         else:
            self.datacenter[host["datacenter"]["name"]].append(host["ShortHostname"])
             
         # Build server attribute list
         serverAttributes = {}
         serverAttributes['IP'] = host["primaryBackendIpAddress"]
         self.servers[host["ShortHostname"]] = serverAttributes
     

   def get_server_list(self):
      object_mask = "mask[id,fullyQualifiedDomainName," \
                    "primaryBackendIpAddress," \
                    "tagReferences[tag[name]]," \
                    "datacenter]"
 
      # Get virtual server list
      mgr = SoftLayer.VSManager(self.client)
      for vs in mgr.list_instances(mask=object_mask):
         self.add_server_to_list(vs)
 
      # Get bare metal servers
      hsl = SoftLayer.HardwareManager(self.client)
      for hs in hsl.list_hardware(mask=object_mask):
         self.add_server_to_list(hs)
 

   def write_inventory(self):
      # host_vars structure
      if not os.path.exists(HOST_VARS_DIR):
         os.makedirs(HOST_VARS_DIR)
 
      inventoryFile = open(INVENTORY_FILE,"w")
 
      for cat in self.categories.keys():
         if cat != "kube":
            inventoryFile.write("[" + cat + "]\n")
            for host in self.categories[cat]:
               # write host vars
               inventoryFile.write(host + "\n")
               file = open(HOST_VARS_DIR+"/"+host,"w")
               file.write("ansible_host: " + self.servers[host]['IP'] + "\n")
               file.close()        
            inventoryFile.write("\n")
      for dc in self.datacenter.keys():
         inventoryFile.write("[" + dc + "]\n")
         for host in self.datacenter[dc]:
            if not host.startswith("kube"):
               inventoryFile.write(host + "\n")
         inventoryFile.write("\n")
      inventoryFile.close()

if __name__ == "__main__":
   exit(Inventory())


Quelques notes:

Les nodes Kubernetes managés sont visibles dans l’infrastructure classique d’IBM comme n’importe quelle VM (VSI dans la terminologie IBM) mais vous ne pouvez pas vous y connecter. Ils sont donc ajoutés à la catégorie « Kube » avant d’être ignorés.


Un fichier distinct est créé dans hosts_var pour chaque serveur contenant son address IP. Vous pourriez y ajouter d’autres variables comme les paramètres iSCSI, etc…


Le script récupère les machines virtuelles ainsi que les machines physique bare metal. Vous pouvez commenter l’une de ces sections si vous n’en avez pas besoin, épargnant un appel à IBM.

 

Aucune Réponse

Mar 26 2021

Diagrammes de Gantt en Heure

Publié par sous Divers

Je voulais montrer les temps d’exécution des tâches d’un plan de reprise d’activité sur un diagramme de Gantt pour un plus bel effet qu’une liste ennuyeuse de temps de de démarrage et de fin, mais je n’ai trouvé aucun outil gérant les heures sur une journée/24 heures.

Les softs Gantt comme GanttProject proposent trop de fonctionnalités dont je n’ai pas besoin pour un simple rapport. J’ai donc opté pour la fonction Sparkline sur Google Sheets: c’est gratuit, et ca reste assez facile même s’il faut travailler un peu pour le faire fonctionner avec des heures. C’est aussi disponible sur Excel (ou tout autre tableur comme Google Sheets) évidemment.

Qu’est-ce que Sparkline? En résumé, Sparkline est un graphique dans une cellule Excel (ou équivalent) destiné à donner une tendance. Les graphiques en barres sont parfaits pour les diagrammes de Gantt.

Diagrammes de Gantt en heure


Il n’y a pas de min, et max fonctionne uniquement pour des nombres sur les graphiques en barres, c’est pour cela que j’ai créé 2 colonnes Start delay et Duration en minutes. Des formules basiques sur les les heures de début et de fin du projet et des tâches permettent de les remplir automatiquement.

=HEURE(D5-$D$3)*60+MINUTE(D5-$D$3); Start delay
=HEURE(E5-D5)*60+MINUTE(E5-D5); Duration


Les cellules Sparkline sont construites à partir de ces 2 valeurs; La première barre est blanche pour positionner la barre de couleur au bon endroit. La valeur Max est tout simplement la durée du projet.

=SPARKLINE(F5:G5,{"charttype","bar"\"color1","white"\"color2","#199698"\"max",$G$3})
 

Aucune Réponse

Mar 16 2021

Faites de Beaux Diagrammes avec le Diagram as Code

Publié par sous Python

Le Diagram as Code est un sujet bien présent en ce moment qui apporte de nombreux avantages. Parmi lesquels:
– Garder une trace des changements, qui et quoi
– Stocker sur un dépôt de code comme simple texte
– Pas besoin de réaligner les flèches ou bouger les icônes quand on ajoute des éléments
– Plus rapide une fois prise en main
– C’est du code, et vous savez combien les devs aiment faire des diagrammes manuels
– le rendu des diagrammes, tout est aligné proprement
– De nombreuses icônes disponibles


Une bibliothèque de diagrammes open source est disponible sur diagrams.mingrammer.com en Python et Go. Je ne décrirai pas les étapes d’installation, c’est très bien expliqué dans leur documentation. Ils fournissent aussi de très bons diagrammes d’exemples.
Je vais tenter de convertir un vieux diagramme fait sur Microsoft Visio il y a longtemps en diagram as code. Cette image vient d’un article de réplication Mysql.

Visio Diagram


Exemple de Diagram as Code


Voici le code que j’ai écrit pour générer l’image:

from diagrams import Cluster, Diagram, Edge
from diagrams.azure.compute import *
from diagrams.azure.database import *
 
with Diagram("Replication", show="False", direction='TB'):
 
  slaves = []
  clients= []
 
  master = SQLServers("Master")
  with Cluster("slaves"):
    for s in range(3):
      slave = SQLDatabases("slave"+str(s+1))
      slaves.append(slave)
 
  for c in range(3):
    client = VM("client"+str(c+1))
    clients.append(client)
    clients[c] >> Edge(color="darkgreen",label="Reads") >> slaves[c]
    
  clients >> Edge(color="red",label="Writes") >> master
  master >> Edge(color="blue",label="Replication") >> slaves[1]

Moins de 20 lignes de code, c’est tout. Les icônes sont celles du répertoire Azure mais j’aurais pu en prendre d’autres. La seconde image est à peu près la même mais j’ai supprimé la direction qui devient gauche vers droite par défaut. Les labels sont mieux gérés dans cette direction comme vous le voyez, même si ce n’est toujours pas parfait avec des flèches multiples.
J’ai aussi enlevé le label « Read » au milieu pour un meilleur alignement en liant des objets simple plutôt que des tableaux. J’ai aussi remplacé

clients[c] >> Edge(color="darkgreen",label="Reads") >> slaves[c]

par (en dehors de la boucle for):

for i in [0,2]: clients[i] >> Edge(color="darkgreen",label="Reads") >> slaves[i]


Difficultés rencontrées

Il peut s’avérer un peu compliqué d’obtenir exactement ce que vous voulez surtout avec des niveaux multiples connectés les uns aux autres. Vous pouvez experimenter et changer les comportements en jouant avec les groupements par Cluster. Ca peut être utile quand vous voulez que les niveaux 2 et 4 soient regroupés par exemple mais ca peut aussi devenir brouillon comme sur ce cluster Mysql:

Mysql Replication Diagram as code


En un mot, cette implémentation de Diagram as Code est puissant et efficace même si l’on perd du contrôle sur le placement des éléments. Un petit inconvénient pour une très bonne librairie. Une fois familiarisé avec toutes ces petites astuces, vous pouvez créer de magnifiques diagrammes. Voici un exemple d’architecture basique Kubernetes:

Kubernetes Diagram as Code
 

Aucune Réponse

« Précédent - Suivant »