Download PDF

La description de ce résultat n'est pas accessible à cause du fichier robots.txt de ce site.

8MB taille 28 téléchargements 636 vues
Ansible hors des sentiers battus Aurélien Maury

#DevoxxFR #ansibleRocks

1

whoami

#DevoxxFR #ansibleRocks

2

whoami

#DevoxxFR #ansibleRocks

2

uname

@YesWeScale

#DevoxxFR #ansibleRocks

3

Agenda

#DevoxxFR #ansibleRocks

4

Elevator pitch

#DevoxxFR #ansibleRocks

5

Python

#DevoxxFR #ansibleRocks

6

Orchestration

#DevoxxFR #ansibleRocks

7

Configuration

#DevoxxFR #ansibleRocks

8

Idempotence

#DevoxxFR #ansibleRocks

9

Sans agent

#DevoxxFR #ansibleRocks

10

SSH

#DevoxxFR #ansibleRocks

11

« Getting started »

#DevoxxFR #ansibleRocks

12

« Getting started »

ansible-playbook

#DevoxxFR #ansibleRocks

12

OK !

#DevoxxFR #ansibleRocks

13

OK !

#DevoxxFR #ansibleRocks

13

SSH-fu

#DevoxxFR #ansibleRocks

14

SSH-fu # $HOME/.ssh/config Host bastion Hostname User IdentityFile

84.39.41.33 admin ~/.ssh/bastion_key

Host 192.168.47.* ProxyCommand ssh -W %h:%p bastion User admin IdentityFile ~/.ssh/zone_key Host * ControlMaster ControlPath ControlPersist

#DevoxxFR #ansibleRocks

auto ~/.ssh/mux-%r@%h:%p 15m

15

SSH-fu # $HOME/.ssh/config Host bastion Hostname User IdentityFile

84.39.41.33 admin ~/.ssh/bastion_key

Host 192.168.47.* ProxyCommand ssh -W %h:%p bastion User admin IdentityFile ~/.ssh/zone_key Host * ControlMaster ControlPath ControlPersist

#DevoxxFR #ansibleRocks

auto ~/.ssh/mux-%r@%h:%p 15m

16

SSH-fu # $HOME/.ssh/config Host bastion Hostname User IdentityFile

84.39.41.33 admin ~/.ssh/bastion_key

Host 192.168.47.* ProxyCommand ssh -W %h:%p bastion User admin IdentityFile ~/.ssh/zone_key Host * ControlMaster ControlPath ControlPersist

#DevoxxFR #ansibleRocks

auto ~/.ssh/mux-%r@%h:%p 15m

17

SSH-fu # $WORKSPACE/ssh.cfg Host bastion Hostname User IdentityFile

84.39.41.33 admin ~/.ssh/bastion_key

Host 192.168.47.* ProxyCommand ssh -W %h:%p -F ssh.cfg bastion User admin IdentityFile ~/.ssh/zone_key Host * ControlMaster ControlPath ControlPersist

#DevoxxFR #ansibleRocks

auto ~/.ssh/mux-%r@%h:%p 15m

18

Hosts

#DevoxxFR #ansibleRocks

19

Host Inventory [web_servers] 192.168.47.11 192.168.47.12 192.168.47.13 [db_servers] 192.168.47.10 [production:children] web_servers db_servers [production:vars] ansible_ssh_user=admin ansible_ssh_private_key_file=/home/ops/.ssh/id_rsa.prod

#DevoxxFR #ansibleRocks

20

Dynamic Inventory

#DevoxxFR #ansibleRocks

21

Dynamic Inventory

ansible --inventory-file=./static_inventory

#DevoxxFR #ansibleRocks

21

Dynamic Inventory

ansible --inventory-file=./static_inventory

ansible --inventory-file=./executable_returning_json

#DevoxxFR #ansibleRocks

21

