### Overview
Containers are typically transient and do not retain data once terminated. Kubernetes addresses this by providing volumes that share the lifetime of a Pod, not the containers within. Persistent volumes (PVs) and persistent volume claims (PVCs) allow data to outlive Pods, ensuring data durability across container restarts and Pod recreations. This chapter explores these concepts and their configurations.
### Introducing Volumes
Volumes in Kubernetes are directories accessible to containers within a Pod. They support different types of backend storage, from local disks to network file systems.
#### Volume Spec
Here's a simple example using `emptyDir`, which is a temporary directory that gets deleted when the Pod dies:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: fordpinto
namespace: default
spec:
containers:
- image: simpleapp
name: gastank
command:
- sleep
- "3600"
volumeMounts:
- mountPath: /scratch
name: scratch-volume
volumes:
- name: scratch-volume
emptyDir: {}
```
This creates a Pod with a container that mounts a directory `/scratch`.
### Volume Types
Several volume types are available, each suitable for different scenarios:
- **emptyDir**: Temporary storage that lives as long as the Pod does.
- **hostPath**: Mounts a file or directory from the host node's filesystem.
- **NFS**: Network File System volume for shared storage.
- **iSCSI**: Block storage over IP networks.
- **rbd, CephFS, GlusterFS**: For block and file storage in distributed systems.
- **gcePersistentDisk, awsElasticBlockStore**: Cloud provider-specific storage solutions.
- **CSI**: Container Storage Interface for standardizing volume plugin interfaces.
#### Example: Shared Volume
```yaml
apiVersion: v1
kind: Pod
metadata:
name: exampleA
spec:
containers:
- name: alphacont
image: busybox
volumeMounts:
- mountPath: /alphadir
name: sharevol
- name: betacont
image: busybox
volumeMounts:
- mountPath: /betadir
name: sharevol
volumes:
- name: sharevol
emptyDir: {}
```
To verify shared access:
```bash
$ kubectl exec -ti exampleA -c betacont -- touch /betadir/foobar
$ kubectl exec -ti exampleA -c alphacont -- ls -l /alphadir
total 0
-rw-r--r-- 1 root root 0 Nov 19 16:26 foobar
```
### Persistent Volumes and Claims
Persistent Volumes (PVs) are storage resources in the cluster. Persistent Volume Claims (PVCs) are requests for those resources.
#### Persistent Volume Example
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: 10Gpv01
labels:
type: local
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/somepath/data01"
```
#### Persistent Volume Claim Example
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
```
#### Using PVC in a Pod
```yaml
apiVersion: v1
kind: Pod
metadata:
name: testpod
spec:
containers:
- name: app
image: busybox
volumeMounts:
- name: test-volume
mountPath: /data
volumes:
- name: test-volume
persistentVolumeClaim:
claimName: myclaim
```
### Dynamic Provisioning
Dynamic provisioning automates the creation of storage resources based on StorageClass definitions.
#### StorageClass Example
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
```
### Using Secrets
Secrets provide a way to store and manage sensitive information, such as passwords and tokens, securely.
#### Creating and Using Secrets
```bash
$ kubectl create secret generic mysql --from-literal=password=root
```
#### Secret YAML Example
```yaml
apiVersion: v1
kind: Secret
metadata:
name: mysql
data:
password: TEZUckAxbgo=
```
#### Using Secrets in a Pod
```yaml
apiVersion: v1
kind: Pod
metadata:
name: dbpod
spec:
containers:
- name: db
image: mysql:5.5
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql
key: password
```
### ConfigMaps
ConfigMaps store configuration data as key-value pairs, allowing decoupling of configuration artifacts from image content.
#### Creating and Using ConfigMaps
```bash
$ kubectl create configmap myconfig --from-file=config.js
```
#### ConfigMap YAML Example
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfig
data:
config.js: |
{
"key": "value"
}
```
#### Using ConfigMaps in a Pod
```yaml
apiVersion: v1
kind: Pod
metadata:
name: configpod
spec:
containers:
- name: app
image: busybox
env:
- name: CONFIG
valueFrom:
configMapKeyRef:
name: myconfig
key: config.js
```
### Using Kubernetes for Machine Learning
Kubernetes excels at deploying and managing ML workloads, especially for scaling GPU resources. Here are some tools and frameworks:
- **PyTorch**: Popular deep learning framework.
- **Kubeflow**: Comprehensive toolkit for ML on Kubernetes.
- **KServe**: Framework for serving machine learning models.
#### Example: PyTorch Job with GPU Support
```yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pytorch-job
spec:
template:
spec:
containers:
- name: pytorch
image: pytorch/pytorch:latest
resources:
limits:
nvidia.com/gpu: 1
command: ["python", "-c", "print('Hello, PyTorch on Kubernetes!')"]
restartPolicy: Never
```
Deploy the PyTorch Job with:
```bash
$ kubectl apply -f pytorch-job.yaml
```
### Conclusion
Kubernetes provides a robust framework for managing state and data within containers. By leveraging persistent volumes, secrets, and ConfigMaps, you can ensure data persistence, security, and configuration management across your applications. Additionally, Kubernetes offers powerful tools for scaling and managing machine learning workloads, making it an excellent choice for ML in production.
Continue: [[08-Services]]