
Kubernetes 应用配置管理
Volumes介绍
Pod Volumes
1. 如果一个Pod中某一个容器异常退出,被kubelet拉起如何保证之前的重要数据不丢?
2. 同一个Pod的多个容器如何共享数据?
Kubernetes Volume 类型:
1. 本地存储: emptydir/hostpath…
2. 网络存储:
- in-tree: awsElasticBlockStore/gcePersistentDisk/nfs …
- out-of-tree: flexvolume/csi等网络存储volume plugins
3. Projected Volume: secret/configmap/downwardAPI/serviceAccountToken
4. PVC与PV体系
Persistent Volumes(持久卷)
Pod中声明的volume的生命周期与Pod相同,以下常见场景:
1. Pod销毁重建(如Deployment管理的Pod镜像升级)
2. 宿主机故障迁移(如StatefulSet管理的Pod带远程volume迁移)
3. 多Pod共享同一个数据volume
4. 数据volume snapshot,resize等功能的扩展实现
不足之处:
使用Pod Volumes无法准确表达数据volume复用/共享语义,新功能扩展很难实现。
优化:
如果能将存储与计算分离,使用不同的组件(Controllers)管理存储与计算资源,解耦Pod与Volume的生命周期关联,可以很好的解决这些场景下的问题。
PersistentVolumeClaim(PVC)设计意图
有了PV,为什么又设计了PVC?
1. 职责分离,PVC中只声明自己需要的存储size,access mode(单node独占还是多node共享?只读还是读写访问?)等业务真正关心的存储需求(不用关心存储实现细节),PV和其对应的后端存储信息则由交给cluster admin统一运维和管控,安全访问策略更容易控制。
2. PVC简化了User对存储的需求,PV才是存储的实际信息的承载体,通过kube-controller-manager中的PersisentVolumeController将PVC与合适的PV bound到一起,从而满足User对存储的实际需求。
3. PVC像是面向对象编程中抽象出来的接口,PV是接口对应的实现。
Static Volume Provisioning
Static Volume Provisioning的不足:
Cluster Admin需要提前规划或预测存储需求,而User的需求是多样化的,很容易导致User提交的PVC找不到合适的PV。
(举例我只需要20G,但你告诉我只有50G和100G的PV,这样就造成了资源浪费)
更好的方式:
Cluster Admin只创建不同类型存储的模板,User在PVC中指定使用哪种存储模板以及自己需要的大小、访问方式等参数,然后K8s自动生成相应的PV对象。
Dynamic Volume Provisioning
这里的StorageClass就是前文所说的创建PV的模板,它包含了创建某种具体类型的PV所需要的参数信息,User无需关心这些PV的细节。
而K8s则会结合PVC和SC两者的信息动态创建PV对象
Pod Volumes使用
.spec.volumes 声明pod的volumes信息
.spec.containers.volumeMounts声明container如何使用pod的volumes
多个container共享同一个volume时,可以通过.spec.containers.volumeMounts.subPath隔离不同容器在同个volume上数据存储的路径
Static Volume Provisioning
以使用阿里云文件存储(NAS)为例:
Cluster Admin:
1. 通过阿里云文件存储控制台,创建NAS文件系统和添加挂载点。
2. 创建PV对象,将NAS文件系统大小,挂载点,以及PV的access mode,reclaim policy等信息添加到PV对象中。
User:
1. 创建PVC对象,声明存储需求。
2. 创建应员工pod并通过.spec.volumes中通过PVC声明volume,通过.spec.containers.volumeMounts声明container挂载使用该volume。
系统管理员预先创建PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nas
labels:
alicloud-pvname: pv-nas
spec:
capacity:
storage: 5Gi # 该volume的总容量大小
accessModes:
- ReadWriteMany # 该volume可以被多个node上的pod挂载使用且都具有读写权限
persisentVolumeReclaimPolicy: Retain # 该volume使用后被release之后的回收策略
csi:
driver: nasplugin.csi.alibabacloud.com # 指定由什么volume plugin来挂载该volume(需要提前在node上部署)
volumeHandle: pv-nas
volumeAttributes:
server: "2564f49129-ysu87.cn-shenzhen.nas.aliyuncs.com"
path: "/csi"
mountOptions:
- nolock,tcp,noresvport
- vers=3
参数 | 描述 |
---|---|
driver | 定义驱动类型。本例中取值为nasplugin.csi.alibabacloud.com ,表示使用阿里云NAS CSI插件。 |
volumeHandle | 配置PV的名称。 |
server | NAS挂载点。 |
path | 挂载子目录,极速NAS需要以/share开头 |
vers | 挂载NAS数据卷的NFS协议版本号,推荐使用v3;极速类型NAS只支持v3。 |
AccessModes | PV访问策略控制列表,必须同PVC的访问策略控制列表匹配才能绑定(bound) - ReadWriteOnce只允许单node访问 - ReadOnlyMany允许多个node只读访问 - ReadWriteMany允许多node读写访问 一个PV可以设置多个访问策略,PVC与PV bound时,PV Controller会优先找到 AccessModes 列表最短并且匹配PVC AccessModes 列表的 PV 集合,然后从该集合中找到Capacity最小且符合PVC size 需求的PV对象 |
PersistentVolumeReclaimPolicy | PV被release之后(与之bound的PVC被删除)回收再利用策略 - Recycle - Delete: volume被release之后直接delete,需要volume plugin支持 - Retain: 默认策略,由系统管理员来手动管理该volume |
StorageClassName | PVC可通过该字段找到相同值的PV(静态provisioning),也可通过字段对应的storageclass从而动态provisioning新PV对象 |
NodeAffinity | 限制可以访问该volume的nodes,对使用该volume的pod的调度有影响(因为使用该volume的pod只能调度访问该PV的node上才能正常访问) |
用户创建PVC对象
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc-nas
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
selector:
matchLabels:
alicloud-pvname: pv-nas
创建应用示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-nas
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
volumeMounts:
- name: pv-nas
mountPath: "/data"
volumes:
- name: pv-nas
persistentVolumeClaim:
claimName: pvc-nas
Dynamic Volume Provisioning
# 创建storage-class-topology.yaml文件。
vim storage-class-topology.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: alicloud-disk-topology-ssd
provisioner: diskplugin.csi.alibabacloud.com
parameters:
type: cloud_ssd
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
参数 | 描述 |
---|---|
provisioner | 配置为diskplugin.csi.alibabacloud.com。标识StorageClass使用阿里云云盘provisioner插件创建。 |
type | 标识云盘类型,支持cloud_efficiency、cloud_ssd、cloud_essd、available四种参数,其中available会对ESSD、SSD、高效依次尝试创建,直到创建成功。 |
reclaimPolicy | 云盘的回收策略,默认为Delete,支持Retain。 Delete模式:删除PVC的时候,PV和云盘会一起删除。 Retain模式:删除PVC的时候,PV和云盘数据不会被删除,需要您手动删除。 如果数据安全性要求高,推荐使用Retain方式以免误删数据。 |
encrypted | 可选参数,标识创建的云盘是否加密。默认情况是false,创建的云盘不加密。 |
volumeBindingMode | WaitForFirstConsumer时表示使用延迟绑定,即调度器先调度pod,并根据pod的可用区信息创建云盘。 |
allowVolumeExpansion | 配置为true时,可以实现云盘的自动扩容。 |
performanceLevel | 值为PL1、PL2、或PL3。更多信息,请参见容量范围与性能级别的关系。 |
# 执行以下命令,创建StorageClass。
kubectl apply -f storage-class-csi.yaml
创建 PVC 以下模板为创建动态卷PV的示例YAML。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: disk-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 25Gi
storageClassName: alicloud-disk-ssd
注意:storage:定义申请云盘大小,最小为20GiB。
创建应用
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: pvc-disk
mountPath: /data
volumes:
- name: pvc-disk
persistentVolumeClaim:
claimName: disk-pvc
PV状态流转
达到released状态的PV无法根据Reclaim Policy回到available状态而再次bound新的PVC。此时,如果想复用原来PV对应的存储中的数据,只有两种方式:
1. 复用old PV中记录的存储信息新建PV对象。
2. 直接从PVC对象复用,即不unbound PVC和PV(即:StatefulSet处理存储状态的原理)。
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

