Categorieën: Alle

door christophe Mias 1 maand geleden

1326

Ansible

Ansible est un outil puissant pour l'automatisation des tâches sur plusieurs serveurs. L'utilisation de la ligne de commande (CLI) permet d'exécuter des modules, tels que "shell" pour lancer des commandes shell, "

Ansible

Ansible

Grande ligne

Langage
JSON
YAML
Usage
Sujet secondaire
CONFIGURATION

Path multiple

DEPLOYEMENT
ORCHESTRATION ET AUTOMATISATION

fonctionnement

Configuration
inventaire/inventory

Résumé:


  1. * inventory = inventaire des machines et de leurs variables
  2. * élément éssentiel car il décrit votre infra :* vos serveurs* vos types de serveurs
  3. * deux types d'instances :* hosts* groupes
  4. * plusieurs formats :* ini = plat* yaml = plus homogène* json = pour manipuler
  5. * possiblité d'utiliser des patterns
  6. * inventory = * fichier d'inventaire* répertoire group_vars* répertoire host_vars

répertoires associés

* variables d'inventaires:- fichier d'inventaire- group_vars (répertoire)- host_vars (répertoire)

├── 00_inventory.yml├── group_vars│   ├── all.yml│   ├── dbserver.yml│   └── webserver│       ├── vault.yml│       └── webserver.yml└── host_vars    ├── srv1    │   └── srv1.yml    └── srv2.yml

host_vars

group_vars

├── dev│   ├── 00_inventory.yml│   ├── group_vars│   │   ├── all.yml│   │   ├── dbserver.yml│   │   └── webserver│   │       ├── vault.yml│   │       └── webserver.yml│   └── host_vars│       ├── srv1│       │   └── srv1.yml│       └── srv2.yml├── prod│   ├── 00_inventory.yml│   ├── group_vars│   │   ├── all.yml│   │   ├── dbserver.yml│   │   └── webserver│   │       ├── vault.yml│   │       └── webserver.yml│   └── host_vars│       ├── srv1│       │   └── srv1.yml│       └── srv2.yml└── stage    ├── 00_inventory.yml    ├── group_vars    │   ├── all.yml    │   ├── dbserver.yml    │   └── webserver    │       ├── vault.yml    │       └── webserver.yml    └── host_vars        ├── srv1        │   └── srv1.yml        └── srv2.yml

on retrouve cette structure dans la sortie de ansible-config, ex:

 

tree

.
├── 00_inventory.yml
├── group_vars
│   └── common
│       └── params.yml
├── host_vars

cat group_vars/common/params.yml

ansible_python_interpreter: /usr/bin/python3
var1: serveurs de test

on retrouve les variables dans l'arborescence:

 cat  00_inventory.yml &&  ansible-inventory -i 00_inventory.yml --list --yaml
all:
  children:
    common:
      hosts:
       node[1:5]:
all:
  children:
    common:
      hosts:
        node1:
          ansible_python_interpreter: /usr/bin/python3
          var1: serveurs de test
        node2:
          ansible_python_interpreter: /usr/bin/python3
          var1: serveurs de test
        node3:
          ansible_python_interpreter: /usr/bin/python3
          var1: serveurs de test
        node4:
          ansible_python_interpreter: /usr/bin/python3
          var1: serveurs de test
        node5:
          ansible_python_interpreter: /usr/bin/python3
          var1: serveurs de test
    ungrouped: {}

ansible -i "node2," all -b -e "var1=xavki" -m debug -a 'msg={{ var1 }}'

détail:

-i "node2," = dans le groupe All , prendre en compte le node2 seul
-b = "become" = élévation des droits
-e = passage de la variable en cli
-m = le module utilisé (ici debug)
-a = l'argument associé au module

ansible -i 00_inventory.yml all -m debug -a 'msg={{ var1 }}'

node4 | SUCCESS => {
    "msg": "serveurs de test"
}
node1 | SUCCESS => {
    "msg": "serveurs de test"
}
node3 | SUCCESS => {
    "msg": "serveurs de test"
}
node2 | SUCCESS => {
    "msg": "serveurs de test"
}
node5 | SUCCESS => {
    "msg": "serveurs de test"
}

Inventaire dynamique

Documentation :

https://docs.ansible.com/ansible/latest/plugins/inventory.html

https://docs.ansible.com/ansible/latest/dev_guide/developing_inventory.html

https://github.com/ansible-collections/community.general/tree/main/scripts/inventory


ex: nmap.yml

plugin: nmap
strict: false
address: 172.17.0.0/24


