CKA Prep - Storage
This post is part of a series which contains my study notes for the Certified Kubernetes Administrator (CKA) exam.
Note: Unless specifically indicated, text and examples in this post all come directly from the official Kubernetes documentation. I attempted to locate and extract the relevant portions of the kubernetes.io documentation that applied to the exam objective. However, I encourage you to do your own reading. I cannot guarantee that I got all of the important sections.
Storage
The Exam Curriculum breaks down the fourth exam topic into the following objectives:
- Understand storage classes, persistent volumes
- Understand volume mode, access modes and reclaim policies for volumes
- Understand persistent volume claims primitive
- Know how to configure applications with persistent storage
Understand Storage Classes, Persistent Volumes, Volume Mode, Access Modes and Reclaim Policies for Volumes
NOTE: I combined the first 2 objectives as they are so closely related.
Relevant search terms for Kubernetes Documentation: storage class, persistent volume
Kubernetes Documentation Links
- Storage Classes
- Change the default StorageClass
- Persistent Volumes
- Change the Reclaim Policy of a PersistentVolume
API Objects
- Storage Class - (shortname sc) “provides a way for administrators to describe the “classes” of storage they offer. Different classes might map to quality-of-service levels, or to backup policies, or to arbitrary policies determined by the cluster administrators. Kubernetes itself is unopinionated about what classes represent. This concept is sometimes called “profiles” in other storage systems.”
- Persistent Volume - (shortname pv) “a piece of storage in the cluster that has been provisioned by an administrator or dynamically provisioned using Storage Classes. It is a resource in the cluster just like a node is a cluster resource. PVs are volume plugins like Volumes, but have a lifecycle independent of any individual Pod that uses the PV.”
Concepts
Storage Classes
-
Example StorageClass Resource:
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: standard provisioner: kubernetes.io/aws-ebs parameters: type: gp3 reclaimPolicy: Delete allowVolumeExpansion: true mountOptions: - debug volumeBindingMode: WaitForFirstConsumer
-
The name of the storage class is used when storage of that class is provisioned.
-
The provisioner setting determines which volume plugin will be used to provision the storage
-
The reclaimPolicy setting governs how the system will manage persistent volumes using the storage class that are created dynamically. The permitted values are
Retain
andDelete
. The default value isDelete
. -
The mountOptions setting allows mount options to be defined for the storage class.
-
The allowVolumeExpansion setting determines whether a Persistent Volume Claim created using the Storage Class can be expanded after creation.
-
The volumeBindingMode setting controls when volume binding will occur
- immediate - “indicates that volume binding and dynamic provisioning occurs once the PersistentVolumeClaim is created.”
- WaitForFirstConsumer - “will delay the binding and provisioning of a PersistentVolume until a Pod using the PersistentVolumeClaim is created.”
-
The parameters settings define configuration options that are specific to each provisioner.
-
-
“Depending on the installation method, your Kubernetes cluster may be deployed with an existing StorageClass that is marked as default. This default StorageClass is then used to dynamically provision storage for PersistentVolumeClaims that do not require any specific storage class.”
-
The default StorageClass has an annotation
storageclass.kubernetes.io/is-default-class
set totrue
. Any other value or absence of the annotation is interpreted asfalse
. -
If more than one StorageClass is set to default then any PVC that doesn’t specify a storage class will not be created.
Persistent Volumes
-
Sample Persistent Volume resource:
apiVersion: v1 kind: PersistentVolume metadata: name: pv0003 spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle storageClassName: slow mountOptions: - hard - nfsvers=4.1 nfs: path: /tmp server: 172.17.0.2
- capacity - the storage capacity of the PV
- volumeMode - either
filesystem
orblock
(filesystem
is the default volume mode) - accessMode - valid options are
ReadWriteOnce
,ReadOnlyMany
,ReadWriteMany
, orReadWriteOncePod
(see below for details) - persistentVolumeReclaimPolicy - valid options are
Retained
,Recycled
, andDeleted
(see below for details) - storageClassName - the name of the storage class for the volume.
-
Persistent Volumes (PVs) and Persistent Volume Claims (PVCs) go through the following lifecycle
-
Provisioning
- Static – where the PV is created by an Administrator. These PVs are associated with real storage that can be consumed by PVCs.
- Dynamic – if the PVC references a storage class that supports dynamic provisioning then the associated PV is provisioned automatically to satisfy the PVC
-
Binding – the PVC is bound to the PV. Persistent Volume Claims are exclusive; once bound there is a one to one relationship between PV and PVC. Binding only occurs if the access mode of the PV matches the PVC and the requested amount of storage in the PVC is greater than or equal to the storage allocated for the PV. Persistent Volume Claims will remain unbound indefinitely if a matching Persistent Volume does not exist. Labels and selectors may be used to bind a Persistent Volume Claim to a specific Persistent Volume if desired.
-
Using – Pods use claims as volumes. Users schedule Pods and access their claimed PVs by including a persistentVolumeClaim section in a Pod’s volumes block. The cluster inspects the claim to find the bound volume and mounts that volume for a Pod. For volumes that support multiple access modes, the user specifies which mode is desired when using their claim as a volume in a Pod. Once a user has a claim and that claim is bound, the bound PV belongs to the user for as long as they need it.
-
Storage Object in Use Protection – ensures that PersistentVolumeClaims (PVCs) in active use by a Pod and PersistentVolume (PVs) that are bound to PVCs are not removed from the system, as this may result in data loss. If a user deletes a PVC in active use by a Pod, the PVC is not removed immediately. PVC removal is postponed until the PVC is no longer actively used by any Pods. Also, if an admin deletes a PV that is bound to a PVC, the PV is not removed immediately. PV removal is postponed until the PV is no longer bound to a PVC.
-
Reclaiming – When a user is done with their volume, they can delete the PVC objects from the API that allows reclamation of the resource. The reclaim policy for a PV tells the cluster what to do with the volume after it has been released of its claim. Currently, volumes can either be Retained, Recycled, or Deleted.
-
Retained – The Retain reclaim policy allows for manual reclamation of the resource. When the PersistentVolumeClaim is deleted, the PersistentVolume still exists and the volume is considered “released”. But it is not yet available for another claim because the previous claimant’s data remains on the volume.
-
Recycled – If supported by the underlying volume plugin, the Recycle reclaim policy performs a basic scrub (rm -rf /thevolume/*) on the volume and makes it available again for a new claim.
NOTE that this option is deprecated. Dynamic provisioning is recommended.
-
Deleted – For volume plugins that support the Delete reclaim policy, deletion removes both the Persistent Volume object from Kubernetes, as well as the associated storage asset in the external infrastructure, such as an AWS EBS, GCE PD, Azure Disk, or Cinder volume. Volumes that were dynamically provisioned inherit the reclaim policy of their Storage Class, which defaults to Delete.
-
-
-
-
The access mode defined for the PVC must match the access mode for the PV in order for the claim to be successful. If there is no PV with an access mode that matches the access mode defined in the PVC then the PVC will stay in an unbound state.The available access modes for PVs and PVCs are as follows:
- ReadWriteOnce – the volume can be mounted as read-write by a single node. ReadWriteOnce access mode still can allow multiple pods to access the volume when the pods are running on the same node.
- ReadOnlyMany – the volume can be mounted as read-only by many nodes.
- ReadWriteMany – the volume can be mounted as read-write by many nodes.
- ReadWriteOncePod – the volume can be mounted as read-write by a single Pod. Use ReadWriteOncePod access mode if you want to ensure that only one pod across the whole cluster can read that PVC or write to it. This is only supported for CSI volumes and Kubernetes version 1.22+.
Note: Not every type of storage supports every access mode.
-
A Persistent Volume will be in one of the following phases:
- Available – a free resource that is not yet bound to a claim
- Bound – the volume is bound to a claim
- Released – the claim has been deleted, but the resource is not yet reclaimed by the cluster
- Failed – the volume has failed its automatic reclamation
The CLI will show the name of the PVC bound to the PV.
Understand Persistent Volume Claims Primitive
Relevant search terms for Kubernetes Documentation: persistent volume claim
Kubernetes Documentation Links
API Objects
- PersistentVolumeClaims - (shortname pvc) “Each PVC contains a spec and status, which is the specification and status of the claim. The name of a PersistentVolumeClaim object must be a valid DNS subdomain name.”
Concepts
-
Generally speaking, a PVC is bound to a PV when the attributes of the PVC match the attributes of an existing PV or a PV is generated to match the PVC in the case of dynamic provisioning (see above).
Note: Persistent Volumes are not
namespaced
; however, Persistent Volume Claims arenamespaced
. -
Sample Persistent Volume Claim resource:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim spec: accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: storage: 8Gi storageClassName: slow selector: matchLabels: release: "stable" matchExpressions: - {key: environment, operator: In, values: [dev]}
-
Persistent Volume Claims have many of the same attributes as Persistent Volumes
-
capacity - the requested storage capacity of the PVC
-
volumeMode - either
filesystem
orblock
(filesystem
is the default volume mode) -
accessMode - valid options are
ReadWriteOnce
,ReadOnlyMany
,ReadWriteMany
, orReadWriteOncePod
(see above for details) -
storageClassName - the requested storage class for the PVC.
-
Selector - “Claims can specify a label selector to further filter the set of volumes. Only the volumes whose labels match the selector can be bound to the claim. The selector can consist of two fields:”
-
“
matchLabels
- the volume must have a label with this value” -
“
matchExpressions
- a list of requirements made by specifying key, list of values, and operator that relates the key and values. Valid operators include In, NotIn, Exists, and DoesNotExist.”
“All of the requirements, from both
matchLabels
andmatchExpressions
, are ANDed together – they must all be satisfied in order to match.” -
-
Know How to Configure Applications with Persistent Storage
Relevant search terms for Kubernetes Documentation: volumes
Kubernetes Documentation Links
- Volumes
- emptyDir
- Configure a Pod to Use a Volume for Storage
- Configure a Pod to Use a PersistentVolume for Storage
Concepts
There are two ways for a Persistent Volume to be mounted on a Pod.
- Manual Provisioning
- Manually create a Persistent Volume
- Create a Persistent Volume Claim with properties that match the Persistent Volume so that the Persistent Volume Claim is bound to the Persistent Volume.
- Create a new Pod with a Volume that includes the name of the Persistent Volume Claim and then add a volume mount to the container spec to mount the volume in a specific container on the Pod.
- Dynamic Provisioning
- Create a new storage class or identify an existing storage class that supports dynamic provisioning.
- Create a new Persistent Volume Claim which includes the
storageClassName
property that identifies the storage class supporting dynamic provisioning. - When the Persistent Volume Claim is created, a Persistent Volume will be provisioned dynamically.
- Create a new Pod with a Volume that includes the name of the Persistent Volume Claim and then add a volume mount to the container spec to mount the volume in a specific container on the Pod.
Mounting an emptyDir in a Pod
-
“An
emptyDir
volume is first created when a Pod is assigned to a node, and exists as long as that Pod is running on that node. As the name says, theemptyDir
volume is initially empty. All containers in the Pod can read and write the same files in theemptyDir
volume, though that volume can be mounted at the same or different paths in each container. When a Pod is removed from a node for any reason, the data in theemptyDir
is deleted permanently.” -
“Some uses for an
emptyDir
are:”- “scratch space, such as for a disk-based merge sort”
- “checkpointing a long computation for recovery from crashes”
- “holding files that a content-manager container fetches while a webserver container serves the data”
“Depending on your environment,
emptyDir
volumes are stored on whatever medium that backs the node such as disk or SSD, or network storage. However, if you set theemptyDir.medium
field to"Memory"
, Kubernetes mounts a tmpfs (RAM-backed filesystem) for you instead. While tmpfs is very fast, be aware that unlike disks, tmpfs is cleared on node reboot and any files you write count against your container’s memory limit.” -
Sample Pod resource with an emptyDir
apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: k8s.gcr.io/test-webserver name: test-container volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {}
- The
volumes:
section has theemtptyDir: {}
. - The ``volumeMounts:
section in the container spec references the
name:` of the volume.
- The
Mounting a Persistent Volume Claim in a Pod
-
“Pods access storage by using the claim as a volume. Claims must exist in the same namespace as the Pod using the claim. The cluster finds the claim in the Pod’s namespace and uses it to get the PersistentVolume backing the claim. The volume is then mounted to the host and into the Pod.”
-
Sample Pod resource with a volume and a PVC
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: myfrontend image: nginx volumeMounts: - mountPath: "/var/www/html" name: mypd volumes: - name: mypd persistentVolumeClaim: claimName: myclaim
- The
volumes:
section references the Persistent Volume Claim - The ``volumeMounts:
section in the container spec references the
name:` of the volume.
- The
Creating a New PV, a new PVC, and Mounting the PVC in a Pod – hostPath
-
“Kubernetes supports hostPath for development and testing on a single-node cluster. A hostPath PersistentVolume uses a file or directory on the Node to emulate network-attached storage.”
-
“In a production cluster, you would not use hostPath. Instead a cluster administrator would provision a network resource like a Google Compute Engine persistent disk, an NFS share, or an Amazon Elastic Block Store volume. Cluster administrators can also use StorageClasses to set up dynamic provisioning.”
-
Sample Persistent Volume resource YAML
apiVersion: v1 kind: PersistentVolume metadata: name: task-pv-volume labels: type: local spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce hostPath: path: "/var/log"
Note: “A PV with no
storageClassName
has no class and can only be bound to PVCs that request no particular class.” -
Sample Persistent Volume Claim resource YAML
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: task-pv-claim spec: storageClassName: "" accessModes: - ReadWriteOnce resources: requests: storage: 750Mi
Note: If a default storage class has been configured on the cluster then it will automatically be assigned to the PVC if the
StorageClassName
is not included in thespec
. IncludestorageClassName: ""
in the spec if you do not want the default storage class to be assigned to the PVC. -
Sample Pod resource YAML
apiVersion: v1 kind: Pod metadata: name: task-pv-pod spec: volumes: - name: task-pv-storage persistentVolumeClaim: claimName: task-pv-claim containers: - name: task-pv-container image: nginx ports: - containerPort: 80 name: "http-server" volumeMounts: - mountPath: "/usr/share/nginx/html" name: task-pv-storage
And that’s a wrap for this topic.