Herramientas de usuario

Herramientas del sitio


wiki2:ansible

Ansible básico

Lets skim it

Inventory: fichero en /etc u otro independiente donde se guarda una lista de hosts a los que ansible va a acceder.

Modulo: utilidad dentro de Ansible para realizar unas tareas concretas en el host.

Playbook: conjunto de instrucciones para que Ansible ejecute en el host indicado. Se escriben en YAML.

Tasks: las instrucciones a ejecutar dentro del playbook.

Ansible Galaxy: Módulos\playbooks no oficiales.

El parámetro -b (become) hace que se ejecute como root. Para que nos pida la contraseña usaremos el parámetro -K.

Para ejecutar pequeños comandos independientes usaremos el comando ansible.

Para ejecutar un playbook usaremos ansible-playbook.

-i hosts.txt indica qué fichero de hosts usar.

Por defecto Ansible lanzará los comandos en remoto como el usuario que estés en local.

Puedes poner archivos de configuración como ansible.cfg en el directorio donde trabajes, .ansible.cfg en tu home o /etc/ansible/ansible.cfg.

Los handlers son notificaciones dentro de un playbook que se ejecutarán si ocurre algo con una task.

First steps and terms

Install and config

sudo apt-get install ansible
sudo cp /etc/ansible/hosts /etc/ansible/hosts.org

Edit the /etc/ansible/hosts.org file. Now you can check if the configuration was okay:

ansible all -m ping

Note: Python software should be installed on the target machine.

Connect without pem

ansible all -m ping -u alfred -k
  • -u <username> to set the username of the connection.
  • -k for asking the password.

Use modules

Modules let you to launch personalized commands on the target system.

Modules list

Parameters:

  • -b (become) to use sudo, for asking for password -K.
  • -m <module> exec that module.
  • -a '<arguments>' arguments for the module

apt

Install nginx

ansible all -b -K -m apt -a 'pkg=nginx state=installed update_cache=true'

Inside a playbook:

- name: Install Server Basics
  apt: pkg={{ item }} state=installed update_cache=true
  with_items:
    - acl
    - unattended-upgrades
    - policykit-1
    - ntp
    - wget
    - curl
    - vim
    - ack-grep
    - git
    - unzip
    - htop
    - tmux

copy

