Avr 13 2021
Rendez Ansible 6X Plus Rapide avec ces 3 Astuces
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
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.