# Certified Kubernetes Administrator (CKA) : Part-2: Storage

## Background
This blog is a part of a mini-series  for preparing for the CKA exam. This blog would focus on the concepts related to storage.

## How to read through the various blogs in this mini-series
Please feel free to go through all blogs (or) a particular blog, for a concept that You want to have a quick review. However, I would recommend going through the exam tips, as it may help You better organize Your time.
1. Part-1 : [Tips](https://sriram.uscconsulting.net/certified-kubernetes-administrator-cka-part-1-tips)
2. Part-2: Storage - You are reading this
3. Part-3 to Part-8: would update the links here as I publish them

## Environment
Examples are executed using Docker Desktop on Mac, with Kubernetes.
```
% kubectl get nodes
NAME             STATUS   ROLES           AGE     VERSION
docker-desktop   Ready    control-plane   4h33m   v1.24.0
```

## Storage Usecases
Although Kubernetes supports many types of volumes, I would discuss on three particular use cases that could probably come up in the exam. Since exam does not assume familiarity with a particular storage technology, focussing on these limited storage options may be fine.
- emtpydir volume mounted inside a pod
- hostpath volume mounted inside a pod
- Persistent Volume Claim used to provide storage to a pod

### emptydir volume mounted inside a pod
- An emptydir volume lasts for the life of the Pod, even if the Container terminates and restarts. 
- volumes are defined in the pod spec using volumes and containers.volumeMounts fields.
- The following yaml is available at the following [link](https://kubernetes.io/docs/tasks/configure-pod-container/configure-volume-storage/).

```
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    volumeMounts:
    - name: redis-storage
      mountPath: /data/redis
  volumes:
  - name: redis-storage
    emptyDir: {}
```

- Create Pod using above yaml
- Now, describe the pod and check that volume is mounted:

```
% kubectl describe pod redis
...
    Mounts:
      /data/redis from redis-storage (rw)
...
```

### hostPath volume mounted inside a pod
- storage is provided from the host node's filesystem
- update the volumes.hostPath.path to your local filesystem

```
apiVersion: v1
kind: Pod
metadata:
  name: task-pv-hostpath
spec:
  volumes:
    - name: task-pv-hostpath
      hostPath:
        path: /Users/sriramcvn/k8s_hostpath
        type: Directory
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-hostpath
```

- Create Pod using above yaml
- Now, describe the pod and check that volume is mounted:

```
% kubectl describe pod task-pv-hostpath
...
    Mounts:
      /usr/share/nginx/html from task-pv-hostpath (rw)
...
```

### PersistentVolume used to provide storage for a Pod
- PersistentVolume related api objects abstracts how storage is provided from how it is consumed.
- we would first create a local storage class (notice the VolumeBindingMode setting - storage is not bound until pod is created)

```
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
```

- then, we would create persistent volume
- update local.path to your local filesystem

```
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /Users/sriramcvn/k8s_local
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - docker-desktop
```

- then, we would create persistent volume claim
- storageClassName is used to map to the available persistent volumes

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: task-pv-claim
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
```

- Check that storage is not yet bound as pod is not created

```
% kubectl get sc
NAME                 PROVISIONER                    RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-storage        kubernetes.io/no-provisioner   Delete          WaitForFirstConsumer   false                  4s

% kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS    REASON   AGE
local-pv   2Gi        RWO            Delete           Available           local-storage            5s

% kubectl get pvc
NAME            STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS    AGE
task-pv-claim   Pending                                      local-storage   5s
```

- Now create the pod using following yaml and check that volume is bound

```
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
```
```
% kubectl apply -f pv-pod.yml 
pod/task-pv-pod created
% kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS    REASON   AGE
local-pv   2Gi        RWO            Delete           Bound    default/task-pv-claim   local-storage            63s
% kubectl get pvc
NAME            STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
task-pv-claim   Bound    local-pv   2Gi        RWO            local-storage   41s
```
## References
- [Volumes](https://kubernetes.io/docs/concepts/storage/volumes/)
- [Persistent Volumes](https://kubernetes.io/docs/concepts/storage/persistent-volumes/)
- [Configure a Pod to use volume for storage](https://kubernetes.io/docs/tasks/configure-pod-container/configure-volume-storage/)
- [Configure a Pod to use persistent volume for storage](https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/)