- copy:
    src: "{{ item }}"
    dest: /etc/fooapp/
    owner: root
    mode: 600
  with_fileglob:
    - /playbooks/files/fooapp/*
- name: Your copy task
  copy: src={{ item.src }} dest={{ item.dest }}
  with_items:
    - { src: 'containerizers', dest: '/etc/mesos/containerizers' }
    - { src: 'another_file', dest: '/etc/somewhere' }
    - { src: 'dynamic', dest: '{{ var_path }}' }
- name: Copy multiple files to multiple directories
  copy: src={{ item.0 }} dest={{ item.1 }}
  with_together:
    - [ 'file1', 'file2', 'file3' ]
    - [ '/dir1/', '/dir2/', '/dir3/' ]

shell

ansible all -b -m shell -a 'apt-get install nginx'

Playbooks

You will have a playbook file example.yml, to run it: ansible-playbook example.yml -b -K -u alfred -k.

Structure:

---
- hosts: <hosts group to launch>
  tasks:
   - name: <title for the task>   
     <module>: <parameters>

Examples:

---
- hosts: local
  tasks:
   - name: Install Nginx
     apt: pkg=nginx state=installed update_cache=true

We can use Playbooks to run multiple Tasks, add in variables, define other settings and even include other playbooks.

Handlers

You can add handlers, which are tasks that will be automatically launched when an event occours. You only need to add this section:

  handlers:
   - name: <identifier>
     <module>: <parameters>

Notifiers are only run if the Task is run. For example, if I already had Nginx installed, an “Install Nginx” task would not be run and the notifier would not be called.

Example:

---
- hosts: local
  tasks:
   - name: Install Nginx
     apt: pkg=nginx state=installed update_cache=true
     notify:
      - Start Nginx

  handlers:
   - name: Start Nginx
     service: name=nginx state=started

Variables

- hosts: local
  vars:
   - docroot: /var/www/serversforhackers.com/public
...
   - name: Create Web Root
     when: nginxinstalled|success
     file: dest={{ '{{' }} docroot {{ '}}' }} mode=775 state=directory owner=www-data group=www-data
     notify:
      - Reload Nginx

If you are not quoting an argument that starts with a variable will throw an error. For example,

vars: 
   age_path: {{vivek.name}}/demo/ 
   
{{vivek.name}} 

The right one would be:

vars: 
   age_path: "{{vivek.name}}/demo/"

Roles

It's like a playbook but divided in several directories and files, each one with a file main.yml. In those files we can add whatever is required into that role:

  • files: For files that we'll want copied into our servers.
  • handlers: For thase Handlers that were once within the Playbook.
  • meta: For dependencies.
  • templates: For Jinja2 templates.
  • tasks: For the tasks list.
  • vars: For a variables list.

We need to configure ansible to tell it where to run the roles. For that we will use the file /etc/ansible/ansible.cfg. For example, nginx Role located at /vagrant/ansible/roles/nginx will be configured as:

roles_path    = /vagrant/ansible/roles

Then, to run it we will create the file server.yml:

---
- hosts: all
  roles:
    - nginx

And to run them:

ansible-playbook -b server.yml

Facts

They are variables that Ansible gather from the target system, such as the number of CPU cores, available ipv4 and ipv6 networks, mounted disks, Linux distribution and more.

Facts are often useful in Tasks or Template configurations. For example Nginx is commonly set to use as any worker processors as there are CPU cores.

user www-data www-data;
worker_processes {{ ansible_processor_cores }};
pid /var/run/nginx.pid;

Ansible facts all start with ansible_ and are globally available for use any place variables can be used: Variable files, Tasks, and Templates.

To access all the facts:

ansible hostname -m setup

Then:

{{ ansible_facts["eth0"]["ipv4"]["address"] }}

OR alternatively:

{{ ansible_facts.eth0.ipv4.address }}

You can disable facts:

- hosts: whatever
  gather_facts: no

Vaults

To put encrypted information that will be used on the playbooks.

Use Ansible Vault to encrypt secure data, making it more safe if your playbooks or Roles end up in version control or are otherwise shared.

Tips and tricks

Become

---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_user: postgres

You can also use other privilege escalation methods, like su:

---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_method: su

Ansible command

Version

ansible --version

List hosts

ansible --list-hosts all
ansible -i development.txt --list-hosts all
 ansible --list-hosts webserver

Check connection

ansible -m ping all

Send commands

 ansible -m command -a "ls" all

Environment variables

For using local environment variables:

- debug: msg="{{ lookup('env','HOME') }} is an environment variable"

In this way you can set variables:

- hosts: all
  vars:
    local_shell:  "{{ lookup('env','SHELL') }}"
  tasks:
    - debug:
        msg: "{{ local_shell }}"

output
------
"msg": "/bin/sh"

For targetting proxies

- hosts: all
  remote_user: root
  tasks:
    - apt: name=cobbler state=installed
      environment:
        http_proxy: http://proxy.example.com:8080

The environment can also be stored in a variable, and accessed like so:

- hosts: all
  remote_user: root
  # here we make a variable named "proxy_env" that is a dictionary
  vars:
    proxy_env:
      http_proxy: http://proxy.example.com:8080
  tasks:
    - apt: name=cobbler state=installed
      environment: "{{proxy_env}}"

You can also use it at a play level:

- hosts: testhost
  roles:
     - php
     - nginx
  environment:
    http_proxy: http://proxy.example.com:8080

Passing variables on the command line

In addition to vars_prompt and vars_files, it is possible to set variables at the command line using the --extra-vars (or -e) argument.

ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"

It also allows to set in JSON format:

ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}'
ansible-playbook arcade.yml --extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'

Also in YAML string format:

ansible-playbook release.yml --extra-vars '
version: "1.23.45"
other_variable: foo'

ansible-playbook arcade.yml --extra-vars '
pacman: mrs
ghosts:
- inky
- pinky
- clyde
- sue'

Even vars from a JSON or YAML file:

ansible-playbook release.yml --extra-vars "@some_file.json"

Executing locally

local_action is an alternative way of doing delegate_to: localhost.

Troubleshooting

Yaml does not support tab based indentation and supports space based indentation, so one needs to be careful about the same.

Use verbose mode with ansible command parameters -v -vv.

Use modules 'debug' and 'register'

Notes

Inventory variables

[localhost]
127.0.0.1 variable1=value1 variable2=value2

[webservers]
webserver.awesomecompany.ly ansible_ssh_host=55.44.33.22

Split a command

You can split this…

  - name: Find geographical region of this server
    local_action: uri url=http://locator/studio/{{ ansible_default_ipv4.address}} method=GET return_content=yes register=locator_output

… in this:

- name: Find geographical region of this server
  uri:
    url: http://locator/studio/{{ ansible_default_ipv4.address}}
    method: GET
    return_content: yes
  register: locator_output
  delegate_to: localhost

Playbooks examples

---
- hosts: local
  vars:
   - docroot: /var/www/serversforhackers.com/public
  tasks:
   - name: Add Nginx Repository
     apt_repository: repo='ppa:nginx/stable' state=present
     register: ppastable

   - name: Install Nginx
     apt: pkg=nginx state=installed update_cache=true
     when: ppastable|success
     register: nginxinstalled
     notify:
      - Start Nginx

   - name: Create Web Root
     when: nginxinstalled|success
     file: dest={{ '{{' }} docroot {{ '}}' }} mode=775 state=directory owner=www-data group=www-data
     notify:
      - Reload Nginx

  handlers:
   - name: Start Nginx
     service: name=nginx state=started

    - name: Reload Nginx
      service: name=nginx state=reloaded
--- 
   name: install and configure DB
   hosts: testServer
   become: yes

   vars: 
      oracle_db_port_value : 1521
   
   tasks:
   -name: Install the Oracle DB
      yum: <code to install the DB>
    
   -name: Ensure the installed service is enabled and running
   service:
      name: <your service name>

Setting the become and hosts in the header:

---
- name: Install nginx
  hosts: host.name.ip
  become: true

  tasks:
  - name: Add epel-release repo
    yum:
      name: epel-release
      state: present

  - name: Install nginx
    yum:
      name: nginx
      state: present

  - name: Insert Index Page
    template:
      src: index.html
      dest: /usr/share/nginx/html/index.html

  - name: Start NGiNX
    service:
      name: nginx
      state: started

Multiple plays:

---
- hosts: webservers
  remote_user: root

  tasks:
  - name: ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf

- hosts: databases
  remote_user: root

  tasks:
  - name: ensure postgresql is at the latest version
    yum:
      name: postgresql
      state: latest
  - name: ensure that postgresql is started
    service:
      name: postgresql
      state: started

A right one:

--- 
- hosts: puma
  gather_facts: no
  become: yes
  name: Deploy PUMA
  tasks:
  - name: Send Docker images
    debug: msg="hola"

  - name: Load Docker images
    debug: msg="{{ lookup('env','HOME') }} is an environment variable"

  - name: Start PUMA
    debug: msg="{{ lookup('env','HOME') }} is an environment variable"
  
#    copy:
#     src: "{{ item }}"
#     dest: ~
#     owner: root
#     mode: 600
#    with_fileglob:
#     - ../dist/*
wiki2/ansible.txt · Última modificación: 2020/05/09 09:25 (editor externo)