# Virtualisatie

Virtueel is het antoniem van werkelijk. Met virtualisatie bedoelen we het opzetten van virtuele systemen of systeemonderdelen, die op dezelfde manier werken als hun werkelijke tegenhangers.

# Hypervisor en virtuele machine

Bij virtualisatie zal virtualisatiesoftware de toegang tot de hardware onderscheppen. De virtualisatiesoftware creëert hiervoor een gevirtualiseerde omgeving die een virtuele machine of VM genoemd wordt. Voor het maken en beheren van de virtuele machines wordt een hypervisor of VMM gebruikt.

Twee belangrijke begrippen:

  • De host (Ned. gastheer, gastvrouw) Is de werkelijke computer met een besturingssysteem en virtualisatiesoftware.
  • De guests (Ned. gasten) Zijn één of meerdere virtuele machines met een eigen besturingssysteem.

Het gastbesturingssysteem is zich niet bewust van de virtualisatie. De virtuele machine gedraagt zich net als een werkelijke computer.

# Soorten virtualisatie

# Emulatie

Bij emulatie kan of mag het gastbesturingssysteem de fysieke hardware niet rechtstreeks aanspreken. Dit laat toe dat de machine-instructies vertaald worden naar machine-instructies voor een compleet ander soort hardware. Bijvoorbeeld ARM-instructies uitvoeren op een x86-processor, of 64-bit-instructies uitvoeren op een 32-bit-processor.

Deze aanpak laat maximale flexibiliteit toe, maar vanzelfsprekend is de vertaling is nadelig voor de snelheid. Doordat de snelheid van processors toeneemt, is de overhead voor het vertalen steeds kleiner.

Voorbeelden van emulatie:

# Native virtualization (full virtualization)

Bij native virtualization moeten de machine-instructies van de guest geschikt zijn voor de hardware van de host, omdat de gevirtualiseerde hardware rechtstreeks aangesproken kan worden.

Bij native virtualization wordt een volledige computer gesimuleerd, daarom spreekt men ook soms van full virtualization. Hierdoor is het mogelijk om een standaard besturingssysteem (zonder specifieke aanpassingen) te installeren op de VM. Bepaalde onderdelen, zoals netwerkkaarten of grafische kaarten worden wel nog geëmuleerd.

Emulatie heeft als voordeel dat de virtuele machines steeds dezelfde stuurprogramma’s kunnen gebruiken, ongeacht de fysieke hardware. Het nadeel is dan weer het snelheidsverlies.

Voorbeelden van native virtualization:

# Paravirtualization

Bij paravirtualization wordt geen hardware geëmuleerd. De hardware wordt via speciale API’s in het hostbesturingssysteem aangesproken. Hierdoor moet het gastbesturingssysteem speciaal aangepast zijn. De Hypervisor moet hierdoor minder complex zijn, en is daardoor potentieel sneller dan bij native virtualization. De meeste native virtualization hypervisors en besturingssystemen hebben ondersteuning voor paravirtualization.

Voorbeelden van hypervisors met paravirtualization:

  • Microsoft Hyper-V (Windows 10 en Windows Server 2019)
  • Citrix XenServer
  • Xen Hypervisor

VMware Server ondersteunt ook paravirtualization via VMI, de open specificatie van een paravirtualizationinterface van VMware.

# Virtuele harddisks

Virtuele harddisks worden opgeslagen in bestanden:

  • VDI (Oracle VM VirtualBox)
  • VMDK
  • VHD (Microsoft)

# Virtual appliances

Een virtual appliance is een volledig kant-en-klare installatie en configuratie van een virtual machine. Meestal heeft de virtual appliance een specifiek doel, bijvoorbeeld een webserver of een installatie van een CMS.

Virtual appliances worden op gespecialiseerde sites vaak onder de vorm van een OVF-bestand aangeboden, zowel gratis als commercieel. Het is uiteraard ook mogelijk om zelf een VM te exporteren naar een dergelijk bestand.

# Containers

Het besturingssysteem van de host met daarboven een hypervisor die een of meerdere guests heeft met elk nog eens een eigen besturingssysteem kan wat van het goede te veel zijn. Sinds een aantal jaar zijn containers een efficiënter alternatief voor een VM.

Een container is een applicaties die in een container image verpakt is en op een container runtime gedeployed werd.

