Door Pieter Vogelaar 19 Juli 2018
Minikube is ideaal om een Kubernetes cluster te gebruiken als lokale Docker ontwikkelomgeving. In een ontwikkelworkflow heb je waarschijnlijk broncode op je host machine staan; het zou geweldig zijn als de Docker containers in het cluster deze konden mounten. Zo zijn wijzigingen in de code direct zichtbaar en testbaar. De stappen in deze blog post zijn getest met Minikube versie v0.28.0.Mounten is bijvoorbeeld mogelijk met:
minikube start --mount --mount-string ./sources:/sources
En door het gebruik van hostPath in het volume.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-api
namespace: default
labels:
app: my-api
spec:
replicas: 1
selector:
matchLabels:
app: my-api
template:
metadata:
labels:
app: my-api
spec:
containers:
- name: my-api
imagePullPolicy: Never
image: my-api:v1
ports:
- containerPort: 80
volumeMounts:
- name: code
mountPath: /var/www/app
volumes:
- name: code
hostPath:
path: /sources/my-api
---
apiVersion: v1
kind: Service
metadata:
name: my-api
namespace: default
labels:
app: my-api
spec:
selector:
app: my-api
ports:
- name: app-port
port: 80
nodePort: 30101
type: NodePort
Standaard wordt de VirtualBox VM driver gebruikt. Bij het gebruik van de mount hierboven krijg je een VirtualBox shared folder. Voor een project met veel bestanden, zoals een PHP framework als Symfony, kan het laden van een pagina wel 20-30 seconden duren, wat extreem traag is.
Echter kunnen er NFS mounts worden gebruikt, die geven een geweldige snelheid! Bekijk de vergelijking. Het laden van het eerste pagina verzoek duurt 5 seconden en daarna milliseconden.
NFS server
Configureer je sources directory als export /etc/exports in de NFS server die draait op je host machine. Op deze manier kunnen containers de source code mounten. Dit is veel sneller dan de standaard VirtualBox shared folder mount. Deze actie is eenmalig, de NFS service laadt /etc/exports bij het herstarten van de host machine.
Let op: Het Minikube IP kan anders zijn na het minikube delete en minikube start commando. Zorg ervoor dat de NFS export het juiste Minikube IP bevat.
Mac OS X
echo "$(realpath .)/sources -alldirs -mapall="$(id -u)":"$(id -g)" $(minikube ip)" | sudo tee -a /etc/exports && sudo nfsd restart
Controleer of de entry actief is door op de host machine uit te voeren:
showmount -e 127.0.0.1
Dit zou het volgende resultaat moeten geven:
Exports list on 127.0.0.1:
/Absolute/path/to/sources 192.168.99.100
Linux
Vergelijkbaar met het commando hierboven voor Mac OS X, maar de service naam kan verschillende, afhankelijk van de Linux distributie.
Windows
Met winnfsd werkt het zelfs geweldig op Windows! Maar let op dat je NFS versie 3 in plaats van de standaard versie 4 configureert.
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: default-sources-volume
spec:
capacity:
storage: 15Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
nfs:
# The address 192.168.99.1 is the Minikube gateway to the host. This way
# not the container IP will be visible by the NFS server on the host machine,
# but the IP address of the `minikube ip` command. You will need to
# grant access to the `minikube ip` IP address.
server: 192.168.99.1
path: '/C/Users/myname/minikube/sources/default'
mountOptions:
- nfsvers=3
- udp
UDP protocol vanwege https://github.com/winnfsd/winnfsd/issues/68. De content van nfs-pathfile.txt. Toegang is toegestaan voor sub directories binnen deze directory.
C:\Users\myname\minikube\sources
Het commando:
C:\Users\myname\bin\WinNFSd.exe -pathFile "C:\Users\myname\etc\nfs-pathfile.txt"
Het Kubernetes en WinNFSd pad is hoofdletter gevoelig, let goed op dat het klopt!
NFS mounts
De voorbeelden in deze sectie zijn voorzien van het voorvoegsel “default-”, wat verwijst naar de default namespace. De voorbeelden werken ook als er meerdere namespaces worden gebruikt! Herhaal in dat geval simpelweg de stappen voor elke namespace en vervang “default” door de juiste naam. Let er ook op dat je de namespace key binnen de YAML-bestanden aanpast.
Een belangrijk aandachtspunt is dat persistent volumes globaal zijn, terwijl persistent volume claims binnen een specifieke namespace bestaan.
Configureer een PersistentVolume in een bestand default-sources-volume.yaml:
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: default-sources-volume
spec:
capacity:
storage: 15Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
nfs:
# The address 192.168.99.1 is the Minikube gateway to the host. This way
# not the container IP will be visible by the NFS server on the host machine,
# but the IP address of the `minikube ip` command. You will need to
# grant access to the `minikube ip` IP address.
server: 192.168.99.1
path: '/Absolute/path/to/sources/default'
Maak actief met:
kubectl apply -f ./default-sources-volume.yaml
Configureer een PersistentVolumeClaim in een bestand default-sources-volume-claim.yaml:
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: sources-volume-claim
namespace: default
spec:
storageClassName: standard
accessModes:
- ReadWriteMany
resources:
requests:
storage: 15Gi
Maak actief met:
kubectl apply -f ./default-sources-volume-claim.yaml
Nu kun je het NFS persistent volume naar je host machine gebruiken in je container. Maak een bestand aan met de naam my-api.yaml:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-api
namespace: default
labels:
app: my-api
spec:
replicas: 1
selector:
matchLabels:
app: my-api
template:
metadata:
labels:
app: my-api
spec:
containers:
- name: my-api
imagePullPolicy: Never
image: my-api:v1
ports:
- containerPort: 80
volumeMounts:
- name: code
mountPath: /var/www/app
subPath: my-api
volumes:
- name: code
persistentVolumeClaim:
claimName: sources-volume-claim
---
apiVersion: v1
kind: Service
metadata:
name: my-api
namespace: default
labels:
app: my-api
spec:
selector:
app: my-api
ports:
- name: app-port
port: 80
nodePort: 30101
type: NodePort
Maak actief met:
kubectl apply -f ./my-api.yaml
Nu heb je snelle mounts van je containers naar je host machine en een hele fijne ontwikkel workflow!
Alternatief: NFS mount direct in de VM
Minikube heeft een sub commando “ssh”, hiermee kun je bijvoorbeeld Docker images bouwen met de docker client in de Minikube VM met:
minikube ssh "docker build -t myimage:latest -f /host-sources ."
Om een NFS mount /host-sources aan te maken:
echo 'Mounting (NFS) /host-sources inside the Minikube VM'
sources_dir=$(realpath .)/sources
# In case of Windows drive C, uppercase the drive letter so it matches with the WinNFSd exports
sources_dir=${sources_dir/\/c\//\/C\/}
# The address 192.168.99.1 is the Minikube gateway to the host. NFS version 3 to be compatible with WinNFSd
minikube ssh "sudo mkdir -p /host-sources && sudo mount -t nfs -o nfsvers=3,tcp 192.168.99.1:${sources_dir} /host-sources"
Gebruik udp in plaats van tcp voor Windows om problemen met hangen te voorkomen. Deze NFS mount kan ook worden herbruikt voor Docker containers met een hostPath volume mount.
Vogelaar Solutions helpt organisaties met DevOps, platform engineering en web development. Neem contact op voor een vrijblijvend gesprek.