Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Dit is de transcriptie optredens op DevOps-40 2020-03-18:

Vanaf de tweede commit wordt elke code verouderd, omdat De oorspronkelijke ideeën beginnen af ​​te wijken van de harde werkelijkheid. Dit is noch goed, noch slecht; het is een gegeven waar moeilijk over te discussiëren valt en waar mee geleefd moet worden. Een deel van dit proces is refactoring. Infrastructuur herstructureren als code. Laat het verhaal beginnen over hoe je Ansible binnen een jaar kunt herstructureren en niet gek wordt.

De geboorte van erfenis

Dag #1: Patiënt nul

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Er was eens een voorwaardelijk project. Het had een Dev-ontwikkelteam en Ops-ingenieurs. Ze waren hetzelfde probleem aan het oplossen: hoe je servers moest inzetten en een applicatie moest draaien. Het probleem was dat elk team dit probleem op zijn eigen manier oploste. Bij het project werd besloten om Ansible in te zetten om kennis tussen de Dev- en Ops-teams te synchroniseren.

Dag #89: De geboorte van erfenis

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Zonder het zelf te merken wilden ze het zo goed mogelijk doen, maar het bleek erfenis. Hoe gebeurde dit?

  • We hebben hier een dringende taak, laten we een vuile hack uitvoeren en deze vervolgens repareren.
  • Je hoeft geen documentatie te schrijven en alles is duidelijk wat hier aan de hand is.
  • Ik ken Ansible/Python/Bash/Terraform! Kijk hoe ik kan ontwijken!
  • Ik ben een Full Stack Overflow-ontwikkelaar en heb dit gekopieerd van StackOverflow. Ik weet niet hoe het werkt, maar het ziet er cool uit en lost het probleem op.

Als gevolg hiervan kun je een onbegrijpelijk type code krijgen waarvoor geen documentatie bestaat, het is niet duidelijk wat het doet, of het nodig is, maar het probleem is dat je het moet ontwikkelen, aanpassen, krukken en ondersteuningen moet toevoegen , waardoor de situatie nog erger wordt.

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

Dag #109: Bewustwording van het probleem

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Het aanvankelijk bedachte en geïmplementeerde IaC-model voldoet niet langer aan de eisen van gebruikers/business/andere teams, en de tijd om wijzigingen aan te brengen in de infrastructuur is niet meer acceptabel. Op dit moment komt het besef dat het tijd is om actie te ondernemen.

IaC-refactoring

Dag #139: Heeft u echt refactoring nodig?

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Voordat u zich haast tot refactoring, moet u een aantal belangrijke vragen beantwoorden:

  1. Waarom heb je dit allemaal nodig?
  2. Heb je tijd?
  3. Is kennis voldoende?

Als u niet weet hoe u de vragen moet beantwoorden, zal de refactoring eindigen voordat deze zelfs maar is begonnen, of kan het alleen maar erger worden. Omdat ervaring gehad( Wat ik heb geleerd van het testen van 200 regels infrastructuurcode), vervolgens ontving het project een verzoek om hulp om de rollen op te lossen en deze met tests te bedekken.

Dag #149: Voorbereiding van de refactoring

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Het eerste is voorbereiding. Bepaal wat we gaan doen. Om dit te doen, communiceren we, vinden we probleemgebieden en bedenken we manieren om ze op te lossen. We leggen de resulterende concepten op de een of andere manier vast, bijvoorbeeld een samenvloeiend artikel, zodat wanneer de vraag rijst “wat is het beste?” of "wat is juist?" Wij zijn de weg niet kwijtgeraakt. In ons geval bleven we bij het idee verdeel en heers: we breken de infrastructuur op in kleine stukjes/stenen. Met deze aanpak kun je een geïsoleerd stukje infrastructuur nemen, begrijpen wat het doet, het bedekken met tests en het veranderen zonder bang te hoeven zijn iets kapot te maken.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Het blijkt dat het testen van infrastructuur de hoeksteen wordt en hier is het de moeite waard om de piramide voor het testen van infrastructuur te noemen. Precies hetzelfde idee dat in ontwikkeling is, maar dan voor infrastructuur: we gaan van goedkope snelle tests die simpele zaken controleren, zoals inspringen, naar dure volwaardige tests die de hele infrastructuur inzetten.

