Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Esta es la transcripción actuaciones en DevOps-40 2020-03-18:

A partir de la segunda confirmación, cualquier código se vuelve heredado, porque Las ideas iniciales comienzan a alejarse de la dura realidad. Esto no es ni bueno ni malo, es un hecho difícil de discutir y con el que hay que vivir. Parte de este proceso es la refactorización. Refactorización de infraestructura como código. Que comience la historia sobre cómo refactorizar Ansible en un año y no volverse loco.

El nacimiento del legado

Día #1: Paciente Cero

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Érase una vez un proyecto condicional. Tenía un equipo de desarrollo de desarrollo e ingenieros de operaciones. Estaban resolviendo el mismo problema: cómo implementar servidores y ejecutar una aplicación. El problema fue que cada equipo resolvió este problema a su manera. En el proyecto, se decidió utilizar Ansible para sincronizar el conocimiento entre los equipos de desarrollo y operaciones.

Día #89: El nacimiento del legado

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Sin darse cuenta, quisieron hacerlo lo mejor posible, pero resultó ser un legado. ¿Como sucedió esto?

  • Tenemos una tarea urgente aquí, hagamos un truco sucio y luego solucionémoslo.
  • No es necesario escribir documentación y todo está claro lo que está pasando aquí.
  • ¡Conozco Ansible/Python/Bash/Terraform! ¡Mira cómo puedo esquivar!
  • Soy un desarrollador de Full Stack Overflow y copié esto de stackoverflow. No sé cómo funciona, pero se ve bien y resuelve el problema.

Como resultado, puede obtener un tipo de código incomprensible para el cual no hay documentación, no está claro qué hace, si es necesario, pero el problema es que necesita desarrollarlo, modificarlo, agregarle muletas y soportes. , empeorando aún más la situación.

- hosts: localhost
  tasks:
    - shell: echo -n Z >> a.txt && cat a.txt
      register: output
      delay: 1
      retries: 5
      until: not output.stdout.find("ZZZ")

Día #109: Conciencia del problema

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

El modelo IaC inicialmente concebido e implementado ya no cumple con los requisitos de los usuarios/negocios/otros equipos, y el tiempo para realizar cambios en la infraestructura deja de ser aceptable. En este momento, llega el entendimiento de que es hora de actuar.

refactorización de IaC

Día #139: ¿Realmente necesitas refactorizar?

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Antes de apresurarse a refactorizar, debe responder una serie de preguntas importantes:

  1. ¿Por qué necesitas todo esto?
  2. ¿Tienes tiempo?
  3. ¿Es suficiente el conocimiento?

Si no sabe cómo responder las preguntas, entonces la refactorización terminará incluso antes de comenzar, o puede que empeore. Porque tenido experiencia ( Lo que aprendí al probar 200 líneas de código de infraestructura), luego el proyecto recibió una solicitud de ayuda para arreglar los roles y cubrirlos con pruebas.

Día #149: Preparando la refactorización

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Lo primero es prepararse. Decidir qué haremos. Para ello, nos comunicamos, encontramos áreas problemáticas y encontramos formas de resolverlas. Registramos los conceptos resultantes de alguna manera, por ejemplo un artículo en confluencia, para que cuando surja la pregunta “¿qué es mejor?” o "¿cuál es correcto?" No hemos perdido el rumbo. En nuestro caso, nos atenemos a la idea. divide y vencerás: dividimos la infraestructura en pequeños pedazos/ladrillos. Este enfoque le permite tomar una pieza aislada de infraestructura, comprender qué hace, cubrirla con pruebas y cambiarla sin temor a romper nada.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Resulta que las pruebas de infraestructura se convierten en la piedra angular y aquí vale la pena mencionar la pirámide de pruebas de infraestructura. Exactamente la misma idea que está en desarrollo, pero para la infraestructura: estamos pasando de pruebas rápidas y baratas que verifican cosas simples, como la sangría, a pruebas costosas y completas que implementan toda la infraestructura.

