Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Esta é a transcrición actuacións en DevOps-40 2020-03-18:

A partir do segundo commit, calquera código pasa a ser legado, porque as ideas iniciais comezan a diverxer da dura realidade. Isto non é nin bo nin malo, é un feito que é difícil de discutir e que hai que vivir. Parte deste proceso é a refactorización. Refactorización da infraestrutura como código. Que comece a historia de como refactorizar Ansible nun ano e non volverse tolo.

O nacemento do legado

Día #1: Paciente Cero

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Había unha vez un proxecto condicional. Tiña un equipo de desenvolvemento de desenvolvemento e enxeñeiros de operacións. Estaban resolvendo o mesmo problema: como despregar servidores e executar unha aplicación. O problema foi que cada equipo resolveu este problema á súa maneira. No proxecto, decidiuse usar Ansible para sincronizar o coñecemento entre os equipos de Dev e Ops.

Día #89: O nacemento do legado

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Sen decatarse eles mesmos, quixeron facelo o mellor posible, pero resultou ser un legado. Como ocorre isto?

  • Temos unha tarefa urxente aquí, imos facer un hack sucio e despois solucionalo.
  • Non tes que escribir documentación e todo está claro o que está a pasar aquí.
  • Coñezo Ansible/Python/Bash/Terraform! Mira como podo esquivar!
  • Son un programador de Full Stack Overflow e copiei isto de stackoverflow, non sei como funciona, pero parece xenial e resolve o problema.

Como resultado, pódese conseguir un tipo de código incomprensible para o que non hai documentación, non está claro o que fai, se é necesario, pero o problema é que hai que desenvolvelo, modificalo, engadir muletas e soportes. , facendo a situación aínda peor.

- 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: Concienciación do problema

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

O modelo de IaC concibido e implementado inicialmente xa non cumpre os requisitos dos usuarios/empresas/outros equipos, e o tempo para facer cambios na infraestrutura deixa de ser aceptable. Neste momento, chega a entender que é hora de tomar medidas.

Refactorización de IaC

Día #139: ¿Realmente necesitas refactorización?

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Antes de apurar a refactorización, debes responder a unha serie de preguntas importantes:

  1. Por que necesitas todo isto?
  2. Tes tempo?
  3. É suficiente o coñecemento?

Se non sabes como responder ás preguntas, entón a refactorización rematará antes de que comece, ou só pode empeorar. Porque tiña experiencia ( O que aprendín probando 200 liñas de código de infraestrutura), entón o proxecto recibiu unha solicitude de axuda para fixar os roles e cubrilos con probas.

Día #149: Preparación da refactorización

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

O primeiro é preparar. Decide o que imos facer. Para iso, comunicámonos, atopamos áreas problemáticas e buscamos formas de resolvelos. Rexistramos os conceptos resultantes dalgún xeito, por exemplo un artigo en confluencia, de xeito que cando xorde a pregunta "que é o mellor?" ou "cal é correcto?" Non perdemos o camiño. No noso caso, seguimos a idea divide e goberna: dividimos a infraestrutura en pequenos anacos/ladrillos. Este enfoque permítelle tomar unha peza illada de infraestrutura, comprender o que fai, cubrila con probas e cambiala sen medo a romper nada.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Resulta que as probas de infraestruturas convértense na pedra angular e aquí paga a pena mencionar a pirámide de probas de infraestruturas. Exactamente a mesma idea que está en desenvolvemento, pero para infraestruturas: estamos pasando de probas rápidas baratas que verifican cousas sinxelas, como sangría, a probas caras e completas que despregan toda a infraestrutura.

Intentos de proba Ansible

Antes de describir como cubrimos as probas de Ansible no proxecto, describirei os intentos e enfoques que tiven a oportunidade de utilizar anteriormente para comprender o contexto das decisións tomadas.

Día no -997: prestación da SDS

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

A primeira vez que probei Ansible foi nun proxecto para desenvolver SDS (Software Defined Storage). Hai un artigo separado sobre este tema
Como romper bicicletas por muletas ao probar a súa distribución, pero en resumo, acabamos cunha pirámide de probas invertida e as probas pasamos 60-90 minutos nun papel, o que é moito tempo. A base foron probas e2e, é dicir. implantamos unha instalación completa e despois probámola. O que aínda era máis agravante foi a invención da súa propia bicicleta. Pero debo admitir que esta solución funcionou e permitiu unha versión estable.

Día # -701: Ansible e cociña de proba

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

O desenvolvemento da idea de proba de Ansible foi o uso de ferramentas preparadas, a saber, probar cociña / cociña-ci e inspeccionar. A elección foi determinada polo coñecemento de Ruby (para máis detalles, consulte o artigo sobre Habré: Os programadores de YML soñan con probar Ansible?) funcionou máis rápido, uns 40 minutos para 10 papeis. Creamos un paquete de máquinas virtuais e realizamos probas dentro.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