Ansible-testpogingen

Voordat we gaan beschrijven hoe we Ansible-tests in het project hebben behandeld, zal ik de pogingen en benaderingen beschrijven die ik eerder heb kunnen gebruiken om de context van de genomen beslissingen te begrijpen.

Dag nr. -997: SDS-voorziening

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

De eerste keer dat ik Ansible testte, was tijdens een project om SDS (Software Defined Storage) te ontwikkelen. Er is een apart artikel over dit onderwerp
Hoe u fietsen over krukken kunt breken bij het testen van uw distributie, maar kortom, we eindigden met een omgekeerde testpiramide en bij het testen hebben we 60-90 minuten aan één rol besteed, wat lang is. De basis waren e2e-tests, d.w.z. we hebben een volwaardige installatie neergezet en vervolgens getest. Wat nog erger was, was de uitvinding van zijn eigen fiets. Maar ik moet toegeven dat deze oplossing werkte en een stabiele release mogelijk maakte.

Dag # -701: Ansible en testkeuken

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

De ontwikkeling van het Ansible-testidee was het gebruik van kant-en-klare tools, namelijk testkeuken/keuken-ci en inspec. De keuze werd bepaald door kennis van Ruby (zie voor meer details het artikel over Habré: Dromen YML-programmeurs ervan Ansible te testen?) werkte sneller, ongeveer 40 minuten voor 10 rollen. We hebben een pakket virtuele machines gemaakt en daarbinnen tests uitgevoerd.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Over het algemeen werkte de oplossing, maar er was wat sediment vanwege de heterogeniteit. Toen het aantal geteste mensen werd verhoogd tot 13 basisrollen en 2 metarollen die kleinere rollen combineerden, begonnen de tests plotseling 70 minuten te duren, wat bijna twee keer zo lang is. Het was moeilijk om over XP-praktijken (extreme programming) te praten, omdat... niemand wil 2 minuten wachten. Dit was de reden om de aanpak te veranderen

Dag # -601: Ansible en molecuul

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Conceptueel gezien is dit vergelijkbaar met testkitchen, alleen hebben we het testen van rollen naar Docker verplaatst en de stapel gewijzigd. Als gevolg hiervan werd de tijd teruggebracht tot een stabiele 20-25 minuten voor 7 rollen.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Door het aantal geteste rollen te verhogen naar 17 en 45 rollen te linten, hebben we dit in 28 minuten uitgevoerd op 2 Jenkins-slaven.

Dag #167: Ansible-tests toevoegen aan het project

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Hoogstwaarschijnlijk zal het niet mogelijk zijn om de refactoring-taak snel uit te voeren. De taak moet meetbaar zijn, zodat je hem in kleine stukjes kunt breken en de olifant stukje voor stukje kunt opeten met een theelepel. Er moet inzicht zijn of u zich in de goede richting beweegt en hoe lang u nog moet gaan.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Over het algemeen maakt het niet uit hoe het gedaan zal worden, je kunt op een vel papier schrijven, je kunt stickers op de kast plakken, je kunt taken aanmaken in Jira, of je kunt Google Docs openen en de huidige status opschrijven. daar. De benen groeien door het feit dat het proces niet onmiddellijk is, het zal lang en vervelend zijn. Het is onwaarschijnlijk dat iemand wil dat je geen ideeën meer hebt, moe wordt en overweldigd raakt tijdens het refactoring.

De refactoring is eenvoudig:

  • Eten.
  • Slapen.
  • Code.
  • IaC-test.
  • herhaling

en dit herhalen we totdat we het beoogde doel bereiken.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Het is misschien niet mogelijk om alles meteen te testen, dus onze eerste taak was om te beginnen met het linten en het controleren van de syntaxis.

Dag #181: Groene bouwmeester

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Linting is een kleine eerste stap richting Green Build Master. Dit zal vrijwel niets kapot maken, maar het geeft je wel de mogelijkheid om processen te debuggen en groene builds te maken in Jenkins. Het idee is om gewoonten binnen het team te ontwikkelen:

  • Rode tests zijn slecht.
  • Ik kwam om iets te repareren en tegelijkertijd de code een beetje beter te maken dan vóór jou.

