Herramientas de usuario

Herramientas del sitio


informatica:ciberseguridad:cursos:curso_ansible_automatizacion_it:conceptos_avanzados

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
informatica:ciberseguridad:cursos:curso_ansible_automatizacion_it:conceptos_avanzados [2023/05/08 17:56] – [Tareas, Plays y Playbooks I] tempwininformatica:ciberseguridad:cursos:curso_ansible_automatizacion_it:conceptos_avanzados [2023/05/08 21:32] (actual) – [Templates I] tempwin
Línea 143: Línea 143:
   * Deben comenzar con letra   * Deben comenzar con letra
   * Pueden contener letras, números y guiones bajos.   * Pueden contener letras, números y guiones bajos.
 +
 ===== Tareas, Plays y Playbooks I ===== ===== Tareas, Plays y Playbooks I =====
  
Línea 206: Línea 207:
 </WRAP> </WRAP>
  
-Ejemplo de nuestro primer playbook:+Ejemplo de nuestro primer playbook (''primer_playbook.yaml''):
  
 <code yaml> <code yaml>
Línea 222: Línea 223:
 Lo ejecutamos: Lo ejecutamos:
  
-<code yaml>+<code>
 ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml
 +</code>
 +
 +También podríamos añadirle la opción ''-v'' para obtener más información de la salida:
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -v
 </code> </code>
  
