Docker中有 volumes的概念,在Docker中,volume是 对 物理节点服务器node路径目录的一种映射,也就是 我们可以把服务器的一个目录挂载给镜像使用。
同样的,k8s创建的pod也可以挂载volume,而且不仅仅支持 pod所在的服务器node的目录映射,也可以挂载其他网络存储的作为目录挂载。
k8s支持volumes的类型如下:
1、awsElasticBlockStore
2、azureDisk
3、azureFile
4、cephfs
5、cinder
6、configMap
7、csi
8、downwardAPI
9、emptyDir
10、fc (fibre channel)
11、flexVolume
12、flocker
13、gcePersistentDisk
14、gitRepo (deprecated)
15、glusterfs
16、hostPath
17、iscsi
18、local
19、nfs
20、persistentVolumeClaim
21、projected
22、portworxVolume
23、quobyte
24、rbd
25、scaleIO
26、secret
27、storageos
28、vsphereVolume
相关类型的使用参考 Volumes
PVC是persistentVolumeClaim类型的缩写。
PVC是把云集群的node当成一个资源池,占用相应的物理空间作为 网络的存储空间,提供给k8s的pod来挂载使用。
更多详细参考和pvc的使用方法 Persistent Volumes
持久型的pvc使用的 预先创建好的nfs或者 node的空间,会一直占用着资源,造成不使用时的浪费。
而且预先创建好的pvc有可能跟pod不是一个 可用区,将造成 跨可用区的流量费用。
k8s针对这种情况 有storageclass的用法,可以让用户动态创建pvc。
详情参考 Storage Classes
使用s3拉取到 动态pvc中,动态创建pvc通过拓扑感知能够让pvc跟 pod在同一个可用区中,通过内网交互,省去流量费用。
因为s3拉取流量是按次数计费,当文件大 次数小时 ,费用可忽略不计。
所以 这种动态pvc方案 可以很好的降低 大参考文件的存储和交互成本。
声明创建storageClassName,这个地方根据我们使用的底层技术不同会有不同,比如使用rbd,ceph,nfs等等
这里以nfs为例
创建serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
创建nfs-provisioner.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: nfs-provisioner
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-provisioner
spec:
serviceAccount: nfs-client-provisioner #这个要与刚才创建的serviceaccount 的名字一致
containers:
- name: nfs-provisioner
image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: example.com/nfs #这里名字自定义,要记住storageclass 后面要用到
- name: NFS_SERVER
value: [已配置的NFS系统的IP地址]
- name: NFS_PATH
value: [已配置的NFS系统的挂载路径]
volumes:
- name: nfs-client-root
nfs:
server: [已配置的NFS系统的IP地址]
path: [已配置的NFS系统的挂载路径] #这里需要注意,如果用的公有云服务的nfs 或者nas,必须要提前创建好目录
StorageClass.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: nfs-name
provisioner: example.com/nfs #这里的名字要跟之前创建nfs-client deployment里写的名字一样
声明创建pvc
spark-pvc.yaml
#声明
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-name
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: nfs-name
注意这里ReadWriteOnce表示只允许一个pod以读写模式挂载
ReadWriteOnce —— 该volume只能被单个节点以读写的方式映射
ReadOnlyMany —— 该volume可以被多个节点以只读方式映射
ReadWriteMany —— 该volume只能被多个节点以读写的方式映射,这种存储可以以读写的方式被多个Pod共享。不是每一种存储都支持这三种方式,像共享方式,目前支持的还比较少,比较常用的是NFS。在PVC绑定PV时通常根据两个条件来绑定,一个是存储的大小,另一个就是访问模式。
如果设置的属性不对,则会报错
Pod "zzq-1584759188679-exec-1" is invalid: spec.containers[0].volumeMounts[1].mountPath: Invalid value: "/tmp2": must be unique
yaml中使用
spark.yaml
container:
image: 123.dkr.ecr.cn-northwest-1.amazonaws.com.cn/module
imagePullPolicy: Always
volumeMounts:
- name: volumes-name
mountPath: /share/tmp/
volumes:
- name: volumes-name
persistentVolumeClaim:
claimName: pvc-name
使用rbac加权限认证的会稍微麻烦些,使用方法参考:
使用rbac的
1,创建serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
2,创建nfs客户端deployment.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccount: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes #这里不能修改
env:
- name: PROVISIONER_NAME
value: example.cn/nfs #这里自定义
- name: NFS_SERVER
value: 123.23.xxx.xxx #写nfs server地址
- name: NFS_PATH
value: /localmnt/storage
volumes:
- name: nfs-client-root
nfs:
server: 123.23.xxx.xxx
path: /localmnt/storage #和之前一样,挂在之前,一定要提前创建,不然k8s 不认识,也不能自动创建
3,创建集群绑定规则clusterrolebinding.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1alpha1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
4,创建集群角色clusterrole.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1alpha1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
5,创建storageclass.yaml
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: standard
provisioner: example.cn/nfs #这里跟之前创建nfs client端里定义的名字一样
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: volumes-pvc-
spec:
entrypoint: volumes-pvc-example
volumeClaimTemplates: # define volume, same syntax as k8s Pod spec
- metadata:
name: vpcname # name of volume claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
storageClassName: gp2-topology
templates:
- name: volumes-pvc-example
steps:
- - name: generate
template: whalesay
- name: whalesay
container:
image: docker/whalesay:latest
command: [sh, -c]
args: ["echo generating message in volume; cowsay hello world | tee /mnt/vol/hello_world.txt"]
# Mount workdir volume at /mnt/vol before invoking docker/whalesay
volumeMounts: # same syntax as k8s Pod spec
- name: vpcname
mountPath: /iter
argo中的PVC声明参考 argo官方文档的volume章节