Een container voor een webapplicatie bestaat dan bijvoorbeeld uit een HTTP-server, databasesoftware, de eigenlijke webapplicatie en de bibliotheken waarvan de webapplicatie gebruikmaakt. Die container kan dan werken op elke server waar de container engine geïnstalleerd is, ongeacht de hardware of het besturingssysteem. Het is ook mogelijk om de onderdelen in aparte containers te zetten.

Het formaat van de containers wordt gestandaardiseerd door OCI (opens new window).

# Virtualisatie VS Containers

Virtualisatie Container
Guest besturingssystemen: Deze hebben elk hun eigen kernel. Dit is ‘expensive’ op vlak van resource allocation. Hierop installeren we dan onze libraries en binaries. Vervolgens kopieëren we hier op onze bestanden (app) Geen besturingsysteem! Gewoon direct containers met hierin de libs en binaries met onze app. De apps staan dus op dezelfde host.
Hypervisor: de link tussen je Host en Guest, deze zal het virtualisatiebestand kunnen lezen. (VMWare, VirtualBox) Geen Hypervisor: het draait een proces genaamd de Docker Daemon. Dit proces faciliteert de docker containers op je systeem, de images die je aanmaakt…
Het besturingssyteem van de Host: Windows, Mac OS, Windows Server of Linux Het besturingssyteem van de Host: Windows, Mac OS, Windows Server of Linux
De infrastructuur: dit is de host. Dat is bijvoorbeeld je laptop, een high-end server. De infrastructuur: dit is de host. Dat is bijvoorbeeld je laptop, een high-end server.

# Docker

Docker Engine (opens new window) is een veelgebruikte container runtime die op zowel Linux, macOS als Windows werkt. Voor de programmeur is handig, want ontwikkeling gebeurt meestal op Windows of macOS, terwijl de webapplicatie later op Linux zal draaien.

  • Lightweight, het bestaat uit kleine images waaruit we containers zullen maken. Dus we moeten niet door het lastige proces van virtualisatie.
  • Draagbaar of portable: we kunnen deze containers draaien op verschillende besturingssystemen. Dankzij docker-files is dit ontzettend gemakkelijk.
  • Performant: er wordt geen besturingssysteem opgestart voor elk proces. Het start dus ook op in enkele seconden.
  • Geen hypervisor: het zal nog sneller werken omdat het communiceert met de hardware van de host. Containers hebben niet hun eigen kernel maar gebruiken dus die van de computer waar ze geïnstalleerd staan.

# Images vs Containers

Een image is een verzameling van software die code en dependencies samen bundelt en men zal kunnen hergebruiken om apps te bouwen en te deployen.

We kunnen in 1 image een volledige tech-stack hebben. Zoals bijvoorbeeld de LAMP of WAMP stack. Een LAMP image bestaat uit verschillende lagen:

  • Linux (base image layer): De echte core van een OS, dus niet het volledige besturingssysteem maar enkel de meest essentiële delen nodig om de rest te kunnen draaien. Zeker en vast niet de UI, device drivers… Dat kan doordat we de Kernel gebruiken van de Host en Daemon zal deze link kunnen leggen.
  • Apache
  • MySQL
  • PHP

Een image kunnen we ook opdelen in 2 delen:

  • File system snapshot: Dit is de eigenlijke code, de dependencies, de libraries etc.
  • Start command: De logica in je image die het mogelijk maakt om te communiceren met de host kernel. Deze definieert hoeveel resources je containers zullen mogen gebruiken. Dit start command zal dan deze processen starten op je host en zorgt er dus voor dat je file system snapshot/je code vlot kan worden uitgevoerd.

Handige metafoor

Een image is een recept en een container zal de taart zijn. Je kan namelijk met 1 recept of lijst van ingrediënten verschillende taarten maken.

# Dockerfile

Een dockerfile is een eenvoudig tekstbestand dat dient als ‘blauwdruk’ en omschrijft hoe je gewenste ‘Docker image’ eruit zal zien. Je omschrijft hier welke commando’s een gebruiker zou moeten runnen om de applicatie op te starten.

Tip

Het is aangeraden om 1 proces te definieëren per container. Als je meerdere processen nodig hebt dan moet je meerdere containers gebruiken. Dat kan met Docker Compose.

In dit onderstaande voorbeeld maken we een docker image/simpele applicatie met Express JS, een Node JS framework. Dankzij Express JS kunnen we server-side data sturen naar de front-end.