Intentos de prueba ansibles

Antes de pasar a describir cómo cubrimos las pruebas de Ansible en el proyecto, describiré los intentos y enfoques que tuve la oportunidad de utilizar anteriormente para comprender el contexto de las decisiones tomadas.

Día No. -997: Provisión de SDS

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

La primera vez que probé Ansible fue en un proyecto para desarrollar SDS (almacenamiento definido por software). Hay un artículo separado sobre este tema.
Cómo romper bicicletas sobre muletas al probar tu distribución, pero en resumen, terminamos con una pirámide de pruebas invertida y en las pruebas dedicamos entre 60 y 90 minutos a un rol, lo cual es mucho tiempo. La base fueron las pruebas e2e, es decir. Implementamos una instalación completa y luego la probamos. Lo que fue aún más irritante fue la invención de su propia bicicleta. Pero debo admitir que esta solución funcionó y permitió una versión estable.

Día # -701: Cocina Ansible y de prueba

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

El desarrollo de la idea de prueba de Ansible fue el uso de herramientas listas para usar, a saber, test kitchen / kitchen-ci e inspec. La elección estuvo determinada por el conocimiento de Ruby (para más detalles, consulte el artículo sobre Habré: ¿Sueñan los programadores de YML con probar Ansible?) trabajó más rápido, unos 40 minutos para 10 roles. Creamos un paquete de máquinas virtuales y realizamos pruebas en su interior.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

En general, la solución funcionó, pero hubo algunos sedimentos debido a la heterogeneidad. Cuando el número de personas evaluadas se incrementó a 13 roles básicos y 2 meta roles que combinan roles más pequeños, de repente las pruebas comenzaron a ejecutarse durante 70 minutos, que es casi 2 veces más. Era difícil hablar de prácticas de XP (programación extrema) porque... Nadie quiere esperar 70 minutos. Esta fue la razón para cambiar el enfoque.

Día # -601: Ansible y molécula.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Conceptualmente, esto es similar a testkitchen, solo que movimos las pruebas de roles a Docker y cambiamos la pila. Como resultado, el tiempo se redujo a 20-25 minutos estables para 7 roles.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Al aumentar el número de roles probados a 17 y vincular 45 roles, ejecutamos esto en 28 minutos en 2 esclavos jenkins.

Día #167: Agregar pruebas de Ansible al proyecto

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Lo más probable es que no sea posible realizar la tarea de refactorización rápidamente. La tarea debe ser medible para que puedas partirla en trozos pequeños y comer el elefante pieza a pieza con una cucharadita. Debe comprenderse si se está avanzando en la dirección correcta y cuánto tiempo queda por recorrer.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

En general, no importa cómo se haga, puedes escribir en una hoja de papel, puedes poner pegatinas en el armario, puedes crear tareas en Jira o puedes abrir Google Docs y anotar el estado actual. allá. Las piernas crecen porque el proceso no es inmediato, será largo y tedioso. Es poco probable que alguien quiera que usted se quede sin ideas, se canse y se sienta abrumado durante la refactorización.

La refactorización es simple:

  • Eat.
  • Sueño.
  • Código.
  • Prueba IaC.
  • Repetición:

y repetimos esto hasta llegar al objetivo previsto.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Puede que no sea posible comenzar a probar todo de inmediato, por lo que nuestra primera tarea fue comenzar con linting y verificar la sintaxis.

Día #181: Maestro de la construcción ecológica

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Linting es un pequeño primer paso hacia Green Build Master. Esto no romperá casi nada, pero le permitirá depurar procesos y realizar compilaciones ecológicas en jenkins. La idea es desarrollar hábitos entre el equipo:

  • Las pruebas rojas son malas.
  • Vine a arreglar algo y al mismo tiempo hacer que el código sea un poco mejor que antes.

Día #193: De linting a pruebas unitarias

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Una vez creado el proceso de obtención del código en el maestro, puede comenzar el proceso de mejora paso a paso: reemplazando el linting con roles de lanzamiento, incluso puede hacerlo sin idempotencia. Es necesario comprender cómo aplicar los roles y cómo funcionan.

