Rob Stewart

stewartcircle.com

CKA Prep - Storage

2022-08-18 13 min read Kubernetes

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, 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

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 and Delete. The default value is Delete.

    • 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 to true. Any other value or absence of the annotation is interpreted as false.

  • 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 or block (filesystem is the default volume mode)
    • accessMode - valid options are ReadWriteOnce, ReadOnlyMany, ReadWriteMany, or ReadWriteOncePod (see below for details)
    • persistentVolumeReclaimPolicy - valid options are Retained, Recycled, and Deleted (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.

top

Understand Persistent Volume Claims Primitive

Relevant search terms for Kubernetes Documentation: persistent volume claim

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 are namespaced.

  • 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 or block (filesystem is the default volume mode)

    • accessMode - valid options are ReadWriteOnce, ReadOnlyMany, ReadWriteMany, or ReadWriteOncePod (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 and matchExpressions, are ANDed together – they must all be satisfied in order to match.”

top

Know How to Configure Applications with Persistent Storage

Relevant search terms for Kubernetes Documentation: volumes

Concepts

There are two ways for a Persistent Volume to be mounted on a Pod.

  1. 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.
  1. 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, the emptyDir volume is initially empty. All containers in the Pod can read and write the same files in the emptyDir 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 the emptyDir 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 the emptyDir.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 the emtptyDir: {}.
    • The ``volumeMounts:section in the container spec references thename:` of the volume.

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 thename:` of the volume.

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 the spec. Include storageClassName: "" 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
    

top

And that’s a wrap for this topic.

Return to the series overview page