En xeral, a solución funcionou, pero había algún sedimento debido á heteroxeneidade. Cando o número de persoas probadas aumentou a 13 roles básicos e 2 meta roles que combinan roles máis pequenos, de súpeto as probas comezaron a executarse durante 70 minutos, o que é case 2 veces máis. Era difícil falar de prácticas de XP (programación extrema) porque... ninguén quere esperar 70 minutos. Este foi o motivo para cambiar o enfoque

Día # -601: Ansible e molécula

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Conceptualmente, isto é semellante a testkitchen, só que movemos a proba de roles a docker e cambiamos a pila. Como resultado, o tempo reduciuse a uns 20-25 minutos estables para 7 papeis.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Ao aumentar a 17 o número de papeis probados e 45 papeis, executámolo en 28 minutos en 2 escravos jenkins.

Día #167: Engadindo probas de Ansible ao proxecto

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

O máis probable é que non sexa posible facer a tarefa de refactorización con présa. A tarefa debe ser medible para poder rompela en anacos pequenos e comer o elefante anaco a anaco cunha culleriña. Debe haber unha comprensión de se está a moverse na dirección correcta, canto tempo falta.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

En xeral, non importa como se faga, podes escribir nun papel, pór adhesivos no armario, podes crear tarefas en Jira ou podes abrir Google Docs e anotar o estado actual. alí. As pernas medran polo feito de que o proceso non é inmediato, será longo e tedioso. É pouco probable que alguén queira que se queime de ideas, se canse e se desborde durante a refactorización.

A refactorización é sinxela:

  • Coma.
  • Durmir.
  • Código.
  • Proba IaC.
  • Repetir

e repetimos isto ata acadar o obxectivo previsto.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Quizais non sexa posible comezar a probar todo de inmediato, polo que a nosa primeira tarefa foi comezar coa linting e comprobando a sintaxe.

Día #181: Mestre de construción verde

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Linting é un pequeno primeiro paso cara a Green Build Master. Isto non romperá case nada, pero permitirache depurar procesos e facer construcións verdes en Jenkins. A idea é desenvolver hábitos entre o equipo:

  • As probas vermellas son malas.
  • Vin para arranxar algo e ao mesmo tempo facer o código un pouco mellor do que era antes.

Día #193: Do listing ás probas unitarias

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Unha vez construído o proceso de incorporación do código ao mestre, podes comezar o proceso de mellora paso a paso: substituíndo a linting por roles de lanzamento, incluso podes facelo sen idempotencia. Debe entender como aplicar os roles e como funcionan.

Día #211: Das probas unitarias ás probas de integración

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Cando a maioría dos papeis están cubertos con probas unitarias e todo está ligado, podes pasar a engadir probas de integración. Eses. probando non un só ladrillo na infraestrutura, senón unha combinación deles, por exemplo, unha configuración de instancia completa.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Usando jenkins, xeramos moitas etapas que aliñaban roles/playbooks en paralelo, despois probas unitarias en contedores e, finalmente, probas de integración.

Jenkins + Docker + Ansible = Probas

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

  1. Paga o repositorio e xera fases de compilación.
  2. Executar as fases do libro de pelusas en paralelo.
  3. Executar fases de rol de pelusa en paralelo.
  4. Executar fases de función de comprobación de sintaxe en paralelo.
  5. Executar fases de rol de proba en paralelo.
    1. Papel de pelusa.
    2. Comproba a dependencia doutros roles.
    3. Comproba a sintaxe.
    4. Crear instancia docker
    5. Executa molecule/default/playbook.yml.
    6. Comprobar a idempotencia.
  6. Realiza probas de integración
  7. Rematar

Día #271: Bus Factor

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Nun primeiro momento, a refactorización realizábase por un pequeno grupo de dúas ou tres persoas. Revisaron o código no master. Co paso do tempo, o equipo desenvolveu coñecementos sobre como escribir código e a revisión do código contribuíron á difusión do coñecemento sobre a infraestrutura e como funciona. O máis destacado aquí foi que os revisores foron seleccionados un por un, segundo un calendario, é dicir. con certo grao de probabilidade subirás a unha nova peza de infraestrutura.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

И здесь должно быть удобно. Удобно делать ревью, видеть в рамках какой задачи оно сделано, историю обсуждений. Мы интегрировали jenkins + bitbucket + jira.

Pero como tal, unha revisión non é unha panacea; dalgún xeito, entramos no código mestre, o que nos fixo probas de fracaso:

- 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 }}"

Despois arranxárono, pero quedou o residuo.

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 as probas

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Co paso do tempo, houbo máis probas, as construcións foron máis lentas, ata unha hora no peor dos casos. Nun dos retros había unha frase como "é bo que haxa probas, pero son lentas". Como resultado, abandonamos as probas de integración en máquinas virtuais e adaptámolas para Docker para facelo máis rápido. Tamén substituímos testinfra por un verificador ansible para reducir o número de ferramentas utilizadas.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

