Disclaimer

Informatiile de mai jos expun o mica parte a capabilitatilor uneltelor prezentate precum si unul dintre numeroasele contexte si scenarii[1] in care pot fi folosite acestea.

Nu presupuneti ca o problema similara trebuie rezolvata in modul expus aici sau ca aceasta e abordarea corecta; scopul acestui document este de a expune

  • o mica parte din ce poate face aceasta unealta

  • un scenariu pur teoretic, cu putina aplicabilitate practica

astfel incat sa va formati o opinie despre conceptele de baza din jurul acesteia.

IaC - Infrastructure as Code

Conceptul se refera la acea categorie de unelte care ne ajuta sa mentinem resursele dintr-un mediu de lucru sub forma de text.

Resursele ce pot fi administrate fac parte dintr-o plaja foarte larga de tehnologii si pot contine:

  • resurse IaaS:: Infrastructure as a Service

    • masini virtuale

    • instante dedicate de baze de date: Database as a Service e.g., AWS RDS i.e., Relational Database Service

    • volume: discuri i.e., block devices

    • routere virtuale: AWS VPC i.e., Virtual Private Cloud, MS Azure Virtual Network

    • subneturi

    • …​

  • resurse SaaS:: Software as a Service

    • Instante i.e., scheme de baze de date

    • Utilizatori in respectivele baze de date

    • Clustere Kubernetes

    • Load Balancere L3/L7

    • …​

  • resurse arbitrare

    • Proiecte, grupuri, etc in platforme precum GitLab

    • record-uri in DNS

    • containere intr-un host Docker

    • …​

Informatii suplimentare despre subiect gasiti pe Wikipedia.

IaC vs click-click

Cream mai jos o masina virtuala intr-o instanta OpenStack folosind modulul server al colectiei openstack.

- name:  Creeaza o instanta
  openstack.cloud.server:
    state: present
    auth:
      auth_url: https://endpoint.iam.instanta.openstack.lan
      username: admin
      password: admin
      project_name: devops-guild
    name: vm-de-test
    image: ubuntu-bionic
    key_name: "ssh-rsa a@b"
    timeout: 200
    flavor: "m1.small"
    network: "devops-guild-net"

Spre deosebire de cateva operatiuni manuale:

Operatiuni manuale pentru replicarea declaratiei de mai sus

Alte unelte folosite in acest sens

Vrei sa folosesti Ansible pentru IaC?

Poate; eu nu. Poate daca:

  • Proiectul pe care lucrezi a investit deja in asta

  • Cei implicati stiu doar Ansible

Altfel, as spune ca:

  • Modelul implicit Ansible este de a se conecta la sisteme remote; aici modulele s-ar executa pe hostul de pe care rulam Ansible → inventarul ar putea arata cam ciudat

  • Nu exista un raspuns corect; nu il cautati, experimentati :^)

Software provision, Configuration management, App deployment

Cu toate ca linia de demarcatie e difuza, spre deosebire de IaC, in zona de configuration management, app deployment etc, atentia e indreptata asupra altor aspecte, precum:

  • serviciile

  • pachetele

  • utilizatorii

  • deployment-ului de aplicatii custom

de pe un sistem dat. Altfel spus, mai putin asupra resurselor de infrastructura si mai mult asupra serviciilor si ecosistemului serviciilor respective.

Configuration management vs click-clack

Scenariu

Vrem sa:

  • cream trei utilizatori, toti parte a grupului primar admini:

    • asterix

    • obelix

    • idefix

  • instalam patru pachete:

    • lynx

    • tmux

    • vsftpd

    • gcc

  • configuram un banner specific la login:

Va rugam politicos sa nu folositi acest sistem daca nu aveti dreptul sa o faceti.  Multumim!

--- Panoramix si echipa

pe o distributie Debian 10 si pe o distributie CentOS 7. Mai intai aratam cum se face 'de mana' dupa documentatie si-apoi vedem cum se poate face folosind o unealta de configuration management.

Click-clack
Cream utilizatorii pe ambele sisteme folosind aceleasi comenzi
sudo groupadd admini
sudo useradd asterix --gid admini
sudo passwd asterix # adaugam o parola pentru userul asterix
sudo useradd obelix --gid admini
sudo useradd idefix --gid admini
Pe Debian instalam pachetele cu
sudo apt-get update
sudo apt-get install lynx tmux vsftpd gcc
Pe CentOS instalam pachetele cu:
sudo yum install lynx tmux vsftpd gcc
Aplicam bannerul ce trebuie afisat la login
cat <<EOF > /workspace/student/motd
Va rugam politicos sa nu folositi acest sistem daca nu aveti dreptul sa o faceti.  Multumim!