Día #211: De las pruebas unitarias a las de integración

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Cuando la mayoría de los roles están cubiertos con pruebas unitarias y todo está desordenado, puede pasar a agregar pruebas de integración. Aquellos. Probar no un solo bloque de la infraestructura, sino una combinación de ellos, por ejemplo, una configuración de instancia completa.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Usando jenkins, generamos muchas etapas que vinculaban roles/libros de jugadas en paralelo, luego pruebas unitarias en contenedores y finalmente pruebas de integración.

Jenkins + Docker + Ansible = Pruebas

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

  1. Consulte el repositorio y genere etapas de compilación.
  2. Ejecute las etapas del libro de jugadas de pelusa en paralelo.
  3. Ejecute etapas de rol de pelusa en paralelo.
  4. Ejecute las etapas del rol de verificación de sintaxis en paralelo.
  5. Ejecute etapas de función de prueba en paralelo.
    1. Papel de pelusa.
    2. Verifique la dependencia de otros roles.
    3. Verifique la sintaxis.
    4. Crear instancia de ventana acoplable
    5. Ejecute molécula/default/playbook.yml.
    6. Comprueba la idempotencia.
  6. Ejecutar pruebas de integración
  7. Acabado

Día #271: Factor de autobús

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Al principio, la refactorización la llevó a cabo un pequeño grupo de dos o tres personas. Revisaron el código en el maestro. Con el tiempo, el equipo desarrolló conocimientos sobre cómo escribir código y la revisión del código contribuyó a la difusión de conocimientos sobre la infraestructura y cómo funciona. Lo más destacado aquí fue que los revisores fueron seleccionados uno por uno, según un cronograma, es decir, con cierto grado de probabilidad subirás a una nueva pieza de infraestructura.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Y debería ser cómodo aquí. Conviene hacer un repaso, ver en el marco de qué tarea se realizó y el historial de discusiones. Hemos integrado jenkins + bitbucket + jira.

Pero como tal, una revisión no es una panacea; de alguna manera, llegamos al código maestro, lo que nos hizo fracasar en las pruebas:

- get_url:
    url: "{{ actk_certs }}/{{ item.1 }}"
    dest: "{{ actk_src_tmp }}/"
    username: "{{ actk_mvn_user }}"
    password: "{{ actk_mvn_pass }}"
  with_subelements:
    - "{{ actk_cert_list }}"
    - "{{ actk_certs }}"
  delegate_to: localhost

- copy:
    src: "{{ actk_src_tmp }}/{{ item.1 }}"
    dest: "{{ actk_dst_tmp }}"
  with_subelements:
    - "{{ actk_cert_list }}"
    - "{{ actk_certs }}"

Luego lo arreglaron, pero quedó el sedimento.

get_url:
    url: "{{ actk_certs }}/{{ actk_item }}"
    dest: "{{ actk_src_tmp }}/{{ actk_item }}"
    username: "{{ actk_mvn_user }}"
    password: "{{ actk_mvn_pass }}"
  loop_control:
    loop_var: actk_item
  with_items: "{{ actk_cert_list }}"
  delegate_to: localhost

- copy:
    src: "{{ actk_src_tmp }}/{{ actk_item }}"
    dest: "{{ actk_dst_tmp }}"
  loop_control:
    loop_var: actk_item
  with_items: "{{ actk_cert_list }}"

Día #311: Acelerar las pruebas

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Con el tiempo, hubo más pruebas y las compilaciones se ejecutaron más lentamente, hasta una hora en el peor de los casos. En una de las retros había una frase como “qué bueno que haya pruebas, pero son lentas”. Como resultado, abandonamos las pruebas de integración en máquinas virtuales y las adaptamos a Docker para hacerlo más rápido. También reemplazamos testinfra con ansible verifier para reducir la cantidad de herramientas utilizadas.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