De applicatie zelf is heel erg eenvoudig:

We initialiseren een package.json-bestand met het commando: npm init. Vervolgens voegen we Express JS toe als dependency. npm install express.

app.js

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello world!');
});

app.listen(process.env.PORT, () => {
  console.log(`I am listening on port ${process.env.PORT}`);
});
1
2
3
4
5
6
7
8
9
10

Om deze applicatie te runnen moeten we simpelweg het commando: PORT=5050 node app.js runnen. Op je locale computer zal dit werken wanneer je node hebt geïnstaleerd. Je kan ook je PORT in een .env bestand plaatsen maar daar hebben we dotenv (opens new window) voor nodig, nu zetten we deze tijdelijk.

Om je tijd uit te sparen kan je een alias/script toevoegen in je package.json:

package.json

"scripts": {
  "start": "node app.js"
}
1
2
3

Het is echter zo dat er verschillende versies zijn van node en dat kan vervelend zijn indien je meerdere projecten aan het ontwikkelen bent en steeds moet wisselen van node versie. Ook als je applicatie ontwikkeld wordt door verschillende developers kan dit problemen geven aangezien er developers zijn met Mac of Windows computer, ze hebben misschien allemaal verschillende Node versies lokaal geïnstalleerd. Daarom is Docker zo nuttig, we maken een container met alle vereiste services, zetten deze ‘vast’ en zo kan je makkelijker een project opstarten wetende dat de services correct zijn én kan je met een gerust hart ook deployen omdat de server ook deze services heeft.

We starten onze app op: npm start en we navigeren naar localhost:5050 (opens new window) en zien Hello World.

Om een app op te starten moeten we natuurlijk eerst docker installeren en hebben we in onze app een dockerfile nodig.

Dockerfile

FROM node:12
WORKDIR /app.js
COPY package*.json ./
RUN npm install
COPY . .
ENV PORT=8080
EXPOSE 8080
CMD ["npm", "start"]
1
2
3
4
5
6
7
8

COPY . . zou de node_modules ook kopieëren maar dat willen we niet dus voegen we een .dockerignore toe. Er mag maar 1 CMD expressie zijn per dockerfile.

Om deze image nu te builden tot een container voeren we volgend commando uit: docker build -t cs-docker-node-express:0.1 .. Zo heb je een succesvolle image gemaakt, nu kan je deze gebruiken om verschillende containers te maken. Je kan deze ook publiceren op een Hub of je eigen server om deze makkelijk te pullen voor latere projecten: docker push.

Als je nu dit project wil draaien op je toestel: docker run cs-docker-node-express:0.1. Maar als je nu surft naar de localhost zal dit niet beschikbaar zijn omdat je de 8080 poort definieert in je docker container maar niet blootstelt aan je lokale computer of host. Je moet dus de port forwarden, dat kan dankzij de -p flag. Je zal een lokale poort assignen aan de poort die je definieerde in de je docker. docker run -p 3000:8080 cs-docker-node-express:0.1. Navigeer nu naar localhost:3000 (opens new window).

Na het sluiten van je CLI zal de docker nog runnen, je kan docker stop cs-docker-node-express runnen of de container stoppen in de Docker Desktop App.

# Docker compose

Een docker-compose bestand zal nodig zijn bij multicontainer setups. Je omschrijft hier de verschillende diensten/services die je in je image wil gebruiken, waar je deze informatie wil opslaan (volumes), welke diensten afhankelijk zijn van elkaar…

docker-compose.yml

version: "3"
services:
  web:
    build: .
    ports:
      - "8080:8080"
  db:
    image: "mysql"
    environment:
      MYSQL_ROOT_PASSWORD: root
    volumes:
      -  db-data:/var/lib/mysql/data

volumes:
  db-data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Deze verzameling van diensten/images runnen we vervolgens runnen met docker-compose up

# Kubernetes

Kubernetes (opens new window) (K8s) is opensource software voor container orchestration. Met deze software kunnen applicaties in een container image automatisch gedeployd en beheerd worden.

Orchestration

Orchestration (Ned. orkestratie) is het automatisch configureren, coördineren en beheren van computersystemen of software.

© 2023 Arteveldehogeschool Laatst bijgewerkt: 13/9/2021 17:43:59