--- Panoramix si echipa
EOF
sudo mv /workspace/student/motd /etc/motd
Configuration management
playbook.yml
---
- hosts: "{{ _hosts | default('all') }}"   # executam asupra tuturor sistemelor despre care stim
  vars:
    utilizatori:
      - user: asterix # Parola este: asterix
        parola: "$6$U9D8CKVFasZBXtfE$jElu7BDrU7bykn2LudE1moTKea3ffK5Tad0P9x2T/U5y0rGm8Q4qcbm/VivSvRy0Yk3b29V0rX3J.KH0UFMEP/"
      - user: obelix
      - user: idefix
    pachete:   # definim o variabila de tip lista pentru stocarea numelor pachetelor
      - lynx
      - tmux
      - vsftpd
      - gcc
    motd: |
      Va rugam politicos sa nu folositi acest sistem daca nu aveti dreptul sa o faceti.  Multumim!

      --- Panoramix si echipa
  tasks:       # executam pasii pe care ni-i dorim
    - name: Instalam grupul
      group:
        name: "admini"

    - name: Instalam utilizatorii
      user:
        name: "{{ item.user }}"
        group: "admini"
        password: "{{ item.parola | default(omit) }}"
        state: present
      loop: "{{ utilizatori }}" # executam modulul `user` pentru fiecare utilizator

    - name: Instalam pachetele
      package:
        name: "{{ pachete }}"
        state: present

    - name: Aplicam bannerul
      copy:
        content: "{{ motd }}"
        dest: "/etc/motd"
        owner: root
        group: root
        mode: "0644"
Am uitat sa creez un utilizator!?
  1. Mai rulez o data acelasi lucru

  2. Rulez doar diferentele

  3. Rescriu pasii intr-un script

  4. Ma folosesc de facilitatea numita idempotenta

Alte solutii?

Destule, nu toate se muleaza 1:1 pe situatia de mai sus.

Ansible

Inventar

Unul sau mai multe fisiere statice, dinamice, sau combinatie intre aceste variante prin care definim sistemele pe care dorim sa le administram.

Pentru constructia inventarului, ansible se foloseste de plugin-uri; acestea pot citi hosturi din fisiere in formate precum .ini sau .yaml, sau pot executa scripturi care la randul lor culeg informatii despre hosturile pe care dorim sa le administram.

Doua hosturi parte din grupul all, unul parte din grupul debian, intr-un inventar static in format .ini
[all]
sistem1.lan
sistem2.lan

[debian]
sistem3.lan
Note
sistem3.lan face parte si din grupul all; toate hosturile fac parte implicit si din grupul all.

Proprietati specifice grupului sau hostului in sine pot fi declarate in directoarele host_vars sau group_vars:

$ inventar/
.
├── group_vars
│   ├── all.yml
│   └── debian.yml
├── host_vars
│   └── sistem1.lan.yml
└── inventar.yml

Playbook

Intr-un playbook descriem:

  • hosturile asupra carora vrem sa aplicam continutul playbook-ului

  • succesiunea de taskuri[2] in sine; un exemplu de task ar putea fi chemarea unui modul ansible specializat pe un grup de actiuni e.g., modulul user, care administreaza aspecte legate de utilizatorii prezenti pe un sistem Linux/Unix:

    • username

    • parola

    • home directory

    • shell folosit

    • …​

Metode de conectare

In mod traditional Ansible foloseste cateva metode de conectare la hosturile tinta:

  • SSH

  • local

  • paramiko_ssh (implementare python SSH) folosita mai ales pentru sisteme mai vechi

Listarea metodelor de conectare disponibile mediului curent
ansible-doc -t connection -l
Un exemplu foarte scurt de playbook
---
- hosts: localhost          # Se aplica masinii de pe care rulez ansible
  connection: local         # Nu folosesc ssh pentru conectare pe acest sistem
  tasks:
    - name: Afiseaza distributia pe care o folosesc
      debug:                # Folosesc modulul debug pentru a afisa o variabila
        var: ansible_distribution

Suplimentar, intr-un playbook mai pot fi descrise:

Variabile

O sumedenie de variabile sunt adunate prin modulul gather_facts executat implicit la rularea playbook-ului.

Acestora li se alatura cele definite in Inventar.

Output al modulului gather_facts
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.0.2.15"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::a00:27ff:fe2d:64d9"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "12/01/2006",
...

Demo?

Documentatie


1. In unele proiecte se foloseste ansible pentru Jinja2, motorul de template-izare folosit de ansible
2. Indiferent ca taskurile reprezinta executia unui modul, chemarea unui rol, definirea unui handler etc