En rigor, hubo un conjunto de medidas:

  1. Cambie a la ventana acoplable.
  2. Elimine las pruebas de roles, que están duplicadas debido a dependencias.
  3. Aumentar el número de esclavos.
  4. Orden de ejecución de la prueba.
  5. Capacidad de pelusa TODO localmente con un comando.

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Como resultado, Pipeline en jenkins también se unificó.

  1. Generar etapas de construcción.
  2. Pelusa todo en paralelo.
  3. Ejecute etapas de función de prueba en paralelo.
  4. Finalizar.

Lecciones aprendidas

Evite las variables globales

Ansible utiliza variables globales, existe una solución parcial en el formulario vars_roles_privados, pero esto no es una panacea.

Dejame darte un ejemplo. Déjanos tener role_a и role_b

# cat role_a/defaults/main.yml
---
msg: a

# cat role_a/tasks/main.yml
---
- debug:
    msg: role_a={{ msg }}

# cat role_b/defaults/main.yml
---
msg: b

# cat role_b/tasks/main.yml
---
- set_fact:
    msg: b
- debug:
    msg: role_b={{ msg }}

- hosts: localhost
  vars:
    msg: hello
  roles:
    - role: role_a
    - role: role_b
  tasks:
    - debug:
        msg: play={{msg}}

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

Lo curioso es que el resultado de los playbooks dependerá de cosas que no siempre son obvias, como el orden en que se enumeran los roles. Desafortunadamente, esta es la naturaleza de Ansible y lo mejor que se puede hacer es usar algún tipo de acuerdo, por ejemplo, dentro de un rol, usar solo la variable descrita en este rol.

BAD: utilizar variable global.

# cat roles/some_role/tasks/main.yml
---
debug:
  var: java_home

BUENA: V defaults definir las variables necesarias y luego utilizarlas únicamente.

# cat roles/some_role/defaults/main.yml
---
r__java_home:
 "{{ java_home | default('/path') }}"

# cat roles/some_role/tasks/main.yml
---
debug:
  var: r__java_home

Variables de rol de prefijo

BAD: utilizar variable global.

# cat roles/some_role/defaults/main.yml
---
db_port: 5432

BUENA: En roles para variables, use variables con el prefijo del nombre del rol; esto, al observar el inventario, hará que sea más fácil comprender lo que está sucediendo.

# cat roles/some_role/defaults/main.yml
---
some_role__db_port: 5432

Usar variable de control de bucle

BAD: Usar variable estándar en bucles item, si esta tarea/libro de estrategias se incluye en alguna parte, esto puede provocar un comportamiento inesperado

---
- hosts: localhost
  tasks:
    - debug:
        msg: "{{ item }}"
      loop:
        - item1
        - item2

BUENA: Redefinir una variable en un bucle mediante loop_var.

---
- hosts: localhost
  tasks:
    - debug:
        msg: "{{ item_name }}"
      loop:
        - item1
        - item2
      loop_control:
        loop_var: item_name

Verificar variables de entrada

Acordamos utilizar prefijos de variables; no sería superfluo comprobar que estén definidos como esperamos y, por ejemplo, no hayan sido anulados por un valor vacío.

BUENA: Verifique las variables.

- name: "Verify that required string variables are defined"
  assert:
    that: ahs_var is defined and ahs_var | length > 0 and ahs_var != None
    fail_msg: "{{ ahs_var }} needs to be set for the role to work "
    success_msg: "Required variables {{ ahs_var }} is defined"
  loop_control:
    loop_var: ahs_var
  with_items:
    - ahs_item1
    - ahs_item2
    - ahs_item3

Evite diccionarios hashes, use estructura plana

Si un rol espera un hash/diccionario en uno de sus parámetros, entonces si queremos cambiar uno de los parámetros secundarios, necesitaremos anular todo el hash/diccionario, lo que aumentará la complejidad de la configuración.

BAD: Utilice hash/diccionario.

---
user:
  name: admin
  group: admin

BUENA: Utilice una estructura variable plana.