En rigor, houbo unha serie de medidas:

  1. Cambiar ao docker.
  2. Elimina as probas de roles, que se duplican debido ás dependencias.
  3. Aumentar o número de escravos.
  4. Orde de execución de proba.
  5. Capacidade de pelusa TODOS localmente cun comando.

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Como resultado, Pipeline on jenkins tamén se unificou

  1. Xerar fases de construción.
  2. Lint todo en paralelo.
  3. Executar fases de rol de proba en paralelo.
  4. Rematar.

As leccións aprendidas

Evite as variables globais

Ansible usa variables globais, hai unha solución parcial no formulario variables_papel_privada, pero esta non é unha panacea.

Déixame un exemplo. Imos ter 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}}

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

O curioso é que o resultado dos playbooks dependerá de cousas que non sempre son obvias, como a orde na que se enumeran os papeis. Desafortunadamente, esta é a natureza de Ansible e o mellor que se pode facer é usar algún tipo de acordo, por exemplo, dentro dun rol, use só a variable descrita neste rol.

BAD: use a variable global.

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

BOA: V defaults definir as variables necesarias e despois utilizar só elas.

# 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

Prefixo de variables de rol

BAD: use a variable global.

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

BOA: Nos roles para variables, use as variables co prefixo do nome do rol; isto, ao observar o inventario, facilitará a comprensión do que está a suceder.

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

Use a variable de control de bucle

BAD: Use a variable estándar en bucles item, se esta tarefa/libro de xogos está incluído nalgún lugar, isto pode provocar un comportamento inesperado

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

BOA: Redefinir unha variable nun bucle mediante loop_var.

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

Comprobar as variables de entrada

Acordamos empregar prefixos variables; non sería superfluo comprobar que están definidos como esperamos e, por exemplo, non foron substituídos por un valor baleiro

BOA: Comproba as 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 os dicionarios hash, use estrutura plana

Se un rol espera un hash/dicionario nalgún dos seus parámetros, entón se queremos cambiar un dos parámetros fillos, teremos que anular todo o hash/dicionario, o que aumentará a complexidade da configuración.

BAD: Usa hash/dicionario.

---
user:
  name: admin
  group: admin

BOA: Use unha estrutura variable plana.

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

Crea libros e papeis idempotentes

Os papeis e os libros de xogo deben ser idempotentes, porque reduce a deriva da configuración e o medo a romper algo. Pero se usas molécula, este é o comportamento predeterminado.

Evite usar módulos de shell de comandos

Usar un módulo de shell dá como resultado un paradigma de descrición imperativo, en lugar do declarativo, que é o núcleo de Ansible.

Proba os teus papeis a través dunha molécula

A molécula é unha cousa moi flexible, vexamos algúns escenarios.

Molécula Múltiples instancias

В molecule.yml na sección platforms pode describir moitos hosts que pode 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, estes anfitrións poden 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 Molecule é posible usar ansible para comprobar que a instancia foi configurada correctamente, ademais, esta é a predeterminada desde a versión 3. Non é tan flexible como testinfra/inspec, pero podemos comprobar que o contido do ficheiro coincide coas nosas 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

Ou implementa o servizo, agarda a que estea dispoñible e fai unha proba de fume:

---
  - 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

Pon lóxica complexa en módulos e complementos

Ansible defende un enfoque declarativo, polo que cando fai ramificación de código, transformación de datos, módulos de shell, o código faise difícil de ler. Para combater isto e que sexa sinxelo de entender, non sería superfluo combater esta complexidade creando os seus propios módulos.

Resume Consellos e Trucos

  1. Evite as variables globais.
  2. Prefixo de variables de rol.
  3. Use a variable de control de bucle.
  4. Comprobar as variables de entrada.
  5. Evite os dicionarios hash, use estrutura plana.
  6. Crea libros e papeis idempotentes.
  7. Evite usar módulos de shell de comandos.
  8. Proba os teus papeis a través dunha molécula.
  9. Pon lóxica complexa en módulos e complementos.

Conclusión

Como comezar a probar Ansible, refactorizar o proxecto nun ano e non volverse tolo

Non podes ir e refactorizar a infraestrutura nun proxecto, aínda que teñas IaC. Este é un proceso longo que require paciencia, tempo e coñecemento.

UPD1 2020.05.01/20/30 XNUMX:XNUMX — Para o perfil principal dos libros de xogo que podes usar callback_whitelist = profile_tasks comprender o que funciona exactamente durante moito tempo. Despois pasamos Clásicos de aceleración Ansible. Tamén podes probar mitógeno
UPD2 2020.05.03/16/34 XNUMX:XNUMX - Versión en inglés

Fonte: www.habr.com

Engadir un comentario