Jenkins som ett alternativ till Ansible Tower
Ansible Tower kommer med en stor prislapp, speciellt för ett mindre företag eller en privatperson. AWX å andra sidan är helt fritt, men kräver numera Kubernetes. För den som vill automatisera sina Ansible Playbooks går det dock bra att använda Jenkins som en ersättning för Tower och AWX.
Jenkins är ett CI/CD-verktyg (continuous integration/continuous delivery) som är helt fritt och har öppen källkod. Det är ett verktyg för att automatisera hela cykeln av mjukvaru-utveckling; från kompilering, testning och paketering till publicering. Men i själva verket går det att använda Jenkins till så mycket mer – det är ett allt-i-allo-verktyg. Här kommer vi att använda Jenkins för att exekvera Ansible Playbooks.
Ett Jenkins-jobb går att trigga på en rad olika sätt, exempelvis via ett API, en förändring på filsystemet eller schemalagt på en specifik tidpunkt. När ett jobb har körts kan vi se exakt vad som hände i loggen. Det finns även ett plugin för Ansible till Jenkins. Med detta får vi stöd för bland annat Ansible Vault. Lösenord för Ansible Vault-filer kan vi spara i Jenkins under Credentials. Jag använder själv Jenkins på detta sättet, bland annat för att uppdatera system och förnya Let’s Encrypt-certifikat bakom en failover.
Installationen av Jenkins kommer inte att behandlas i denna artikeln då det
finns många sätt att installera det på. Det går att installera Jenkins via
operativsystemets pakethanterare, via en .war
-fil eller via en
Docker-avbild. Det finns också färdiga molnavbilder för Jenkins hos de stora
molnleverantörerna. I denna guiden utgår vi från att Jenkins har installerats
via operativsystemets pakethanterare på en Debian- eller Ubuntu-dator.
Installera Ansible på servern
För att Jenkins ska kunna använda Ansible behöver vi först installera det på datorn eller servern som kör Jenkins. Här kommer vi att installera Ansible som ett PIP-paket i en viruell Pythonmiljö. Fördelen med detta är att vi får en isolerad Ansiblemiljö som är nyare än den som finns i operativsystemetes pakethanterare. En annan fördel är att vi kan ha flera Ansible-installationer om det skulle behövas.
För att kunna skapa virtuella Pythonmiljöer behöver vi installera paketen
python3-pip
och python3-venv
i Debian och Ubuntu. På Fedora och CentOS
räcker det att installera python3-pip
; paketet för virtuella miljöer ingår
redan i Python-paketet.
Jag väljer att placera allt Ansible-material under katalogen
/home/jenkins-stuff/ansible
och sätter användaren och gruppen jenkins som
ägare.
#> mkdir -p /home/jenkins-stuff/ansible
#> chown -R jenkins:jenkins /home/jenkins-stuff
Därefter byter jag användare till jenkins (denna skapas autoamtiskt vid installationen av Jenkins):
#> su jenkins
$>
Nu kan vi installera Ansible:
$> cd /home/jenkins-stuff/ansible
$> python3 -m venv env
$> source env/bin/activate
(env) $> pip install wheel
[...]
(env) $> pip install ansible
[...]
Nu kan vi testa så att installationen fungerar:
(env) $> ansible --version
ansible [core 2.12.3]
[...]
Installera och konfigurera Ansible-pluginet i Jenkins
När vi nu har en fungerande Ansible-installation behöver vi installera ett plugin för Ansible i Jenkins.
I Jenkins webb-GUI välj Dashboard → Manage Jenkins. Välj sedan Manage Plugins. Under fliken Available söker vi efter ett plugin som heter Ansible plugin. När vi hittat det väljer vi att installera pluginet. Eventuellt kan du behöva starta om Jenkins efter att du installerat det.
Vi behöver också tala om för Jenkins var Ansible-pluginet kan hitta den
Ansible-installation vi gjorde tidigare. Gå till Dashboard → Manage
Jenkins igen och därefter Global Tool Configuration. Långt ner på sidan
hittar vi Ansible. Klicka på Ansible installations…. Klicka sedan
på Add Ansible. Fyll i ett namn för denna Ansible-installationen,
exempelvis Ansible eller MinAnsible. Under Path to ansible executables
directory skriver vi den kompletta sökvägen till Ansible. I mitt fall blir
det /home/jenkins-stuff/ansible/env/bin
.
Det är allt vi behöver konfigurera för att själv pluginet ska fungera.
Skapa en playbook, inventarie och tillhörande filer
Nästan steg blir att skapa en playbook på vår Jenkins-server och alla de tillhörande filer som behövs, så som en inventariefil, grupp- och värdinställningar med mera.
Vi kommer att placera alla Ansible-filer, så som
playbooks, inventarie-filer, katalogerna group_vars
och host_vars
med mera
under /home/jenkins-stuff/ansible
.
I detta exemplet använder vi en enkel playbook som uppdaterar Debian- och
RedHat-baserade system. Vi kommer att använda en lösenordsskyddad SSH-nyckel
för att logga in på servrarna som ska uppdateras. sudo
och root-lösenorden
kommer vi att spara krypterat med Ansible Vault i host_vars
- och
group_vars
-katalogerna. Vi börjar med filerna för playbooken.
Filerna för vår playbook
Dessa filerna är för själva playbooken. Vi placerar dem under
/home/jenkins-stuff/ansible
.
upgrade.yml
Detta är vår playbook, det är den vi kommer att exekvera från Jenkins. Jag
använder här serial: 1
för att bara uppdatera en server i taget om något
skulle gå snett.
# Playbook for upgrading Debian/Ubuntu systems and reboot it if
# there were updates applied.
- hosts: ankeborg
become: true
serial: 1
tasks:
- import_tasks: upgrade-apt.yml
- import_tasks: upgrade-dnf.yml
handlers:
- import_tasks: reboot-linux.yml
upgrade-apt.yml
# Tasks for upgrading Debian-based systems and reboot if
# updates were applied.
- name: Update Debian-based systems
when: ansible_os_family == 'Debian'
apt:
update_cache: yes
upgrade: dist
notify: Reboot machine
upgrade-dnf.yml
# Tasks for upgrading RedHat/CentOS/Fedora systems reboot if
# updates were applied.
- name: Upgrade RedHat-based systems
when: ansible_os_family == 'RedHat'
dnf:
name: "*"
state: latest
update_cache: yes
update_only: yes
notify: Reboot machine
reboot-linux.yml
- name: Reboot machine
reboot:
msg: "Reboot initiated by Ansible"
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 30
test_command: whoami
Inventariefilen
Vi behöver också en inventariefil så att Ansible vet vilka värdar vi ska
uppdatera. Här har jag döpt gruppen till ankeborg och värdarna efter
invånarna i Ankeborg. Anpassa filen efter dina egna värdar. Även denna filen
ska placeras under /home/jenkins-stuff/ansible
.
hosts
[ankeborg]
knatte.nixnet.jke ansible_host=192.168.0.29
fnatte.nixnet.jke ansible_host=192.168.0.24
tjatte.nixnet.jke ansible_host=192.168.0.42
joakim.nixnet.jke ansible_host=192.168.0.47
Grupp- och värdinställningar
Vissa av mina värdar använder su
med en riktig root-användare och vissa
andra använder sudo
för att utföra uppgifter som root. De flesta använder
sudo
med samma lösenord för alla värdarna, därför konfigurerar jag detta för
hela gruppen. Därefter specificerar jag de avvikande värdarna var för sig.
Om du inte redan har katalogerna group_vars
och host_vars
i
/home/jenkins-stuff/ansible
behöver du skapa dem först.
group_vars/ankeborg.yml
ansible_user: jake
ansible_become_pass: peak-airspeed
ansible_become_method: sudo
Eftersom vi lagrar lösenordet i filen är det säkrast om vi krypterar den med
ansible-vault
. Här väljer jag lösenordet popcorn-pants för filen.
(env) $> pwd
/home/jenkins-stuff/ansible
(env) $> ansible-vault encrypt group_vars/ankeborg.yml --ask-vault-password
Vault password:
host_vars/joakim.nixnet.jke.yml
ansible_become_method: su
ansible_become_pass: speech-fargo
Även denna filen krypterar vi ansible-vault
med samma lösenord:
(env) $> ansible-vault encrypt host_vars/joakim.nixnet.jke.yml --ask-vault-password
Vault password:
host_vars/knatte.nixnet.jke.yml
ansible_become_method: su
ansible_become_pass: speech-fargo
Vi gör samma sak här – krypterar filen med ansible-vault
med samma lösenord:
(env) $> ansible-vault encrypt host_vars/knatte.nixnet.jke.yml --ask-vault-password
Vault password:
Acceptera värdarnas SSH-fingeravtryck
För att undvika att SSH-anslutningarna stannar vid att acceptera värdarnas SSH-fingeravtryck är det enklast om vi manuellt ansluter till dem en gång. Vi behöver inte logga in nu, utan bara acceptera deras fingeravtryck.
(env) $> ssh knatte.nixnet.jke
The authenticity of host 'knatte (192.168.0.29)' can't be established.
ECDSA key fingerprint is SHA256:yYw0JoqD9u07ikSGa14tIl2yXVEf77jG1caooBnnK88.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'knatte' (ECDSA) to the list of known hosts.
^D
Upprepa proceduren för samtliga värdar.
Konfigurera Jenkins att köra vår playbook
Nu behöver vi konfigurera allting i Jenkins, exempelvis SSH-nyckeln till
värdarna, lösenordet för ansible-vault
, sökvägen till vår playbook och några
andra saker.
SSH-nyckeln
Det första vi behöver göra är att lägga in SSH-nyckeln i Jenkins som används för att logga in på värdarna. Här förutsätter jag att du redan har en nyckel och har kopierat den publika delen till värdarna.
I mitt exempel använder jag det globala credentials-utrymmet eftersom jag är ensam användare i Jenkins. Har du en mer avancerad uppsättning av Jenkins placerar du den där det passar bäst.
I Jenkins GUI välj Dashboard → Manage Jenkins → Manage Credentials. Under Store väljer du Jenkins och sedan Global credentials (unrestricted). Här kan vi lägga till SSH-nyckeln genom att klicka på Add Credentials.
Under Kind väljer vi SSH Username with private key. I fältet Username skriver vi in användarnamnet som används för att logga in på värdarna. I mitt fall är detta jake. I ID-fältet skriver vi något som identifierar denna nyckeln, exempelvis användarnamnet. Under Private Key välj Enter directly, klicka på Add och klistra in nyckeln i textfältet. Om nyckeln är skyddad av ett lösenord skriver du in det i fältet Passphrase. Spara sedan genom att klicka på Save.
Lösenordet för Ansible Vault
Vi behöver skapa ytterligare en credentials, nämligen lösenordet för de
filer som vi krypterade med ansible-vault
.
Fortfarande under Dashboard → Manage Jenkins → Manage Credentials → Store → Jenkins → Global credentials (unrestricted) väljer vi Add Credentials igen. Denna gången väljer vi typen Secret text. I fältet Secret skriver vi in lösenordet för valven vi skapde. I mitt fall är detta popcorn-pants. Under ID väljer jag det beskrivande namnet ankeborgs-valv.
Skapa ett Jenkins-jobb för vår playbook
Nu är det dags att skapa själva jobbet som kommer att köra vår playbook.
Gå till Dashboard och välj New Item. Skriv ett namn för jobbet, exempelvis Uppdatera Ankeborg. Välj sedan Freestyle project och klicka på OK.
Nu kan vi välj hur jobbet ska triggas. Under Build Triggers väljer jag
Build periodically för att uppdatera servrarna regelbundet. I textrutan
Schedule skriver jag in 15 04 28 * *
. Detta kommer att köra jobbet
klockan 04:15 den 28:e varje månad.
Under Build ska vi nu lägga till två byggsteg. Det första blir att sätta några miljövariabler för Ansible, och det andra blir blir att köra vår Ansible Playbook. Vi börjar därför med att klicka på Add build-step och väljer Inject Environment variables. I textrutan Properties Content skriver vi in följande:
PYTHONPATH=/home/jenkins-stuff/ansible/env/lib
ANSIBLE_HOME=/home/jenkins-stuff/ansible
Klicka sedan på Add build-step igen. Denna gången väljer vi Invoke Ansible
Playbook. I rutan Playbook path anger vi sökvägen till playbooken, i vårt
fall blir det /home/jenkins-stuff/ansible/upgrade.yml
.
Under Inventory väljer vi File or host list och anger sökvägen
/home/jenkins-stuff/ansible/hosts
.
Under Credentials väljer vi den användare och SSH-nyckel som ska användas för att logga in på värdarna. I mitt fall är detta jake.
Under Vault Credentials väljer vi lösenordet för valven vi skapade. I mitt fall är detta ankeborgs-valv.
Spara allting genom att klicka på Save.
Testköra
Nu kan vi testköra jobbet genom att gå till Dashboard och klicka på jobbet Uppdatera Ankeborg. Här kan vi starta jobbet manuellt genom att klicka på Build Now.
Under Build History dyker jobbet upp efter några sekunder. Det går att följa vad som händer i jobbet genom att klicka på byggjobbet, exempelvis #1, och sedan Console Output. När jobbet har avslutats utan några fel ändras statusen till en grön bock. Annars avslutas det med ett rött kryss.
Avslutning
Detta är bara ett exempel på hur det går att köra Ansible Playbooks via Jenkins. Det går att göra betydligt mer avancerade uppsättningar. Exempelvis går det att trigga bygget från ett API, hämta playbook-filerna genom Git, eller exekvera playbooks från andra Jenkins-noder och mycket mer.
Nyhetsbrev
Nyhetsuppdateringar från tidningen direkt till din inkorg, helt kostnadsfritt. Avsluta när du vill.
Relaterade artiklar
-
Avlyssna trafik på servern med Wireshark och TShark
Wireshark är ett ovärderligt verktyg för att felsöka nätverkskonfigurationer, applikationer, API:er, demoner och mycket annat. I kombination med
tshark
kan vi dessutom avlyssna trafiken på en server i realtid. -
Var försiktig med att curl:a skript som root
Att installera program i Linux genom att omdirigera utdata från Curl till skalet är snabbt och smidigt. Men det är ack så farligt om du inte känner till programmet eller dess ursprung.
-
Vidarebefordran av SSH-agenten
SSH agent forwarding, eller vidarebefordran av SSH-agenten, innebär att man kan vidarebefordra SSH-agenten till ett fjärrsystem. På så sätt behöver man inte kopiera sin privata SSH-nyckel till fjärrsystemet, eller skapa flera nycklar för olika system. Men det finns risker med det.
-
Hämta data från API:er med cURL och jq
Med cURL och jq går det att extrahera data från API:er direkt från kommandoraden. Jq är en JSON-tolkare och beskrivs av utvecklarna som sed och awk för JSON.
Senaste nyheterna och inläggen
-
Avlyssna trafik på servern med Wireshark och TShark
Wireshark är ett ovärderligt verktyg för att felsöka nätverkskonfigurationer, applikationer, API:er, demoner och mycket annat. I kombination med
tshark
kan vi dessutom avlyssna trafiken på en server i realtid. -
Mysig stämning på sommarens första demoparty
I helgen var det Reunion 2024 i Kvidinge Folkets hus, sommarens första skånska demoparty. Partyt organiserades av Jesper “Skuggan” Klingvall. På plats fanns ett 30-tal besökare.
-
Sommarens skånska demopartyn
Årets sommar bjuder på två skånska demopartyn. Först ut är Reunion i Kvidinge den 28–30 juni. Därefter är det Pågadata i Örtofta den 9–11 augusti.
-
Riskerna med BankID som ingen pratar om
BankID är ett säkert och smidigt sätt att identifiera sig online. Men i takt med dess ökade popularitet och användning har det blivit en svag länk – en single point of failure – på mer än ett sätt.
-
Polisernas fängelsedomar står fast
Efter tre år är målet mot de två poliser som olovligen tog sig in i en berusad mans bostad i Landskrona och misshandlade honom klart. Högsta domstolen beslutade den sjätte mars att avvisa överklagan. Fängelsedomarna för poliserna står därmed fast.
Utvalda artiklar
-
Mysig stämning på sommarens första demoparty
I helgen var det Reunion 2024 i Kvidinge Folkets hus, sommarens första skånska demoparty. Partyt organiserades av Jesper “Skuggan” Klingvall. På plats fanns ett 30-tal besökare.
-
Datorparty i Landskrona
I helgen höll Syntax Society sitt årliga sommarparty. Platsen var en källarlokal i Landskrona där ett femtontal personer medverkade.
-
Det första Pågadata har ägt rum
I helgen ägde det första Pågadata rum – uppföljaren till Gubbdata. Platsen var Folkets Hus i Kvidinge. Organisatör av partyt var Johan “z-nexx” Osvaldsson med hjälp från Jesper “Skuggan” Klingvall. Partyt hade över 100 anmälda deltagare.
-
Även hovrätten fäller poliserna för att ha satt dit oskyldig
Hovrätten fastställer straffet för de två poliser som förra året dömdes till vardera ett års fängelse av Lunds tingsrätt för att ha misshandlat och satt dit en oskyldig man. De båda poliserna ska även betala skadestånd till mannen.
-
Retroloppis i Påarp
Idag var det retroloppis hos Andreas Nilsson i Påarp. På baksidan av huset fanns hundratals spel uppradade på långa bord. Trots friska vindar och sval temperatur var loppisen välbesökt.
CyberInfo Sverige är ett it- och medieföretag i nordvästra Skåne som tillhandahåller böcker, utbildningar, nyheter och konsulttjänster inom Linux, säkerhet och programmering.
CyberInfo Sverige är godkänd för F-skatt, är momsregistrerat och innehar
utgivningsbevis för webbplatsen www.cyberinfo.se.