Dag #193: Van pluisjes tot unit-tests

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Nadat u het proces heeft ingebouwd om de code in de master te krijgen, kunt u beginnen met het proces van stapsgewijze verbetering - door linting te vervangen door startrollen, kunt u het zelfs doen zonder idempotentie. U moet begrijpen hoe u rollen moet toepassen en hoe ze werken.

Dag #211: Van unit- naar integratietesten

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Wanneer de meeste rollen zijn bedekt met unit-tests en alles in de war is, kunt u doorgaan met het toevoegen van integratietests. Die. het testen van geen enkele baksteen in de infrastructuur, maar een combinatie daarvan, bijvoorbeeld een volledige instanceconfiguratie.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Met behulp van Jenkins hebben we veel fasen gegenereerd waarin rollen/playbooks parallel werden samengevoegd, vervolgens unit-tests in containers en ten slotte integratietests.

Jenkins + Docker + Ansible = Testen

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

  1. Bekijk de opslagplaats en genereer bouwfasen.
  2. Voer lint-playbook-fasen parallel uit.
  3. Voer lintrolfasen parallel uit.
  4. Voer syntaxiscontrolerolfasen parallel uit.
  5. Voer testrolfasen parallel uit.
    1. Lint rol.
    2. Controleer de afhankelijkheid van andere rollen.
    3. Controleer de syntaxis.
    4. Docker-instantie maken
    5. Voer molecule/default/playbook.yml uit.
    6. Controleer de idempotentie.
  6. Voer integratietests uit
  7. Finish

Dag #271: Busfactor

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

In eerste instantie werd de refactoring uitgevoerd door een kleine groep van twee of drie personen. Ze hebben de code in de master beoordeeld. In de loop van de tijd ontwikkelde het team kennis over het schrijven van code en codebeoordeling droeg bij aan de verspreiding van kennis over de infrastructuur en hoe deze werkt. Het hoogtepunt hierbij was dat de reviewers één voor één werden geselecteerd, volgens een schema, d.w.z. met een zekere mate van waarschijnlijkheid klim je in een nieuw stuk infrastructuur.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

En het moet hier comfortabel zijn. Het is handig om een ​​evaluatie uit te voeren, te zien in het kader van welke taak het is uitgevoerd en de geschiedenis van de discussies. We hebben jenkins + bitbucket + jira geïntegreerd.

Maar als zodanig is een recensie geen wondermiddel; op de een of andere manier kwamen we in de mastercode terecht, waardoor we floptests kregen:

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

Toen hebben ze het gerepareerd, maar het residu bleef achter.

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

Dag #311: Testen versnellen

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

In de loop van de tijd waren er meer tests en verliepen de builds langzamer, in het ergste geval tot een uur. Op een van de retro’s stond een zin als “het is goed dat er tests zijn, maar die zijn traag.” Als gevolg hiervan hebben we de integratietests op virtuele machines stopgezet en deze aangepast zodat Docker deze sneller maakt. We hebben ook testinfra vervangen door een ansible verifier om het aantal gebruikte tools te verminderen.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Strikt genomen was er een reeks maatregelen:

  1. Schakel over naar docker.
  2. Verwijder roltesten, die dubbel worden uitgevoerd vanwege afhankelijkheden.
  3. Verhoog het aantal slaven.
  4. Bestelling proefdraaien.
  5. Vermogen om te pluizen ALLEMAAL lokaal met één commando.

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Als gevolg hiervan werd Pipeline op Jenkins ook verenigd

  1. Genereer bouwfasen.
  2. Lint allemaal parallel.
  3. Voer testrolfasen parallel uit.
  4. Finish.

Lessen uit het verleden

Vermijd globale variabelen

Ansible gebruikt globale variabelen, er is een gedeeltelijke oplossing in het formulier private_role_vars, maar dit is geen wondermiddel.

Laat me je een voorbeeld geven. Laat ons hebben 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}}

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Het grappige is dat het resultaat van draaiboeken zal afhangen van zaken die niet altijd voor de hand liggen, zoals de volgorde waarin rollen worden vermeld. Helaas is dit de aard van Ansible en het beste wat je kunt doen is een soort overeenkomst gebruiken, bijvoorbeeld om binnen een rol alleen de variabele te gebruiken die in deze rol wordt beschreven.

BAD: gebruik de globale variabele.

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