récupération de l(inventaire

samik@Abacus:~/ansible_dir(abacustraining⚡) » ansible-inventory -i nmap.yml --list -y --output test.yml
samik@Abacus:~/ansible_dir(abacustraining⚡) » cat test.yml 
all:
 children:
  ungrouped:
   hosts:
    node1:
     ip: 172.17.0.2
     nginx_port: 8888
     ports:
     - port: '22'
      protocol: tcp
      service: ssh
      state: open
     var1: groupvar
    node2:
     ip: 172.17.0.3
     nginx_port: 8888
     ports:
     - port: '22'
      protocol: tcp
      service: ssh
      state: open
     var1: groupvar
    node3:
     ip: 172.17.0.4
     nginx_port: 8888
     ports:
     - port: '22'
      protocol: tcp
      service: ssh
      state: open
     var1: groupvar
    node4:
     ip: 172.17.0.5
     nginx_port: 8888
     ports:
     - port: '22'
      protocol: tcp
      service: ssh
      state: open
     var1: groupvar

ansible -i nmap.yml all -m ping
[WARNING]: Platform linux on host node3 is using the discovered Python interpreter at
/usr/bin/python3.7, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more
information.
node3 | SUCCESS => {
  "ansible_facts": {
    "discovered_interpreter_python": "/usr/bin/python3.7"
  },
  "changed": false,
  "ping": "pong"
}
[WARNING]: Platform linux on host node4 is using the discovered Python interpreter at
/usr/bin/python3.7, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more
information.
node4 | SUCCESS => {
  "ansible_facts": {
    "discovered_interpreter_python": "/usr/bin/python3.7"
  },
  "changed": false,
  "ping": "pong"
}
...

inventory généré

 ansible-inventory -i nmap.yml --list
{
  "_meta": {
    "hostvars": {
      "node1": {
        "ip": "172.17.0.2",
        "nginx_port": 8888,
        "ports": [
          {
            "port": "22",
            "protocol": "tcp",
            "service": "ssh",
            "state": "open"
          }
        ],
        "var1": "groupvar"
      },
      "node2": {
        "ip": "172.17.0.3",
        "nginx_port": 8888,
        "ports": [
          {
            "port": "22",
            "protocol": "tcp",
            "service": "ssh",
            "state": "open"
          }
        ],
        "var1": "groupvar"
      },
      "node3": {
        "ip": "172.17.0.4",
        "nginx_port": 8888,
        "ports": [
          {
            "port": "22",
            "protocol": "tcp",
            "service": "ssh",
            "state": "open"
          }
        ],
...
        "var1": "groupvar"
      },
      "node4": {
        "ip": "172.17.0.5",
        "nginx_port": 8888,
        "ports": [
          {
            "port": "22",
            "protocol": "tcp",
            "service": "ssh",
            "state": "open"
          }
        ],
        "var1": "groupvar"
      }
    }
  },
  "all": {
    "children": [
      "ungrouped"
    ]
  },
  "ungrouped": {
    "hosts": [
      "node1",
      "node2",
      "node3",
      "node4"
    ]

les différents plugins par défaut sont à configurer ici:

* ansible.cfg

[inventory]
# enable inventory plugins, default: 'host_list', 'script', 'auto', 'yaml', 'ini', 'toml'
#enable_plugins = host_list, virtualbox, yaml, constructed

le fichier de base

inventory.json

$ ansible-inventory -i 00_inventory.yml --list

{
    "_meta": {
        "hostvars": {
            "172.17.0.2": {
                "ansible_python_interpreter": "/usr/bin/python3"
            },
            "172.17.0.3": {
                "ansible_python_interpreter": "/usr/bin/python3"
            },
            "172.17.0.4": {
                "ansible_python_interpreter": "/usr/bin/python3"
            },
            "172.17.0.5": {
                "ansible_python_interpreter": "/usr/bin/python3"
            },
            "172.17.0.6": {
                "ansible_python_interpreter": "/usr/bin/python3"
            },
            "172.17.0.7": {
                "ansible_python_interpreter": "/usr/bin/python3"
            }
        }
    },
    "all": {
        "children": [
            "ungrouped"
        ]
    },
    "ungrouped": {
        "hosts": [
            "172.17.0.2",
            "172.17.0.3",
            "172.17.0.4",
            "172.17.0.5",
            "172.17.0.6",
            "172.17.0.7"
        ]
    }
}

Inventory.yml

cat 00_inventory.yml                            

all:
  vars:
    ansible_python_interpreter: /usr/bin/python3
  hosts:
    172.17.0.7:
    172.17.0.6:
    172.17.0.5:
    172.17.0.4:
    172.17.0.3:
    172.17.0.2:

 ansible-inventory -i 00_inventory.yml --list --yaml

all:
  children:
    ungrouped:
      hosts:
        172.17.0.2:
          ansible_python_interpreter: /usr/bin/python3
        172.17.0.3:
          ansible_python_interpreter: /usr/bin/python3
        172.17.0.4:
          ansible_python_interpreter: /usr/bin/python3
        172.17.0.5:
          ansible_python_interpreter: /usr/bin/python3
        172.17.0.6:
          ansible_python_interpreter: /usr/bin/python3
        172.17.0.7:
          ansible_python_interpreter: /usr/bin/python3

hosts

Appelé fichier ini:

[imac]
localhost ansible_connection=local
imacpat
[laptop]
mbp
kaisenlinux
[vm]
abacus
[tab]
nexus
ipadkris



ansible-inventory --list --toml
[imac.hosts.imacpat]

[imac.hosts.localhost]
ansible_connection = "local"

[laptop.hosts.kaisenlinux]

[laptop.hosts.mbp]

[tab.hosts.ipadkris]

[tab.hosts.nexus]

[vm.hosts.abacus]

commande

ansible-inventory

ansible-inventory

usage: ansible-inventory [-h] [--version] [-v] [-i INVENTORY] [--vault-id VAULT_IDS]
                         [--ask-vault-password | --vault-password-file VAULT_PASSWORD_FILES] [--playbook-dir BASEDIR]
                         [--list] [--host HOST] [--graph] [-y] [--toml] [--vars] [--export] [--output OUTPUT_FILE]
                         [host|group]

positional arguments:
  host|group

optional arguments:
  --ask-vault-password, --ask-vault-pass
                        ask for vault password
  --export              When doing an --list, represent in a way that is optimized for export,not as an accurate
                        representation of how Ansible has processed it
  --output OUTPUT_FILE  When doing --list, send the inventory to a file instead of to the screen
  --playbook-dir BASEDIR
                        Since this tool does not use playbooks, use this as a substitute playbook directory.This sets the
                        relative path for many features including roles/ group_vars/ etc.
  --toml                Use TOML format instead of default JSON, ignored for --graph
  --vars                Add vars to graph display, ignored unless used with --graph
  --vault-id VAULT_IDS  the vault identity to use
  --vault-password-file VAULT_PASSWORD_FILES, --vault-pass-file VAULT_PASSWORD_FILES
                        vault password file
  --version             show program's version number, config file location, configured module search path, module location,
                        executable location and exit
  -h, --help            show this help message and exit
  -i INVENTORY, --inventory INVENTORY, --inventory-file INVENTORY
                        specify inventory host path or comma separated host list. --inventory-file is deprecated
  -v, --verbose         verbose mode (-vvv for more, -vvvv to enable connection debugging)
  -y, --yaml            Use YAML format instead of default JSON, ignored for --graph

Actions:
  One of following must be used on invocation, ONLY ONE!

  --graph               create inventory graph, if supplying pattern it must be a valid group name
  --host HOST           Output specific host info, works as inventory script
  --list                Output all hosts info, works as inventory script

Show Ansible inventory information, by default it uses the inventory script JSON format
ERROR! No action selected, at least one of --host, --graph or --list needs to be specified.

--graph

ansible-inventory   --graph
@all:
  |--@common:
  |  |--@dbserver:
  |  |  |--node4
  |  |  |--node5
  |  |--@webserver:
  |  |  |--node1
  |  |  |--node2
  |  |  |--node3
  |--@monitoring:
  |  |--@dbserver:
  |  |  |--node4
  |  |  |--node5
  |  |--@nocommon:
  |  |  |--node6
  |  |--@webserver:
  |  |  |--node1
  |  |  |--node2
  |  |  |--node3
  |--@ungrouped:
ansible-inventory   -i 00_inventory.yml --graph
@all:
  |--@common:
  |  |--node1
  |  |--node2
  |  |--node3
  |  |--node4
  |  |--node5
  |--@ungrouped:

--list

--toml

ajout de l'option avec:

pip3 install toml

--yaml

ansible-inventory --list --yaml

all:
  children:
    common:
      children:
        dbserver:
          hosts:
            node4:
              var1: gp_dbserver
            node5:
              var1: node5
        webserver:
          hosts:
            node1:
              var1: gp_webserver
            node2:
              var1: node2
            node3:
              var1: gp_webserver
    monitoring:
      children:
        dbserver:
          hosts:
            node4: {}
            node5: {}
        nocommon:
          hosts:
            node6:
              var1: all
        webserver:
          hosts:
            node1: {}
            node2: {}
            node3: {}
    ungrouped: {}
Precedence des variables

ANSIBLE : Precedence des variables


* 23 types / localisation :
        command line values (eg “-u user”)        role defaults [1]        inventory file or script group vars [2]        inventory group_vars/all [3]        playbook group_vars/all [3]        inventory group_vars/* [3]        playbook group_vars/* [3]        inventory file or script host vars [2]        inventory host_vars/* [3]        playbook host_vars/* [3]        host facts / cached set_facts [4]        play vars        play vars_prompt        play vars_files        role vars (defined in role/vars/main.yml)        block vars (only for tasks in block)        task vars (only for the task)        include_vars        set_facts / registered vars        role (and include_role) params        include params        extra vars (always win precedence)

roles
Exemple2

ANSIBLE : Ex - Monitoring > node exporter


Objectif : série de vidéo de mise en pratique autour du monitoring

prometheus / grafana / node-exporter...



* travail sur 4 noeuds

1- un de monitoring (prometheus/grafana)

2- tous monitoré par node exporter


* structure = inventory + playbook + role node exporter


Informations des conteneurs :


  => /samik-debian-4 - 172.17.0.5

  => /samik-debian-3 - 172.17.0.4

  => /samik-debian-2 - 172.17.0.3

  => /samik-debian-1 - 172.17.0.2

- name: Install Nodeexporter
  hosts: all
  become: yes
  roles:
    - node-exporter
- name: Install prometheus grafana
  hosts: monito
  become: yes
  roles:
    - monito
    - grafana


phase3

role grafana

---
# handlers file for roles/grafana
- name: restart_grafana
  systemd:
    name: grafana-server
    state: restarted
    enabled: yes
    daemon_reload: yes


dashboard-node-exporter.yml.j2

apiVersion: 1
providers:
- name: 'node-exporter'
  orgId: 1
  folder: ''
  type: file
  disableDeletion: false
  updateIntervalSeconds: 10 
  options:
    path: /var/lib/grafana/node-exporter.json


---
# tasks file for roles/grafana
- name: install gpg
  apt:
    name: gnupg,software-properties-common
    state: present
    update_cache: yes
    cache_valid_time: 3600
- name: add gpg hey
  apt_key:
    url: "https://packages.grafana.com/gpg.key"
    validate_certs: no
- name: add repository
  apt_repository:
    repo: "deb https://packages.grafana.com/oss/deb stable main"
    state: present
    validate_certs: no
- name: install grafana
  apt:
    name: grafana
    state: latest
    update_cache: yes
    cache_valid_time: 3600
- name: change admin user
  lineinfile:
    path: /etc/grafana/grafana.ini
    regexp: "{{ item.before }}"
    line: "{{ item.after }}"
  with_items:
  - { before: "^;admin_user = admin", after: "admin_user = {{ grafana_admin_user }}"}
  - { before: "^;admin_password = admin", after: "admin_password = {{ grafana_admin_password }}"}
  notify: restart_grafana
- name: start service grafana-server
  systemd:
    name: grafana-server
    state: started
    enabled: yes
- name: wait for service up
  uri:
    url: "http://127.0.0.1:3000"
    status_code: 200
  register: __result
  until: __result.status == 200
  retries: 120
  delay: 1
- name: add prometheus datasource
  grafana_datasource:
    name: "prometheus-local"
    grafana_url: "http://127.0.0.1:3000"
    grafana_user: "{{ grafana_user_admin }}"
    grafana_password: "{{ grafana_admin_password }}"
    org_id: "1"
    ds_type: "prometheus"
    ds_url: "127.0.0.1:9090"
  changed_when: false
- name: install node exporter dashboard
  get_url:
    url: https://raw.githubusercontent.com/rfrail3/grafana-dashboards/master/prometheus/node-exporter-full.json
    dest: /var/lib/grafana/node-exporter.json
    mode: '0755'
- name: activate dashboard for node exporter
  template:
    src: dashboard-node-exporter.yml.j2
    dest: /etc/grafana/provisioning/dashboards/dashboard-node-exporter.yml
    mode: 0755
  notify: restart_grafana

grafana_admin_user: "admin"
grafana_admin_password: "password"

phase2

role monito

prometheus.yml.j2

#jinja2: lstrip_blocks: "True"
{{ prometheus_var_config | to_nice_yaml(indent=2) }}
{% if prometheus_node_exporter_group %}
- job_name: node_exporter
  scrape_interval: 15s
  static_configs:
  - targets:
{% for server in groups[prometheus_node_exporter_group] %}
    - {{ server }}:9100
{% endfor %}
{% endif %}


prometheus.j2

# Set the command-line arguments to pass to the server.
ARGS="--web.enable-lifecycle --storage.tsdb.retention.time={{ prometheus_retention_time }} --web.console.templates=/etc/prometheus/consoles --web.console.libraries=/etc/prometheus/console_libraries

---
# handlers file for roles/monito
- name: restart_prometheus
  systemd:
    name: prometheus
    state: restarted
    enabled: yes
    daemon_reload: yes

- name: reload_prometheus
  uri: 
    url: http://localhost:9090/-/reload
    method: POST
    status_code: 200


---
# tasks file for roles/monito
- name: update and install prometheus
  apt:
    name: prometheus
    state: latest
    update_cache: yes
    cache_valid_time: 3600
- name: prometheus args
  template:
    src: prometheus.j2
    dest: /etc/default/prometheus
    mode: 0644
    owner: root
    group: root
  notify: restart_prometheus
- name: prometheus configuration file
  template:
    src: prometheus.yml.j2
    dest: "{{ prometheus_dir_configuration }}/prometheus.yml"
    mode: 0755
    owner: prometheus
    group: prometheus
  notify: reload_prometheus
- name: start prometheus
  systemd:
    name: prometheus
    state: started
    enabled: yes

- meta: flush_handlers


---
# defaults file for roles/monito
prometheus_dir_configuration: "/etc/prometheus"
prometheus_retention_time: "365d"
prometheus_scrape_interval: "30s"
prometheus_node_exporter: true
prometheus_node_exporter_group: "all"
prometheus_env: "production"
prometheus_var_config: 
  global:
    scrape_interval: "{{ prometheus_scrape_interval }}"
    evaluation_interval: 5s 
    external_labels:
      env: '{{ prometheus_env }}'
  scrape_configs:
    - job_name: prometheus
      scrape_interval: 5m
      static_configs:
        - targets: ['{{ inventory_hostname }}:9090']


phase1

LES TASKS DU ROLE



* vérifier si node exporter est déjà installé

roles node-exporter

node_exporter.service.j2

[Unit]
Description=Node Exporter Version {{node_exporter_version}}
After=network-online.target
Wants=network-online.target


[Service]
User={{ node_exporter_user }}
Group={{ node_exporter_user }}
Type=simple
ExecStart={{ node_exporter_bin }}


[Install]
WantedBy=multi-user.target



handler

---
# handlers file for roles/node-exporter
- name: reload_daemon_and_restart_node_exporter
  systemd:
    name: node_exporter
    state: restarted
    daemon_reload: yes
    enabled: yes


tasks

---
# tasks file for roles/node-exporter
- name: check if node exporter exist
  stat:
    path: "{{ node_exporter_bin }}"
  register: __check_node_exporter_present
- name: create node exporter user
  user:
    name: "{{ node_exporter_user }}"
    append: true
    shell: /usr/sbin/nologin
    system: true
    create_home: false
    home: /
- name: create node exporter config dir
  file:
    path: "{{ node_exporter_dir_conf }}"
    state: directory
    owner: "{{ node_exporter_user }}"
    group: "{{ node_exporter_group }}"


    # on récupère la version via le module shell
- name: if node exporter exist get version
  shell: "cat /etc/systemd/system/node_exporter.service | grep Version | sed s/'.*Version '//g"
  when: __check_node_exporter_present.stat.exists == true
  changed_when: false
  register: __get_node_exporter_version


- name: download and unzip node exporter if not exist
  unarchive:
    #src: "https://github.com/prometheus/node_exporter/releases/download/v{{ node_exporter_version }}/node_exporter-{{ node_exporter_version }}.linux-amd64.tar.gz"
    src: "https://github.com/prometheus/node_exporter/releases/download/v{{ node_exporter_version }}/node_exporter-{{ node_exporter_version }}.{{ node_exporter_platform }}.tar.gz"
    dest: /tmp/
    remote_src: yes
#  when: __check_node_exporter_present.stat.exists == false
  when: __check_node_exporter_present.stat.exists == false or not __get_node_exporter_version.stdout == node_exporter_version
- name: move the binary to the final destination
  copy:
    src: "/tmp/node_exporter-{{ node_exporter_version }}.{{ node_exporter_platform}}/node_exporter"
    dest: "{{ node_exporter_bin }}"
    owner: "{{ node_exporter_user }}"
    group: "{{ node_exporter_group }}"
    mode: 0755
    remote_src: yes
 # when: __check_node_exporter_present.stat.exists == false
  when: __check_node_exporter_present.stat.exists == false or not __get_node_exporter_version.stdout == node_exporter_version
- name: clean
  file:
    path: "/tmp/node_exporter-{{ node_exporter_version }}.{{ node_exporter_platform}}/node_exporter"
    state: absent
- name: install service
  template:
    src: node_exporter.service.j2
    dest: /etc/systemd/system/node_exporter.service
    owner: root
    group: root
    mode: 0755
  notify: reload_daemon_and_restart_node_exporter


- meta: flush_handlers


- name: service always started
  systemd:
    name: node_exporter
    state: started
    enabled: yes


default

---
# defaults file for roles/node-exporter
node_exporter_version: "1.0.1"
node_exporter_bin: /usr/local/bin/node_exporter
node_exporter_user: node-exporter
node_exporter_group: "{{ node_exporter_user }}"
node_exporter_dir_conf: /etc/node_exporter
node_exporter_platform: "linux-arm64"

Exemple1

3 roles

nginx

ROLE NGINX : installation du serveur nginx

                        - name: install nginx    apt:      name: nginx,curl      state: present      cache_valid_time: 3600      update_cache: yes  - name: remove default file    file:      path: "{{ item }}"      state: absent    with_items:    - "/etc/nginx/sites-available/default"    - "/etc/nginx/sites-enabled/default"  - name: install vhost    template:      src: default_vhost.conf.j2      dest: /etc/nginx/sites-available/default_vhost.conf      owner: root      group: root      mode: 0644    notify: reload_nginx  - name: Flush handlers    meta: flush_handlers                    

users

* ROLE USERS : création d'un user et ajout de la clef ssh

                                              
                                          
- name: création du user devops    user:      name: devops      shell: /bin/bash      groups: sudo      append: yes      password: "{{ 'password' | password_hash('sha512') }}"    become: yes  - name: Add devops user to the sudoers    copy:      dest: "/etc/sudoers.d/devops"      content: "devops  ALL=(ALL)  NOPASSWD: ALL"    become: yes  - name: Deploy SSH Key    authorized_key:       user: devops      key: "{{ lookup('file', '/tmp/xavki.pub') }}"      state: present    become: yes

ssh_keygen

* ROLE SSH_KEYGEN : génération d'une clef

                                              
                                          
- name: mon premier playbook  hosts: localhost  connection: local  roles:  - ssh_keygen  - name: generate SSH key"    openssh_keypair:      path: /tmp/xavki      type: rsa      size: 4096      state: present      force: no

initialisation

creer: un dossier roles
executer: ansible-galaxy init monrole
résultat:
 
 
tree -a
.
└── monrole
  ├── defaults
  │  └── main.yml
  ├── files
  ├── handlers
  │  └── main.yml
  ├── meta
  │  └── main.yml
  ├── README.md
  ├── tasks
  │  └── main.yml
  ├── templates
  ├── tests
  │  ├── inventory
  │  └── test.yml
  ├── .travis.yml
  └── vars
    └── main.yml

Playbook

nombreuses options : -i : inventory


Variable d'environnement

Documentation :

https://docs.ansible.com/ansible/latest/user_guide/playbooks_environment.html

Objectifs : Définir des variables d'environnement et utiliser un prompt


* différents endroits pour définir les variables d'environnement

* playbook

* tasks

prompt

* var prompt : interrogation de l'utilisateur

  vars_prompt:
    - name: nom
  tasks:
  - name: echo
    shell: "echo Salut {{ nom }}"
    register: __output
  - name: print
    debug:
      var: __output


* avec phrase et valeur par défaut

  vars_prompt:
  - name: env
    prompt: "Quel est votre environnement ? prod/stage/dev"
    default: dev
  environment:
    ENV: "{{ env }}"
  tasks:
  - name: echo
    shell: "echo Salut $ENV"
    register: __output
  - name: print
    debug:
      var: __output

* exemples:

- name: utilisation du module shell et command
  hosts: all
  environment:
    PATHLIB: "/var/lib/"
    ENV: "{{ env }}"
  vars_prompt: 
    - name: nom
    - name: env
      prompt: "Quel est votre environnement ? prod/stage/dev"
      default: dev
  tasks:
  - name: echo
    shell: echo $PATHLIB
    register: __output
    changed_when: false
  - name: print
    debug:
      var: __output
  - name: echo
    shell: "echo Salut $ENV"
    register: __output
  - name: print
    debug:
      var: __output

environment



- name: utilisation du module shell et command
  hosts: all
  environment:
    PATHLIB: "/var/lib/"
  tasks:
  - name: echo
    shell: echo $PATHLIB
    register: __output
  - name: print
    debug:
      var: __output


* variable d'environnement de la machine ansible

  - name: echo
    shell: "echo {{ lookup('env', 'ENV') | default('stage', True) }}"
    register: __output
  - name: print
    debug:
      var: __output


modules

docker

ANSIBLE : module docker login & docker_image


* Objectif : construction, build et push d'images docker

Documentation :

https://docs.ansible.com/ansible/latest/collections/community/general/docker_image_module.html


Prérequis :

* docker

* python3-docker ou pip3 install docker


PARAMETRES :

* api_version : version de l'api docker (docker info)

* archive_path : cas d'une image en tar, chemin d'accès

* build : pour constuire une image * args : clef/valeur * cache_from : images sources utilisées en cache * container_limits: limite applicable aux conteneurs POUR LE BUILD * cpusetcpus : spécificier le cpu (taskset) * cpushares : poids des cpus * memory : mémoire maximum * memswap : mémoire total (mem + swap) , -1 = disable swap

	* dockerfile : nom du fichier Dockerfile
	* /etc/hosts : utilisé lors du build (liste : ip / adresses)
	* http_timeout : timeout lors du build
	* network : utilisé pour le RUN
	* no_cache: ne pas utiliser de cache
	* path : chemin de contexte pour le build
	* pull : dowload du/des FROM
	* rm : suppression des images intermédiaires après le build
	* target : image finale résultant de plusieurs stage
	* use_config_proxy : utilisation d'un proxy

ANSIBLE : module docker login & docker_image


* buildargs (deprecated) : idem build > args

* ca_cert : vérficiation du serveur par ca (DOCKER_CERT_PATH)

* client_cert : tls client

* client_key : tls client clef

* containers_limit (deprecated) : idem build > container_limits

* debug : activation du mode debug

* docker_hosts : par défaut socket local sinon tcp/ssh

* dockerfile (deprecated) : cf build

* force : à utiliser avec le state absent pour forcer la suppression

* force_source : refaire build, load, pull d'une image qui existe déjà

* force_tag : forcer le tagging d'une image

* http_timeout (deprecated) : cf build ANSIBLE : module docker login & docker_image


* load_path : load une image via son archive tar

* name : nom de l'image url_registry/nom

* nocache : ne pas utiliser le cache au build

* path (deprecated) : cf build

* pull : idem

* push : idem

* repository : chemin vers le dépôt

* rm (deprecated) : cd build

* source : origine de l'image : * build : dockerfile * load : archive tar * pull : pull d'une registry * local : déjà présente dans le cache local ANSIBLE : module docker login & docker_image


* ssl_version : version ssl pour docker

* state : present / build / absent

* tag : tag de l'image

* timeout : délai pour le timeout du daemon docker

* tls : connexion chiffrée vers l'api docker

* tls_hostname : hostname pour le tls

* validate_certs : check tls

login

* cas du build & push

  - include_vars: /home/oki/.vault.yml
  - name: docker login
    docker_login:
      registry_url: registry.gitlab.com
      username: xavki
      password: "{{ vault_token_gitlab }}"
      reauthorize: yes
  - name: build
    docker_image:
      build:
        path: /tmp/build/
        dockerfile: Dockerfile
        pull: yes
        cache_from:
        - alpine:3.9
      source: build
      name: registry.gitlab.com/xavki/testflux
      tag: v1.1


Container

* Objectif : lancement d'image docker

Documentation :

https://docs.ansible.com/ansible/latest/collections/community/general/docker_container_module.html


Prérequis :

* docker

* python3-docker ou pip3 install docker


PARAMETRES :

ANSIBLE : module docker_container


image

* pull simple d'une image

  - name: Pull an image
    docker_image:
      name: alpine
      tag: latest
      source: pull


* retaguer une image

  - name: Pull an image
    docker_image:
      name: alpine
      tag: latest
      repository: myregistry/monimage:v1.0

ANSIBLE : module docker login & docker_image


* import via un tar (docker save)

  - name: copy image
    copy:
      src: image.test.v1.0.tar
      dest: /tmp/
  - name: Pull an image
    docker_image:
      name: archive
      tag: v1.0
      load_path: /tmp/image.test.v1.0.tar
      source: load

Exemple build

* build d'image via Dockerfile

  - name: copy files
    file:
      path: /tmp/build
      state: directory
  - name: copy image
    copy:
      src: app/
      dest: /tmp/build
  - name: build
    docker_image:
      name: imgbuild
      tag: v1.0
      source: build
      build:
        path: /tmp/build/app/
        dockerfile: Dockerfile
        cache_from:
        - alpine:3.9

ANSIBLE : module docker login & docker_image


* cas du build & push

  - include_vars: /home/oki/.vault.yml
  - name: docker login
    docker_login:
      registry_url: registry.gitlab.com
      username: xavki
      password: "{{ vault_token_gitlab }}"
      reauthorize: yes
  - name: build
    docker_image:
      build:
        path: /tmp/build/
        dockerfile: Dockerfile
        pull: yes
        cache_from:
        - alpine:3.9
      source: build
      name: registry.gitlab.com/xavki/testflux
      tag: v1.2
      push: yes 

assemble

ANSIBLE : Module ASSEMBLE


Documentation :

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/assemble_module.html


PARAMETRES

* backup : sauvegarde du fichier avant changement

* decrypt : déchiffrer automatiquement par défaut ou pas le vault

* delimiter : séparation entre chaque fichier

* dest : la destination (fichier)

* group : groupe du fichier de destination

* regexp : regular expression de pattern des fichiers sources

* remote_src

* src : répertoire source



* validate : commande de validation ANSIBLE : Module ASSEMBLE


* simple via uniquement le remote

  - name: dir
    file:
      path: /tmp/sources
      state: directory
  - name: copy
    copy:
      src: "files/{{ item }}"
      dest: /tmp/sources/
    with_items:
    - t1
    - t2
    - t3
  - name: test assemble
    assemble:
      src: /tmp/sources
      dest: /tmp/myconf.cfg

ANSIBLE : Module ASSEMBLE


* ajouter un delimiter

delimiter: '### START FRAGMENT ###'


* sans remote src

  - name: test assemble
    assemble:
      src: files/
      dest: /tmp/myconf.cfg
      remote_src: no

Shell/command

Documentation :

https://docs.ansible.com/ansible/2.5/modules/shell_module.html

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html

Objectifs : lancer des commandes shell

Command vs Shell > command : options réduites (lance des commandes simples) shell : utilisation de tout ce qui est dans la CLI (pipe...)


PARAMETRES : COMMAND

* argv : ligne de commande sous forme de liste

* chdir : change de répertoire

* cmd : commande lancée

* creates : la commande n'est pas lancée si le fichier existe

* removes : inverse de creates, si le fichier existe la commande est lancée

* stdin : spécifier une valeur entrante via stdin

* stdin_add_newline : passe une ligne pour le stdin

* strip_empyt_ends : supprimer les lignes vides


* simple :
  - name: test
    command:
      cmd: ls
    register: __output

* changement de directory :
  - name: test
    command:
      cmd: ls
      chdir: /etc/
    register: __output
ANSIBLE : Modules COMMAND & SHELL

* commande en liste :
  - name: test
    command:
      argv:
      - ls
      - -larth
    register: __output

* sous condition si le fichier n'existe pas
  - name: touch
    file:
      path: /tmp/xavki
      state: touch
  - name: test
    command: 
      cmd: ls -lath /tmp
      creates: /tmp/xavki
    register: __output
  - name: debug
    debug:
      var: __output
ANSIBLE : Modules COMMAND & SHELL

* inverse : si il existe
  - name: test
    command: 
      cmd: ls -lath /tmp
      removes: /tmp/xavki
ANSIBLE : Modules COMMAND & SHELL

PARAMTRES : SHELL
* chdir : changement de répertoire d'exécution
* creates : la commande est lancée si le fichier n'existe pas
* executable : choix du shell utilisé
* removes : inverse de creates
* stdin : définir un stdin
* warn : afficher ou non les warn
ANSIBLE : Modules COMMAND & SHELL

* exemple simple :
  - name: test
    shell: cat /etc/hosts | grep 127
    register: __output
  - name: debug
    debug:
      var: __output

* exemple avec un bloc
  - name: test
    shell: |
      cat /etc/hosts
      ls /etc/
    register: __output
  - name: debug
    debug:
      var: __output

* exemple avec des variables d'environnement
  - name: test
    shell: echo "Hello $MAVAR"
    environment:
      MAVAR: "xavki"
    register: __output

uri

Objectifs : passer des requêtes http ou https et interagir avec


PARAMETRES :

* HEADER_ : paramètre header pour passer vos requêtes

* body : si activation du format json récupérer une variable

* body_format : format du body json ou raw

* creates : si le fichier existe la tâche n'est pas lancée

* dest : répertoire de destination

* follow_redirects : suivre les redirections

* force_basic_aut : forcer le basic auth

* headers : ajout de header (format yaml)

* method : GET / POST/ DELETE / PUT / HEAD / PATCH / TRACE...

* others : autre argument pour le file module (fichier créé)

* password : pour le basic auth

* removes : supprime le fichier avant

* return_content : pour récupérer le contenu

* status_code : 200, 301... [200,201...]

* timeout : en seconde

* url : target

* user : pour basic_auth

* validate_certs : stricte tls ou non 

* cas simple
- name: test
  hosts: all
  tasks:
  - name: uri
    uri: 
      url: http://xavki.blog
      method: GET
      validate_certs: False

* vérification du status
- name: test
  hosts: all
  tasks:
  - name: uri
    uri: 
      url: http://xavki.blog
      method: GET
      validate_certs: False
      status_code: 200
ANSIBLE : Module URI

* liste de code retour
  - name: uri
    uri: 
      url: https://httpbin.org/status/500
      method: POST
      status_code: [200,201,301]
      validate_certs: False

* récupération du contenu
- name: test
  hosts: all
  tasks:
  - name: uri
    uri: 
      url: http://httpbin.org/get
      return_content: yes
      method: GET
    register: __content
  - name: debug
    debug:
      var: __content.content
ANSIBLE : Module URI

* utilisation du format json
  - name: uri
    uri: 
      url: https://httpbin.org/get
      method: GET
      return_content: yes
      validate_certs: False
      body_format: json
    register: __body
  - name: debug
    debug:
      var: __body.json.url

* validation du contenu
- name: test
  hosts: all
  tasks:
  - name: uri
    uri: 
      url: http://xavki.blog
      return_content: yes
      method: GET
      validate_certs: False
    register: __content
    failed_when: " 'xavki' not in __content.content"
ANSIBLE : Module URI

* basic auth
   hosts: all
  tasks:
  - name: uri
    uri: 
      url: https://httpbin.org/basic-auth/toto/test
      user: "toto"
      password: "test"
      method: GET
      validate_certs: False
  
  - name: uri2
    uri: 
      url: https://httpbin.org/basic-auth/tot/test
      user: "toto"
      password: "test"
      method: GET
      validate_certs: False



Gather Facts & module Setup

Documentation : * setup : https://docs.ansible.com/ansible/2.3/setup_module.html * gather facts : https://docs.ansible.com/ansible/latest/user_guide/playbooks_vars_facts.html 
* facts > données relatives aux machines plus ou moins détaillées (réduit, non collectés...) * networks * devices * os * hardware * connexion utilisée * montages/volumes... 
* ansible_facts : dictionnaire contenant tous les facts

set_fact

ANSIBLE : Module SET_FACT


Documentation :

https://docs.ansible.com/ansible/latest/collections/ansible/builtin/set_fact_module.html


PARAMETRES

* cacheable : ajouté au cache (défaut non)


  - name: set fact
    set_fact:
      mavariable: "Hello tout le monde !!"
  - name: debug
    debug:
      var: mavariable

ANSIBLE : Module SET_FACT


* exemple avec éléments calculés

  vars:
    var1: "hello"
    var2: "je suis"
  tasks:
  - name: get user
    command: "echo $USER"
    register: __user
  - name: date
    set_fact:
      mavariable: "{{ var1 }} {{ var2 }} {{ __user.stdout }} sur {{ ansible_hostname }}"
  - name: debug
    debug:
      var: mavariable

ANSIBLE : Module SET_FACT


* le gather fact datetime :

  - name: date
    debug:
      var: ansible_date_time


* si cache (ansible.cfg)

#cache facts
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/facts_cache
# two hours timeout
fact_caching_timeout = 7200

ANSIBLE : Module SET_FACT


* contourner le cache

  - name: date without cache
    shell: "date +%Y-%m-%d"
    register: shell_date
  - set_fact:
      date: "{{ shell_date.stdout }}"


 ansible-playbook -i 00_inventory.yml -D pbfact.yml 

PLAY [exemple synchro] ********************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [172.17.0.5]
ok: [172.17.0.3]
ok: [172.17.0.4]
ok: [172.17.0.2]

TASK [get user] ***************************************************************************************
changed: [172.17.0.2]
changed: [172.17.0.4]
changed: [172.17.0.3]
changed: [172.17.0.5]

TASK [date] *******************************************************************************************
ok: [172.17.0.3]
ok: [172.17.0.4]
ok: [172.17.0.5]
ok: [172.17.0.2]

TASK [debug] ******************************************************************************************
ok: [172.17.0.5] => {
  "mavariable": "hello je suis samik sur samik-debian-4"
}
ok: [172.17.0.3] => {
  "mavariable": "hello je suis samik sur samik-debian-2"
}
ok: [172.17.0.4] => {
  "mavariable": "hello je suis samik sur samik-debian-3"
}
ok: [172.17.0.2] => {
  "mavariable": "hello je suis samik sur samik-debian-1"
}

PLAY RECAP ********************************************************************************************
172.17.0.2         : ok=4  changed=1  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0  
172.17.0.3         : ok=4  changed=1  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0  
172.17.0.4         : ok=4  changed=1  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0  
172.17.0.5         : ok=4  changed=1  unreachable=0  failed=0  skipped=0  rescued=0  ignored=0  


* soit en cli

ansible -i 00_inventory.yml all -m setupansible -i 00_inventory.yml all -m setup -a "filter=ansible_user*"

* soit par la variable
  - name: debug    debug:      var: ansible_facts

apt_key

https://docs.ansible.com/ansible/2.5/modules/apt_key_module.html* apt_repository : https://docs.ansible.com/ansible/2.5/modules/apt_repository_module.html
APT_KEY

PARAMETRES :


* data > directement fournir la clef

Exemple avec docker

ANSIBLE : Installation dépôt APT - ex : docker

Quelques exemples :


* à partir d'un fichier

- name: Add a key from a file on the Ansible server.  apt_key:    data: "{{ lookup('file', 'apt.asc') }}"    state: present

* à partir d'une url
- name: Add an Apt signing key to a specific keyring file  apt_key:    id: 9FED2BCBDCD29CDF762678CBAED4B06F473041FA    url: https://ftp-master.debian.org/keys/archive-key-6.0.asc    keyring: /etc/apt/trusted.gpg.d/debian.gpg

* suppression d'une clef
- name: Remove a Apt specific signing key, leading 0x is valid  apt_key:    id: 0x9FED2BCBDCD29CDF762678CBAED4B06F473041FA    state: absent

linefile

ANSIBLE : Modules LINEINFILE


Documentation : * https://docs.ansible.com/ansible/2.5/modules/lineinfile_module.html
PARAMETRES :
* attributes
* backrefs : pour utiliser des captures via regexp
* backup : réalise un backup avant modification
* create : si le fichier n'existe pas il est créé (default no)
* firstmatch : avec insertafter ou insertbefore s'exécute via la première occurence
* group : groupe propriétaire du fichier
* insertafter : insertion après la ligne recherché (default EOF > regex sans backrefs)
* insertbefore : idem after > mais avant la ligne
* line : ligne à ajouter ou remplacer (éventuellement avec la capture)
* mode : permissions (0755 ou u+rwx,g+rx,o+rx)
* owner : propriétaire du fichier
* path : chemin du fichier
* regexp : expression régulière permettant de rechercher la ligne (et éventuellement faire un capture)
* state : la ligne doit être présente/modifiée ou supprimée
* validate : commande de validation de la ligne

exemples 2

avec regexp sous condition:


- name: change admin user
  lineinfile:
    path: /etc/grafana/grafana.ini
    regexp: "{{ item.before }}"
    line: "{{ item.after }}"
  with_items:
  - { before: "^;admin_user = admin", after: "admin_user = {{ grafana_admin_user }}"}
  - { before: "^;admin_password = admin", after: "admin_password = {{ grafana_admin_password }}"}

ANSIBLE : Modules LINEINFILE


* cas le plus simple mais le moins courant : ajout d'une ligne

```
  - name: lineinfile
    lineinfile: 
      dest: /tmp/test.conf 
      line: "test"
      state: present
      create: True
```


Rq: si changement de line > nlle ligne




* recherche d'une ligne précise et modification

```
    lineinfile:
      dest: /tmp/test.conf
      line: "test 2"
      regexp: "^test$"
      state: present
      create: True
```


<br>


* modification avec capture

```
    lineinfile:
      dest: /tmp/test.conf
      line: 'je suis le nombre : \1'
      regexp: "^test ([0-2])$"
      backrefs: yes
      state: present
      create: True
```


Rq: si 2 runs attention


--------------------------------------------------------------------------------------


# ANSIBLE : Modules LINEINFILE



<br>


* commenter une ligne avec plus ou moins de précision


```
    lineinfile:
      dest: /tmp/test.conf
      line: '# \1'
      regexp: "(^je suis le nombre : [0-2])"
      backrefs: yes
      state: present
      create: True
```


<br>


* ajout avant une ligne

```
    lineinfile:
      dest: /tmp/test.conf
      line: "Ma nouvelle ligne"
      insertbefore: '# je suis le nombre : [0-2]'
      state: present
      create: True
```


Rq : idem after


--------------------------------------------------------------------------------------


# ANSIBLE : Modules LINEINFILE



<br>


* supprimer une ligne soit par regexp ou par line

```
  - name: lineinfile
    lineinfile:
      dest: /tmp/test.conf
      regexp: "^Ma nouvelle ligne"
      #line: "^Ma nouvelle ligne"
      state: absent
```


<br>


* avec backup avant modification


```
  - name: lineinfile
    lineinfile: 
      dest: /tmp/test.conf
      regexp: "^#"
      state: absent
      backup: yes
```


get-url

GET_URL

Documentation : * https://docs.ansible.com/ansible/latest/collections/ansible/builtin/get_url_module.html


PARAMETRES : 
* attributes


* http_agent: spécifier un agent

Exemple27

                        
                          
                        
                        
                        
  - name: dest locale puis dispatch

                        
    get_url:

                        
      url: https://github.com/prometheus/node_exporter/releases/download/v1.0.1/node_exporter-1.0.1.linux-amd64.tar.gz

                        
      dest: /tmp/

                        
      validate_certs: no

                        
    delegate_to: localhost

                        
    run_once: yes

                        
  - name: dispatch

                        
    unarchive:

                        
      src: /tmp/node_exporter-1.0.1.linux-amd64.tar.gz

                        
      dest: /tmp/
                      

archive


UNARCHIVE

Documentation :* https://docs.ansible.com/ansible/2.5/modules/unarchive_module.html

Prérequis : unzip, tar


PARAMETRES :
* attributes : attributs du fichier
* copy : deprecated > utiliser remote_src
* creates : si un répertoire ou fichier exist la tâche n'est pas lancé
* decrypt : (default yes) déchiffrer les fichiers vaultés
* dest : destination des éléments
* exclude : fichier ou chemin à exclure de unarchive
* extra_opt : options complémentaires
* group : groupe propriétaire
* keep_newer : garder le plus récent
* list_files : retourne la liste des fichiers de l'archive
* mode : permissions (0755, u+rwx,g+rx,o+rx)
* remote_src : passer par le host ansible pour pousser récupérer l'archive
* src : no > copy du fichier vers les cibles, yes > download et pousse
* unsafe_writes : éviter les corruptions de fichiers
* validate_certs : dans le cas de https (default yes)

exemple : https://github.com/prometheus/node_exporter/releases/download/v1.0.1/node_exporter-1.0.1.linux-amd64.tar.gz

Exemple26


* copy de la machine ansible et dezip sur la machine cible:

  - name: test unarchive    unarchive:      src: /tmp/node_exporter-1.0.1.linux-amd64.tar.gz      dest: /home/oki/


* avec url utilisation de remote_src

  - name: test unarchive    unarchive:      src: https://github.com/prometheus/node_exporter/releases/download/v1.0.1/node_exporter-1.0.1.linux-amd64.tar.gz      dest: /home/oki/      remote_src: yes


- name: unarchive /get url
  hosts: all
  become: yes
  tasks:
  - name: installation de tar unzip
    apt:
      name: "{{ pkg}}"
      update_cache: yes
      state: present
      cache_valid_time: 3600
    vars: 
      pkg:
      - tar 
      - unzip
  - name: test unarchive local
    unarchive:
      src: /tmp/zip.tgz
      dest: /home/samik/
  - name: test unarchive via https
    unarchive:
      src: https://github.com/prometheus/node_exporter/releases/download/v1.0.1/node_exporter-1.0.1.linux-amd64.tar.gz
      dest: /home/samik/
      remote_src: yes

  - name: dest locale puis dispatch
    get_url:
      url: https://github.com/prometheus/node_exporter/releases/download/v1.0.1/node_exporter-1.0.1.linux-amd64.tar.gz
      dest: /tmp/
      validate_certs: no
    delegate_to: localhost
    run_once: yes
  - name: dispatch
    unarchive:
      src: /tmp/node_exporter-1.0.1.linux-amd64.tar.gz
      dest: /tmp/



autre fichier:

- name: test unarchive/geturl
  hosts: all
  become: yes
  tasks:
  - name: test unarchive
    unarchive:
      src: /tmp/node_exporter-1.0.1.linux-amd64.tar.gz
      dest: /home/samik/
  - name: test unarchive
    unarchive:
      src: https://github.com/prometheus/node_exporter/releases/download/v1.0.1/node_exporter-1.0.1.linux-amd64.tar.gz
      dest: /home/samik/
      remote_src: yes
  - name: start haproxy service
    get_url:
      url: https://downloads.apache.org/tomcat/tomcat-10/v10.0.0-M9/bin/apache-tomcat-10.0.0-M9.tar.gz
      dest: /opt/tomcat8.tar.gz
      mode: 0755
      checksum: sha512:547ae280792b8684d11154f678584d0c4eb5af645cc8145e04da6de6d115b7bca03122191e6447cdb3497b85357181ca3fd9716d8a2dbc86461cf28f3df3ee91
      group: samik
      owner: samik


systemd

Documentation :

Objectifs : gestion des services systemd et reload

Documentation : https://docs.ansible.com/ansible/2.5/modules/systemd_module.html


PARAMETRES :
* daemon_reexec :
* daemon_reload : exécute un reload pour prendre en compte les changements de conf systemd
* enabled : active le démarrage au boot du service
* force : écraser les liens symboliques systemd
* masked : masquer l'unité systemd
* name : nom du service systemd
* no_block : ne pas attendre la fin de l'opération pour continuer
* scope: systemd manager pour un user ou l'ensemble des users
* state : started /stopped / reloaded / restarted
* user : deprecated

Exemple25


* le plus simple :

- name: Make sure a service is running  systemd:    name: haproxy    state: started

* arrêt
- name: Make sure a service is running  systemd:    name: haproxy    state: started

* activation au boot
- name: Make sure a service is running  systemd:    name: haproxy    state: started    enabled: yes


* exécuter avant si nécessaire un daemon-reload
- name: Make sure a service is running  systemd:    name: haproxy    state: started    enabled: yes    daemon-reload: yes

* s'assurer sa présence dans le list-units
- name: Make sure a service is running  systemd:    name: haproxy    state: started    enabled: yes    daemon-reload: yes    masked: no

* juste faire un daemon-reload
- name: Make sure a service is running  systemd:    daemon-reload: yes

handlers

flush des handlers

* attention quand jouer le trigger ? par defaut, il est joué toujours en fin de playbook, le flush permet de resetter en cours de PB.

  - name: Flush handlers    meta: flush_handlers
- name: Check if need to restart  stat:     path: /var/run/reboot.pending  register: __need_reboot  changed_when: __need_reboot.stat.exists  notify: reboot_server

exemple24

- name: premier playbook
  hosts: all
  become: yes
  vars:
   nginx_port: 8888
  tasks:
  - name: install nginx
    apt:
      name: nginx,curl
      state: present
      cache_valid_time: 3600
      update_cache: yes
  - name: remove default file
    file:
      path: "{{ item }}"
      state: absent
    with_items:
    - "/etc/nginx/sites-available/default"
    - "/etc/nginx/sites-enabled/default"

  - name: install vhost
    template:
      src: default_vhost.conf.j2
      dest: /etc/nginx/sites-available/default_vhost.conf
      owner: root
      group: root
      mode: 0644
    notify: reload_nginx ajout du handlers
  - name: activate vhost
    file:
      src: /etc/nginx/sites-available/default_vhost.conf
      dest: /etc/nginx/sites-enabled/default_vhost.conf
      state: link
  - name: start nginx
    systemd:
      name: nginx
      state: started

  handlers:
  - name: reload_nginx
    systemd:
      name: nginx
      state: reloaded

template

permet de creer un modele à déployer, à inclure en début de fichier:

exemple au début du fichier

#{{ template_run_date }} - "{{ ansible_managed }}" via {{ template_uid }}@{{ template_host }}

Sortie

[samik@samik-centos-1 ~]$ ls /tmp
hello.txt  hello_paul.txt  hello_pierre.txt  hello_xavier.txt

[samik@samik-centos-1 ~]$ cat /tmp/hell*
#2020-10-13 11:15:01.882949 - "Ansible managed" via samik@Abacus

hello samik !!!
#2020-10-13 11:25:41.160516 - "Ansible managed" via samik@Abacus
Hello samik !!!
je suis paul
j'ai 22

#2020-10-13 11:25:43.860866 - "Ansible managed" via samik@Abacus
Hello samik !!!
je suis pierre
j'ai 25

#2020-10-13 11:25:37.609008 - "Ansible managed" via samik@Abacus
Hello samik !!!
je suis xavier
j'ai 40
- name: preparation local
  hosts: all
  vars:
    var1: "samik !!!"
    var2:
      - { nom: "xavier", age: "40" }
      - { nom: "paul", age: "22" }
      - { nom: "pierre", age: "25" }
  tasks:
  - name: template
    template:
      src: montemplate.txt.j2
      dest: "/tmp/hello_{{ item.nom }}.txt"
    with_items:
    - "{{ var2 }}"
#{{ template_run_date }} - "{{ ansible_managed }}" via {{ template_uid }}@{{ template_host }}
Hello {{ var1 }}
je suis {{ item.nom }}
j'ai {{ item.age }}

#{{ template_run_date }} - "{{ ansible_managed }}" via {{ template_uid }}@{{{
     template_host }}
  2 Hello {{ var1 }}
  3 {% for personne in var2 %}
  4     je suis {{ personne.nom }}
  5     j'ai {{ personne.age }}
  6 {% endfor %}
  7

Fetch

permet de récupérer un fichier sur hote distant, ici test avec /etc/host

PB

- name: copie
  hosts: all
  become: yes
  tasks:
  - name: fetch
    fetch:
      src: /etc/hosts
      dest: /tmp/hosts_{{ ansible_hostname }}.txt
#      flat: yes

Exemple22

Avec le "flat":

samik@Abacus:~/ansible_dir(master⚡) » tree /tmp
/tmp
├── hosts_samik-centos-1.txt
└── hosts_samik-centos-2.txt

sans le "flat":

samik@Abacus:~/ansible_dir(master⚡) » tree /tmp
/tmp
├── hosts_samik-centos-1.txt
│   └── 172.17.0.2
│       └── etc
│           └── hosts
└── hosts_samik-centos-2.txt
    └── 172.17.0.3
        └── etc
            └── hosts

Exemples avec nginx

- name: preparation local
  connection: local
  hosts: localhost
  become: yes
  tasks:
  - name: install nginx
    apt:
      name: nginx
      state: present
  - name: clean
    file:
      path: "{{ item }}"
      state: absent
    with_fileglob:
    - /var/www/html/*.html
  - name: permission
    file:
      path: /var/www/html
      owner: samik
      recurse: yes
      state: directory

- name: recup des hosts
  become: yes
  hosts: all
  tasks:
  - name: fetch
    fetch:
      src: /etc/hosts
      dest: /var/www/html/hosts_{{ ansible_hostname }}.txt
      flat: yes

COPY

PARAMETRES :
* attributes : attributs du fichier
* backup : réalise une copie datée avant la copie
* checksum : vérification du ficheir via un hash
* content : dans le cas ou la source n'est pas un fichier mais une variable ou un string
* decrypt : déchiffre les fichiers si ils sont vaultés (défaut : yes)
* dest : localisation du fichier sur les serveurs target
* dicrectory_mode : dans le cas d'une recopie en mode récursif
* follow : indiquer le filesytème dans la destination
* force : remplace le fichier si il est différent de la source
* group : group propriétaire
* local_follow : indique le FS  dans la source
* mode : permissions du fichier ou du répertoire (0755, u+rwx,g+rx,o+rx)
* owner : user propriétiare
* remote_src : no > copie du master vers la target, yes > copie de la target vers la target
* src : localisation de la source* attention : roles / dir files / .
* unsafe_writes : éviter la corruption de fichier
validate : commande jouée pour valider le fichier avant de le copier (le fichier se situe %s)

Exemple20

- name: copie
  hosts: all
  become: yes
  tasks:
  - name: copy
    copy:
      src: "{{ item }}"
      dest: /tmp/
      backup: yes
    with_fileglob:
    - samik*

Exemple21

- name: copie
  hosts: all
  become: yes
  tasks:
  - name: copy
    copy:
      content: |
         Salut
         la team !!
         on est sur {{ ansible_hostname }}
      dest: /tmp/hello.txt

crée le fichier mais ne le modifie pas s'il existe ! un exemple avec sudoers
utilisation de validate:

   - name: Add devops user to the sudoers
     copy:
       dest: "/etc/sudoers.d/devops"
       content: "devops ALL=(ALL)  NOPASSWD: ALL"
       owner: root
       group: root
       mode: 0600
       validate: /usr/sbin/visudo -cf %s

Exemple17

- name: copie
  hosts: all
  become: yes
  tasks:
#  - name: copy
#    copy:
#      src: test.txt
#      dest: /tmp/samik.txt
#      force: no
  - name: copy
    copy:
      src: /tmp/
      dest: /tmp/

Exemple18

- name: copie
  hosts: all
  become: yes
  tasks:
#  - name: copy
#    copy:
#      src: test.txt
#      dest: /tmp/samik.txt
#      force: no
#  - name: copy
#    copy:
#      src: /tmp/
#      dest: /tmp/
   - name: copy
     copy:
      dest: /home/samik
      src: /tmp/samik
      remote_src: yes

Exemple19

* combinaison avec with_items

                            vars:    mesfichiers:      - { source: "xavki1.txt", destination: "/tmp/{{ ansible_hostname }}_xavki1.txt", permission: "0755" }      - { source: "xavki2.txt", destination: "/home/oki/{{ ansible_hostname }}_xavki2.txt", permission: "0644" }  tasks:  - name: copy    copy:      src: "{{ item.source }}"      dest: "{{ item.destination }}"      mode: "{{ item.permission }}"    with_items: "{{ mesfichiers }}"                        

Delegate, run_once, local

Exemple16

Objectifs : gérer les run locaux ou déléguer des tâches* primaire/secondaire


* delegate_to : déléguer une tache à un autre serveur identifié

- name: premier playbook  hosts: all  tasks:  - name: création de fichier    file:      state: touch      path: /tmp/xavki.txt    delegate_to: localhost

Rq : attention au nombre d'itération si plusieurs serveurs


* quelles variables ?

- name: premier playbook  hosts: all  tasks:  - name: debug    debug:      var: var1  - name: debug    debug:      var: var1    delegate_to: localhost

ssh

PARAMETRES : openssh_keypair

* attibutes : attributs des fichiers (non supprimable etc)
* comment : commentaire de la clef
* force : regénère la clef si elle existe déjà
* group : group propriétaire des fichiers
* mode : permisssions (cf file, 0600, u+rw)
* owner : propirétaire
* path : localisation des clefs (attention sécurité de la clef privée)
* regenerate : never / fail / partial_idempotence (si non conforme) / full_idempotence (et si non lisible) / always
* size : taille de la clef
* state : present/absent
* type : rsa / dsa / rsa1 / ecdsa / ed25519
* unsafe_writes : prévenir les corruptions de fichiers

Rq : si password / clef cassé > force : yes

exemple15

- name: ajout de clef ssh et de user
  hosts: all
  tasks:
  - name: generate SSH key"
    openssh_keypair:
      path: /tmp/devops
      type: rsa
      size: 4096
      mode: 0600
      state: present
      force: no
    run_once: yes
    delegate_to: localhost
  - name: création du group sudo
    group:
      name: sudo
    become: yes
  - name: création du user devops
    user:
      name: devops
      shell: /bin/bash
      groups: sudo
      append: yes
      password: "{{ 'password' | password_hash('sha512') }}"
    become: yes
  - name: Add devops user to the sudoers
    copy:
      dest: "/etc/sudoers.d/devops"
      content: "devops  ALL=(ALL)  NOPASSWD: ALL"
    become: yes
  - name: Deploy SSH Key
    authorized_key:
      user: devops
      key: "{{ lookup('file', '/tmp/devops.pub') }}"
      state: present
    become: yes

Reboot

l'inventory:


ansible-inventory -i VCS_inventory.yml --graph             2 ↵
@all:
  |--@centos:
  |  |--192.168.100.101
  |  |--192.168.100.102
  |--@ungrouped:

exemple14

- name: ajout de patch & reboot
  hosts: centos
  become: yes
  remote_user: vagrant
  tasks:
  - name: Upgrade all packages, excluding kernel & foo related packages
    yum:
      name: '*'
      update_cache: yes
      state: latest
      exclude: kernel*,foo*
  - name: vérification à partir du fichier reboot_required
    register: reboot_required_file
    stat:
      path: /var/run/reboot-required


  - name: lancement du reboot avec reboot
    reboot:
      msg: "Reboot via ansible"
      connect_timeout: 5
      reboot_timeout: 300
      pre_reboot_delay: 0
      post_reboot_delay: 10
      test_command: uptime
    when: reboot_required_file.stat.exists

exemple13

- name: ajout de patch & reboot
  hosts: centos
  become: yes
  remote_user: vagrant
  tasks:
  - name: create file
    file:
      path: /tmp/samik.txt
      state: touch
  - name: test
    stat:
      path: /tmp/samik.txt
    register: __file_exist


  - name: lancement du reboot avec reboot
    reboot:
      msg: "Reboot via ansible"
      connect_timeout: 5
      reboot_timeout: 300
      pre_reboot_delay: 0
      post_reboot_delay: 10
      test_command: uptime
    when: __file_exist.stat.exists
  - name: create file2
    file:
      path: /tmp/reboot_ok.txt
      state: touch

yum

exemple3

ici, traitement des 2 type d'OS : debian et Centos, l'inventory:



ansible-inventory -i 00_inventory.yml --graph
@all:
  |--@centos:
  |  |--172.17.0.7
  |  |--172.17.0.8
  |--@debian:
  |  |--172.17.0.2
  |  |--172.17.0.3
  |  |--172.17.0.4
  |  |--172.17.0.5
  |  |--172.17.0.6
  |--@gp1:
  |  |--172.17.0.2
  |--@ungrouped:

- name: ajout de pkg dans les cont
  hosts: debian
  become: yes
  tasks:
#  - name: tree
#    apt:
#      name: tree
#      autoclean: yes
#      update_cache: yes
#      cache_valid_time: 3600
#      state: latest
  - name: multi pack
    apt:
      name: "{{ packs }}"
      autoclean: yes
      update_cache: yes
      cache_valid_time: 3600
      state: latest
    vars:
      packs:
      - zsh
      - openssh-server
- name: ajout sur centos
  hosts: centos
  become: yes
  tasks:
  - name: multi pack
    yum:
      name: "{{ packs }}"
      update_cache: yes
      state: latest
    vars:
      packs:
      - zsh
      - tree

exemple12

- name: ajout de pkg dans les cont
  hosts: all
  become: yes
  tasks:
  - name: tree
    apt:
      name: tree
      autoclean: yes
      update_cache: yes
      cache_valid_time: 60
      state: latest
  - name: multi pack
    apt:
      name: "{{ packs }}"
      autoclean: yes
      update_cache: yes
      cache_valid_time: 60
      state: latest
    vars:
      packs:
      - zsh
      - openssh-server

with_items

Conditionner les taches d'Ansible


A noter: le dico est dans group vars:

 » tree
.
├── 00_inventory.yml
├── ansible_dir
│   ├── 00_inventory.yml
│   ├── group_vars
│   └── host_vars
├── group_vars
│   ├── all.yml
│   └── common
│       └── params.yml


» cat group_vars/all.yml
mondico:
- { dir: "xavki1", file: "fichierA"}
- { dir: "xavki2", file: "fichierB"}
- { dir: "xavki3", file: "fichierC"}
- { dir: "xavki4", file: "fichierD"}

Exemple11

ici, on créé un rep aves comme item le nom du serveur appartenant à gp1:
ansible-inventory -i 00_inventory.yml --graph
@all:
  |--@gp1:
  |  |--172.17.0.2
  |--@ungrouped:
  |  |--172.17.0.3
  |  |--172.17.0.4
  |  |--172.17.0.5
  |  |--172.17.0.6

- name: pb avec boucle
  hosts: all
  become: yes
  tasks:
#  - name: ajout de tree
 #   apt:
  #    name: tree
   #   state: present
  - name: modification shell  de samik
    user:
      name: samik
      state: present
      shell: /bin/bash
  - name: boucle création de répertoire
    file:
      path: /tmp/samik/{{ item }}
      state: directory
      recurse: yes
    with_inventory_hostnames:
    - gp1

Exemple10

ANSIBLE : With Item et boucles


* version condensée
  vars:    fichiers:    - { dir: "xavki1", file: "fichierA"}    - { dir: "xavki2", file: "fichierB"}    - { dir: "xavki3", file: "fichierC"}    - { dir: "xavki4", file: "fichierD"}  tasks:  - name: création de fichiers    file:      path: /tmp/xavki/{{ item.dir }}/{{ item.file }}      state: touch    with_items:    - "{{ fichiers }}"

* parcourir une liste de machines de l'inventaire
 with_items:    - "{{ groups['all'] }}"

* en version plus simple :
  - name: création de fichiers    file:      path: /tmp/{{ item }}      state: touch    with_inventory_hostnames:    - all

exemple9


- name: pb avec boucle
  hosts: all
  become: yes
  tasks:
  - name: ajout de tree
    apt:
      name: tree
      state: present
  - name: modification shell  de samik
    user:
      name: samik
      state: present
      shell: /bin/bash
  - name: boucle création de répertoire
    file:
      path: /tmp/samik/{{ item }}
      state: directory
      recurse: yes
    with_items:
    - samik1
    - samik2
    - samik3
    - samik4

  - name: création de fichiers
    file:
      path: /tmp/xavki/{{ item.dir }}/{{ item.file }}
      state: touch
    with_items: "{{ mondico }}"

register & stat

exemple7

* récupération d'une clef

  - name: debug    debug:      var: __fichier_xavki.stat.exists

* utilisation conditionnnel
  - name: création répertoire xavki    file:      path: /tmp/xavki      state: directory    when: __fichier_xavki.stat.exists

* exemple:
  tasks:  - name: création d'un fichier    file:      path: /tmp/xavki.txt      state: touch      owner: root    when: xavki_file is defined  - name: check avec stat    stat:      path: /tmp/xavki.txt    register: __fichier_xavki  - name: debug    debug:      var: __fichier_xavki.stat.exists  - name: création répertoire xavki    file:      path: /tmp/xavki      state: directory    when: __fichier_xavki.stat.exists and xavki_file is defined

exemple8

playbook

 cat   playbook.yml

- name: abacus premier  Playbook
  hosts: all
  become: yes
  tasks:
  - name: creation du fichier
    file:
      path: /tmp/samik.txt
      state: touch
      mode: 0755
  - name: test de stat
    stat:
      path: /tmp/samik.txt
    register: __outdestat
  - name : affiche stat complet
    debug:
      var: __outdestat
  - name : affiche stat
    debug:
      var: __outdestat.stat.exists
  - name: création répertoire samik
    file:
     path: /tmp/samik
     state: directory
    when: __outdestat.stat.exists 

.stat.exists correspond au champ que l'on veut extraire pour la condition, cf le fichier de sortie.

sortie

ansible-playbook -i 00_inventory.yml   playbook.yml



PLAY [abacus premier  Playbook] ***********************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************
ok: [172.17.0.4]
ok: [172.17.0.6]
ok: [172.17.0.3]
ok: [172.17.0.2]
ok: [172.17.0.5]

TASK [creation du fichier] ****************************************************************************************************
changed: [172.17.0.6]
changed: [172.17.0.4]
changed: [172.17.0.2]
changed: [172.17.0.3]
changed: [172.17.0.5]

TASK [test de stat] ***********************************************************************************************************
ok: [172.17.0.6]
ok: [172.17.0.5]
ok: [172.17.0.2]
ok: [172.17.0.3]
ok: [172.17.0.4]

TASK [affiche stat complet] ***************************************************************************************************
ok: [172.17.0.6] => {
    "__outdestat": {
        "changed": false,
        "...


        ...
            "xusr": true
        }
    }
}
ok: [172.17.0.2] => {
    "__outdestat": {
        "changed": false,
        "failed": false,
        "stat": {
            "atime": 1602086939.4785962,
            "attr_flags": "",
            "attributes": [],
            "block_size": 4096,
            "blocks": 0,
            "charset": "unknown",
            "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
            "ctime": 1602086939.4785962,
            "dev": 48,
            "device_type": 0,
            "executable": true,
            "exists": true,
            "gid": 0,
            "gr_name": "root",
            "inode": 288270,
            "isblk": false,
            "ischr": false,
            "isdir": false,
            "isfifo": false,
            "isgid": false,
            "islnk": false,
            "isreg": true,
            "issock": false,
            "isuid": false,
            "mimetype": "unknown",
            "mode": "0755",
            "mtime": 1602086939.4785962,
            "nlink": 1,
            "path": "/tmp/samik.txt",
            "pw_name": "root",
            "readable": true,
            "rgrp": true,
            "roth": true,
            "rusr": true,
            "size": 0,
            "uid": 0,
            "version": null,
            "wgrp": false,
            "woth": false,
            "writeable": true,
            "wusr": true,
            "xgrp": true,
            "xoth": true,
            "xusr": true
        }
    }
}

TASK [affiche stat] ***********************************************************************************************************
ok: [172.17.0.6] => {
    "__outdestat.stat.exists": true
}
ok: [172.17.0.5] => {
    "__outdestat.stat.exists": true
}
ok: [172.17.0.4] => {
    "__outdestat.stat.exists": true
}
ok: [172.17.0.3] => {
    "__outdestat.stat.exists": true
}
ok: [172.17.0.2] => {
    "__outdestat.stat.exists": true
}

TASK [création répertoire samik] **********************************************************************************************
ok: [172.17.0.6]
ok: [172.17.0.4]
ok: [172.17.0.5]
ok: [172.17.0.3]
ok: [172.17.0.2]

PLAY RECAP ********************************************************************************************************************
172.17.0.2                 : ok=6    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
172.17.0.3                 : ok=6    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
172.17.0.4                 : ok=6    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
172.17.0.5                 : ok=6    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
172.17.0.6                 : ok=6    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

exemple6

* création d'un fichier

  - name: création d'un fichier    file:      path: /tmp/xavki.txt      state: touch      owner: xavki

* utilisation de stat
  - name: check avec stat    stat:      path: /tmp/xavki.txt

* récupération de la variable
  - name: check avec stat    stat:      path: /tmp/xavki.txt    register: __fichier_xavki_exist  - name: debug    debug:      var: __fichier_xavki

user

Equivalence : useradd/adduser/userdel/deluser/luseradd

exemple5

- name: création de xavki
  user:
    name: xavki
    state: present
    uid: 1200
    groups: sudo
    append: yes
    generate_ssh_key: yes
    password: "{{ 'password' | password_hash('sha512') }}"

- name: création du user xavki
  user:
    name: xavki
    state: present
    generate_ssh_key: yes
    uid: 1200
    groups: sudo
    append: yes
    password: "{{ 'password' | password_hash('sha512') }}"
  register: mavar
- name: debug
    debug:
      msg: "{{ mavar }}"

- name: suppression du user xavki
  user:
    name: xavki
    state: absent

examples4

* création d'un user avec password

- name: création de xavki  user:    name: xavki    state: present    password: "{{ 'password' | password_hash('sha512') }}"   

* ajout au groupe sudo
- name: création de xavki  user:    name: xavki    state: present    groups: sudo    append: yes    password: "{{ 'password' | password_hash('sha512') }}"   

file

exemple3:

* touch avec idempotence

  - name: touch idempotent    file:      path: /tmp/xavki.txt      state: touch      mode: 0755      modification_time: preserve      access_time: preserve

* à l'inverse
  - name: touch sans idempotence    file:      path: /tmp/xavki/1/2/3      state: touch      mode: 0755      modification_time: now      access_time: now

exemple2: file


* modification du groupe et des droits (RWX-RX-RX - 0755) | stat

- name: création du répertoire /tmp/xavki  file:    path: /tmp/xavki/    state: directory    owner: root    group: root    mode: 0755  become: yes

* récursivité (pour directory uniquement
  - name: création du répertoire /tmp/xavki    file:      path: /tmp/xavki/1/2/3/4      recurse: yes      state: directory      owner: root      group: root      mode: 0755

  - name: création du répertoire /tmp/xavki    file:      path: /tmp/xavki/1/2/3/4/fichier.txt      state: touch      owner: root      group: root      mode: 0755

suite...

* lien symbolique = lien vers fichier (diff avec hardlink = lien vers inode)

  - name: création du répertoire /tmp/xavki    file:      src: /tmp/xavki/1/2/3/4/      dest: /tmp/symlink      state: link  #hard      owner: root      group: root      mode: 0755

Rq: idempotence


* suppression de fichier

  - name: dir sans idempotence    file:      path: /tmp/xavki.txt      state: absent

* suppression de répertoire récursive
  - name: dir sans idempotence    file:      path: /tmp/xavki/      state: absent

structure

l'indentation est importante (python oblige !)

-name: titre de l'action

hosts: all

-become: yes

 - name: abacus premier  Playbook
   2   │   hosts: all
   3   │   become: yes

tasks:

exemples

- name: Mon Playbook !!  hosts: all  remote_user: vagrant  become_user: yes  tasks:  - name: je debug    debug:      msg: "{{ var1 }}"

Exécution

ansible-playbook exemple_playbook.yml


PLAY [copie du fichier master.gitconfig] *************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************
[WARNING]: Platform linux on host kaisenlinux is using the discovered Python interpreter at /usr/bin/python, but future
installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [kaisenlinux]
ok: [localhost]

TASK [copy] ******************************************************************************************************************
changed: [kaisenlinux]
ok: [localhost]

PLAY [mise à jour des packets désirés brew] **********************************************************************************

TASK [Gathering Facts] *******************************************************************************************************
[WARNING]: Platform linux on host abacus is using the discovered Python interpreter at /usr/bin/python, but future
installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
ok: [abacus]
ok: [kaisenlinux]
fatal: [nexus]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host nexus port 2222: Operation timed out", "unreachable": true}
fatal: [ipadkris]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host ipadkris port 22: Operation timed out", "unreachable": true}

TASK [homebrew] **************************************************************************************************************
fatal: [abacus]: FAILED! => {"changed": false, "msg": "Failed to find required executable brew in paths: /usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/games:/sbin:/usr/sbin:/usr/local/sbin"}
fatal: [kaisenlinux]: FAILED! => {"changed": false, "msg": "Failed to find required executable brew in paths: /usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/games:/sbin:/usr/sbin:/usr/local/sbin"}

PLAY RECAP *******************************************************************************************************************
abacus                     : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
ipadkris                   : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0
kaisenlinux                : ok=3    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
nexus                      : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0

CLI
gather facts

ansible all -m gather_facts --tree /tmp/facts

# Display facts from all hosts and store them indexed by I(hostname) at C(/tmp/facts).


exemple

ansible all -m gather_facts -a "filter=ansible_distribution"  |head


[WARNING]: Platform linux on host node5 is using the discovered Python interpreter at /usr/bin/python3.7, but future
installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
node5 | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "Debian",
        "discovered_interpreter_python": "/usr/bin/python3.7"
    },
    "changed": false,
    "deprecations": []
}

ansible -i "node2," all -m gather_facts -a "filter=ansible_distribution*"

fetch

récupérer un fichier

ansible -i "node2," all -m fetch -a 'src=/tmp/titi.txt dest=xavki.txt flat=yes'

flat = fichier plat


copy

idem scp

ansible -i "node2," all -m copy -a 'src=toto.txt dest=/tmp/titi.txt'

service

ansible -i "node2," all -b -m service -a 'name=nginx state=stopped'

apt

ansible -i "node2," all -b -m apt -a 'name=nginx state=latest'

raw

ansible -i 00_inventory.yml centos -b -m raw -a "yum install python38 -y "

utile lorsque python n'est pas installé sur le serveur/conteneur

ansible -i "node2," all -u vagrant -b -K -m raw -a "apt install -y git"

debug

ansible all -b -e "var1=xavki" -m debug -a 'msg={{ var1 }}'

détail:

-i "node2," = dans le groupe All , prendre en compte le node2 seul
-b = "become" = élévation des droits
-e = passage de la variable en cli
-m = le module utilisé (ici debug)
-a = l'argument associé au module
shell

ansible -i "node2," all -u vagrant -m shell -a "ps aux | grep vagrant | wc -l" --one-line

detail:

-m = module shell 
-a = argument "ps aux | grep vagrant | wc -l" 
--one-line = sortie sur une ligne
command

ansible -i "node2," all -u vagrant -m command -a uptime

ping

ansible all -m ping

(test simple de fonctionnement)

imackris | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname imackris: nodename nor servname provided, or not known",
    "unreachable": true
}
[WARNING]: Platform linux on host abacus is using the discovered Python interpreter at /usr/bin/python,
but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more
information.
abacus | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
[WARNING]: Platform linux on host kaisenlinux is using the discovered Python interpreter at
/usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more
information.
kaisenlinux | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
[WARNING]: Platform darwin on host imacpat is using the discovered Python interpreter at
/usr/bin/python, but future installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more
information.
imacpat | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
mbp | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host mbp port 22: Operation timed out",
    "unreachable": true
}
nexus | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host nexus port 2222: Operation timed out",
    "unreachable": true
}
ipadkris | UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: ssh: connect to host ipadkris port 22: Operation timed out",
    "unreachable": true
}

Exemple

ansible all -i "localhost," -m debug -a "msg='Hello Ansible'"

-i

inventory

fichier inventaire

defini les nodes impactés,
ex:
[gp_patricia]
mbp
imacpat
[gp_kris]
kaisenlinux
abacus
nexus
ipadkris


Fichiers de configuration

plusieurs lieux possible, défini par ordre de priorité


* exemple :
inventory       = /etc/ansible/hostsforks           = 5sudo_user       = rootask_sudo_pass   = Trueask_pass        = Truegathering       = implicitgather_subset   = allroles_path      = /etc/ansible/roleslog_path        = /var/log/ansible.logvault_password_file = /path/to/vault_password_filefact_caching_connection =/tmppipelining = False
Commande
ansible-config
ansible-config
usage: ansible-config [-h] [--version] [-v] {list,dump,view} ...
ansible-config: error: the following arguments are required: action

usage: ansible-config [-h] [--version] [-v] {list,dump,view} ...

View ansible configuration.

positional arguments:
  {list,dump,view}
    list            Print all config options
    dump            Dump configuration
    view            View configuration file

optional arguments:
  --version         show program's version number, config file location, configured module search path, module location,
                    executable location and exit
  -h, --help        show this help message and exit
  -v, --verbose     verbose mode (-vvv for more, -vvvv to enable connection debugging)

view

ansible-config view|head -20

# Example config file for ansible -- https://ansible.com/
# =======================================================

# Nearly all parameters can be overridden in ansible-playbook
# or with command line flags. Ansible will read ANSIBLE_CONFIG,
# ansible.cfg in the current working directory, .ansible.cfg in
# the home directory, or /etc/ansible/ansible.cfg, whichever it
# finds first

# For a full list of available options, run ansible-config list or see the
# documentation: https://docs.ansible.com/ansible/latest/reference_appendices/config.html.

[defaults]
inventory       = $HOME/hosts
#library         = ~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
#module_utils    = ~/.ansible/plugins/module_utils:/usr/share/ansible/plugins/module_utils
remote_tmp      = .ansible/tmp
local_tmp       = ~/.ansible/tmp
#forks           = 5
#poll_interval   = 0.001

depend de l'emplacement

astuce pour localiser le fichier config pris en compte:


ansible -v imac -m ping


Using /Users/samik/.ansible.cfg as config file
...

list

ansible-config list|head -20

ACTION_WARNINGS:
  default: true
  description:
  - By default Ansible will issue a warning when received from a task action (module
    or action plugin)
  - These warnings can be silenced by adjusting this setting to False.
  env:
  - name: ANSIBLE_ACTION_WARNINGS
  ini:
  - key: action_warnings
    section: defaults
  name: Toggle action warnings
  type: boolean
  version_added: '2.5'
AGNOSTIC_BECOME_PROMPT:
  default: true
  description: Display an agnostic become prompt instead of displaying a prompt containing
    the command line supplied become method
  env:
  - name: ANSIBLE_AGNOSTIC_BECOME_PROMPT
lieu du playbook
ansible.cfg
/etc/ansible
defini par variable
ANSIBLE_CONFIG
dossier de base USER
~/.ansible/ansible.cfg

.ansible

ll -R $HOME/.ansible*
-rw-r--r--  1 samik  staff    19K  3 mai 11:31 /Users/samik/.ansible.cfg

/Users/samik/.ansible:
total 0
drwx------  2 samik  staff    64B 12 aoû 18:30 cp
drwx------  2 samik  staff    64B 12 aoû 18:29 tmp

/Users/samik/.ansible/cp:

/Users/samik/.ansible/tmp:

.ansible.cfg

egrep -v "#|^$" /Users/samik/.ansible.cfg
[defaults]
inventory       = $HOME/hosts
remote_tmp      = .ansible/tmp
local_tmp       = ~/.ansible/tmp
nocows = 1
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[sudo_become_plugin]
[selinux]
[colors]
[diff]

head -20 /Users/samik/.ansible.cfg
# Example config file for ansible -- https://ansible.com/
# =======================================================

# Nearly all parameters can be overridden in ansible-playbook
# or with command line flags. Ansible will read ANSIBLE_CONFIG,
# ansible.cfg in the current working directory, .ansible.cfg in
# the home directory, or /etc/ansible/ansible.cfg, whichever it
# finds first

# For a full list of available options, run ansible-config list or see the
# documentation: https://docs.ansible.com/ansible/latest/reference_appendices/config.html.

[defaults]
inventory       = $HOME/hosts
#library         = ~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
#module_utils    = ~/.ansible/plugins/module_utils:/usr/share/ansible/plugins/module_utils
remote_tmp      = .ansible/tmp
local_tmp       = ~/.ansible/tmp
#forks           = 5
#poll_interval   = 0.001