Skip to content

Instantly share code, notes, and snippets.

@mhenriks
Created January 30, 2023 13:46
Show Gist options
  • Select an option

  • Save mhenriks/d3b916a0dee981a1ccf507ba92d7fd83 to your computer and use it in GitHub Desktop.

Select an option

Save mhenriks/d3b916a0dee981a1ccf507ba92d7fd83 to your computer and use it in GitHub Desktop.

Artisanal Populators

The Goal

This document will explain how Volume Populators work under the covers by creating our "artisanal" populator. I say artisanal because we will be populating the PVCs manually ourselves using just kubectl. No controllers!

The PVC will look something like this:

kind: PersistentVolumeClaim
metadata:
  name: populated-pvc
spec:
  dataSourceRef:
    apiGroup: artisanal.populators.com
    kind: ThankYou
    name: thanks-mike
  storageClassName: rook-ceph-block
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

Once created, the PVC will be in Pending state until we feel like populating it. And by "populating", I mean placing a nice thank you note on the root of the PVC filesystem.

Create Populator CustomResourceDefinition

The dataSourceRef field of the PersistentVolumeClaim refers to an instance of a Custom Resource. So we must declare a CustomResourceDefinition.

cat <<EOF | k create -f -
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: thankyous.artisanal.populators.com
spec:
  group: artisanal.populators.com
  names:
    kind: ThankYou
    listKind: ThankYouList
    plural: thankyous
    singular: thankyou
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        properties:
          apiVersion:
            type: string
          kind:
            type: string
          spec:
            properties:
              name:
                type: string
            required:
            - name
            type: object
        required:
        - spec
        type: object
    served: true
    storage: true
EOF

Create Populator Custom Resource

cat <<EOF | k create -f -
apiVersion: artisanal.populators.com/v1alpha1
kind: ThankYou
metadata:
  name: thanks-mike
spec:
  name: Mike
EOF

Create PersistentVolumeClaim

STORAGECLASS=rook-ceph-block
cat <<EOF | k create -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: populated-pvc
spec:
  dataSourceRef:
    apiGroup: artisanal.populators.com
    kind: ThankYou
    name: thanks-mike
  storageClassName: ${STORAGECLASS}
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
EOF
k describe pvc populated-pvc

Observe "Assuming an external populator will provision the volume" event

Create PVC'

k create ns artisanal-pop
cat <<EOF | k create -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  namespace: artisanal-pop
  name: populated-pvc-prime
spec:
  storageClassName: ${STORAGECLASS}
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
EOF
k describe pvc -n artisanal-pop

Populate PVC'

THANK_YOU_NAME=$(k get thankyou thanks-mike -o=jsonpath='{.spec.name}')
cat <<EOF | k create -f -
apiVersion: v1
kind: Pod
metadata:
  namespace: artisanal-pop
  name: populator-pod
spec:
  containers:
  - name: fedora
    image: fedora:36
    command: ["/bin/bash", "-c"]
    args: ["echo 'Thank you very very much ${THANK_YOU_NAME}' > /pvc/thanks.txt"]
    volumeMounts:
    - name: pvc
      mountPath: /pvc
  restartPolicy: OnFailure
  volumes:
  - name: pvc
    persistentVolumeClaim:
      claimName: populated-pvc-prime
EOF
k get pod -n artisanal-pop populator-pod -w

Wait for pod status to be Completed

 k delete pod -n artisanal-pop populator-pod

Rebind PersistentVolume to target PVC

This is where the magic happens! We reset the claimref to point from PVC' to the target PVC

PV_NAME=$(k get pvc -n artisanal-pop populated-pvc-prime -o=jsonpath='{.spec.volumeName}')
PVC_NAME=populated-pvc
PVC_NAMESPACE=default
PVC_UID=$(k get pvc -n $PVC_NAMESPACE $PVC_NAME -o=jsonpath='{.metadata.uid}')
PVC_RESOURCEVERSION=$(k get pvc -n $PVC_NAMESPACE $PVC_NAME -o=jsonpath='{.metadata.resourceVersion}')

k patch pv $PV_NAME --patch "{\"metadata\": {\"annotations\": {}},\"spec\": {\"claimRef\": {\"namespace\": \"$PVC_NAMESPACE\", \"name\": \"$PVC_NAME\", \"uid\": \"$PVC_UID\", \"resourceVersion\": \"$PVC_RESOURCEVERSION\"}}}"

k get -A pvc -w

See that populated-pvc is now Bound while populated-pvc-prime is Lost

k delete pvc -n artisanal-pop populated-pvc-prime

Validate Population (read thank you note)

cat <<EOF | k create -f -
apiVersion: v1
kind: Pod
metadata:
  name: reader-pod
spec:
  containers:
  - name: fedora
    image: fedora:36
    command: ["tail"]
    args: ["-f", "/dev/null"]
    volumeMounts:
    - name: pvc
      mountPath: /pvc
  restartPolicy: OnFailure
  volumes:
  - name: pvc
    persistentVolumeClaim:
      claimName: populated-pvc
EOF
k wait pod/reader-pod --for=condition=ready --timeout=60s
k exec -ti reader-pod -- cat /pvc/thanks.txt

Cleanup

k delete pod reader-pod
k delete crd thankyous.artisanal.populators.com
k delete pvc populated-pvc

WaitForFirstCOnsumer Support

Create WFFC PVC

STORAGECLASS=hostpath-csi
cat <<EOF | k create -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: populated-pvc
spec:
  dataSourceRef:
    apiGroup: artisanal.populators.com
    kind: ThankYou
    name: thanks-mike
  storageClassName: ${STORAGECLASS}
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
EOF
k describe pvc populated-pvc

Create Target Pod

cat <<EOF | k create -f -
apiVersion: v1
kind: Pod
metadata:
  name: reader-pod
spec:
  containers:
  - name: fedora
    image: fedora:36
    command: ["tail"]
    args: ["-f", "/dev/null"]
    volumeMounts:
    - name: pvc
      mountPath: /pvc
  restartPolicy: OnFailure
  volumes:
  - name: pvc
    persistentVolumeClaim:
      claimName: populated-pvc
EOF

Check for volume.kubernetes.io/selected-node Annotation

k get pvc populated-pvc -o yaml

Cleanup

k delete pod reader-pod
k delete pvc populated-pvc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment