Menedzseljük a saját gépünket!

Amikor új gépet kapunk a munkahelyen, az mindig egy jó érzés. Mire szép lassan belakjuk és letöltünk rá mindent: böngészőt, IDE-t, egyéb csomagokat, beállítgatjuk a háttérképet, Steamet, Spotify-t és még sok mást. Ez az első pár alkalommal még egy kellemes élmény, mert az újdonság varázsa megszépíti az egészet, de amikor már az ötödik közel ugyanolyan laptopra kell mindezt megtenni, akkor már kevésbé élvezetes. Arról nem is beszélve, hogy a munkáltató minden percét megsiratja, ugyanis amíg telepítgetünk, addig bizony egy forintot se termelünk.
A szerverek konfiguráció menedzsmentjére és automatizálására már bevált módszerek vannak, de a saját asztali gépünkre vagy laptopunkra ezeket valamiért nem annyira használjuk. Holott, ha ügyesen csináljuk, akkor minden egyes ilyen újratelepítéssel értékes órákat spórolhatunk meg, nem beszélve arról az érzésről, amikor már azt hittük, hogy mindennel végeztünk, de a projekt első buildelésénél kiderül, hogy még valami hiányzik.
Az egyik ilyen eszköz az Ansible, amivel mi is fogunk foglalkozni a továbbiakban. Akad persze sok másik hasonló eszköz, de talán ez az egyik legkisebb erőforrás igényű - hiszen nem akarunk szervert üzemeltetni csak azért, hogy a saját gépünket menedzseljük -, és viszonylag könnyen érthető szintaxisa van.
A cikkben Linux rendszerekről lesz szó, de MacOS-en is használhatjuk, igaz némileg korlátozottan. Először azonban fontos megvizsgálni, hogy milyen gyakran is telepítünk újra gépet, hogy lássuk egyáltalán megéri-e? Ha tízévente egyszer, akkor bizonyára nem igazán éri mindez meg. Sajnos nem mindenki tud ennyire vigyázni a gépére, így akik szeretik felelősség nélkül széttúrni a rendszert, azoknak inkább szól ez a cikk. A másik csoport, akik - lévén rengeteg Linux disztribúció van a piacon - gyakran váltogatják a rendszerüket, próbálgatnak újakat. Ezt akár virtuális gépen, akár fizikain teszik, az automatizmus a segítségükre lehet.
Szintén jól jöhet, ha van egy otthoni és egy munkahelyi gépünk, amiket közel azonos konfiguráción akarunk tartani.
Viszont sok a szöveg és kevés a kód, lássunk hozzá!
Szóval mi is ez az ansible? Az ansible egy python alapú eszköz, aminek a segítségével egy központi gépről tudunk más gépeket menedzselni. Ez úgynevezett agentless, azaz nem igényli azt, hogy az általa menedzselt gépen bármilyen speciális program fusson, így elég a központi gépre feltelepíteni, a többit SSH-n megoldja. A mi esetünkben a központi gép és a menedzselt gép is a localhost lesz, így ez nem is számít.
Először is telepítsük azt. A Linux/MacOS rendszereken a python megtalálható, így mi most annak a segítségével fogjuk telepíteni azt:
1
$ python -m pip install --user ansible
Ezzel már el is érhetővé válik az ansible parancs, amivel megállapíthatjuk, hogy minden klappol-e?
1
2
3
4
5
6
7
$ ansible --version
ansible 2.10.6
config file = None
configured module search path = [u'/home/tacsiazuma/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /home/tacsiazuma/.local/lib/python2.7/site-packages/ansible
executable location = /home/tacsiazuma/.local/bin/ansible
python version = 2.7.18 (default, Mar 8 2021, 13:02:45) [GCC 9.3.0]
Mint mondtam, mi nem akarunk szervert igénybe venni ehhez, viszont nem ússzuk meg, hogy valahol tároljuk a konfigurációt. Erre egy github-os repository-t fogok használni, szóval hozzatok ti is létre egyet és utána klónozzátok azt le magatokhoz:
1
$ git clone https://github.com/letscodehu/localhost-ansible
Az ansible hoz magával egy speciális parancsot is, ami különösen jó lesz nekünk, ez pedig az ansible-pull. Ez lényegében annyit csinál, hogy egy távoli repositoryból letölti a konfigurációt és aztán nekiáll feldolgozni azt. Tehát pontosan jó lesz nekünk. Viszont ahhoz az kell, hogy ez a távoli repository tartalmazzon is valamit, így vigyük fel a konfigurációt!
Yaml fájlokat fogunk használni, amit sokan nem szeretnek, habár már kiirthatatlanul beleitta magát a devops világba. Legyen a fájl pl local.yml
:
1
2
3
4
5
- hosts: localhost
become: true
tasks:
- name: Install tmux
apt: name=tmux
Elég egyszerű kis konfiguráció, nem? Annyit adunk meg neki, hogy a localhoszton dolgozzon, utána, mivel az apt parancshoz root user kell, ezért a become: true
-val jelezzük, hogy szükség lesz egy privilégium eszkalációra a feladatok végrehajtására. Ha jelszó nélküli sudo van beállitva, akkor nincs más dolgunk, ha szükség van jelszóra, akkor pedig a paranccsorban hozzáfűzzük, hogy --ask-become-pass
és rákérdez a jelszóra, amit használni fog. Ezután pedig felsoroljuk, hogy milyen feladatokat is kell végrehajtani a tasks
alatt. Mindnek van neve, valamint egy hozzá tartozó modul, ami esetünkben az apt. Minden ilyen modulhoz elég jó dokumentáció van, példákkal, ennek például itt, de használhatjuk az ansible-doc parancsot is:
1
ansible-doc apt
Innen láthatjuk is, hogy lényegében az apt segítségével telepítjük vele a tmux csomagot. A taskok definíciója gyakorlatilag így néz ki:
1
2
3
4
5
6
tasks:
- name: feladat neve, mi adjuk meg
modulneve: paraméter=érték
paraméter: érték
paraméter: érték
általános_paraméterek: érték
Akkor most nézzük, hogy tudjuk ezt lefuttatni?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ansible-playbook local.yml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] ************************************************************************************************************************************************************
TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [localhost]
TASK [Install tmux] *********************************************************************************************************************************************************
ok: [localhost]
PLAY RECAP ******************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Na akkor mi is történt itt? A két warning azért van, mert nem egy localhosttal szoktak dolgozni, hanem több hosttal, azokat csoportokba szedve, stb. Ez az a bizonyos inventory, amit hiányol. Egy ilyen yaml fájl jelent egy play-t, a benne levő elemek pedig a taskok.
Az install tmux
még ismerős, de ez a gathering facts
micsoda? Ez pontosan az, aminek tűnik, a célgépről összegyűjt információkat az ansible, környezeti változókat, stb. amik később hasznosak lehetnek. Na de ez még annyira nem volt hasznos, kicsit dobjuk fel, nem? Oké, hogy van tmux, de kell még pl neovim. Sőt, jó volna ha tmuxból is újat kapnánk, így legyen egy apt update előtte, nem?
A neovim telepítő linkje itt található:
https://github.com/neovim/neovim/wiki/Installing-Neovim#linux
Ezt felhasználva:
1
2
3
4
5
6
7
8
9
10
11
12
13
- hosts: localhost
become: true
tasks:
- name: update repositories
apt: update_cache=yes
changed_when: False
- name: Install tmux
apt: name=tmux
- name: Install neovim
get_url:
url: https://github.com/neovim/neovim/releases/latest/download/nvim.appimage
dest: /usr/local/bin/neovim
mode: '0755'
Most felvettünk két új elemet. Az egyik, hogy az apt updatet lefuttatjuk, hogy biztosan a legfrissebb csomagokat húzzuk le, pl tmuxból. A neovimet másképp telepítjük majd, itt egy app imaget használunk. A get_url
HTTP(S) forrásokból tud letölteni fájlokat, amiket amúgy lehet cURL-al oldanánk meg. Megadhatjuk, hogy honnan, hova töltsön le, valamint a célfájl jogosultságait is beállíthatjuk egy lépésben. Sokan egyébként arra esküsznek, hogy nekik nem kell semmit telepíteni szinte, hiszen mindent dockerben futtatnak. Na és a dockert hogy telepítik? Kézzel? Akkor automatizáljuk azt is! Azonban ezt nem egy fájlba fogjuk pakolni, hanem elkezdjük szeparálni a dolgokat.
1
2
$ mkdir tasks
$ vim tasks/terminal.yml
Ide kerülnek azok, amik pl a terminálhoz szükséges elemek:
1
2
3
4
5
6
7
8
9
10
- name: update repositories
apt: update_cache=yes
changed_when: False
- name: Install tmux
apt: name=tmux
- name: Install neovim
get_url:
url: https://github.com/neovim/neovim/releases/latest/download/nvim.appimage
dest: /usr/local/bin/neovim
mode: '0755'
Ami új lehet itt az a changed_when: False
. Az ansible jelzi, ha valamelyik hoston változást okozott az egyik modul. Ezzel a kapcsolóval ezt ki tudjuk kapcsolni az adott taskra. Miért? Mert nem akarjuk, hogy mindig azt jelezze, hogy változott valami, holott csak újabb csomagok érhetőek el.
Ezután pedig csinálunk egy playt a dockernek is:
1
$ vim tasks/docker.yml
Amibe az ahhoz szükséges elemek kerülnek:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- name: Install required system packages
apt: name= state=latest update_cache=yes
loop: [ 'apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common', 'python3-pip', 'virtualenv', 'python3-setuptools']
- name: Add Docker GPG apt Key
apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker Repository
apt_repository:
repo: deb https://download.docker.com/linux/ubuntu bionic stable
state: present
- name: Update apt and install docker-ce
apt: update_cache=yes name=docker-ce state=latest
- name: Install Docker Module for Python
pip:
name: docker
Cserébe a local.yml
elkezd egyszerűsödni:
1
2
3
4
5
- hosts: localhost
become: true
tasks:
- include: tasks/docker.yml
- include: tasks/terminal.yml
Ilyenkor, ha include
-ot használunk, akkor lényegében azokat a fájlokat egy az egyben beemeli oda, ezért nem kellett a fájlok elejére a tasks:
sem.
Ez mondjuk még nem minden, hiszen pl a neovimhez felrakhatjuk a csomagkezelőt, letölthetjük a vimrc
fájlunkat githubról, telepíthetjük a plugineket a háttérben:
1
2
3
4
5
6
7
8
9
10
11
12
13
- name: Install vundle
git:
repo: https://github.com/VundleVim/Vundle.vim.git
dest: ~/.vim/bundle/Vundle.vim
become_user: tacsiazuma
- name: Setup vimrc
get_url:
url: https://raw.githubusercontent.com/Tacsiazuma/dotfiles/master/vimrc
dest: /home/tacsiazuma/.vimrc
become_user: tacsiazuma
- name: Install neovim plugins
command: nvim +PluginInstall +qall
become_user: tacsiazuma
A vundlet git clone
segítségével is felrakhatnánk, azonban az ansible modulok segítségével jobb mindez, ugyanis az úgynevezett idempotencia a cél a műveleteknél. Azaz ha többször lefuttatjuk ugyanazokat a taskokat egy gépen, akkor az állapot ugyanaz lesz. A modulok, ha látják, hogy már elértük a kívánt célt, akkor nem csinálnak semmit. Ellenben a git clone
mindig lefut és másodjára már hibát jelezne, mert a mappa már létezik.
A become_user
itt is fontos, ugyanis nem szeretnénk root felhasználóként létrehozni fájlokat, neovimet futtatni meg főleg, mert akkor másik vim configot használna.
Ez eddig viszont főleg azoknak jó, akik a terminálban élnek. Mi a helyzet a külsejével a rendszernek? Kedvenc téma, háttérkép? Ez is megoldható, amíg Linuxról van szó! Mivel most egy ubuntut akarunk testreszabni, ami Gnome asztali környezettel érkezik, ezért nevezzük a fájlt, amibe csoportosítjuk mindezt gnome.yml
-nak. Ha pl KDE-vel akarjuk mindezt, akkor lehet kde.yml
is a neve, hogy aztán ezeket a módosításokat tudjuk csoportosítgatni.
Beállítjuk először a háttérképet, utána pedig témákat. Töltsünk le valami jó háttérképet és nevezzük el wallpaper.jpg
-nek (vagy amilyen kiterjesztése van) és másoljuk a files
mappába. Igaz nem jó dolog képeket és hasonló dolgokat verziókövetni, de remélhetőleg nem fogjuk folyton cserélgetni azt. Alternatív megoldásként használhatjuk a korábban látott get_url
módszert is.
1
2
3
4
5
6
7
- name: Install python-psutil package
apt: name=python3-psutil
- name: Copy wallpaper
copy: src=files/wallpaper.jpg dest=/home/tacsiazuma/.wallpaper.jpg owner=tacsiazuma group=tacsiazuma mode=600
- name: Set GNOME Wallpaper
become_user: tacsiazuma
dconf: key="/org/gnome/desktop/background/picture-uri" value="'file:///home/tacsiazuma/.wallpaper.jpg'"
A python3-psutil
csomagra azért van szükség, hogy az ansible dconf modul működjön. Ezután felmásoljuk a háttérképet a home mappánkba, .wallpaper.jpg
néven, így rejtett fájl lesz, ezután pedig a dconf háttérképre vonatkozó kulcsának beállítjuk az elérési útját.
Persze mehetünk tovább és átállíthatjuk a témát is:
1
2
3
4
5
- name: Install arc theme
apt: name=arc-theme
- name: Set Arc theme
become_user: tacsiazuma
dconf: key="/org/gnome/desktop/interface/gtk-theme" value="'Arc'"
Természetesen ne felejtsük el ezeket a playeket is includeolni a local.yml
-ben:
1
2
3
4
tasks:
- include: tasks/docker.yml
- include: tasks/terminal.yml
- include: tasks/gnome.yml
Ezután pedig nézzük, hogy is tudjuk ez tegy lépésben megtenni, hogy ne kelljen lehúzni a repot? Erre lesz jó a korábban említett ansible-pull
! A változásokat commitoljuk, majd pusholjuk fel githubra. Ezután nincs más dolgunk, mint egy lépésben lehúzni azt és a benne levő playbookot lejátszani:
1
ansible-pull -U https://github.com/letscodehu/localhost-ansible
Ha új rendszert telepítünk, akkor ennyi dolgunk lesz összesen.
Láthatjuk, hogy viszonylag könnyen tudjuk szépen egymás után fűzni a parancsokat, amikkel testreszabhatjuk a gépünket. Persze ez igényli azt is, hogy a konfigurációt naprakészen tartsuk. A dconf
ebben segítségünkre lehet, hiszen a rendszeren végzett nem fájl vagy csomagszintű beállításokat végig tudjuk követni. Nincs más dolgunk, mint a friss telepítéskor kidumpolni, majd a módosítások után is és a két fájlt összevetni, hogy megtaláljuk a módosításokat:
1
2
3
dconf dump / > initial.txt
dconf dump / > changed.txt
diff initial.txt changed.txt
így már látjuk is, hogy miket módosítottunk, amiket a dconf
kezel.
Ha pedig már a saját gépünket elkezdtük így menedzselni és nem állnak messze tőlünk a szerverek, akkor lehet érdemes azok menedzsmentjét is automatizálni, nemde?
Na de mi a helyzet a .bashrc
-vel, .tmux.conf
-al, .Xmodmap
-el? Ezeket is pakoljuk be ide és másolgassuk őket? Szerencsénkre erre is lesz egy megoldás, a dotfiles
nevű python csomag és egy másik github repo segítségével, amit a folytatásban fogunk kitárgyalni és integrálni az ansible playbookunkba.