Dynamic Inventory --list { "databases" : { "hosts" : [ "host1.example.com", "host2.example.com" ], "vars" : { "a" : true } }, "webservers" : [ "host2.example.com", "host3.example.com" ], "atlanta" : { "hosts" : [ "host1.example.com", "host4.example.com"], "vars" : { "b" : false }, "children": [ "marietta", "5points" ] }, "marietta" : [ "host6.example.com" ] }

#DevoxxFR #ansibleRocks

22

Dynamic Inventory --host $HOST { "favcolor" : "red", "ntpserver" : "wolf.example.com", "monitoring" : "pack.example.com" }

#DevoxxFR #ansibleRocks

23

Dynamic Inventory

#DevoxxFR #ansibleRocks

24

One more thing

La confiance n’exclut pas le contrôle.

#DevoxxFR #ansibleRocks

25

Modules

#DevoxxFR #ansibleRocks

26

Il y a sûrement un module pour ça

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive Messaging - rabbitmq_[binding, exchange, queue, ...]

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive Messaging - rabbitmq_[binding, exchange, queue, ...] Monitoring - zabbix, nagios, sensu, monit, datadog

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive Messaging - rabbitmq_[binding, exchange, queue, ...] Monitoring - zabbix, nagios, sensu, monit, datadog Network - A10, F5, Openswitch, cumulus, get_url

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive Messaging - rabbitmq_[binding, exchange, queue, ...] Monitoring - zabbix, nagios, sensu, monit, datadog Network - A10, F5, Openswitch, cumulus, get_url Notification - jabber, slack, mail, irc, hipchat

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive Messaging - rabbitmq_[binding, exchange, queue, ...] Monitoring - zabbix, nagios, sensu, monit, datadog Network - A10, F5, Openswitch, cumulus, get_url Notification - jabber, slack, mail, irc, hipchat Packaging - apt, yum, pip, bower, npm, homebrew

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive Messaging - rabbitmq_[binding, exchange, queue, ...] Monitoring - zabbix, nagios, sensu, monit, datadog Network - A10, F5, Openswitch, cumulus, get_url Notification - jabber, slack, mail, irc, hipchat Packaging - apt, yum, pip, bower, npm, homebrew Source control - git, gitlab, hg, subversion

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive Messaging - rabbitmq_[binding, exchange, queue, ...] Monitoring - zabbix, nagios, sensu, monit, datadog Network - A10, F5, Openswitch, cumulus, get_url Notification - jabber, slack, mail, irc, hipchat Packaging - apt, yum, pip, bower, npm, homebrew Source control - git, gitlab, hg, subversion System - known_host, authorized_key, user, group

#DevoxxFR #ansibleRocks

27

Il y a sûrement un module pour ça Cloud - Amazon, Cloudstack, Openstack, VMWare, DO Clustering - consul, zookeeper Commands - shell, script, expect Database - mysql, postgresql, redis, riak Files - copy, fetch, lineinfile, template, unarchive Messaging - rabbitmq_[binding, exchange, queue, ...] Monitoring - zabbix, nagios, sensu, monit, datadog Network - A10, F5, Openswitch, cumulus, get_url Notification - jabber, slack, mail, irc, hipchat Packaging - apt, yum, pip, bower, npm, homebrew Source control - git, gitlab, hg, subversion System - known_host, authorized_key, user, group Windows - trucs windows inconnus de moi

#DevoxxFR #ansibleRocks

27

Appel à un module - name: un joli titre c’est mieux apt: pkg="tmux" state=present update_cache=yes - name: un joli titre c’est mieux apt: pkg="screen" state=present

#DevoxxFR #ansibleRocks

28

with_items - name: un joli titre c’est mieux apt: pkg="{{ item }}" state=present update_cache=yes with_items: - tmux - screen

#DevoxxFR #ansibleRocks

29

