Ansible
# Ansible
Ansible (opens new window) is een open-source software provisioning, configuratie management, en applicatie-deployment tool die infrastructuur als code mogelijk maakt. Het draait op alle Linux systemen (als ook Unix systemen) en Microsoft Windows, en kan deze ook configureren. Het bevat een eigen declaratieve taal om systeemconfiguratie te beschrijven. Ansible is geschreven in 2013 door Michael DeHaan en in 2015 overgenomen door Red Hat die nu commerciele ondersteuning bied. Voor ons is Ansible een handige tool omdat het agentless is. Het maakt tijdelijk op afstand verbinding via SSH of Windows Remote Management (waardoor PowerShell op afstand kan worden uitgevoerd) om zijn taken uit te voeren, tegenover sommige alternatieven als Chef of Puppet is voor Ansible op de server geen installatie nodig! Dit laat ons toe sneller servers op te zetten.
In dit deel focussen we op het gebruik op Linux (meer bepaald Ubuntu). Windows installatie van Ansible is moeilijker.
Ansible gaat ons toelaten om in YAML formaat Linux en Windows servers te configureren. We kunnen bestanden aanmaken, configuratie aanpassen en software installeren. In vergelijking met een script is een paar verschillen:
Ansible laat ons toe meerdere servers tegelijk te configureren en beheren doormiddel van inventories.
Ansible checkt na het verbinden met je server wat al gebeurd is en zorgt dat je server bij elke Ansible-run op to date is met wat in je Ansible configuratie staat. Je kan dus gerust je installatie laten staan Ansible checkt dit steeds voor het uitvoeren. Dit laat je toe snel servers toe te voegen.
# Installatie
Ansible moeten we enkel installeren op de client. Hiervoor raad ik aan een Ubuntu Desktop te installeren.
Installeer Ansible via APT:
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
2
3
4
# Concepten
Deze concepten komen voor in Ansible. Hiermee bouw je een Ansible setup op:
# Control node
Elke machine waarop Ansible is geïnstalleerd. Je kab Ansible-opdrachten en -playbooks uitvoeren door het ansible
of ansible-playbook
commando uit te voeren.
Vaak is dit onze laptop, maar het kan ook een andere server zijn waar heel je team aan kan.
# Managed nodes
Dit zijn de servers die je beheert met Ansible. Managed nodes worden ook wel eens "hosts" genoemd. Ansible wordt niet geïnstalleerd op managed nodes.
# Inventory
Een lijst vanmanaged nodes. Een inventoryfile wordt ook wel eens een "hostfile" genoemd. Je inventory kan informatie specificeren zoals IP adressen voor elke managed node. Een inventory kan ook beheemanaged rde nodes organiseren, groepen aanmaken en nesten voor eenvoudiger schalen.
# Modules
De eenheden van code die Ansible uitvoert. Elke module heeft een specifiek gebruik, van het beheren van gebruikers op een specifiek type database tot het beheren van VLAN-interfaces op een specifiek type netwerkapparaat. Je kan een enkele module aanroepen met een taak, of meerdere verschillende modules aanroepen in een playbook. Vele van deze modules worden meegeleverd of zijn te vinden op het internet. Deze modules besperen ons tijd door al expertise te gebruiken van mede-Ansible-gebruikers.
# Task
De eenheden van actie in Ansible. Je kan een enkele taak eenmalig uitvoeren met een ad-hoc commando.
# Playbooks
Geordende lijsten van tasks, opgeslagen zodat je die taken herhaaldelijk in die volgorde kunt uitvoeren. Playbooks kunnen zowel variabelen als taken bevatten. Playbooks worden geschreven in YAML.
# Getting started
We hebben al Ansible geinstalleerd op onze Ubuntu. We gaan enkele acties uitvoeren als demo van Ansible. We gaan snel in een cloud provider een VM aanmaken en deze configureren met Ansible.
We zorgen ervoor dat we we een SSH key hebben:
ssh-keygen # en volg de stappen
cat ~/.ssh/id_rsa.pub
2
Je kan deze key nu ingeven bij het aanmaken van de VM.
# Project opzetten
We maken een map aan waar we ons Ansible project in kunnen zetten. We openen de map hierna in een editor als Visual Studio Code.
Alseerst maken we een file met naam hosts
(verander de username wel)
[servers]
<IP> ansible_user=ubuntu ansible_python_interpreter=/usr/bin/python3
2
Nu maken we een file met naam ansible.cfg
[defaults]
inventory = hosts
host_key_checking = False
2
3
Je kan nu zien of Ansible de hosts herkent:
$ ansible all --list-hosts
hosts (1):
141.148.244.47
2
3
TIP: in WSL kan een gedeelde map van Windows gezien worden als "world writable" wat in Ansible een security mechanisme triggered je kan hier rond werken door het expliciet toe te laten in een environment variable:
export ANSIBLE_CONFIG=$(pwd)/ansible.cfg
We pingen (SSH test in dit geval) nu de servers:
$ ansible all -m ping
Nu maken we een file met naam main.yml
- hosts: servers # installer dit op all hosts onder "servers:
tasks:
- name: Create a directory if it does not exist
become: yes # become is kort voor become_user root
file:
path: /ansible_was_here
state: directory
- name: Install SL
become: yes
apt:
name: sl
state: present
update_cache: yes
2
3
4
5
6
7
8
9
10
11
12
13
14
We voeren nu de file uit:
$ ansible-playbook main.yml
We zien nu dat Ansible de map /ansible_was_here
heeft aangemaakt alsook dat de SL is geïnstalleerd. Als we dit opnieuw draaien bevestigt Ansible dat de map al bestaat en dat de SL al geïnstalleerd is. We kunnen deze verwijderen Ansible terug draaien en onze servers zijn weer inorde!
# Roles
In dit voorbeeld hebben we op al onze servers hetzelfde gezet, nu dit is meestal niet het geval. We spreken vaak van server roles. Dit zijn rollen die een bepaalde server kan aannemen. We zien hieronder een typische structuur voor zo een rollen:
ansible/
├── roles
│ ├── common
│ │ └── tasks
│ ├── web_server
│ │ ├── handlers
│ │ ├── tasks
│ │ │ ├── main.yml
│ │ │ ├── setup_db.yml
│ │ │ └── setup_nginx.yml
│ │ └── templates
│ │ └── nginx_site_config.j2
├── hosts_production
├── hosts_staging
├── mail.yml
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Onze main.yaml
zegt dan welke server tags welke roles krijgen
- hosts: web_hosts
roles:
- common
- web_server
2
3
4
Elke role heeft een structuur:
tasks
zijn onze taken, we starten altijd met demain.yml
templates
zijn templates voor files, hierdoor kan je variables gebruiken in configuratie fileshandlers
zijn handlers voor de acties, bijvoorbeeld als een configuratie file wordt aangepast de service te herstarten
# Plugins
Absible heeft een groot ecosysteem van plugins, je hebt vele externe maar ook ingebouwde plugins. De volledige lijst van ingebouwde kan je op de Ansible site vinden (opens new window).
# Top Modules
# APT
- name: Install MariaDB
become: yes
apt:
name: mariadb-server
state: present
update_cache: yes
2
3
4
5
6
# Services
- name: Restart apache2
service:
name: apache2
state: restarted
2
3
4
# Copy
- name: Write some content in a file /tmp/hello.txt
copy:
dest: /tmp/hello.txt
content: |
Good Morning!
Awesome sunshine today.
2
3
4
5
6
- name: Copy a new "ntp.conf file into place, backing up the original if it differs from the copied version
copy:
src: /mine/ntp.conf
dest: /etc/ntp.conf
owner: root
group: root
mode: "0644"
backup: yes
2
3
4
5
6
7
8
# File
- name: Change file ownership, group and permissions
file:
path: /etc/foo.conf
owner: foo
group: foo
mode: "0644"
2
3
4
5
6
- name: Create a directory if it does not exist
file:
path: /etc/some_directory
state: directory
mode: "0755"
2
3
4
5
- name: Delete content & directory
file:
state: absent
path: /home/ubuntu/tempfiles/
2
3
4
# Lineinfile
- name: Add a line to a file
lineinfile:
path: /etc/hosts
line: 192.168.1.99 foo.lab.net foo
2
3
4
# Git
- name: Clone a Git repo
git:
repo: https://github.com/ansible/ansible-examples.git
dest: /src/ansible-examples
2
3
4
# Archive
- name: Compress directory /path/to/foo/ into /path/to/foo.tgz
archive:
path: /path/to/foo
dest: /path/to/foo.tgz
2
3
4
# Command
- name: Change the working directory to somedir/ and run the command as db_owner if /path/to/database does not exist.
command: /usr/bin/make_database.sh db_user db_name
become: yes
become_user: db_owner
args:
chdir: somedir/
creates: /path/to/database
2
3
4
5
6
7
# Opdracht
We hebben onze eerste stappen gezet in Ansible, nu is het aan jouw om je eeste Ansible playbooks te schrijven!
We willen een playbook voor het opzetten van een webserver:
- Installeer apache
- Installeer PHP
- Maak een index.php pagina met de inhoud van onderaan
<?php
echo '<h1>Hello Ansible</h1>';
phpinfo();
2
3
Standaard gaat Oracle cloud alle poorten blocken in iptables
, ook hier kunnen we in plaats van commando's te schrijven een playbook gebruiken:
- name: Allow incoming connections
become: yes
iptables:
chain: INPUT
jump: ACCEPT
flush: yes
- name: Allow outgoing connections
iptables:
chain: OUTPUT
jump: ACCEPT
flush: yes
become: yes
- name: Allow forwarding of connections
iptables:
chain: FORWARD
jump: ACCEPT
flush: yes
become: yes
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Ansible voor Cisco IOS
We kunnen Ansible natuurlijk ook voor meer dan enkel voor Linux servers gaan gebruiken. Een mogelijke integratie is de lessen netwerkbeheer met Cisco IOS. De IOS Collection (opens new window) heeft een uitgebreide lijst van modules voor Cisco apparaten. Ook voor IOS-XE (opens new window) is er een Ansible Collection.
Tips
Onze les switchen kunnen verouderd zijn en een oude SSH key exchange gebruiken. Dit kan je oplossen door de oude key exhanges in te schakelen:
sudo nano /etc/ssh/ssh_config
Unquoten de lijn Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
En voeg onderaan toe:
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms +ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa
2
3
In requirements.yml
voegen we de volgende toe:
---
collections:
- name: cisco.ios
2
3
Dan installeren we de plugin:
ansible-galaxy collection install -r requirements.yml
Alle aparaten waar we op willen werken moeten natuurlijk SSH enabled hebben als ook een IP hebben. We kunnen deze dan ook in een hosts file zetten.
We kunnen hierna deze modules gebruiken om onze router/switch te configureren.
Je kan vele voorbelden vinden in de GitHub repository.
Dit zijn is een klein vorbeeldje:
---
- hosts: switches
vars:
vlan_id: 998
vlan_name: Ansible_VLAN
tasks:
- name: Ensure Fa2/0/5 is configured for access vlan 20
cisco.ios.ios_l2_interface:
name: FastEthernet2/0/5
mode: access
access_vlan: { { vlan_id } }
2
3
4
5
6
7
8
9
10
11
12
Probeer de Ansible IOS Demo (opens new window) eens uit! Probeer nu ook twee switches tegelijk te configureren met licht verschillende configuraties.
# Resources
Ga je in je project Ansible gebruiken? Lees dan zeker deze resources!
- Ansible Documentation (opens new window)
- Ansible "registers" (opens new window) - laat acties alleen toe als iets veranderd is (bv server herstart)
- More complex structures (opens new window)
- Example project (opens new window)