Línea 237: Línea 244:
 ===== Tareas, Plays y Playbooks II ===== ===== Tareas, Plays y Playbooks II =====
  
 +Vamos a coger el playbook de la sección anterior y complicarlo un poco más añadiéndole otra play:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  gather_facts: false # para que no traiga los facts por defecto
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  gather_facts: false
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state=present
 +</code>
 +
 +Antes de ejecutar, revisamos la sintaxis del fichero:
 +
 +<code>
 +ansible-playbook primer_playbook.yaml --syntax-check
 +</code>
 +
 +Si todo va bien, ejecutamos el playbook:
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -v
 +</code>
 +
 +Vemos que falla porque no el usuario no tiene permisos para instalar el paquete ''nginx''. Podemos indicar que necesitamos elevar privilegios con ''become: yes'':
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  gather_facts: false # para que no traiga los facts por defecto
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  gather_facts: false
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state=present
 +</code>
 +
 +En la máquina destino, tenemos que evitar que pida la contraseña el usar ''sudo''. Para ello, hay que editar el fichero ''/etc/sudoers'' y la línea que comienza por ''%sudo'' dejarla de la siguiente manera:
 +
 +<code>
 +%sudo ALL=(ALL) NOPASSWD: ALL
 +</code>
 +
 +Modificamos más el playbook para incluir variables:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  gather_facts: false # para que no traiga los facts por defecto
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  gather_facts: false
 +  vars:
 +    state: absent
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state={{ state }}
 +</code>
 +
 +Lo que añadamos entre llaves (''{{}}'') se sustituirá por el valor que le hayamos dado. En este caso ''state'' es ''absent'', así que es lo mismo que si hubiéramos puesto:
 +
 +<code yaml>
 +    apt: name=nginx state=absent
 +</code>
 +
 +Si ejecutamos ahora ese playbook, desinstalará nginx.
 ===== Qué son los handlers y para qué se usan ===== ===== Qué son los handlers y para qué se usan =====
 +
 +Los **handlers** son tareas especiales que se ejecutan al final de una play si son notificadas por otra tarea cuando ocurre un cambio.
 +
 +<code yaml>
 +tasks:
 +- name: httpd package is present
 +  yum:
 +    name: httpd
 +    state: latest
 +  notify: restart httpd
 +    
 +- name: latest index.html file is present
 +  copy:
 +    src: files/index.html
 +    dest: /var/www/html
 +    
 +handlers:
 +- name: restart httpd
 +  service:
 +    name: httpd
 +    state: restarted
 +</code>
 +
 +<WRAP center round info 60%>
 +Los handlers se definen al final del Playbook
 +</WRAP>
 +
 +Seguimos trabajando con nuestro playbook:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  gather_facts: false # para que no traiga los facts por defecto
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +      
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Lo ejecutamos:
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -vv
 +</code>
 +
 +Si observamos el resultado, vemos que el servidor web nginx se reinicia, pero esto no nos interesa. Queremos que se reinicie solo cuando sea necesario. Aquí entran en escena los **handlers**:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  gather_facts: false # para que no traiga los facts por defecto
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Si lanzamos ahora el playbook, conseguiremos que solo se reinice nginx cuando se instale.
 +
 +Vamos a pasar variables por línea de comando con la opción ''-e'':
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -vv -e "state=absent"
 +</code>
 +
 +Ansible, en lugar de usar la varible ''state'' definida en el playbook, aplica la que pasamos por la línea de comandos. Por tanto, se eliminará nginx.
  
 ===== Condicionales ===== ===== Condicionales =====
 +
 +Ansible permite incluir condiciones a la hora de ejecutar las tareas basándose en la evaluación de una variable, fact u otra tarea previa en tiempo de ejecución.
 +
 +<code yaml>
 +---
 +- name: install Apache webserver
 +  hosts: all
 +  tasks:
 +    - name: Install Apache on Ubuntu Server
 +      apt: name=apache2 state=present
 +      become: yes
 +      when: ansible_os_family == "Debian" and ansible_distribution_version == "18.04"
 +</code>
 +
 +Trabajando con nuestro ''primer_playbook.yaml'':
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    when: ansible_os_family == "RedHat"
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +<WRAP center round todo 60%>
 +Poner ejemplo de salida
 +</WRAP>
 +
 +Veremos ahora el uso de condicionales utilizando una variable que hemos usado como salida de una tarea:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    register: contenido # registro de la salida de 'ls'
 +    
 +  - name: comprobar ficheros
 +    debug:
 +      msg: "El directorio no está vacío"
 +    when: contenido.stdout != ""
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +<WRAP center round todo 60%>
 +Poner ejemplo de salida de ejecución del anterior playbook
 +</WRAP>
  
 ===== Tags ===== ===== Tags =====
 +
 +Los //tags// permiten ejecutar un subconjunto de tareas en un playbook.
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    register: contenido # registro de la salida de 'ls'
 +    tags:
 +      - listar
 +    
 +  - name: comprobar ficheros
 +    debug:
 +      msg: "El directorio no está vacío"
 +    when: contenido.stdout != ""
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Lo ejecutamos añadiendo la opción ''%%--%%tags'':
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -vv --tags "listar"
 +</code>
 +
 +<WRAP center round todo 60%>
 +Poner ejemplo de salida del comando anterior.
 +</WRAP>
 +
 +También podríamos incluir //tags// en una play entera:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  tags: segunda_play
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    register: contenido # registro de la salida de 'ls'
 +    tags:
 +      - listar
 +    
 +  - name: comprobar ficheros
 +    debug:
 +      msg: "El directorio no está vacío"
 +    when: contenido.stdout != ""
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -vv --tags "segunda_play"
 +</code>
 +
 +<WRAP center round todo 60%>
 +Poner ejemplo de salida del comando anterior.
 +</WRAP>
  
 ===== Templates I ===== ===== Templates I =====
 +
 +Ansible integra el motor de //templating// [[https://jinja.palletsprojects.com/en/2.11.x/|jinja2]] para:
 +
 +  * Fijar y modificar variables
 +  * Utilizar lógica condicional
 +  * Generar ficheros de configuración utilizando variables
 +
 +Insertar una variable:
 +
 +<code>
 +INTERFACES="{{ dhcp_interface }}"
 +</code>
 +
 +Iterar sobre una lista:
 +
 +<code>
 +search ws.nsrc.org
 +{$ for host in use_dns_servers %}
 +nameserver {{ host }}
 +{% endfor %}
 +</code>
 +
 +<WRAP center round info 60%>
 +Se puede probar jinga online por ejemplo desde este [[http://jinja.quantprogramming.com/|Jinja2 live parser]] o [[https://j2live.ttl255.com/|este otro]]
 +</WRAP>
 +
 +Jinja2 permite utilizar [[https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html|filtros]] para transformar información almacenada en variables.
  
 ===== Templates II ===== ===== Templates II =====
 +
 +Usaremos jinja2 con Ansible. Vamos a crear un fichero ''template_ejemplo.j2'':
 +
 +<code>
 +Hola!
 +
 +Nginx en la versión {{ version }} se está ejecutando en {{ servidor }}
 +</code>
 +
 +Modificamos nuestro Playbook para añadir una tercera play:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  tags: segunda_play
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    register: contenido # registro de la salida de 'ls'
 +    tags:
 +      - listar
 +    
 +  - name: comprobar ficheros
 +    debug:
 +      msg: "El directorio no está vacío"
 +    when: contenido.stdout != ""
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +- name: tercera play
 +  hosts: all
 +  become: no
 +  tags: tercera_play
 +  vars:
 +    version: "5.13"
 +    servidor: "Ubuntu"
 +
 +  tasks:
 +    - name: imprimir template
 +      template:
 +        src: template_ejemplo.js # fichero con template Jinja2
 +        dest: /home/ansible/archivo.txt
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Revisamos sintaxis:
 +
 +<code>
 +ansible-playbook --syntax-check primer_playbook.yaml
 +</code>
 +
 +Lanzamos el playbook centrándonos en la última play que hemos hecho:
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -vv --tags "tercera_play"
 +</code>
 +
 +Si todo ha funcionado bien, se habrá creado el fichero ''/home/ansible/archivo.txt'' con el contenido:
 +
 +<code>
 +Hola!
 +
 +Nginx en la versión 5.13 se está ejecutando en Ubuntu.
 +</code>
 +
 +Vamos a añadir más variables en la tercera play:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  tags: segunda_play
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    register: contenido # registro de la salida de 'ls'
 +    tags:
 +      - listar
 +    
 +  - name: comprobar ficheros
 +    debug:
 +      msg: "El directorio no está vacío"
 +    when: contenido.stdout != ""
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +- name: tercera play
 +  hosts: all
 +  become: no
 +  tags: tercera_play
 +  vars:
 +    version: "5.13"
 +    servidor: "Ubuntu"
 +    coches: ["Mercedes", "Nissan", "Renault", "Ford"]
 +
 +  tasks:
 +    - name: imprimir template
 +      template:
 +        src: template_ejemplo.j2 # fichero con template Jinja2
 +        dest: /home/ansible/archivo.txt
 +
 +    - name: ejemplo loop con templates
 +      template:
 +        src: template_ejemplo_2.j2
 +        dest: /home/ansible/archivo_2.txt
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Creamos la plantilla ''template_ejemplo_2.j2'':
 +
 +<code>
 +La lista de coches contiene las siguientes marcas:
 +
 +{% for item in coches %}
 +
 +  {{ item }}
 +{% endfor %}
 +</code>
 +
 +Revisamos sintaxis:
 +
 +<code>
 +ansible-playbook --syntax-check primer_playbook.yaml
 +</code>
 +
 +Lanzamos el playbook centrándonos en la última play que hemos hecho:
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -vv --tags "tercera_play"
 +</code>
 +
 +En el equipo destino tendremos un nuevo archivo ''/home/ansible/archivo_2.txt'':
 +
 +<code>
 +La lista de coches contiene las siguientes marcas:
 +
 +  Mercedes
 +  
 +  Nissan
 +  
 +  Renault
 +  
 +  Ford
 +</code>
 +
 +Si no queremos el espacio tras cada elemento, usaríamos un guion antes del cierre del foreach:
 +
 +<code>
 +{%- endfor %}
 +</code>
 +
 +Si queremos que se transforme el texto a todo mayúscula, podemos usar el filtro ''upper'':
 +
 +<code>
 +La lista de coches contiene las siguientes marcas:
 +
 +{% for item in coches %}
 +
 +  {{ item | upper }}
 +{% endfor %}
 +</code>
 +
 +Finalmente, veremos inyección de variables en código HTML. Creamos el fichero ''template_ejemplo_3.j2'':
 +
 +<code>
 +<html>
 +    <h1>Nginx se está ejecutando en {{ ansible_hostname }}</h1>
 +</html>
 +</code>
 +
 +En nuestro Playbook vamos a añadir una tercera tarea en  la tercera play:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  tags: segunda_play
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: ls
 +    register: contenido # registro de la salida de 'ls'
 +    tags:
 +      - listar
 +    
 +  - name: comprobar ficheros
 +    debug:
 +      msg: "El directorio no está vacío"
 +    when: contenido.stdout != ""
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +- name: tercera play
 +  hosts: all
 +  become: yes # para tener permisos para escribir en la carpeta del servidor web
 +  tags: tercera_play
 +  vars:
 +    version: "5.13"
 +    servidor: "Ubuntu"
 +    coches: ["Mercedes", "Nissan", "Renault", "Ford"]
 +
 +  tasks:
 +    - name: imprimir template
 +      template:
 +        src: template_ejemplo.j2 # fichero con template Jinja2
 +        dest: /home/ansible/archivo.txt
 +
 +    - name: ejemplo loop con templates
 +      template:
 +        src: template_ejemplo_2.j2
 +        dest: /home/ansible/archivo_2.txt
 +
 +     - name: mostrar un nuevo fichero index
 +       template:
 +         src: template_ejemplo_3.j2
 +         dest: /var/www/html/index.html
 +         mode: 0755
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Revisamos sintaxis:
 +
 +<code>
 +ansible-playbook --syntax-check primer_playbook.yaml
 +</code>
 +
 +Lanzamos el playbook centrándonos en la última play que hemos hecho:
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -vv --tags "tercera_play"
 +</code>
  
 ===== Bloques y gestión de errores ===== ===== Bloques y gestión de errores =====
 +
 +Los bloques crean grupos lógicos de tareas y además permiten gestionar errores.
 +
 +Para ignorar errores podemos usar la etiqueta ''ignore_errors'':
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  tags: segunda_play
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios
 +    command: lz # Ponemos un comando incorrecto a propósito
 +    register: contenido # registro de la salida de 'ls'
 +    tags:
 +      - listar
 +    ignore_errors: yes
 +    
 +  - name: comprobar ficheros
 +    debug:
 +      msg: "El directorio no está vacío"
 +    when: contenido.stdout != ""
 +    
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: copiar index
 +    copy:
 +      src: index.html
 +      dest: /var/www/html
 +
 +- name: tercera play
 +  hosts: all
 +  become: yes # para tener permisos para escribir en la carpeta del servidor web
 +  tags: tercera_play
 +  vars:
 +    version: "5.13"
 +    servidor: "Ubuntu"
 +    coches: ["Mercedes", "Nissan", "Renault", "Ford"]
 +
 +  tasks:
 +    - name: imprimir template
 +      template:
 +        src: template_ejemplo.j2 # fichero con template Jinja2
 +        dest: /home/ansible/archivo.txt
 +
 +    - name: ejemplo loop con templates
 +      template:
 +        src: template_ejemplo_2.j2
 +        dest: /home/ansible/archivo_2.txt
 +
 +     - name: mostrar un nuevo fichero index
 +       template:
 +         src: template_ejemplo_3.j2
 +         dest: /var/www/html/index.html
 +         mode: 0755
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Al ejecutar, dará error cuando llegue a "listar directorios", pero continuará la ejecución porque le hemos dicho que los ignores.
 +
 +Vamos a crear dos bloques en nuestro playbook:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  tags: segunda_play
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios y comprobar ficheros
 +    block:
 +    - name: listar directorios
 +      command: lz # Ponemos un comando incorrecto a propósito
 +      register: contenido # registro de la salida de 'ls'
 +      tags:
 +        - listar
 +
 +    - name: comprobar ficheros
 +      debug:
 +        msg: "El directorio no está vacío"
 +      when: contenido.stdout != ""
 +
 +  - name: instalar nginx y copiar index
 +    block:
 +    - name: instalar nginx
 +      apt: name=nginx state="{{ state }}"
 +      notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +    - name: copiar index
 +      copy:
 +        src: index.html
 +        dest: /var/www/html
 +
 +- name: tercera play
 +  hosts: all
 +  become: yes # para tener permisos para escribir en la carpeta del servidor web
 +  tags: tercera_play
 +  vars:
 +    version: "5.13"
 +    servidor: "Ubuntu"
 +    coches: ["Mercedes", "Nissan", "Renault", "Ford"]
 +
 +  tasks:
 +    - name: imprimir template
 +      template:
 +        src: template_ejemplo.j2 # fichero con template Jinja2
 +        dest: /home/ansible/archivo.txt
 +
 +    - name: ejemplo loop con templates
 +      template:
 +        src: template_ejemplo_2.j2
 +        dest: /home/ansible/archivo_2.txt
 +
 +     - name: mostrar un nuevo fichero index
 +       template:
 +         src: template_ejemplo_3.j2
 +         dest: /var/www/html/index.html
 +         mode: 0755
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Vamos a hacer también una gestión más inteligente de los errores con la etiqueta ''rescue'':
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  tags: segunda_play
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios y comprobar ficheros
 +    block:
 +    - name: listar directorios
 +      command: lz # Ponemos un comando incorrecto a propósito
 +      register: contenido # registro de la salida de 'ls'
 +      tags:
 +        - listar
 +
 +    - name: comprobar ficheros
 +      debug:
 +        msg: "El directorio no está vacío"
 +      when: contenido.stdout != ""
 +
 +
 +    rescue: 
 +      - name: listar directorios
 +        commando: ls 
 +
 +
 +  - name: instalar nginx y copiar index
 +    block:
 +    - name: instalar nginx
 +      apt: name=nginx state="{{ state }}"
 +      notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +    - name: copiar index
 +      copy:
 +        src: index.html
 +        dest: /var/www/html
 +
 +
 +- name: tercera play
 +  hosts: all
 +  become: yes # para tener permisos para escribir en la carpeta del servidor web
 +  tags: tercera_play
 +  vars:
 +    version: "5.13"
 +    servidor: "Ubuntu"
 +    coches: ["Mercedes", "Nissan", "Renault", "Ford"]
 +
 +  tasks:
 +    - name: imprimir template
 +      template:
 +        src: template_ejemplo.j2 # fichero con template Jinja2
 +        dest: /home/ansible/archivo.txt
 +
 +    - name: ejemplo loop con templates
 +      template:
 +        src: template_ejemplo_2.j2
 +        dest: /home/ansible/archivo_2.txt
 +
 +     - name: mostrar un nuevo fichero index
 +       template:
 +         src: template_ejemplo_3.j2
 +         dest: /var/www/html/index.html
 +         mode: 0755
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Cuando ejecutamos el playbook, al llegar al bloque "listar directorios", da error, entonces salta a la sección ''rescue'' y ejecuta lo que está definido ahí.
 +
 +También podríamos usar la etiqueta ''always'' si queremos que algo se ejecute haya errores o no:
 +
 +<code yaml>
 +...
 +  tasks:
 +  - name: listar directorios y comprobar ficheros
 +    block:
 +    - name: listar directorios
 +      command: lz # Ponemos un comando incorrecto a propósito
 +      register: contenido # registro de la salida de 'ls'
 +      tags:
 +        - listar
 +
 +    - name: comprobar ficheros
 +      debug:
 +        msg: "El directorio no está vacío"
 +      when: contenido.stdout != ""
 +
 +    rescue: 
 +      - name: listar directorios
 +        commando: ls 
 +
 +    always:
 +      - name: mensaje de always
 +        debug:
 +          msg: "Este código se ejecuta siempre"
 +</code>
  
 ===== Bucles ===== ===== Bucles =====
  
 +Los bucles se usan para realizar una tarea múltiples veces, como por ejemplo crear muchos usuarios, instalar varios paquetes, etc.
 +
 +Se emplea la palabra reservada ''loop''.
 +
 +Vamos a modificar la primera play de nuestro playbook de ejemplo:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  # gather_facts: true 
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +  - name: echo items
 +    command: echo "{{ item }}"
 +    loop:
 +      - uno
 +      - dos
 +
 +- name: segunda play
 +  hosts: servidor_web
 +  become: yes
 +  tags: segunda_play
 +  gather_facts: false
 +  vars:
 +    state: present
 +  
 +  tasks:
 +  - name: listar directorios y comprobar ficheros
 +    block:
 +    - name: listar directorios
 +      command: lz # Ponemos un comando incorrecto a propósito
 +      register: contenido # registro de la salida de 'ls'
 +      tags:
 +        - listar
 +
 +    - name: comprobar ficheros
 +      debug:
 +        msg: "El directorio no está vacío"
 +      when: contenido.stdout != ""
 +
 +
 +    rescue: 
 +      - name: listar directorios
 +        commando: ls 
 +
 +
 +  - name: instalar nginx y copiar index
 +    block:
 +    - name: instalar nginx
 +      apt: name=nginx state="{{ state }}"
 +      notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +    - name: copiar index
 +      copy:
 +        src: index.html
 +        dest: /var/www/html
 +
 +
 +- name: tercera play
 +  hosts: all
 +  become: yes # para tener permisos para escribir en la carpeta del servidor web
 +  tags: tercera_play
 +  vars:
 +    version: "5.13"
 +    servidor: "Ubuntu"
 +    coches: ["Mercedes", "Nissan", "Renault", "Ford"]
 +
 +  tasks:
 +    - name: imprimir template
 +      template:
 +        src: template_ejemplo.j2 # fichero con template Jinja2
 +        dest: /home/ansible/archivo.txt
 +
 +    - name: ejemplo loop con templates
 +      template:
 +        src: template_ejemplo_2.j2
 +        dest: /home/ansible/archivo_2.txt
 +
 +     - name: mostrar un nuevo fichero index
 +       template:
 +         src: template_ejemplo_3.j2
 +         dest: /var/www/html/index.html
 +         mode: 0755
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Al ejecutar el playbook, veremos en la salida que se muestra esos dos elementos (uno y dos) para cada uno de los equipos del inventario.
 +
 +Añadimos más cosas:
 +
 +<code yaml>
 +(...)
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +  - name: echo items
 +    command: echo "{{ item }}"
 +    loop:
 +      - uno
 +      - dos
 +
 +  - name: listar inventario
 +    debug: 
 +      msg: "{{ item }}"
 +    loop: "{{ groups['all'] }}"
 +
 +(...)
 +</code>
 +
 +<WRAP center round todo 60%>
 +Mostrar salida del comando anterior
 +</WRAP>
 +
 +Vamos a usar ahora diccionarios:
 +
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  hosts: all
 +  become: yes
 +  gather_facts: true
 +  
 +  tasks:
 +  - name: comprobar conexión
 +    ping:
 +      data: funcionando
 +
 +  - name: echo items
 +    command: echo "{{ item }}"
 +    loop:
 +      - uno
 +      - dos
 +
 +  - name: listar inventario
 +    debug: 
 +      msg: "{{ item }}"
 +    loop: "{{ groups['all'] }}"
 +    
 +  - name: crear usuarios
 +    user:
 +      name: "{{ item.name }}"
 +      state: present
 +      groups: "{{ item.groups }}"
 +    loop:
 +      - { name: 'user1', groups: 'sudo'}
 +      - { name: 'user2', groups: 'sudo'}
 +      
 +(...)
 +</code>
 +
 +Revisamos sintaxis:
 +
 +<code>
 +ansible-playbook --syntax-check primer_playbook.yaml
 +</code>
 +
 +Lanzamos el playbook centrándonos en la última play que hemos hecho:
 +
 +<code>
 +ansible-playbook -i /home/pepito/inventario -u ansible_user --key-file /home/pepito/.ssh/id_rsa primer_playbook.yaml -vv 
 +</code>
 +
 +Si vamos al equipo/s destino, se habrían creado los usuarios ''user1'' y ''user2'' (en Linux podemos mirar el contenido del fichero ''/etc/passwd''.
 +
 +Si quisiéramos eliminar los usarios, cambiaríamos el valor de ''state'' a ''absent'':
 +
 +<code yaml>
 +(...)
 +  - name: crear usuarios
 +    user:
 +      name: "{{ item.name }}"
 +      state: absent
 +      groups: "{{ item.groups }}"
 +    loop:
 +      - { name: 'user1', groups: 'sudo'}
 +      - { name: 'user2', groups: 'sudo'}
 +(...)
 +</code>
 ===== Qué son los Roles en Ansible ===== ===== Qué son los Roles en Ansible =====
  
 +Los roles permiten organizar, paquetizar y reusar nuestro código de forma más práctica. 
 +
 +Tendríamos una estructura de carpetas donde incluiremos los roles que queramos.
 +
 +  * ''site.yaml''
 +  * ''roles/''
 +    * ''common/''
 +      * ''files/'': archivos a desplegar en el equipo objetivo.
 +      * ''templates/''
 +      * ''tasks/''
 +      * ''handlers/''
 +      * ''vars/''
 +      * ''defaults/''
 +      * ''meta/'': permite incluir dependencias entre roles
 +    * ''apache/''
 +      * ''files/''
 +      * ''templates/''
 +      * ''tasks/''
 +      * ''handlers/''
 +      * ''vars/''
 +      * ''defaults/''
 ===== Creando nuestro primer Rol ===== ===== Creando nuestro primer Rol =====
 +
 +Crearemos la carpeta principal ''roles'':
 +
 +<code>
 +mkdir roles
 +</code>
 +
 +Dentro de ella, vamos a crear el rol ''nginx'', que será otra carpeta más:
 +
 +<code>
 +mkdir nginx
 +</code>
 +
 +Dentro de ''nginx'', crearemos el resto de carpetas que espera ansible:
 +
 +<code>
 +mkdir defaults files handlers tasks templates
 +</code>
 +
 +Por tanto, si nos vamos al directorio padre, tendríamos la siguiente estructura de carpetas:
 +
 +<code>
 +├── roles
 +│   └── nginx
 +│       ├── defaults
 +│       ├── files
 +│       ├── handlers
 +│       ├── tasks
 +│       └── templates
 +</code>
 +
 +Partimos del siguiente playbook:
 +<code yaml>
 +# Este es nuestro primer playbook
 +- name: primera play
 +  become: yes
 +  hosts: servidor_web
 +  tags: primera_play
 +  gather_facts: false 
 +  vars:
 +    state: present
 +  
 +  tasks:
 +
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: crear index
 +    template:
 +      src: template_ejemplo_3.j2
 +      dest: /var/www/html/index.html
 +      mode: 0755
 +
 +  - name: copiar script
 +    copy:
 +      src: simple_script.sh
 +      dest: /tmp/simple_script.sh
 +
 +   handlers:     
 +   - name: reiniciar nginx
 +     service:
 +       name: nginx
 +       state: restarted
 +</code>
 +
 +Vamos a mover los distintos elemenos de ese playbooks a donde deben estar. Por ejemplo, las tareas irán a ''roles/nginx/tasks/main.yaml'':
 +
 +<code yaml>
 +---
 +  - name: instalar nginx
 +    apt: name=nginx state="{{ state }}"
 +    notify: reiniciar nginx # Mismo nombre que el handler
 +    
 +  - name: crear index
 +    template:
 +      src: template_ejemplo_3.j2
 +      dest: /var/www/html/index.html
 +      mode: 0755
 +
 +  - name: copiar script
 +    copy:
 +      src: simple_script.sh
 +      dest: /tmp/simple_script.sh
 +</code>
 +
 +Colocaremos ahora el template que usamos en el Playbook (''template_ejemplo_3.j2'') en ''roles/nginx/templates/''
 +
 +Hacemos lo mismo con el script ''simple_script.sh'', pero a la ruta ''roles/nginx/files''.
 +
 +Ahora es el turno de los handlers. Añadiremos un fichero ''main.yaml'' con el contenido:
 +
 +<code yaml>
 +---
 +  - name: reiniciar nginx
 +    service:
 +      name: nginx
 +      state: restarted
 +</code>
 +
 +Nos quedan las variables, crearemos el fichero ''roles/nginx/defaults/main.yaml'':
 +
 +<code yaml>
 +---
 +state: present
 +</code>
 +
 +Nos falta incluir este nuevo rol en algún sitio. En la carpeta raíz, creamos uno llamado, por ejemplo, ''nginx_rol.yaml'':
 +
 +<code yaml>
 +---
 +  - hosts: web # Solo aplicamos a uno de los hosts
 +    become: yes
 +    roles:
 +      - nginx # Rol que vamos a incluir
 +</code>
 +
 +Algo tarde, pero no es mal momento para comentar que podemos crear un fichero de configuración de Ansible: ''ansible.cfg'':
 +
 +<code>
 +[defaults]
 +inventory = /home/pepito/inventario
 +remote_user = ansible
 +private_key_file = /home/pepito/.ssh/id_rsa
 +</code>
 +
 +Ahora es más cómodo lanzar el playbook de la siguiente manera:
 +
 +<code>
 +ansible-playbook nginx_role.yaml -vv
 +</code>
 +
 ===== Recursos ===== ===== Recursos =====
  
   * [[https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html|YAML syntax]]   * [[https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html|YAML syntax]]
   * [[https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html|Using variables]]   * [[https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html|Using variables]]
informatica/ciberseguridad/cursos/curso_ansible_automatizacion_it/conceptos_avanzados.1683561366.txt.gz · Última modificación: por tempwin