在 Kubernetes 集群中,容器的生命周期是短暂的,当 Pod 被删除或重启时,容器内的数据会随之丢失。对于 MySQL、Redis 等需要持久化数据的应用来说,持久化存储至关重要。同时,Kubernetes 还提供了特殊容器来应对特定场景的需求,本文将详细介绍这些内容。
一、Kubernetes 持久化存储
1. hostPath 存储
hostPath Volume 允许 Pod 挂载宿主机上的目录或文件,使得容器可以使用宿主机的文件系统进行存储。其生命周期独立于 Pod,只要 Pod 被调度到同一个节点,数据就不会丢失。
创建使用 hostPath 的 Pod:
yaml
apiVersion: v1
kind: Pod
metadata:
name: test-hostpath
spec:
nodeName: k8s-node2 # 指定调度 containers:
- image: nginx
name: test-nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data
type: DirectoryOrCreate # 目录存在则使用,不存在则创建
缺点:存在单点故障,Pod 重新创建必须调度到同一个节点才能保证数据不丢失。
2. NFS 存储
为解决 hostPath 的单点故障问题,可以使用 NFS 作为持久化存储,NFS 支持多个客户端挂载。
搭建 NFS 服务:
- 在服务端安装 nfs-utils 并创建共享目录
shell
yum install -y nfs-utils
mkdir /data -pv
- 配置共享目录
shell
vim /etc/exports
/data 192.168.166.0/24(rw,sync,no_root_squash,no_subtree_check)
systemctl enable --now nfs
exportfs -avr # 使配置生效
- 在所有 worker 节点安装 nfs-utils
shell
yum install nfs-utils -y
systemctl enable --now nfs
创建使用 NFS 的 Pod:
yaml
apiVersion: v1
kind: Pod
metadata:
name: test-nfs
spec:
containers:
- name: test-nfs
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
volumeMounts:
- name: nfs-volumes
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-volumes
nfs:
path: /data # 共享目录
server: 192.168.166.7 # NFS 服务器地址
3. PV 与 PVC
- PV(PersistentVolume):集群中的一块存储,由管理员配置,是集群资源,生命周期独立于使用它的 Pod。
- PVC(PersistentVolumeClaim):用户对存储资源的请求,类似于 Pod 请求节点资源,PVC 可以请求特定大小和访问模式的存储。
PV 和 PVC 的工作原理:
- 供应:静态(管理员创建 PV)或动态(基于 StorageClass 自动创建)
- 绑定:用户创建 PVC 后,Kubernetes 会寻找匹配的 PV 进行绑定,未找到则 PVC 处于未绑定状态
- 使用:Pod 通过 PVC 使用存储资源,PVC 和 PV 一一对应
- 回收 :
- Retain:删除 PVC 后,PV 仍存在且处于 released 状态,数据保留,需手动处理才能再次使用
- Delete:删除 PVC 时,PV 会从 Kubernetes 中移除,相关存储资产也会被删除
创建 PV 和 PVC:
- 先创建 NFS 共享目录
shell
mkdir /data/v{1..10} -p
- 创建 PVC
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
- 应用 PVC 配置
shell
kubectl apply -f my-pvc.yaml
- 查看 PV 和 PVC 状态,STATUS 为 Bound 表示绑定成功
shell
kubectl get pv
创建使用 PVC 的 Pod:
yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-pvc
spec:
containers:
- name: pod-pvc
image: nginx
imagePullPolicy: IfNotPresent
volumeMounts:
- name: nginx-html
mountPath: /usr/share/nginx/html
volumes:
- name: nginx-html
persistentVolumeClaim:
claimName: my-pvc
4. StorageClass
当 PVC 数量众多时,手动创建 PV 维护成本高,Kubernetes 提供 StorageClass 机制实现 PV 的自动创建,它相当于创建 PV 的模板。
StorageClass 运行原理:
- 包含 provisioner(供应商)、parameters 和 reclaimPolicy 等字段
- provisioner 决定使用哪种存储创建 PV,可由内部或外部供应商提供
- 支持卷扩展(allowVolumeExpansion),但仅支持扩容
搭建 StorageClass + NFS 步骤:
- 创建可用的 NFS Server
- 创建 Service Account,用于管控 NFS provisioner 在集群中的运行权限
- 创建 StorageClass,负责建立 PVC 并调用 NFS provisioner
- 创建 NFS provisioner,其功能是在 NFS 共享目录下创建挂载点并建立 PV 与挂载点的关联
创建使用 StorageClass 的 PVC 和 Pod:通过 StorageClass 动态生成 PV,创建 PVC 后,Kubernetes 会自动创建对应的 PV,Pod 挂载该 PVC 即可使用存储。
二、Kubernetes 特殊容器
1. Init 初始化容器
Init 容器在主容器启动之前运行,用于解决服务依赖问题、进行初始化配置等。
应用场景:
- 等待其他模块 Ready,如 Web 服务等待数据库启动
- 做初始化配置,如为主容器准备集群配置信息
- 将 Pod 注册到中央数据库、配置中心等
使用案例:
yaml
apiVersion: v1
kind: Pod
metadata:
name: init-demo
labels:
demo: init-demo
spec:
containers:
- name: init-demo
image: busybox:1.28
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-demo1
image: busybox:1.28
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice;sleep 2; done;']
- name: init-demo2
image: busybox:1.28
imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'until nslookup mysql; do echo waiting for mysql; sleep 2;done;']
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- port: 5566
targetPort: 6655
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 8899
targetPort: 9988
protocol: TCP
2. 临时容器(Ephemeral Containers)
临时容器用于交互式故障排查,当容器崩溃或镜像不包含调试工具时特别有用,例如 Distroless 镜像(轻量级镜像,不含 Shell 和调试工具)。
使用时启用进程名称空间共享有助于查看其他容器中的进程。