---
user_name: admin
user_group: "{{ user_name }}"

Cree manuales y roles idempotentes

Los roles y los manuales deben ser idempotentes, porque reduce la deriva de configuración y el miedo a romper algo. Pero si usas molécula, entonces este es el comportamiento predeterminado.

Evite el uso de módulos de shell de comandos

El uso de un módulo de shell da como resultado un paradigma de descripción imperativo, en lugar del declarativo, que es el núcleo de Ansible.

Pon a prueba tus roles a través de la molécula

La molécula es algo muy flexible, veamos algunos escenarios.

Molécula Múltiples instancias

В molecule.yml en la sección platforms puede describir muchos hosts que puede implementar.

---
    driver:
      name: docker
    platforms:
      - name: postgresql-instance
        hostname: postgresql-instance
        image: registry.example.com/postgres10:latest
        pre_build_image: true
        override_command: false
        network_mode: host
      - name: app-instance
        hostname: app-instance
        pre_build_image: true
        image: registry.example.com/docker_centos_ansible_tests
        network_mode: host

En consecuencia, estos hosts pueden entonces ser converge.yml usar:

---
- name: Converge all
  hosts: all
  vars:
    ansible_user: root
  roles:
    - role: some_role

- name: Converge db
  hosts: db-instance
  roles:
    - role: some_db_role

- name: Converge app
  hosts: app-instance
  roles:
    - role: some_app_role

verificador ansible

En molecula es posible usar ansible para verificar que la instancia se haya configurado correctamente, además, este ha sido el valor predeterminado desde la versión 3. No es tan flexible como testinfra/inspec, pero podemos comprobar que el contenido del archivo coincide con nuestras expectativas:

---
- name: Verify
  hosts: all
  tasks:
    - name: copy config
      copy:
        src: expected_standalone.conf
        dest: /root/wildfly/bin/standalone.conf
        mode: "0644"
        owner: root
        group: root
      register: config_copy_result

    - name: Certify that standalone.conf changed
      assert:
        that: not config_copy_result.changed

O implemente el servicio, espere a que esté disponible y realice una prueba de humo:

---
  - name: Verify
    hosts: solr
    tasks:
      - command: /blah/solr/bin/solr start -s /solr_home -p 8983 -force
      - uri:
          url: http://127.0.0.1:8983/solr
          method: GET
          status_code: 200
        register: uri_result
        until: uri_result is not failed
        retries: 12
        delay: 10
      - name: Post documents to solr
        command: /blah/solr/bin/post -c master /exampledocs/books.csv

Ponga lógica compleja en módulos y complementos

Ansible aboga por un enfoque declarativo, por lo que cuando realiza bifurcaciones de código, transformación de datos y módulos de shell, el código se vuelve difícil de leer. Para combatir esto y que sea fácil de entender, no sería superfluo combatir esta complejidad creando sus propios módulos.

Resumir consejos y trucos

  1. Evite las variables globales.
  2. Variables de rol de prefijo.
  3. Utilice la variable de control de bucle.
  4. Verifique las variables de entrada.
  5. Evite los diccionarios hashes, utilice una estructura plana.
  6. Cree manuales y roles idempotentes.
  7. Evite el uso de módulos de shell de comandos.
  8. Pruebe sus roles a través de moléculas.
  9. Coloque lógica compleja en módulos y complementos.

Conclusión

Cómo empezar a probar Ansible, refactorizar el proyecto en un año y no volverse loco

No puedes simplemente refactorizar la infraestructura de un proyecto, incluso si tienes IaC. Este es un proceso largo que requiere paciencia, tiempo y conocimiento.

UPD1 2020.05.01 20:30 — Para la creación de perfiles principales de libros de jugadas, puede utilizar callback_whitelist = profile_tasks para comprender qué funciona exactamente durante mucho tiempo. Luego pasamos por Clásicos de la aceleración ansible. También puedes probar mitógeno
UPD2 2020.05.03 16:34 - Versión Inglés

Fuente: habr.com

Añadir un comentario