In Kubernetes zijn Persistent Volumes (PV's) en Persistent Volume Claims (PVC's) twee belangrijke concepten. Beide worden gebruikt voor de opslag van data: ze regelen de details over opslag en de implementatie daarvan, bijvoorbeeld de omvang van een volume. Op ons Kubernetes-platform gebruik je ze bijvoorbeeld voor de configuratie van je block storage.
Persistent Volumes vs Persistent Volume Claims
Hoewel ze op elkaar lijken, zijn er verschillen tussen Persistent Volumes en Persistent Volume Claims:
Persistent Volume (PV): Een PV is een stukje opslag in een Kubernetes-cluster. Het is een resource in je cluster net als een node een resource is. PV's hebben een onafhankelijke levensduur van de individuele pods die ze gebruiken. Dit betekent dat de PV blijft bestaan, zelfs als de pods die de PV gebruiken worden verwijderd.
Persistent Volume Claim (PVC): Een PVC is een verzoek om opslag vergelijkbaar met hoe een pod resources gebruikt van een node. Pods gebruiken node resources en PVC's gebruiken PV resources. Claims kunnen specifieke grootte en toegangsmodi aanvragen (zoals, kunnen worden gemount als read-write of read-only).
Kort samengevat is het belangrijkste verschil dat een Persistent Volume aan een cluster gebonden is en een Persistent Volume Claim aan een specifieke namespace (de default namespace als je er geen opgeeft).
Gebruik je een PersistentVolume en/of een PersistentVolumeClaim?
Je kunt een PVC maken zonder een specifieke PV te maken. Als je een PVC maakt zonder een specifieke PV, zal Kubernetes een PV provisioneren met voldoende opslagcapaciteit. Deze wordt automatisch gebonden aan de PVC die hem heeft aangevraagd en is niet beschikbaar voor andere PVCs. Dit wordt dynamische provisioning genoemd en het is een zeer gebruikelijke manier om opslag te beheren in Kubernetes. Wanneer je zowel de PV als PVC gebruikt spreek je over statische provisioning.
Of je een PV of PVC gebruikt hangt vooral af van de vraag of je de PV wil bewaren na het verwijderen van je pods. Dit hangt af van je use case en het is belangrijk om bij dit verschil stil te staan voor je een keuze maakt. Dit is niet alleen belangrijk voor je eigen configuratie, maar ook omdat veel Helm Charts en online voorbeelden van .yaml-objecten een PV en PVC gebruiken en je misschien enkel een PVC wil inzetten.
Om een keuze te kunnen maken tussen dynamische en statische provisioning zetten we een paar voor- en nadelen op een rij:
Voordelen van Dynamische Provisioning:
- Vereenvoudigt het beheer van opslag, omdat je niet handmatig PV's hoeft aan te maken.
- Je voorkomt dat je meer opslag aanvraagt dan je gebruikt doordat je niet meer aanvraagt in je PVC dan je nodig hebt. Bij een PV en PVC combinatie vraag je voor de PV meestal meer ruimte aan zodat je meerdere PVCs kunt koppelen aan die PV.
Nadelen van Dynamische Provisioning:
- Het kan afhankelijk van je configuratie leiden tot onverwachte kosten. Je bent immers redelijk vrij om zo veel opslagruimte aan te vragen als je wilt, bij een statische provisioning kader je dat doorgaans een redelijk eind af.
Voordelen van Statische Provisioning:
- Geeft meer controle over de exacte details van hoe de opslag wordt gecreëerd.
- Kan nuttig zijn in situaties waarin specifieke opslagconfiguraties nodig zijn die niet kunnen worden bereikt met een StorageClass.
Nadelen van Statische Provisioning:
- Vereist (iets) meer handmatig beheer dan dynamische provisioning
- Kan leiden tot verspilling van opslagruimte als PV's worden gecreëerd maar niet (geheel) worden gebruikt.
Voorbeeld van een PV en PVC
PVs en PVCs zijn op dit punt misschien nog enigszins abstract, maar worden al concreter aan de hand van een voorbeeld. Een Persistent Volume kan er als volgt uitzien (in een .yaml-bestand):
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
storageClassName: transip-fast-storage
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
claimRef:
name: my-pvc
namespace: pvc-demo
Een deel van de items in de code hierboven lichten we toe in onze documentatie over het maken van .yaml-objecten. De concepten die allicht nieuw zijn, zijn de volgende:
- spec.storageClassName: Het type opslag dat je kunt gebruiken op een Kubernetes-platform, op te vragen met 'kubectl get sc'. In dit geval transip-fast-storage (de default waarde, gebruikt NVMe) en transip-big-storage (HDD).
- spec.capacity.storage: De hoeveelheid storage uitgedrukt in Gibibytes (Gi) of Gigabytes (G), zie ook Kubernetes' eigen documentatie over resourcegebruik.
- spec.accessModes: De modus waarop het volume gemount wordt, zie deze pagina voor de beschikbare opties (wij ondersteunen op dit moment enkel ReadWriteOnce).
- spec.claimRef: Door een claimRef in te stellen kun je voorkomen dat andere PVCs zich kunnen binden aan de PV.
Een bijbehorende PersistentVolumeClaim kan er op zijn beurt als volgt uitzien:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc
namespace: pvc-demo spec: storageClassName: transip-fast-storage accessModes: - ReadWriteOnce resources: requests: storage: 3Gi
In deze voorbeelden is er dus een PersistentVolume met 10Gi opslagruimte en een PersistentVolumeClaim die 3Gi vraagt van de beschikbare 10Gi opslagruimte in deze specifieke PV. De PersistentVolumeClaim benoemt ook de namespace in de metadata. Een PersistentVolume zelf doet dat niet omdat dat een resource is die zich op het clusterniveau bevindt (in tegenstelling tot de PersistentVolumeClaim).
Let op: Tenzij je de optie leeg laat en de default waarde gebruikt wordt, moet de storageClassName overeen komen bij zowel de PV als PVC. Anders kunnen ze niet aan elkaar binden.
Een eventuele pod kan gebruik van maken van deze PVC als volgt:
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: pvc-demo
spec:
containers:
- name: demo-container
image: nginx
volumeMounts:
- name: my-storage
mountPath: /usr/share/nginx/html
volumes:
- name: my-storage
persistentVolumeClaim:
claimName: my-pvc
Hier geef je simpel gezegd dus aan dat je extra schijfruimte wil koppelen aan /usr/share/nginx/html en dat je daarvoor de eerdere PersistentVolumeClaim met de naam 'my-pvc' (en 3Gi opslag) wil gebruiken.
Een PersistentVolume reserveren
We benoemden het al eerder, maar in principe maakt een PVC automatisch gebruik van ruimte in een beschikbare PV, of levert Kubernetes automatisch de gevraagde PVC. Je kunt echter als jouw use case dat vereist specifiek aangeven welke PVC je toestaat om de PV te gebruiken. Dit helpt voorkomen dat een PVC ongewenst ruimte van een willekeurige PV claimt. In de PV voeg je daarvoor een 'claimRef' toe met daarin de naam en (indien aanwezig) de namespace van de PVC die van de PV gebruik mag maken:
claimRef:
name: my-pvc
In de PVC voeg je op zijn beurt de optie 'volumeName' toe om te verwijzen naar de specifieke PV:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc namespace: pvc-example spec: storageClassName: transip-fast-storage volumeName: my-pv ...
Daarmee zijn we aan het eind gekomen van onze handleiding over Persistent Volumes en Persistent Volume Claims. In onze block storage-handleiding laten we zien hoe je een block storage via een Persistent Volume Claim inzet op je Kubernetes-cluster.