Table des matières
- 2026:
- 2025:
6 billet(s) pour juillet 2026
| Contre DNS | 2026/07/28 09:29 | Jean-Baptiste |
| Limiter la consommation de la RAM d'une application avec les cgroups slices | 2026/07/28 05:29 | Jean-Baptiste |
| Procédure simple augmentation de la SWAP | 2026/07/17 15:49 | Jean-Baptiste |
| Exemple git clone avec Ansible | 2026/07/16 14:47 | Jean-Baptiste |
| Windows exe - Comparaison de fichiers binaires | 2026/07/16 10:25 | Jean-Baptiste |
| Pb git | 2026/07/01 17:36 | Jean-Baptiste |
Notes OpenStack Glance (images)
Install de Glance (Pour gérer les images)
Voir :
sudo yum install openstack-glance penstack-glance-doc
sudo su - postgres
CREATE ROLE glanceuser WITH LOGIN PASSWORD 'toor'; CREATE DATABASE glance OWNER glanceuser ;
source openrc openstack project create service openstack user create --domain default --password-prompt glance openstack role add --project service --user glance admin openstack service create image --name glance --description "Glance Image Service" openstack endpoint create --region RegionOne glance public http://srv-openstack-controller:9292
Conf
- /etc/glance/glance-api.conf
- /etc/glance/glance-registry.conf
/etc/glance/glance-api.conf
[DEFAULT] debug = true [database] connection = postgresql://glanceuser:toor@127.0.0.1/glance [glance_store] stores = file,http default_store = file filesystem_store_datadir = /var/lib/glance/images [keystone_authtoken] www_authenticate_uri = http://srv-openstack-controller:5000/v3: auth_type = password project_domain_name = Default user_domain_name = Default project_name = service username = glance password = toor [paste_deploy] flavor = keystone
Idem pour /etc/glance/glance-registry.conf
su -s /bin/sh -c 'glance-manage db_sync' glance mkdir /var/lib/glance/images chown glance:nobody /var/lib/glance/images/ systemctl start openstack-glance-api.service systemctl start openstack-glance-registry.service systemctl enable openstack-glance-api.service systemctl enable openstack-glance-registry.service
Test
openstack image list wget http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img openstack image create cirros --file cirros-0.3.4-x86_64-disk.img --disk-format qcow2 --container-format bare --public
API CLI
openstack.rc
unset $(set | grep _ENDPOINT_ | cut -d= -f1) unset $(set | grep ^OS_ | cut -d= -f1) export LC_ALL=C # LC_ALL=C.UTF-8 export OS_NO_CACHE='true' export OS_CACERT=/etc/ssl/certs/ export OS_IDENTITY_API_VERSION='3' export OS_AUTH_URL='https://192.168.21.53:5000/v3' export OS_USERNAME=admin export OS_PASSWORD='P@ssw0rd' export OS_PROJECT_NAME=admin export OS_USER_DOMAIN_NAME=Default export OS_PROJECT_DOMAIN_NAME=Default
glance image-list glance image-create --name plop --file plop.vmdk --disk-format vmdk --container-format bare --visibility private
Policy
Voir
OpenStack Glance: allow user to create public images
Notes OpenStack - Nova - console VNC NOVNC spice serial
/opt/stack/horizon/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_console.html /usr/share/qemu/keymaps/
/etc/nova/nova-cpu.conf
[vnc] # Keymap is depecated keymap = fr
/etc/libvirt/qemu/instance-00000023.xml
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='fr'> <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0' keymap='fr'> <graphics type='spice' autoport='yes' listen='0.0.0.0' keymap='fr'>
apt-get install spice-vdagent
/opt/stack/noVNC/vnc_auto.html
Slice à la place de VNC
Voir :
/etc/nova/nova-cpu.conf
[vnc] server_proxyclient_address = 0.0.0.0 server_listen = 0.0.0.0 xvpvncproxy_base_url = http://192.168.56.11:6081/console novncproxy_base_url = http://192.168.56.11:6080/vnc_auto.html vnc_enabled = False novnc_enabled = False [spice] html5proxy_base_url = http://192.168.56.11:6082/spice_auto.html agent_enabled = True enabled = True server_listen = 0.0.0.0 server_proxyclient_address = 192.168.56.11
PS : Two keymap-related configuration options have been deprecated:
- [vnc] keymap
- [spice] keymap
Voir https://docs.openstack.org/releasenotes/nova/rocky.html
systemctl restart devstack@n-*
Certaines modif ne s’appliqueront que sur les nouvelles VMs déployées. puisque c'est la conf /etc/libvirt/qemu/ qui est définie.
apt-get install nova-spiceproxy
WebSocket error: Can't connect to websocket on URL: ws://192.168.56.11:6082/websockify [object Event]
Log de la console KVM/Libvirt
/opt/stack/data/nova/instances/4aa28898-07ce-4f16-8666-4e33e32a7450/console.log
voir /etc/libvirt/qemu/instance-00000006.xml
A tester
aptitude install uwsgi-plugin-python
nova get-vnc-console INSTANCE_NAME VNC_TYPE
Notes OpenStack - Horizon Web UI
Changer le délai de déconnexion
Horizon session timeout
Fichier
- /etc/openstack-dashboard/local_settings.py
- /opt/stack/horizon/openstack_dashboard/local/local_settings.py
local_settings.py
# dashboard session timeout in seconds SESSION_TIMEOUT = 3600
systemctl restart httpd
Voir aussi
/etc/keystone/keystone.conf
[token] expiration = 36000
systemctl restart devstack@keystone.service
Ou encore sous K8S
kubectl -n openstack edit horizon
spec: conf: horizon: local_settings: config: horizon_session_timeout: 14400
Notes OpenStack - Cinder volumes
losetup -f --show /opt/stack/data/stack-volumes-*
Créer un volume puis effacer un volume pour tester.
openstack volume create --size 20 plop openstack volume delete plop
Pb
Pb1
stack@oslack1:~/devstack$ openstack volume service list +------------------+---------------------+------+---------+-------+----------------------------+ | Binary | Host | Zone | Status | State | Updated At | +------------------+---------------------+------+---------+-------+----------------------------+ | cinder-volume | oslack1@lvmdriver-1 | nova | enabled | down | 2019-04-05T15:22:35.771203 | | cinder-scheduler | oslack1 | nova | enabled | up | 2019-04-05T15:23:16.619859 | +------------------+---------------------+------+---------+-------+----------------------------+ stack@oslack1:~/devstack$ openstack volume service set --enable oslack1@lvmdriver-1 cinder-volume stack@oslack1:~/devstack$ openstack volume service list +------------------+---------------------+------+---------+-------+----------------------------+ | Binary | Host | Zone | Status | State | Updated At | +------------------+---------------------+------+---------+-------+----------------------------+ | cinder-volume | oslack1@lvmdriver-1 | nova | enabled | down | 2019-04-05T15:23:24.881781 | | cinder-scheduler | oslack1 | nova | enabled | up | 2019-04-05T15:23:26.621806 | +------------------+---------------------+------+---------+-------+----------------------------+
Solution
/etc/cinder/cinder.conf
[lvmdriver-1] #volume_group = stack-volumes-lvmdriver-1 volume_group = ubuntu-vg
systemctl restart 'devstack@c-*'
Pb2
Impossible d'effacer un volume Le pb venait que le volume était en état “reserved”
openstack volume set --state available 671c5fc7-00bd-4452-be82-645e10d59236 openstack volume delete 671c5fc7-00bd-4452-be82-645e10d59236
Bonnes pratiques Ansible
Voir :
Principes / Philosophie
Les 12 facteurs
Zen de Python
https://fr.wikipedia.org/wiki/Zen_de_Python
import this
Bonnes pratiques propres à Ansible I
Idempotents
- Privilégier les modules natifs
- Utiliser les handlers pour le redémarrage de services
- Utiliser
changed_whenA(creates) ou A(removes)
Codes de retour corrects \ Change_when \ Si Appel API → Changed (par défaut)
Exemple :
- name: call api register: plop uri: url: https://tower.acme.fr/api/v2/job_templates/93/launch/ method: POST force: true force_basic_auth: true user: username password: 'P@ssw0rd' validate_certs: false # body_format: form-urlencoded body_format: json headers: Content-Type: "application/json" body: | { "extra_vars": { "git_path": "/project/plop", "git_user": "gittoken" } } status_code: 201
Éviter autant que possible l'appel au M(shell) \ Éviter d'utiliser les M(script) et M(command) \ Privilégier M(command) à M(shell) \ Si variables Jinja en argument à M(shell) : utiliser quote pour échapper les caractères spéciaux. Pour M(command), M(shell), M(script), contrôler le code de retour avec
registerfailed_whenchanged_whenou bien : penser à utiliser A(creates) ou A(removes)
Exemple :
- name: Check if my_package is installed command: dpkg-query -W my_package register: my_package_check_deb failed_when: my_package_check_deb.rc > 1 changed_when: my_package_check_deb.rc == 1 check_mode: false - name: systemd-escape ansible.builtin.command: /usr/bin/timeout --kill-after=15 10 /usr/bin/systemd-escape -p --suffix=mount {{ CIFS_MOUNT_PATH | quote }} register: unit_systemd changed_when: false check_mode: false failed_when: - unit_systemd.rc != 0 # OK - unit_systemd.rc != 124 # Timeout. SIGTERM - unit_systemd.rc != 137 # Timeout. SIGKILL
Utiliser les handlers pour redémarrer les services Mais attention avec les modules (import*), les handlers ne sont pas déclenchés par défaut. Faire ansible.builtin.meta: flush_handlers
Ansible-lint
Ne pas utiliser de module obsolète “Deprecated” (RA_QUA_N2)
Corriger le code pour chaque avertissement.
Nommer chaque tâche
Les noms de tâche devraient être uniques (RA_QUA_N3)
Conformité ansible-lint
Conformité indentation yamllint
Préciser le owner/group/chmod pour M(copy), M(template)…
Encodage fichiers
Si beaucoup de données préférer les déplacer files/ plutôt que d'utiliser M(copy) A(content)
Deux types de fichiers :
- Fichier texte de tailles réduite
- Taille < 100K ou mime-encoding = us-ascii / utf-8
- Binary large object (BLOB)
- Taille > 100k ou mime-encoding = binary
BLOB - fichiers binaires et fichier textes volumineux
find . -type f -wholename "*/files/*" -size +100k find . -type f -wholename "*/files/*" -size -100k -exec file --mime-encoding {} + | awk -F: '/binary/ { print $1 }'
- Systématiquement vérifier le hash, par exemple en utilisant A(checksum) avec M(copy) et M(get_url)
- Devrait être dépôt dédié sépare de Git
- Exemple : Artifact / S3 (MinIO) / NAS (NFS) / HTTP
- Garder une arborescence similaire aux petits textes : le chemin doit contenir le nom de rôles ou du playbook
- Une référence unique. Un seul rôle (ou un seul playbook) fait appel directement à ce fichier.
- Si deux roles ou besoin de ce même fichier : créer un 3em rôle et faire un dépendance de rôle.
Bonnes pratiques propres à Ansible II
Si pas besoin des facts : mettre gather_facts à false (RA_PERF_N3)
Si besoin de facts récuper seulement les facts utiles (RA_PERF_N3)
- name: Get minimal facts ansible.builtin.setup: gather_subset: - '!all' - distribution
Playbook pouvant fonctionner un Dry-Run (--check) (RA_TEST_N2)
check_mode: falsequand nécessaire
Ne pas utilisez ignore_errors: true et encore moins pour un playbook entier. Préferez “failed_when:” (RA_QUA_N1)
Éviter d’utiliser delegate_to surtout, dans les rôles (RA_QUA_N1)
Pour les templates et les fichiers, systématiquement sauf si non applicable mettre en commentaire que ce fichier est géré par Ansible. (RA_QUA_N1)
Exemple : all.yml
ansible_managed: This file is managed by ansible. Manual changes are likely to be overwritten !
Pièges
Run_once
run_once will be executed at each serial execution in the play. That means, if you choose serial = 1, it will be asked to confirm as many times as the quantity of targets on the play.
Check Ansible docs: https://docs.ansible.com/ansible/latest/user_guide/playbooks_strategies.html#running-on-a-single-machine-with-run-once
When used together with serial, tasks marked as run_once will be run on one host in each serial batch. If the task must run only once regardless of serial mode, use when: inventory_hostname == ansible_play_hosts_all[0] construct.
Attention aux slicing !
Limiter l'usage des ressources
- name: Installation d'un logiciel sur plusieurs serveurs avec throttle ansible.builtin.apt: name: nginx state: present async: 600 # Exécution en mode asynchrone avec un délai maximum de 10 minutes poll: 5 # Vérification toutes les 5 secondes throttle: 3 # Limite à 3 installations simultanées when: inventory_hostname in groups['webservers']
Bonnes pratiques AWX
Voir :
Ne pas utiliser M(vars_prompt) (remplacé par les “Surveys” et extra-vars) (RA_QUA_N1)
Ne pas utiliser M(pause) sans timeout (RA_QUA_N1)
Utiliser des inventaires dynamiques (If you have an external source of truth) (RA_QUA_N3)
- single source of truth (SSOT) architecture, or single point of truth (SPOT)
Variable Management for Inventory - Keeping variable data along with the hosts and groups definitions (see the inventory editor) is encouraged, rather than using group_vars/ and host_vars/
Autoscaling - Using the “callback” feature to allow newly booting instances to request configuration is very useful for auto-scaling scenarios or provisioning integration.$
Larger Host Counts - Consider setting “forks” on a job template to larger values to increase parallelism of execution runs. Voir : Strategy, Mitogen, Slicing, Async (Asynchronous) (RA_PERF_N3)
Ne pas utiliser Verbosity à 4 ou 5. Eviter d'augmenter la verbosité si l'inventaire est conséquent
Ne pas mettre les facts des nœuds dans la base de données - Ne pas activer “Enable Fact Storage” Le cache des facts doit être sur les managed_hosts et non coté serveur (RA_GEN_N1)
Ne pas faire de command: ansible-galaxy ni de shell: ansible-galaxy, mais utiliser la manière native de AAP / AWX (RA_QUA_N1)
Bonnes pratiques IT
Logger (via AWX, ou via un callback plugin, ARA Records Ansible…). Et utiliser la directive no_log: pour les secrets. Voir aussi : https://docs.ansible.com/ansible/latest/reference_appendices/config.html
Tester les playbooks sur un environnement hors prod.
Mettre en place des tests unitaires :
- Molecule
Utiliser le cache que cela est possible :
- Pour les facts (facts caching) (RA_PERF_N3)
- Mais éviter “Enable Fact Storage” qui met les fact dans la base de données
- Pour les inventaires (cache_plugin, Fact Cache)
[inventory] cache = True cache_plugin = memory cache_timeout = 1800
Bonnes pratiques code
Éviter le code spaghetti
Assert extra_var, controler les inputs des utilisateurs (RA_SEC_N1)
Assert sur les cibles (RA_SEC_N2)
Faire les contrôle de plus tôt possible.
Exemple : Contrôle avant d'effectuer la connexion : playbook localhost avec gather_facts=false Playbook dédié : ansible.builtin.import_playbook: _assert_extra_vars.yml
Utiliser un logiciel de gestion de versions tel que Git (RA_GEN_N1) Use Source Control https://ansible.readthedocs.io/projects/awx/en/24.6.1/userguide/best_practices.html
Utiliser l'encodage UTF8 (RA_GEN_N1)
Remplacer les tabulations par 2 espaces (A config si ce n'est pas le cas dans l'IDE) (RA_GEN_N1)
Factoriser - Éviter de dupliquer du code - Don't Repeat Yourself (DRY) (RA_GEN_N3) Dans la mesure du possible, seulement se répéter est mieux que d'écrire un code difficilement lisible. Car “à la pureté, privilégie l'aspect pratique.”
- En créant des rôles en les appelant avec des arguments / variables
module_defaults(If you frequently call the same module with the same arguments)- En utilisant import* et include* (attention aux notify avec include)
- En utilsant
block
Utiliser SonarQube ou équivalent (RA_GEN_N4)
Petits textes
- Utiliser le charset
utf-8(ouus-asciisi aucun caractère unicode) - Convertir le charset
iso-8859-1et autres enutf-8 - Devrait être dans
<role_name>/files/(ou dansfiles/si appelé directement depuis un playbook)
Encodage fichier
- UTF-8
- Pas de tabulation (Utiliser un IDE avec greffon pour Ansible ou configurer son IDE pour remplacer les tabulations par deux espaces)
Utiliser les modules déjà existant / ne pas réinventer la roue (RA_GEN_N1)
ansible-doc -l |grep reboot ansible-doc ansible.builtin.reboot
Si pas présent, chercher si une collection / un rôle n'existe pas déjà
ansible-galaxy search reboot
Timeout après 5s (async)
--- - name: Test hosts: localhost tasks: - name: Sleep ansible.builtin.command: /bin/sleep 60 async: 10 # poll: 5
Voir : https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_checkmode.html#check-mode-dry
Éviter command: cat. Préférez :
- name: get actual effective params slurp: src: /proc/cmdline become: true register: all_current_activ_params - name: show effective params debug: msg: "{{ all_current_activ_params.content | b64decode }}"
run_once
https://github.com/ansible/ansible-lint/issues/1026#issuecomment-685849603
Ansible ignores run_once with the free strategy which means your tasks are run many times, once for each valid inventory host
Si run_once, toujours préciser le delegate_to ou when: inventory_hostname ==
Il est aussi possible de faire quelque chose comme :
- command: /opt/application/upgrade_db.py when: inventory_hostname == webservers[0]
Les tâches marquées comme run_once seront exécutées sur un hôte dans chaque série de lot. Si la tâche ne doit s'exécuter qu'une seule fois quel que soit le “serial” mode , utilisez
when: inventory_hostname == ansible_play_hosts_all[0]
Convention dev
Commencer chaque playbook par contrôler les entrées de l'utilisateur. \
- Grâce au M(assert) et M(fail)
- Grâce à
argument_specs.yml
Contrôler que la cible correspond bien \ Exemple :
- Bonne version OS
- Agent pas déjà installé via autre autre procédure…
- Espace disque et autres ressources disponibles sur la cible
Portée des variables
DEFAULT_PRIVATE_ROLE_VARS
M(ansible.builtin.include_roles) and M(ansible.builtin.import_roles) C(public)
Import vs include
Modules :
- ansible.builtin.import_playbook
- ansible.builtin.import_role
- ansible.builtin.import_tasks
- ansible.builtin.include_role
- ansible.builtin.include_tasks
- ansible.builtin.include_vars
You cannot use loops on 'import_tasks' statements. You should use 'include_tasks' instead.
Sécurité
Mettre les become que sur les tâches nécessitant les privilèges, et non sur tous le playbook (RA_SEC_N1)
- RBAC CRUD
- Logs
- AWX
- Callback
- community.general.syslog_json
Utiliser no_log: true pour les taches utilisant des secrets (RA_SEC_N1)
Pour les données sensibles utiliser ansible-vault ou les Crendential AWX (RA_SEC_N1)
Troubleshooting untrusted templates
https://docs.ansible.com/ansible/devel/porting_guides/porting_guide_12.html
export _ANSIBLE_TEMPLAR_UNTRUSTED_TEMPLATE_BEHAVIOR=fail
https://docs.ansible.com/ansible/devel/porting_guides/porting_guide_core_2.19.html#untrusted-templates export ANSIBLE_DISPLAY_TRACEBACK=always
Performance
Voir :
- Mettre en cache les facts (fact_caching) (mais sur les noeuds, pas en DB) (RA_PERF_N3)
- Analyser les temps d’exécution anormalement long
callback_whitelist = timer, profile_tasks - Utiliser Mitogen
- Garder les tunnels SSH ouverts
Eviter de boucler innutilement - vérifier si le module prends des listes (RA_PERF_N2)
- name: Install packages ansible.builtin.package: name: "{{ item }}" state: present loop: - curl - wget
- name: Install packages ansible.builtin.package: name: - curl - wget
Tests
- tests manuels
- tests unitaire
- tests fonctionnels
Autres
Ping
Voir Ansible Ping ICMP
Convention de nommage
Naming things
- Use valid Python identifiers following standard naming conventions of being in snake_case_naming_schemes for all YAML or Python files, variables, arguments, repositories, and other such names (like dictionary keys).
- Do not use special characters other than underscore in variable names, even if YAML/JSON allow them.
Source : https://redhat-cop.github.io/automation-good-practices/#_naming_things
name
For example, if you have a task named Restart server inside a file named tasks/deploy.yml, this rule suggests renaming it to deploy | Restart server Source : https://ansible.readthedocs.io/projects/lint/rules/name/#nameprefix
role-name
(snake case) Role names must contain only lowercase alphanumeric characters and the underscore _ character. Role names must also start with an alphabetic character. Source : https://ansible.readthedocs.io/projects/lint/rules/role-name/
var-naming
… Variable names must contain only lowercase alphanumeric characters and the underscore _ character. Variable names must also start with either an alphabetic or underscore _ character. … role_name_ as a prefix … Source : https://ansible.readthedocs.io/projects/lint/rules/var-naming/
Extra_vars
Voir : https://github.com/openshift/openshift-ansible/blob/master/docs/style_guide.adoc
Exemple : cli_plop
Register
Convention pour les register. Exemple r_foo
Autres
Les listes seront nommées avec un s finals. L'emploi du pluriel indique plusieurs éléments possibles
Définir et respecter une convention de nommage
Convention pour les variables, il doit être possible de distinguer deux types (fonctionnel) de variables :
- Entrées utilisateurs
- Variables internes
Nommer les templates Jinja avec l’extension j2 (RA_CONV_REQ)
Préférer les variables a plat plutôt que les variables dictionnaires (RA_CONV_OPT)
endpoint_url: endpoint_port:
plutôt que
endpoint: url: port:
Boucles
De préférence nommer la variable de boucle (loop_var) à la place d'utiliser le nom par défaut item (RA_CONV_OPT)
C'est plus lisible, et cela permet un fonctionnement non équivoque en cas de boucles imbriqués.
Il est recommandé de définir une convention de nommage pour la variable de boucle. Par exemple d'avoir toujours un suffixe _item
Exemple :
- include_tasks: inner.yml loop: - 1 - 2 - 3 loop_control: loop_var: outer_item
Utiliser label dans loop_control pour rendre l'affichage plus lisible
Fichiers / templates
Pour les roles contenants beaucoup de fichiers dans “files/” privilégier une arborescence comme suit (RA_CONV_OPT)
- files/etc/nginx/sites-available/plop
- files/etc/systemd/system/plop.service
- templates/etc/nginx/site-aviable/plop.j2
Annexes
Outils
- Formation
- Ansible-lint
- yamllint
- Sonarqube
- CI/CD Gitlab-CI