GOED: V defaults definieer de noodzakelijke variabelen en gebruik deze later alleen.

# 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

Geef rolvariabelen een voorvoegsel

BAD: gebruik de globale variabele.

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

GOED: Gebruik in rollen voor variabelen variabelen voorafgegaan door de rolnaam; dit, door naar de inventaris te kijken, zal het gemakkelijker maken om te begrijpen wat er gebeurt.

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

Gebruik luscontrolevariabele

BAD: Gebruik standaardvariabele in lussen item, als deze taak/playbook ergens is opgenomen, kan dit tot onverwacht gedrag leiden

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

GOED: Een variabele in een lus opnieuw definiëren via loop_var.

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

Controleer invoervariabelen

We hebben afgesproken om variabele voorvoegsels te gebruiken; het zou niet overbodig zijn om te controleren of deze zijn gedefinieerd zoals we verwachten en bijvoorbeeld niet zijn overschreven door een lege waarde

GOED: Variabelen controleren.

- 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

Vermijd hashes-woordenboeken, gebruik een platte structuur

Als een rol een hash/woordenboek in een van zijn parameters verwacht, moeten we, als we een van de onderliggende parameters willen wijzigen, de hele hash/woordenboek overschrijven, wat de configuratiecomplexiteit zal vergroten.

BAD: Gebruik hash/woordenboek.

---
user:
  name: admin
  group: admin

GOED: Gebruik een vlakke variabele structuur.

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

Creëer idempotente draaiboeken en rollen

Rollen en draaiboeken moeten idempotent zijn, omdat vermindert configuratiedrift en de angst om iets kapot te maken. Maar als u moleculen gebruikt, is dit het standaardgedrag.

Vermijd het gebruik van opdrachtshellmodules

Het gebruik van een shell-module resulteert in een imperatief beschrijvingsparadigma, in plaats van het declaratieve paradigma, wat de kern is van Ansible.

Test je rollen via molecuul

Moleculen zijn heel flexibel. Laten we eens naar een paar scenario's kijken.

Molecuul Meerdere exemplaren

В molecule.yml in sectie platforms je kunt veel hosts beschrijven die je kunt inzetten.

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

Dienovereenkomstig kunnen deze gastheren dat dan zijn converge.yml gebruik:

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

Ansible-verificateur

In molecule is het mogelijk om ansible te gebruiken om te controleren of de instantie correct is geconfigureerd, bovendien is dit de standaard sinds release 3. Het is niet zo flexibel als testinfra/inspec, maar we kunnen wel controleren of de inhoud van het bestand aan onze verwachtingen voldoet:

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

Of zet de dienst in, wacht tot deze beschikbaar komt en doe een rooktest:

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

Zet complexe logica in modules en plug-ins

Ansible pleit voor een declaratieve aanpak, dus als je codevertakkingen, datatransformaties en shell-modules uitvoert, wordt de code moeilijk leesbaar. Om dit tegen te gaan en het eenvoudig te begrijpen te houden, zou het niet overbodig zijn om deze complexiteit te bestrijden door uw eigen modules te maken.

Vat tips en trucs samen

  1. Vermijd globale variabelen.
  2. Geef rolvariabelen een voorvoegsel.
  3. Gebruik luscontrolevariabele.
  4. Controleer invoervariabelen.
  5. Vermijd hashes-woordenboeken, gebruik een platte structuur.
  6. Creëer idempotente draaiboeken en rollen.
  7. Vermijd het gebruik van opdrachtshellmodules.
  8. Test je rollen via molecuul.
  9. Zet complexe logica in modules en plug-ins.

Conclusie

Hoe u Ansible kunt testen, het project binnen een jaar opnieuw kunt opbouwen en niet gek kunt worden

Je kunt niet zomaar de infrastructuur van een project herstructureren, zelfs als je over IaC beschikt. Dit is een lang proces dat geduld, tijd en kennis vereist.

UPD1 2020.05.01 20:30 — Voor primaire profilering van draaiboeken die u kunt gebruiken callback_whitelist = profile_tasks om lange tijd te begrijpen wat precies werkt. Dan gaan wij door Ansible-acceleratieklassiekers. Je kunt het ook proberen mitogeen
UPD2 2020.05.03 16:34 - Engels versie

Bron: www.habr.com

Voeg een reactie