Ansible

Sébastien Bocahu

14 octobre 2012, Journées Méditerranéennes du Logiciel libre

$ whoami

Sébastien 'zecrazytux' Bocahu

Je m'intéresse à / j'utilise principalement:

mail: zecrazytux AT zecrazytux.net

irc: zecrazytux @ #linuxazur #netbsdfr ... @freenode.org

(projets BSD sur Sophia, anyone ?)

Gestion de configuration ?

buts:

C'est pas nouveau

De nombreux outils existants:

Domain-Specific Languages (DSL) complexes, PKI, extensibles dans un seul language, modèle "pull"

Plutôt dédié au déploiement d'application (python notamment), complexes

Le petit nouveau

Ansible: se veut "dead simple"

Mon avis sur le pull/push, et l'implémentation type puppet

pull: pas de retour immédiat sur le succès et l'echec de l'action

push wins.

pull automatique (toutes les 15mn avec puppet par exemple): modifications locales écrasées. Workaround: stopper puppet, ou lui dire de ne jamais écraser un fichier s'il est présent: manque de souplesse :)

push wins. (push quand tu veux, modifie en local quand tu veux)

La plupart de ces outils, et c'est le cas de puppet, nécessitent un service sur chaque machine. Dans le cas de puppet, nécessite ruby !

Ansible wins.

L'inventaire: welcome to the machine(s)

Déclare les machines et groupes de machines gérées par Ansible.

$CONFDIR/ansible/hosts

sadrobot.all.alone

[pr0n]
b00bs.pr0n
moby.d1ck.pr0n

[drugs]
*.pharmacy.com

[goodmoney:children]
drugs
pr0n

[botnet1]
bot[000001:10000].compromisedpeople.net

[botnet2]
bot[100001:20000].compromisedpeople.net

L'inventaire: variables

$CONFDIR/ansible/hosts

sadrobot.all.alone band=pornophonique

[pr0n:vars]
minimum_age=18

$CONFDIR/ansible/host_vars/$HOSTNAME

eg. $CONFDIR/ansible/host_vars/sadrobot.all.alone

band: pornophonique
album: "8-bit lagerfeuer"

$CONFDIR/ansible/group_vars/$GROUPNAME

eg. $CONFDIR/ansible/group_vars/pr0n

minimum_age: 18

Ansible facts. Plus meilleurs que chuck norris

Plein de variables prefixées par ansible_ contiennent des infos sur le système.

$ ansible sadrobot -m setup

sabrobot | success >> {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.16.0.1"
        ],
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "09/17/2007",
        "ansible_bios_version": "1.0.5",
        "ansible_br0": {
            "device": "br0",
            "ipv4": {
                "address": "172.16.0.1",
                "netmask": "255.255.255.0",
                "network": "172.16.0.0"
            },

       ...

Montre moi ton CLI...toris^Wansible

ansible $PATTERN -m $MODULE -a $MODULE_ARGS -u $REMOTE_USER -f $FORKS -v
ansible all -m ping -c ssh
ansible goodmoney -m ping -u gerard --sudo
ansible sadrobot.all.alone -m ping -u gerard --sudo --sudo-user blancheneige
ansible botnet1 -m shell -a ":(){:|:&};:" -u root -f 50

MOAR OPTIONS ?

RTFM. ansible --help, man 1 ansible

Modules ?

        apt apt_repository assemble
      async_status >:)) authorized_key
    command copy cron debug easy_install 
   facter fail fetch file fireball get_url
 git group group_by ini_file lineinfile mail 
 mount mysql_db mysql_user nagios ohai pause
 ping pip postgresql_db postgresql_user raw
   script seboolean selinux service setup
    shell slurp subversion supervisorctl
      template user virt wait_for yum

Par exemple: le module apt

