đĄ Gallium
Ansible-osuus eroaa Bash, PowerShell ja Python osuuksista siten, että valmista koodia tarjoillaan merkittävästi aiempaa vähemmän. Tämä osio on kurssin loppusilaus, jossa yhdistellään Bash ja Python -osuuksissa opittua Ansibleen. PowerShell hylätään toistaiseksi, koska Ansible Control Noden tulee olla Unix-pohjainen, ja Bash on valmiina saatavilla.
Gallium-osiossa tehdään minimum viable product. Tämä tehdään muutamassa vaiheessa.
# | Vaihe | TyĂśkalu | Tavoite |
---|---|---|---|
1 | venv | UV + Python | Isolate our dependencies from system level Python |
2 | Ansible | UV | Asennetaan Ansible Core |
3 | Virtual Machines | Bash, Multipass | Create 2x Multipass VM |
4 | Inventory Generation | Python script | Generate Ansible Inventory from Multipass output |
5 | Playbook | VS Code | Write a Hello World level Playbook |
6 | Test Run | Ansible | Run the playbook |
Kuhunkin osioon on oma tärppinsä alla. Lopulta sivun pohjalla on tehtäviä, jotka sisältävät nämä vaiheet.
Tärpit
1ď¸âŁ Venv
Käytämme Pythonin paketin- ja projektinhallintaan tyÜkalua nimeltään uv.Onko se asennettuna jo Python-osion tiimoilta? Jos ei, asenna se. Se asentuu yhdellä komennolla, joka lÜytyy uv sivulta.
Voit luoda uuden Application tyypin projektin alla näkyvillä käskyillä. Huomaa, että projekti luodaan siihen hakemistoon, missä olet nyt. Varmista, että olet oikeassa hakemistossa, kuten $PROJECT_ROOT/ansible/
. Huomaa, että teemme applikaation nimeltään ansible-managed-node
. Tämä siksi, että haluamme vältellä päällekäisyyttä pelkän ansible
-nimisen projektin kanssa. Muutoin import
voi mennä pieleen tietyissä tilanteissa.
# Install a new uv-managed Python
uv python install 3.12
# Pin this directory to use the installed Python (.python-version)
uv python pin 3.12
# Create a new uv-managed Python project
uv init --name "ansible-managed-node" --bare --app .
Voit kokeilla REPL:iä näin:
$ uv run python
Creating virtual environment at: .venv
Python 3.12 (...) [...]
Type "help" for more information.
>>>
Law of UV
Huomaa, että uv
hallinnoi Pythonia.
- Ălä pidä muita Pythoneita.
- Jos ajat Pythonia, käsky alkaa
uv run <komento>
. - Jos asennat paketteja, käytä
uv add <paketti>
.
Unohda system-level Python eli /bin/python3
. Siihen ei ole asennettu eikä siihen aiota asentaa ansiblea tai muita riippuvuuksia, joita tämä applikaatio sattuu tarvitsemaan.
2ď¸âŁ Ansible
Nyt voimme asentaa Ansible Coren tähän meidän luomaamme applikaatioon. Ei siis system-wide Pythoniin. Ălä sovella omia käskyjä tekoälyn hallusinaatioiden perusteella. Lue mieluummin alla oleva tärppi.
3ď¸âŁ Virtual Machines
Voit luoda virtuaalikoneita Multipass-tyÜkalulla. Nimeä ne järkevästi, kuten ansible-1
ja ansible-2
. Voit käyttää alla olevia komentoja.
Kun myĂśhemmin haluat tuhota koneet, aja komennot:
Olisikohan tässä kenties järkevää käyttää skriptejä create-vms.sh
ja destroy-vms.sh
? No olisi! Tee tämä skriptinä.
4ď¸âŁ Inventory Generation
Ansiblea varten tarvitsemme joko koneiden hostnamet tai IP-osoitteen Inventory-tyÜkaluun. PÜllerÜn ratkaisu olisi aina käydä käsin korvaamassa IP-osoitteet kun koneet luodaan uusiksi. Tämä ei ole kovin skaalautuva ratkaisu. Sen sijaan voimme luoda skriptin, joka luo meille Inventoryn automaattisesti. Jotta tämä on mahdollista, tarvitset koneiden tiedot koneluettavassa muodossa, ja tämä onnistuu Multipassin avulla.
Mikä parempaa, voimme lopulta luoda Python-skriptin, joka lukee tämän outputin ja kirjoittaa sen tiedostoon config/inventory/hosts.ini
. Lisätään kumpikin kone groupiin multipass
, ja luodaan kummallekin oma ryhmänsä: first
ja second
. Tämä siksi, että voimme jatkossa kohdentaa käskyjä vain yhteen virtuaalikoneeseen helposti. Meillä ei ole DNS-osoitteita hallittuina, emmekä halua joutua kirjoittamaan IP-osoitteita, koska ne vaihtuvat joka kerta kun koneet tuhotaan ja luodaan uusiksi. Skriptiä voisi käyttää käsin näin:
$ multipass list --format json | uv run scripts/multipass-to-inv.py
[INFO] Adding 192.168.64.41 to inventory
[INFO] Adding 192.168.64.42 to inventory
[INFO] Inventory written to config/inventory/hosts.ini
$ cat config/inventory/hosts.ini
[multipass]
192.168.64.41
192.168.64.42
[first]
192.168.64.41
[second]
192.168.64.42
Yllä oleva komento olisi hyvä lisätä aiemmin luomaasi create-vms
-skriptiin, eikÜ vain? Näin inventorio ei voi vahingossa unohtua tilaan, jossa se ei ole ajan tasalla.
Opettajan skripti
Voit käyttää tämän kaltaista skriptiä. Tunnista puuttuvat riippuvuudet ja lisää ne uv add
-komennolla.
import sys
from pydantic import BaseModel
from ipaddress import IPv4Address
from pathlib import Path
TARGET_FILE = Path("config/inventory/hosts.ini")
class VMInfo(BaseModel):
ipv4: list[IPv4Address]
name: str
release: str
state: str
class VMList(BaseModel):
list: list[VMInfo]
def read_raw_json_from_stdin() -> str:
if sys.stdin.isatty():
print("No input string given", file=sys.stderr)
sys.exit(1)
return "".join([line.strip() for line in sys.stdin])
def vmlist_to_ini(vm_list: VMList, ini_file) -> str:
ini_file.parent.mkdir(parents=True, exist_ok=True)
with ini_file.open("w") as f:
f.write("[multipass]\n")
for vm in vm_list.list:
ip = vm.ipv4[0].exploded
print(f"[INFO] Adding {ip} to inventory")
f.write(f"{ip}\n")
f.write("\n[first]\n")
f.write(vm_list.list[0].ipv4[0].exploded)
f.write("\n")
f.write("\n[second]\n")
f.write(vm_list.list[1].ipv4[0].exploded)
if __name__ == "__main__":
raw_json = read_raw_json_from_stdin()
vm_list = VMList.model_validate_json(raw_json)
vmlist_to_ini(vm_list, TARGET_FILE)
print(f"[INFO] Inventory written to {TARGET_FILE}")
5ď¸âŁ Playbook
Luo yksinkertainen Playbook, joka vain tulostaa Hello, World!
. Tämä on hyvä tapa varmistaa, että Ansible toimii ja että koneet ovat saavutettavissa. Voit käyttää pohjana Ansible Community Docs: Creating a playbook ohjeen esimerkkiä.
6ď¸âŁ Test Run Erehdys â
Bug
Nyt on tuikata Playbook käyntiin, ottaa etäisyyttä ja ihailla käsien tyÜtä. Kuten aiemmasta Creating a Playbook -ohjeesta tiedät, komento on:
$ uv run ansible-playbook -i configs/inventory/hosts.ini configs/playbooks/hello.yml
uv run ansible-playbook -i config/inventory/hosts.ini config/playbooks/hello-world.yml
PLAY [Hello World]
fatal: [192.168.64.42]: UNREACHABLE! =>
{
"changed": false,
"msg": "...myuser@192.168.64.42: Permission denied (publickey).",
"unreachable": true
}
Uh oh! Eihän homma toimi laisinkaan, mutta tämä on ihan odotettua. Kuinka me voisimme saada SSH-yhteyden hostiin, johon emme ole lisänneet meidän julkista avainta? Lisäksi, yritimme yhdistää käyttäjällä myuser
, joka on host-koneen käyttäjänimi.
Korjataan tämä tilanne tasan kerran käsin oppimisen vuoksi. Ensi luvussa automatisoimme tämän.
6ď¸âŁ Test Run Korjaus â
Saat lisättyä avaimen näin:
# Copy our public key to the remote hosts
multipass transfer ~/.ssh/id_ed25519.pub ansible-1:/tmp/id_ed25519.pub
multipass transfer ~/.ssh/id_ed25519.pub ansible-2:/tmp/id_ed25519.pub
# Append the public key to authorized_keys in /home/ubuntu/.ssh
multipass exec ansible-1 -- bash -c "cat /tmp/id_ed25519.pub >> ~/.ssh/authorized_keys"
multipass exec ansible-2 -- bash -c "cat /tmp/id_ed25519.pub >> ~/.ssh/authorized_keys"
# Disable SSH host key checking. This means the
# "Are you sure you want to continue connecting (yes/no/[fingerprint])?" prompt is not shown.
# and the host is blindly trusted.
export ANSIBLE_HOST_KEY_CHECKING=False
# Run the playbook using the ubuntu user
uv run ansible-playbook -i config/inventory/hosts.ini config/playbooks/hello-world.yml -u ubuntu
Tulosteen pitäisi olla jotakuinkin:
PLAY [Hello World] *********************
TASK [Gathering Facts] *********************
ok: [192.168.64.45]
ok: [192.168.64.44]
TASK [Print Hello World] *********************
ok: [192.168.64.45] => {
"msg": "Hello, World!"
}
ok: [192.168.64.44] => {
"msg": "Hello, World!"
}
PLAY RECAP *********************
192.168.64.44 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.64.45 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Tehtävät
Tehtävä: Ansible DevausympäristÜ
Luo yllä olevien tärppien avulla devausympäristÜ hakemistoon ansible/
. Projektisi juuren tulisi näyttää siis lopulta tältä:
johnanderton
âââ README.md
âââ ansible/
âââ bash/
âââ pwsh/
âââ python/
Jos tarkastelemme vain ansible/
-hakemistoa, sen tulisi näyttää tältä:
ansible
âââ .python-version
âââ .venv
â âââ .gitignore
â âââ many.files.here
âââ config
â âââ inventory
â â âââ hosts.ini
â âââ playbooks
â âââ hello-world.yml
âââ pyproject.toml
âââ scripts
â âââ create-vms.sh
â âââ destroy-vms.sh
â âââ multipass-to-inv.py
âââ uv.lock
Huomaa, että osa tiedostoista luodaan komentojen avulla, osa käsin. Ălä luo esimerkiksi pyproject.toml
tai uv.lock
tiedostoja käsin. Käytä uv
-tyÜkalua, kuten tärpeissä on neuvottu.
Note
Tuotannossa hakemistorakenne olisi todennäkÜisesti monimutkaisempi. Ansible Docs: Sample Ansible setup antaa esimerkkejä siitä, kuinka hakemistot voivat olla järjestetty.
Tehtävä: Ansible Hello World
Toisinna yllä näkyvät vaiheet siten, että saat Ansiblen tulostamaan Hello, World!
molemmille virtuaalikoneille. Käytä apunasi yllä olevia tärppejä.