with_items - name: add several users user: name={{ item.name }} state=present groups={{ item.groups }} with_items: - { name: 'testuser1', groups: 'wheel' } - { name: 'testuser2', groups: 'root' }

#DevoxxFR #ansibleRocks

30

with_* with_file: - file_1 - file_2 with_fileglob: - files/*.yml with_together: - ['a','b'] - [1,2] with_subelements, with_sequence, with_random_choice, with_indexed_items, with_dict

#DevoxxFR #ansibleRocks

31

Donnez vie à vos snippets

#DevoxxFR #ansibleRocks

32

Donnez vie à vos snippets Faire un module Ansible ?

#DevoxxFR #ansibleRocks

32

Donnez vie à vos snippets Faire un module Ansible ? 15 lignes de Python

#DevoxxFR #ansibleRocks

32

Donnez vie à vos snippets Faire un module Ansible ? 15 lignes de Python Installer un module Ansible ?

#DevoxxFR #ansibleRocks

32

Donnez vie à vos snippets Faire un module Ansible ? 15 lignes de Python Installer un module Ansible ? posez le dans ./library

#DevoxxFR #ansibleRocks

32

Roles

#DevoxxFR #ansibleRocks

33

Structure . ├── ├── │   ├── ├── │   ├── │   ├── │   ├── ├── │   │   └──

README.md defaults └── main.yml files handlers └── main.yml meta └── main.yml tasks └── main.yml templates tests ├── inventory └── test.yml vars └── main.yml

#DevoxxFR #ansibleRocks

--> variables par défaut --> fichiers statiques --> handlers --> fiche d'info et dépendances --> tâches (appels de modules) --> templates Jinja2

--> variables fortes

34

Structure . ├── ├── │   ├── ├── │   ├── │   ├── │   ├── ├── │   │   └──

README.md defaults └── main.yml files handlers └── main.yml meta └── main.yml tasks └── main.yml templates tests ├── inventory └── test.yml vars └── main.yml

--> variables par défaut --> fichiers statiques --> handlers --> fiche d'info et dépendances --> tâches (appels de modules) --> templates Jinja2

--> variables fortes

ansible-galaxy init mon_role_amoi #DevoxxFR #ansibleRocks

34

ansible-galaxy

#DevoxxFR #ansibleRocks

35

ansible-galaxy

https://galaxy.ansible.com

#DevoxxFR #ansibleRocks

35

ansible-galaxy

https://galaxy.ansible.com

ansible-galaxy install yatesr.timezone

#DevoxxFR #ansibleRocks

35

ansible-galaxy # requirements.yml - src: yatesr.timezone - src: https://github.com/bennojoy/nginx - src: https://github.com/bennojoy/nginx version: master name: nginx_role - src: https://some.webserver.example.com/files/master.tar.gz name: http-role

#DevoxxFR #ansibleRocks

36

ansible-galaxy # requirements.yml - src: yatesr.timezone - src: https://github.com/bennojoy/nginx - src: https://github.com/bennojoy/nginx version: master name: nginx_role - src: https://some.webserver.example.com/files/master.tar.gz name: http-role

ansible-galaxy install -r requirements.yml

#DevoxxFR #ansibleRocks

36

Variables

#DevoxxFR #ansibleRocks

37

YAML —-simplest_num: 42 simplest_str: "Terry Pratchett" # Qui lit les commentaires de toutes façons ? some_list: - "DON'T THINK OF IT AS DYING" - "JUST THINK OF IT AS" - "LEAVING EARLY TO AVOID THE RUSH" some_dict: key: "value" other_key: 10 list_of_dict: - { indentation: "is", the_key: "si si" }

#DevoxxFR #ansibleRocks

38

YAML —-simplest_num: 42 simplest_str: "Terry Pratchett" # Qui lit les commentaires de toutes façons ? some_list: - "DON'T THINK OF IT AS DYING" - "JUST THINK OF IT AS" - "LEAVING EARLY TO AVOID THE RUSH" some_dict: key: "value" other_key: 10 list_of_dict: - { indentation: "is", the_key: "si si" }

#DevoxxFR #ansibleRocks

39

YAML —-simplest_num: 42 simplest_str: "Terry Pratchett" # Qui lit les commentaires de toutes façons ? some_list: - "DON'T THINK OF IT AS DYING" - "JUST THINK OF IT AS" - "LEAVING EARLY TO AVOID THE RUSH" some_dict: key: "value" other_key: 10 list_of_dict: - indentation: "is" the_key: "si si" #DevoxxFR #ansibleRocks

40

YAML

{{ playbook_dir }} {{ inventory_dir }}

#DevoxxFR #ansibleRocks

41

Facts ansible -m setup localhost localhost | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "192.168.42.2", "192.168.99.1" ], "ansible_all_ipv6_addresses": [ "fe80::4e8d:79ff:fee8:54fe%en1", "fe80::f0ad:11ff:fee9:fcc8%awdl0" ], "ansible_architecture": "x86_64", "ansible_awdl0": { "device": "awdl0", "flags": [ "UP", "BROADCAST", "RUNNING", "PROMISC", "SIMPLEX", "MULTICAST" #DevoxxFR #ansibleRocks

42

Facts ansible_distribution ansible_distribution_major_version ansible_default_ipv4.address ansible_eth0.ipv4.address ansible_processor_cores ansible_hostname ansible_mounts ansible_interfaces [...]

#DevoxxFR #ansibleRocks

43

Fact caching # ansible.cfg [defaults] gathering = smart fact_caching = redis fact_caching_timeout = 7200

#DevoxxFR #ansibleRocks

44

Fact caching # ansible.cfg [defaults] gathering = smart fact_caching = jsonfile fact_caching_connection = /tmp/facts_cache fact_caching_timeout = 7200

#DevoxxFR #ansibleRocks

45

Set_fact

—-- hosts: target_group become: yes pre_tasks: - shell: > {{ playbook_dir }}/scripts/xml2yaml.py xml/* register: yaml_out

#DevoxxFR #ansibleRocks

46

Set_fact "--styles: - grindcore - disco - punk"

—-- hosts: target_group become: yes pre_tasks: - shell: > {{ playbook_dir }}/scripts/xml2yaml.py xml/* register: yaml_out

#DevoxxFR #ansibleRocks

46

Set_fact "--styles: - grindcore - disco - punk"

—-- hosts: target_group become: yes pre_tasks: - shell: > {{ playbook_dir }}/scripts/xml2yaml.py xml/* register: yaml_out

- set_fact: table_oauth: "{{ yaml_out.stdout | from_yaml }}"

#DevoxxFR #ansibleRocks

46

Set_fact

—-- hosts: target_group become: yes pre_tasks: - include: custom_facts.yml

#DevoxxFR #ansibleRocks

47

Précédence role defaults inventory vars inventory group_vars inventory host_vars playbook group_vars playbook host_vars host facts registered vars set_facts play vars play vars_prompt play vars_files role and include vars block vars (seulement pour les tâches du bloc) task vars (seulement pour la tâche) extra vars (ultime)

#DevoxxFR #ansibleRocks

48

Précédence role defaults inventory vars inventory group_vars inventory host_vars playbook group_vars playbook host_vars host facts registered vars set_facts play vars play vars_prompt play vars_files role and include vars block vars (seulement pour les tâches du bloc) task vars (seulement pour la tâche) extra vars (ultime)

#DevoxxFR #ansibleRocks

49

Rebonjour M. Anderson

#DevoxxFR #ansibleRocks

50

Agent-like

#DevoxxFR #ansibleRocks

51

Agent-like

ansible-playbook

#DevoxxFR #ansibleRocks

51

Agent-like

#DevoxxFR #ansibleRocks

52

Agent-like

git push

#DevoxxFR #ansibleRocks

52

Agent-like

#DevoxxFR #ansibleRocks

53

Agent-like

cron + ansible-pull

#DevoxxFR #ansibleRocks

53

Vagrant

#DevoxxFR #ansibleRocks

54

Vagrant provisioner remote config.vm.provision "ansible" do |ansible| ansible.groups = { "web_servers" => ["vm_one", "vm_two"], "db_servers" => ["vm_three"], "production:children" => [ "web_servers", "db_servers" ], "all_groups:children" => ["production"] } ansible.playbook = "upgrade_stack.yml" end

#DevoxxFR #ansibleRocks

55

Vagrant provisioner remote config.vm.provision "ansible" do |ansible| ansible.groups = { "web_servers" => ["vm_one", "vm_two"], "db_servers" => ["vm_three"], "production:children" => [ "web_servers", "db_servers" ], "all_groups:children" => ["production"] } ansible.playbook = "upgrade_stack.yml" end

#DevoxxFR #ansibleRocks

56

Vagrant provisioner remote config.vm.provision "ansible" do |ansible| ansible.groups = { "web_servers" => ["vm_one", "vm_two"], "db_servers" => ["vm_three"], "production:children" => [ "web_servers", "db_servers" ], "all_groups:children" => ["production"] } ansible.playbook = "upgrade_stack.yml" end

#DevoxxFR #ansibleRocks

57

Vagrant provisioner local config.vm.provision "ansible_local" do |ansible| ansible.playbook = "upgrade_stack.yml" end

#DevoxxFR #ansibleRocks

58

Packer

#DevoxxFR #ansibleRocks

59

Packer : Elevator pitch

#DevoxxFR #ansibleRocks

60

Packer : Elevator pitch

Boot VM • • • • • •

OpenStack AWS Docker Qemu GCE …

#DevoxxFR #ansibleRocks

60

Packer : Elevator pitch

Boot VM • • • • • •

OpenStack AWS Docker Qemu GCE …

#DevoxxFR #ansibleRocks

Provision • • • • • •

Puppet Saltstack Chef Ansible Shell …

60

Packer : Elevator pitch

Boot VM • • • • • •

OpenStack AWS Docker Qemu GCE …

#DevoxxFR #ansibleRocks

Provision • • • • • •

Puppet Saltstack Chef Ansible Shell …

60

Snapshot

build-me.json "provisioners": [
 {
 "type": "file",
 "source": "ansible/requirements.yml",
 "destination": "/tmp/requirements.yml"
 },
 {
 "type": "shell",
 "scripts": [
 "scripts/ansible-seed.sh"
 ]
 },
 {
 "type": "ansible-local",
 "playbook_dir": "ansible",
 "playbook_file": "ansible/bootstrap.yml"
 } }

#DevoxxFR #ansibleRocks

61

build-me.json "provisioners": [
 {
 "type": "file",
 "source": "ansible/requirements.yml",
 "destination": "/tmp/requirements.yml"
 },
 {
 "type": "shell",
 "scripts": [
 "scripts/ansible-seed.sh"
 ]
 },
 {
 "type": "ansible-local",
 "playbook_dir": "ansible",
 "playbook_file": "ansible/bootstrap.yml"
 } }

#DevoxxFR #ansibleRocks

62

build-me.json "provisioners": [
 {
 "type": "file",
 "source": "ansible/requirements.yml",
 "destination": "/tmp/requirements.yml"
 },
 {
 "type": "shell",
 "scripts": [
 "scripts/ansible-seed.sh"
 ]
 },
 {
 "type": "ansible-local",
 "playbook_dir": "ansible",
 "playbook_file": "ansible/bootstrap.yml"
 } }

#DevoxxFR #ansibleRocks

63

build-me.json "provisioners": [
 {
 "type": "file",
 "source": "ansible/requirements.yml",
 "destination": "/tmp/requirements.yml"
 },
 {
 "type": "shell",
 "scripts": [
 "scripts/ansible-seed.sh"
 ]
 },
 {
 "type": "ansible-local",
 "playbook_dir": "ansible",
 "playbook_file": "ansible/bootstrap.yml"
 } }

#DevoxxFR #ansibleRocks

64

Interactions

#DevoxxFR #ansibleRocks

65

Le maître mot

#DevoxxFR #ansibleRocks

66

Logique

#DevoxxFR #ansibleRocks

67

Logique

SSH => Ansible

#DevoxxFR #ansibleRocks

67

Logique

SSH => Ansible (ou Salt-SSH)

#DevoxxFR #ansibleRocks

67

Terraform

#DevoxxFR #ansibleRocks

68

Points de greffe # playbook.yml - shell: cat terraform.tfstate register: raw_tfstate - set_facts: tfstate: "{{ raw_tfstate.stdout | from_json }}"

#DevoxxFR #ansibleRocks

69

Points de greffe # playbook.yml - shell: cat terraform.tfstate register: raw_tfstate - set_facts: tfstate: "{{ raw_tfstate.stdout | from_json }}" tfstate.modules[1].resources['aws_route53_record.elb_cgate'].primary.attributes.zone_id

#DevoxxFR #ansibleRocks

69

Points de greffe

#DevoxxFR #ansibleRocks

70

Points de greffe # main.tf resource "aws_route53_record" "monitor" { zone_id = "${var.network.route53_zone_id}" name = "monitor" type = "A" ttl = "300" records = ["${aws_instance.server.private_ip}"] }

#DevoxxFR #ansibleRocks

70

Points de greffe # main.tf resource "aws_route53_record" "monitor" { zone_id = "${var.network.route53_zone_id}" name = "monitor" type = "A" ttl = "300" records = ["${aws_instance.server.private_ip}"] } output "monitor_zone_id" { value = "${aws_route53_record.monitor.zone_id}" }

#DevoxxFR #ansibleRocks

70

Points de greffe # main.tf resource "aws_route53_record" "monitor" { zone_id = "${var.network.route53_zone_id}" name = "monitor" type = "A" ttl = "300" records = ["${aws_instance.server.private_ip}"] } output "monitor_zone_id" { value = "${aws_route53_record.monitor.zone_id}" } terraform output monitor_zone_id ZSQ642E3K7JC5

#DevoxxFR #ansibleRocks

70

Points de greffe # playbook.yml - shell: cat terraform.tfstate register: raw_tfstate - set_facts: tfstate: "{{ raw_tfstate.stdout | from_json }}" tfstate.modules[1].resources['aws_route53_record.elb_cgate'].primary.attributes.zone_id

#DevoxxFR #ansibleRocks

71

Points de greffe

#DevoxxFR #ansibleRocks

72

Points de greffe # playbook.yml - shell: terraform output monitor_zone_id register: sh_monitor_zid - set_facts: monitor_zid: "{{ sh_monitor_zid.stdout }}"

#DevoxxFR #ansibleRocks

72

Pensées

#DevoxxFR #ansibleRocks

73

Métaphore

#DevoxxFR #ansibleRocks

74

Métaphore

#DevoxxFR #ansibleRocks

74

Métaphore

#DevoxxFR #ansibleRocks

74

Métaphore

+ #DevoxxFR #ansibleRocks

74

Métaphore

+

+ #DevoxxFR #ansibleRocks

74

SYSADMINS because even developers need heroes #DevoxxFR #ansibleRocks

75

#DevoxxFR #ansibleRocks

76

KEEP CALM AND HACK YOUR WAY #DevoxxFR #ansibleRocks

76

Des questions ?

#DevoxxFR #ansibleRocks

77

Merci

@YesWeScale @aurelienmaury

#DevoxxFR #ansibleRocks

78

Merci

@YesWeScale @aurelienmaury

#DevoxxFR #ansibleRocks

78