Virtualizacija korištenjem Virtual Machine Managera
Za jednostavno upravljanje virtualnim strojevima iz grafičkog sučelja koristit ćemo Virtual Machine Manager (kraće virt-manager ili VMM). Virt-manager podržava brojne platforme uključujući Linux Cointainers (LXC) i Xen, a mi ćemo ga koristiti za QEMU i KVM.
Stvaranje virtualnog stroja
Nakon pokretanja virt-managera pritiskom na gumb Create a new virtual machine
pokrećemo proces stvaranja novog virtualnog stroja. U prvom koraku u dijelu Choose how you would like to install the operating system
biramo:
Local install media (ISO image or CDROM)
ako želimo instalirati OS na klasičan način kao na fizičkom računaluImport existing disk image
ako želimo koristiti unaprijed pripremljenu sliku za korištenje na virtualizacijskim sustavima i u oblaku.
Preuzimanje, priprema i odabir slike
Primjerice, za Ubuntu možemo takve slike preuzeti s cloud-images.ubuntu.com. Preuzet ćemo sliku iz direktorija focal
(kodno ime za Ubuntu 20.04 LTS) pa current
; kako radimo na računalu čiji se procesor temelji na arhitekturi x86-64, odnosno AMD64, datoteka koja nam odgovara je focal-server-cloudimg-amd64.img
.
Napravimo kopiju preuzete slike koju ćemo koristiti kod stvaranja virtualnog stroja. Slika ima zadanu veličinu diska od 2 GiB, pri čemu se prazan prostor samo navodi, a zapravo ne zauzima gotovo ništa. Ta će nam veličina za praktične potrebe biti premalena pa je možemo povećati korištenjem QEMU-ovih pomoćnih alata, specifično qemu-img
(dokumentacija). Primjerice, za povećanje na veličinu od 25 GiB naredba je oblika:
$ qemu-img resize moja-ubuntu-slika.img 25G
image resized
Alternativno, sliku možemo povećati za danu veličinu, npr. 30 GiB na način:
$ qemu-img resize moja-ubuntu-slika.img +30G
image resized
Ako provedemo oba koraka, slika će imati 55 GiB.
U drugom koraku stvaranja virtualnog stroja pod Provide the existing storage path:
kliknimo na Browse...
. Zatim u dijalogu koji se otvori pod nazivom Locale or create storage volume
kliknimo na gumb Browse Local
pa pronađimo stvorenu kopiju.
U dijelu Choose the operating system you are installing:
pronađimo Ubuntu 20.04
.
Postavke virtualnog stroja
U trećem koraku biramo postavke memorije i procesora za novostvoreni virtualni stroj. Varijanta Ubuntua koju koristimo nema grafičko sučelje i uredno će raditi s manje od predloženih 4096 MiB RAM-a i 2 CPU-a, odnosno 2048 MiB i 1 CPU će biti dosta. Ta štedljivost će nam biti korisna obzirom da ćemo vremenom stvarati veći broj virtualnih strojeva.
U posljednjem koraku imamo mogućnost prilagodbe konfiguracije uključivanjem kvačice pored Customize configuration before install
i odabira mreže koja će se koristiti. Zasad ostavimo te postavke kakve jesu.
Nakon pokretanja virtualnog stroja uočit ćemo kako se ne možemo prijaviti ma koje korisničko ime i zaporku isprobali jer je potrebno iskorisiti cloud-init za konfiguraciju cloud slike koju smo preuzeli.
Zadatak
U virtualnom stroju instalirajte HTTP poslužitelj Apache (paket apache2
). Iskoristite Firefox ili cURL kako biste se uvjerili da poslužitelj ispravno radi, a zatim (po)maknite zadanu datoteku index.html
i na njenom mjestu stvorite novu datoteku sa sadržajem po vašoj želji.
Tip
Ako ste zaboravili povećati veličinu preuzete slike prije pokretanja virtualnog stroja, moguće je da ćete instalacijom dodatnih paketa popuniti disk. U tom slučaju prvo zaustavite virtualni stroj, povećajte disk, a zatim nakon pokretanja iskoristite naredbu apt
s parametrom --fix-broken
i argumentom install
kako biste instalacijom potrebnih paketa doveli stanje u red:
sudo apt --fix-broken install
Povezivanje na virtualni stroj korištenjem OpenSSH-a
QEMU/KVM u zadanim postavkama mreže (prevođenje mrežnih adresa, engl. network address translation, kraće NAT) dodjeljuje svim virtualnim strojevima adrese u rasponu 192.168.122.0/24. Naredbom ip addr
unutar virtualnog stroja možemo provjeriti koja je adresa dodijeljena tom stroju:
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether e0:d5:5e:25:a1:29 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.147/24 brd 192.168.11.255 scope global dynamic noprefixroute enp5s0
valid_lft 42841sec preferred_lft 42841sec
Na virtualni stroj možemo se povezati OpenSSH-om korištenjem korisničkog imena ubuntu
i zaporke koju smo postavili na način:
$ ssh ubuntu@192.168.122.147
ubuntu@192.168.122.147's password:
Nakon toga možemo normalno pokretati naredbe, npr. možemo provjeriti koliko slobodnog prostora na disku u virtualnom stroju imamo naredbom df -h
.
Stvaranje više virtualnih strojeva
Stvaranjem više kopija Ubuntuove slike i više kopija ranije stvorene slike user-data.img
možemo stvoriti više virtualnih strojeva. Svaki par slika se može koristiti samo za jedan virtualni stroj.
Zadatak
Stvorite još jedan virtualni stroj pa u njemu instalirajte HTTP poslužitelj Apache i modul za PHP (paket libapache2-mod-php
). Prilagodite PHP skriptu:
<?php
$stream = fopen('http://www.example.com/', 'r');
echo stream_get_contents($stream);
fclose($stream);
tako da umjesto sadržaja s www.example.com
povlači i ispisuje sadržaj s vašeg prvog poslužitelja te je spremite kao index.php
, a zatim (po)maknite zadanu datoteku index.html
.
Složenije topologije u oblaku
Web poslužitelji i baza podataka
Zadatak
Stvorite tri virtualna stroja. Na prvom virtualnom stroju instalirajte MariaDB poslužitelj (paket mariadb-server
). Stvorite bazu i u njoj barem jednu tablicu sa stupcima po želji te je popunite podacima po želji. Omogućite pristup sa zaporkom udaljenom korisniku imena po želji (ime domaćina '%'
omogućit će pristup s bilo koje adrese, razmislite je li vam to u interesu).
Naposlijetku, kako biste učinili da se MariaDB veže i na adrese do kojih je moguće doći izvana, promijenite postavku bind-address
u datoteci /etc/mysql/mariadb.conf.d/50-server.cnf
iz vezivanja na lokalnu adresu:
bind-address = 127.0.0.1
u vezivanje na sve adrese:
bind-address = 0.0.0.0
Preostala dva virtualna stroja neka imaju Apache i modul za PHP te PHP-ov modul za MySQL (paket php-mysql
). Na ta dva virtualna stroja stvorite index.php
sadržaja (izvor koda):
<?php
$mysqli = mysqli_connect("database.example.com", "user", "password", "database");
$result = mysqli_query($mysqli, "SELECT mycolumn AS _column FROM mytable");
$row = mysqli_fetch_assoc($result);
echo $row["_column"];
Pritom ćete postavke povezivanja u mysqli_connect()
i upit u mysqli_query()
prilagoditi svojim potrebama.
Uvjerite se pristupanjem IP adresama tih dvaju virtualnih strojeva da sve uspješno radi. (Uputa: Pratite poruke o pogreškama u datoteci /var/log/apache2/error.log
.)
Balansiranje opterećenja web poslužitelja
Zadatak
Dodajte još jedan virtualni stroj i na njemu instalirajte HAProxy (paket haproxy
). Dopunite datoteku /etc/haproxy/haproxy.cfg
sadržajem:
frontend myfrontend
bind :80
default_backend myservers
backend myservers
server apache1 srv1.example.com:80
server apache2 srv2.example.com:80
Prilagodite konfiguraciju svojim potrebama, a zatim se uvjerite da radi balansiranje opterećenja između dva poslužitelja.
Odvojena distribucija statičkih resursa
Zadatak
Na dva virtualna stroja koji imaju HTTP poslužitelj Apache i modul za PHP promijenite format poslanih podataka da bude JSON.
Dodajte još jedan virtualni stroj koji ćete koristiti za distribuciju statičkih sadržaja (HTML, CSS, fontovi, JavaScript, slike, audiovizualne datoteke itd.). Na njemu postavite HTTP poslužitelj Apache (ovaj put bez dodavanja interpretera skriptnih jezika) tako da poslužuje datoteku index.html
oblika:
<!DOCTYPE html>
<html>
<body>
<p>Address received is: <span id="myIP"></span></p>
<script>
var myHeaders = new Headers({ Accept: "application/json" });
const myInit = { headers: myHeaders };
fetch("http://apps.group.miletic.net/ip/", myInit)
.then(function (response) {
return response.json().then(function (data) {
document.getElementById("myIP").innerHTML = data["address"];
});
})
.catch(function (err) {
console.log("Failed to fetch page: ", err);
});
</script>
</body>
</html>
Prilagodite adresu u pozivu funkcije fetch()
tako da hvata podatke s vašeg balansera opterećenja te ostatak JavaScripta i HTML-a po potrebi, ovisno o strukturi JSON-a koju vaš poslužitelj bude vraćao.
Author: Vedran Miletić