k8s之存储卷及pvc
1.存储卷概述
因为pod是有生命周期的,pod一重启,里面的数据就没了,所以我们需要数据持久化存储,在k8s中,存储卷不属于容器,而是属于pod,也就是说同一个pod中的容器可以共享一个存储卷,存储卷可以是宿主机上的目录,也可以是挂载在宿主机上的外部设备.
存储卷类型:
emptyDIR存储卷:pod一重启,存储卷也删除,这叫emptyDir存储卷,一般用于当做临时空间或缓存关系;
hostPath存储卷:宿主机上目录作为存储卷,这种也不是真正意义实现了数据持久性;
SAN(iscsi)或NAS(nfs、cifs):网络存储设备;
分布式存储:ceph,glusterfs,cephfs,rbd
云存储:亚马逊的EBS,Azure Disk,阿里云,关键数据一定要有异地备份
a.emptyDIR存储卷
vim podtest/pod-vol-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-demo namespace: default labels: app: myapp tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v2 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 volumeMounts: - name: html mountPath: /usr/share/nginx/html - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent volumeMounts: - name: html mountPath: /data/ command: ["/bin/sh"] args: ["-c","while true;do echo $(date) >> /data/index.html; sleep 10;done"] volumes: - name: html emptyDir: {} volumeMounts:把哪个存储卷挂到pod中的哪个目录下 emptyDir:不设置意味着对这个参数下的两个选项不做限制
b.hostPath:使用宿主机上目录作为存储卷
kubectl explain pods.spec.volumes.hostPath.type DirectoryOrCreate:要挂载的路径是一个目录,不存在就创建目录; Directory:宿主机上必须实现存在目录,如果不存在就报错; FileOrCreate:表示挂载的是文件,如果不存在就创建; File:表示要挂载的文件必须事先存在,否则就报错. cat pod-hostpath-vol.yaml apiVersion: v1 kind: Pod metadata: name: pod-vol-hostpath namespace: default spec: containers: - name: myapp image: ikubernetes/myapp:v2 volumeMounts: - name: html mountPath: /usr/share/nginx/html/ volumes: - name: html hostPath: path: /data/pod/volume1 type: DirectoryOrCreate hostPath:宿主机上的目录. volumes的名字可以随便取,这是存储卷的名字,但是上面的volumeMounts指定时, name必须和存储卷的名字一致,这样两者才建立了联系.
c.nfs做共享存储
这里为了方便,把master节点当做nfs存储,三个节点均执行 yum -y install nfs-utils # 然后在master上启动nfs mkdir /data/volumes cat /etc/exports /data/volumes 10.0.0.0/16(rw,no_root_squash) systemctl start nfs 在node1和node2上试挂载 mount -t nfs k8s-master:/data/volumes /mnt cat pod-vol-nfs.yaml apiVersion: v1 kind: Pod metadata: name: pod-vol-nfs namespace: default spec: containers: - name: myapp image: ikubernetes/myapp:v2 volumeMounts: - name: html mountPath: /usr/share/nginx/html/ volumes: - name: html nfs: path: /data/volumes server: k8s-master kubectl apply -f pod-vol-nfs.yaml 此时不管pod被建立在哪个节点上,对应节点上是不存放数据的,数据都在nfs主机上
d.pvc和pv
用户只需要挂载pvc到容器中而不需要关注存储卷采用何种技术实现.pvc和pv的关系与pod和node关系类似,前者消耗后者的资源,pvc可以向pv申请指定大小的存储资源并设置访问模式.
在定义pod时,我们只需要说明我们要一个多大的存储卷就行了,pvc存储卷必须与当前namespace的pvc建立直接绑定关系,pvc必须与pv建立绑定关系,而pv是真正的某个存储设备上的空间.
一个pvc和pv是一一对应关系,一旦一个pv被一个pvc绑定了,那么这个pv就不能被其他pvc绑定了,一个pvc是可以被多个pod所访问的,pvc在名称空间中,pv是集群级别的.
将master作为存储节点,创建挂载目录
cd /data/volumes && mkdir v{1,2,3,4,5} cat /etc/exports /data/volumes/v1 10.0.0.0/16(rw,no_root_squash) /data/volumes/v2 10.0.0.0/16(rw,no_root_squash) /data/volumes/v3 10.0.0.0/16(rw,no_root_squash) exportfs -arv showmount -e kubectl explain pv.spec.nfs accessModes模式有: ReadWriteOnce:单路读写,可以简写为RWO; ReadOnlyMany:多路只读,可以简写为ROX; ReadWriteMany:多路读写,可以简写为RWX # 先将存储设备定义为pv cat pv-demo.yaml apiVersion: v1 kind: PersistentVolume metadata: name: pv001 # 定义pv时不用加名称空间,因为pv是集群级别 labels: name: pv001 spec: nfs: path: /data/volumes/v1 server: k8s-master accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: # 分配磁盘空间大小 storage: 3Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv002 labels: name: pv002 spec: nfs: path: /data/volumes/v2 server: k8s-master accessModes: ["ReadWriteOnce"] capacity: storage: 5Gi --- apiVersion: v1 kind: PersistentVolume metadata: name: pv003 labels: name: pv003 spec: nfs: path: /data/volumes/v3 server: k8s-master accessModes: ["ReadWriteMany","ReadWriteOnce"] capacity: storage: 8Gi kubectl apply -f pv-demo.yaml kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS pv001 3Gi RWO,RWX Retain Available pv002 5Gi RWO Retain Available pv003 8Gi RWO,RWX Retain Available
回收策略:
如果某个pvc在pv里面存数据了,后来pvc删了,那么pv里面的数据怎么处理
reclaim_policy:即pvc删了,但pv里面的数据不删除,还保留着;
recycle:即pvc删了,那么就把pv里面的数据也删了;
delete:即pvc删了,那么就把pv也删了.
# 创建pvc的清单文件 kubectl explain pods.spec.volumes.persistentVolumeClaim cat pod-vol-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim # 简称pvc metadata: name: mypvc namespace: default # pvc和pod在同一个名称空间 spec: accessModes: ["ReadWriteMany"] # 一定是pv策略的子集 resources: requests: storage: 7Gi # 申请一个大小至少为7G的pv --- apiVersion: v1 kind: Pod metadata: name: pod-vol-pvc namespace: default spec: containers: - name: myapp image: ikubernetes/myapp:v1 volumeMounts: - name: html # 使用的存储卷的名字 mountPath: /usr/share/nginx/html/ #挂载路径 volumes: - name: html persistentVolumeClaim: claimName: mypvc # 表示要使用哪个pvc
所以pod的存储卷类型如果是pvc,则:pod指定的pvc需要先匹配一个pv,才能被pod所挂载,在k8s 1.10之后,不能手工从底层删除pv.
参考博客:http://blog.itpub.net/28916011/viewspace-2214804/