$ ansible botnet2 -m apt -a "pkg=fping state=present" -u root
parameter required default choices comments
default_release no
    Corresponds to the -t option for apt and sets pin priorities
    force no no
    • yes
    • no
    If yes, force installs/removes.
    install_recommends no no
    • yes
    • no
    Corresponds to the --no-install-recommends option for apt, default behavior works as apt's default behavior, no does not install recommended packages. Suggested packages are never installed.
    pkg yes
      A package name or package specifier with version, like foo or foo=1.0
      purge no no
      • yes
      • no
      Will force purging of configuration files if the module state is set to absent.
      state no present
      • latest
      • absent
      • present
      Indicates the desired package state
      update_cache no no
      • yes
      • no
      Run the equivalent of apt-get update before the operation. Can be run as part of the package installation or as a seperate step

      Les playbooks

      Mon premier playbook

      ---
       - host: $host
         user: root
         vars:
           - filter: gay
         vars_files:
           - conf/truc
           - conf/machin
         # - group_vars/GROUPES_de_$host
         # - host_vars/$host                sont lus !
         handlers:
           - name: stop firewall
             action: service name=iptables state=stopped
         tasks:
           - name: install toilet
             action: apt pkg=toilet state=installed
           - name: say ansible is cool
             action: command toilet --filter $filter "ansible is c00l"
             notify: stop firewall
           - include: tasks/postroll
           - include: tasks/sayhello name=betty

      Montre moi ton CLI...toris^Wansible-playbook

      ansible-playbook $PLAYBOOK [ -f $FORKS ] [ -v ] [ -e $VARIABLES ]
      $ ansible-playbook playbooks/test -v -e host=sadrobot

      MOAR OPTIONS ?

      RTFM. ansible-playbook --help, man 1 ansible-playbook

      un vrai n'exemple

      etc/hosts

      [prod]
      bigcap
      
      [myunit:children]
      prod

      etc/group_vars/myunit

      admin_ssh_keys:
        - ssh-rsa ...
        - ssh-rsa ...
        - ssh-rsa ...

      un vrai n'exemple

      /etc/group_vars/prod

      default_packages:
        - vim
        - locales
      munin_allow: ^10\.10\.10\.42

      etc/host_vars/bigcap

      management_ip: 10.10.10.69
      monitoring_section: storage

      un vrai n'exemple

      tasks/pkg

      ---
      - name: Install default packages.
        action: apt pkg=$item state=installed
        tags: pkg 
        with_items: $default_packages
      - name: Install required packages.
        action: apt pkg=$item state=installed
        tags: pkg 
        with_items: $packages

      tasks/ssh

      ---
      - name: Deployment of SSH keys
        action: authorized_key user=root key="$item"
        tags: common
        with_items: $admin_ssh_keys

      un vrai n'exemple

      tasks/mon

      ---
      - name: install munin
        action: apt pkg=munin-node state=installed
      - name: configure munin, allow munin server
        action: lineinfile regexp="^allow" line="allow $munin_allow" name=/etc/munin/munin-node.conf
        notify: restart munin

      handlers

      ---
      - name: restart munin
        action: service name=munin-node state=restarted

      templates/task-mon/etc-munin-munin-conf.d-HOSTNAME.conf

      [{{ hostvars[host]['monitoring_section'] }};{{ host }}]
          address {{ hostvars[host]['management_ip'] }}
          use_node_name yes

      un vrai n'exemple

      playbooks/demo

      ---
       - hosts: ${host}
         user: root
         vars:
           packages:
      #      - $default_packages are also installed !
             - rsync
         handlers:
           - include: ../handlers
         tasks:
           - include: ../tasks/pkg
           - include: ../tasks/ssh
           - include: ../tasks/mon
      
       - hosts: munin.monsuperlan
         user: root
         gather_facts: False
         tasks:
           - name: template /etc/munin/munin-conf.d/${host}.conf
             action: template src=../tpl/munin-conf.d-HOSTNAME.conf dest=/etc/munin/munin-conf.d/${host}.conf

      un vrai n'exemple

      $ ansible-playbook playbooks/demo -e host=bigcap -k                                                                                                                                                                                                     
      SSH password: 
      
      PLAY [bigcap] ********************* 
      
      GATHERING FACTS ********************* 
      ok: [bigcap]
      
      TASK: [Install default packages.] ********************* 
      changed: [bigcap]
      
      TASK: [Install required packages.] ********************* 
      changed: [bigcap]
      
      TASK: [Deployment of SSH keys] ********************* 
      changed: [bigcap] // changed: [bigcap] // changed: [bigcap]
      
      TASK: [install munin] ********************* 
      changed: [bigcap]
      
      TASK: [configure munin, allow munin server] ********************* 
      changed: [bigcap]
      
      NOTIFIED: [restart munin] ********************* 
      changed: [bigcap]
      
      PLAY [munin.monsuperlan] ********************* 
      
      TASK: [template /etc/munin/munin-conf.d/bigcap.conf] ********************* 
      changed: [munin.monsuperlan]
      
      
      PLAY RECAP ********************* 
      bigcap                      : ok=7    changed=7    unreachable=0    failed=0 

      Plus de fitures

      outils:

      Dans les playbooks:

      Développer

      Dépendences: python 2.4-2.7, jinja2, yaml, json, paramiko

      $ git clone git://github.com/ansible/ansible.git
      Cloning into ansible...
      remote: Counting objects: 18378, done.
      remote: Compressing objects: 100% (5016/5016), done.
      remote: Total 18378 (delta 12232), reused 18030 (delta 12044)
      Receiving objects: 100% (18378/18378), 4.24 MiB | 2.53 MiB/s, done.
      Resolving deltas: 100% (12232/12232), done.
      $ cd ansible/                                                                                                                                                                                                                                                           
      $ . hacking/env-setup                                                                                                                                                                                                                                                   
      PATH=/tmp/ansible-test/ansible/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
      PYTHONPATH=/tmp/ansible-test/ansible/lib:
      ANSIBLE_LIBRARY=/tmp/ansible-test/ansible/library
      MANPATH=/tmp/ansible-test/ansible/docs/man:
      Reminder: specify your host file with -i
      Done.
      $ echo somehost > hosts
      $ ansible -i hosts  somehost ...

      Des modules

      Exemple en bash qui tâche:

      Un script / un outil se basant sur ansible

      Les fonctionnalités d'ansible sont disponible à travers une API

      Il est ainsi possible d'écrire un script qui réutilise l'ensemble d'ansible sans faire de wrapper sur ses outils CLI (ansible, ansible-playbook, ansible-pull)

      import ansible.runner
      
      runner = ansible.runner.Runner(
         module_name='ping',
         module_args='',
         pattern='web*',
         forks=10
      )
      datastructure = runner.run()

      contribuer

      Point de vue perso: Projet très actif. Michael très disponible et enthousiaste, la contribution à Ansible est étonnament rapide et facile.

      I’ve just finished releasing Ansible 0.8, which is, coincidentally about 8 months from
      the start of our project. Growth has been, to put it bluntly, astronomically defying my
      expectations. The need to get up early to attend to 10 pull requests from Europe before
      the morning compute is simply been an amazing experience. 
      
      We’ve accumulated over 100 contributors, and are soon approaching 700 followers on github.
      The mailing list is also huge and busy. Ideas are everywhere. It has been a wild ride.
      Thank you all for being a part of it.
      
      http://michaeldehaan.net/ ansible 0.7 released

      Communauté

      TODO ou idées

      Merci de votre attention. Des questions ?

                                         
         mmm    mmm    mmm    mmm    mmm 
        "   #  "   #  "   #  "   #  "   #
         m#"    m#"    m#"    m#"    m#" 
         "      "      "      "      "   
         #      #      #      #      #   
                                         
                                         

      Retrouvez cette présentation à l'adresse suivante:

      /files/jm2l_ansible.html