卷
emptyDir
当pod分配到某个Node上时,emptyDir卷会被创建,并且在Pod运行期间,卷是一直存在的,当pod因为某些原因被删除,卷也会自动删除。
emptyDir
的一些用途:
- 缓存空间,例如基于磁盘的归并排序。
- 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
- 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。
emptyDir :以内存为介质
当pod删除后,物理机对应的挂载卷也会消失
kubectl run pod1 --image=nginx --image-pull-policy=IfNotPresent=IfNotPresent --dry-run=client -o yaml > pod1.yaml #生成pod1 yaml文件
####################################################
#empty配置示例
[root@cka-master volume]# vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod1
name: pod1
spec:
volumes: #定义卷
- name: vname #卷的名字
emptyDir: {} #卷的类型,不指定默认为emptyDir
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod1
resources: {}
volumeMounts: #挂载卷
- mountPath: /em-volume #挂载在容器中的路径
name: vname #挂载卷的名字
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
####################################################
[root@cka-master volume]# kubectl apply -f pod1.yaml
pod/pod1 created #创建pod
[root@cka-master volume]# kubectl exec pod1 -- ls /em-volume #查看挂载目录
[root@cka-master volume]#
[root@cka-master volume]# kubectl get pods -o wide #查看pod分配到了哪个节点
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod1 1/1 Running 0 9m59s 10.244.115.87 cka-node1 <none> <none>
[root@cka-node1 ~]# docker inspect 6f | grep -A 10 Mounts #查看挂载信息
"Mounts": [
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/8309886f-2ac5-4aad-a411-9d21fc8a2441/volumes/kubernetes.io~empty-dir/vname",
"Destination": "/em-volume",
"Mode": "Z",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
[root@cka-node1 ~]# ls /var/lib/kubelet/pods/8309886f-2ac5-4aad-a411-9d21fc8a2441/volumes/kubernetes.io~empty-dir/vname #查看卷,刚创建是卷是空的
[root@cka-node1 ~]#
[root@cka-master volume]# kubectl exec pod1 -- touch /em-volume/test.txt #创建text.txt
[root@cka-master volume]# kubectl exec pod1 -- ls /em-volume #查看挂载目录,此时看到了上面创建的test.txt
test.txt
[root@cka-node1 ~]# ls /var/lib/kubelet/pods/8309886f-2ac5-4aad-a411-9d21fc8a2441/volumes/kubernetes.io~empty-dir/vname
test.txt #再次去对应的几点查看卷
[root@cka-master volume]# kubectl delete pod pod1 --force #删除pod
#此时在去对应的节点查看卷,发现卷就自动删除了
[root@cka-node1 ~]# ls /var/lib/kubelet/pods/8309886f-2ac5-4aad-a411-9d21fc8a2441/volumes/kubernetes.io~empty-dir/vname
ls: cannot access /var/lib/kubelet/pods/8309886f-2ac5-4aad-a411-9d21fc8a2441/volumes/kubernetes.io~empty-dir/vname: No such file or directory
hostPath
hostPath
卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中。 虽然这不是大多数 Pod 需要的,但是它为一些应用程序提供了强大的逃生舱。
hostPath:以磁盘为介质,挂载到物理机上自己指定的磁盘上,如果指定挂载目录没有,自动创建
[root@cka-master volume]# kubectl run pod2 --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml > pod2.yaml
[root@cka-master volume]# vim pod2.yaml
####################################################
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod2
name: pod2
spec:
volumes:
- name: hp-volume
hostPath:
path: /host-data
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod2
resources: {}
volumeMounts:
- name: hp-volume
mountPath: /hp
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
####################################################
[root@cka-node1 ~]# docker inspect d7 | grep -A 10 Mounts
"Mounts": [
{
"Type": "bind",
"Source": "/host-data", #物理机
"Destination": "/hp", #容器内
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
[root@cka-node1 ~]# ls /host-data/
[root@cka-node1 ~]#
[root@cka-master volume]# kubectl exec pod2 -- ls /hp
[root@cka-master volume]# kubectl exec pod2 -- touch /hp/test.txt
[root@cka-master volume]# kubectl exec pod2 -- ls /hp
test.txt
[root@cka-node1 ~]# ls /host-data/
test.txt #此时可以看到前面创建的test.txt
[root@cka-master volume]# kubectl delete pod pod2 --force #删除pod2
[root@cka-node1 ~]# ls /host-data/
test.txt #当pod2被删除是,卷不会删除
NFS
使用nfs卷可以将nfs(网络文件系统)挂载到Pod中,不同之前的emptyDir,pod删除后卷里的数据不会删除,nfs
卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs
卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。
配置一台nfs服务器
#所有节点安装 nfs-utils
mkdir /nfstest ; echo nfs.txt > nfs.txt
[root@cka-nfs ~]# cat /etc/exports
/nfstest *(rw,async,no_root_squash)
#注: 这里一定要有no_root_squash,不压缩root的权限,具体含义看下面参数说明
参数说明
rw ro | 该目录分享的权限是可擦写 (read-write) 或只读 (read-only),但最终能不能读写,还是与文件系统的 rwx 及身份有关。 |
---|---|
sync async | sync 代表数据会同步写入到内存与硬盘中,async 则代表数据会先暂存于内存当中,而非直接写入硬盘! |
no_root_squash root_squash | 客户端使用 NFS 文件系统的账号若为 root 时,系统该如何判断这个账号的身份?预设的情况下,客户端 root 的身份会由 root_squash 的设定压缩成 nfsnobody, 如此对服务器的系统会较有保障。但如果你想要开放客户端使用 root 身份来操作服务器的文件系统,那么这里就得要开 no_root_squash 才行! |
all_squash | 不论登入 NFS 的使用者身份为何, 他的身份都会被压缩成为匿名用户,通常也就是 nobody(nfsnobody) 啦! |
anonuid anongid | anon 意指 anonymous (匿名者) 前面关于 *_squash 提到的匿名用户的 UID 设定值,通常为 nobody(nfsnobody),但是你可以自行设定这个 UID 的值!当然,这个 UID 必需要存在于你的 /etc/passwd 当中! anonuid 指的是 UID 而 anongid 则是群组的 GID 啰。 |
[root@cka-master volume]# kubectl run pod3 --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml > pod3.yaml
[root@cka-master volume]# vim pod3.yaml
####################################################
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod3
name: pod3
spec:
volumes:
- name: nfs
nfs:
server: 192.168.4.100
path: /nfstest
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod3
resources: {}
volumeMounts:
- name: nfs
mountPath: /nfs
#readOnly: true #只读方式挂载
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
####################################################
[root@cka-master volume]# kubectl apply -f pod3.yaml
pod/pod3 created
[root@cka-master volume]# kubectl exec -it pod3 -- sh -c ">nfs2.txt" #创建nfs2.txt
[root@cka-master volume]# kubectl exec -it pod3 -- ls /nfs
nfs.txt nfs2.txt
[root@cka-nfs ~]#
[root@cka-nfs ~]# ls /nfstest
nfs2.txt nfs.txt #查看nftest
持久卷(Persistent Volume)
一pv只能和一个pvc进行关联
Persistent Volume
apiVersion: v1
kind: PersistentVolume
metadata:
name: 1pv #pv名字
spec:
capacity:
storage: 5Gi #指定pv的容量,后端需要块储存才有效
volumeMode: Filesystem
accessModes: #访问模式
- ReadWriteOnce #卷可以被一个节点以读写方式挂载
persistentVolumeReclaimPolicy: Recycle #回收策略
storageClassName: slow
nfs: #后端储存类型
path: /nfstest #共享的目录
server: 192.168.4.100 #后端服务器地址
访问模式
PersistentVolume 卷可以用资源提供者所支持的任何方式挂载到宿主系统上。 如下表所示,提供者(驱动)的能力不同,每个 PV 卷的访问模式都会设置为 对应卷所支持的模式值。 例如,NFS 可以支持多个读写客户,但是某个特定的 NFS PV 卷可能在服务器 上以只读的方式导出。每个 PV 卷都会获得自身的访问模式集合,描述的是 特定 PV 卷的能力。
访问模式有:
- ReadWriteOnce -- 卷可以被一个节点以读写方式挂载;
- ReadOnlyMany -- 卷可以被多个节点以只读方式挂载;
- ReadWriteMany -- 卷可以被多个节点以读写方式挂载。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
重要提醒! 每个卷只能同一时刻只能以一种访问模式挂载,即使该卷能够支持 多种访问模式。例如,一个 GCEPersistentDisk 卷可以被某节点以 ReadWriteOnce 模式挂载,或者被多个节点以 ReadOnlyMany 模式挂载,但不可以同时以两种模式 挂载。
回收策略
目前的回收策略有:
- Retain -- 手动回收
- Recycle -- 基本擦除 (
rm -rf /thevolume/*
) - Delete -- 诸如 AWS EBS、GCE PD、Azure Disk 或 OpenStack Cinder 卷这类关联存储资产也被删除
目前,仅 NFS 和 HostPath 支持回收(Recycle)。 AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支持删除(Delete)。
[root@cka-master volume]# kubectl apply -f 1pv.yaml
persistentvolume/1pv created
[root@cka-master volume]#
[root@cka-master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
1pv 5Gi RWO Recycle Available
###PV STATUS
阶段
每个卷会处于以下阶段(Phase)之一:
Available(可用)-- 卷是一个空闲资源,尚未绑定到任何申领;
Bound(已绑定)-- 该卷已经绑定到某申领;
Released(已释放)-- 所绑定的申领已被删除,但是资源尚未被集群回收;
Failed(失败)-- 卷的自动回收操作失败。
PersistentVolumeClaims
每个PVC对象都有spec和status部分,分别对应申领的规约和状态。PersistentVolumeClaim对象的名称必须是合法的DNS子域名。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc #pvc名字
spec:
accessModes: #访问规则
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
#storageClassName: slow
[root@cka-master volume]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/mypvc created
[root@cka-master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Pending #此时查看pvc是Pending状态,还没有关联。
pv和pvc关联取决于两个参数
1.capcity
pvc里的要求容量 <= pv --capcity
2.accessmode
必须要相同
#修改storate 8G改成5G,再重新创建pvc,此时pvc就是Bound状态了
[root@cka-master volume]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound 1pv 5Gi RWO 10s
创建pod
####################################################
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod4
name: pod4
spec:
volumes:
- name: pvc
persistentVolumeClaim:
claimName: mypvc
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod4
resources: {}
volumeMounts:
- name: pvc
mountPath: /pvctest
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
####################################################
[root@cka-master volume]# kubectl apply -f pod4.yaml
pod/pod4 created
[root@cka-master volume]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod4 1/1 Running 0 4s
[root@cka-master volume]# kubectl exec pod4 -- ls /pvctest
nfs.txt
nfs2.txt
[root@cka-master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
1pv 5Gi RWO Recycle Available 169m
[root@cka-nfs ~]# ls /nfstest/
[root@cka-nfs ~]#
#当pvc删除后会发现/nfstest下的数据都没了,这是因为PV的回收策略是Recycle,如果想pvc删除后数据保存可以修改回收策略为Retain
测试如下
[root@cka-master volume]# vim 1pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: 1pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
#storageClassName: slow
nfs:
path: /nfstest
server: 192.168.4.100
[root@cka-master volume]# kubectl apply -f 1pv.yaml
persistentvolume/1pv created
[root@cka-master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
1pv 5Gi RWO Retain Available 2s
[root@cka-master volume]# kubectl apply -f pvc1.yaml
persistentvolumeclaim/mypvc created
[root@cka-master volume]# kubectl get pvc mypvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound 1pv 5Gi RWO 5s
[root@cka-master volume]# kubectl apply -f pod4.yaml
pod/pod4 created
[root@cka-master volume]# kubectl exec pod4 -- touch /pvctest/{1..6}.txt
[root@cka-master volume]# kubectl exec pod4 -- ls /pvctest/
1.txt
2.txt
3.txt
4.txt
5.txt
6.txt
#创建完成后此时删除pvc
[root@cka-master volume]# kubectl delete pod pod4 --force
[root@cka-master volume]# kubectl delete pvc mypvc
[root@cka-master volume]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
1pv 5Gi RWO Retain Released volume/mypvc 6m27s
#此时的PV是Released状态,此时去创建pvc,pvc是关联不了的。
[root@cka-nfs nfstest]# ls #此时数据保留了下来
1.txt 2.txt 3.txt 4.txt 5.txt 6.txt
动态卷供应
配置动态卷供应
上面配置持久性存储的时候,是要先创建pv然后才能创建pvc。如果不同的命名空间里同时要创建不同的pvc,那么就需要提前把pv创建好,这样才能为pvc提供存储。这种操作方式太过于麻烦,所有通过 storageClass(简称sc)来解决这个问题。
最终的效果是,管理员不需要提前创建pv,只要创建好 storageClass之后就不用管pv了,用户创建pvc的时候,storageClass 会自动创建出来一个pv 和这个 pvc 进行关联。
kubernetes 自带的分配器包 括:
kubernetes.io/aws-ebs
kubernetes.io/gce-pd
kubernetes.io/glusterfs
kubernetes.io/cinder
kubernetes.io/vsphere-volume
kubernetes.io/rbd
kubernetes.io/quobyte
kubernetes.io/azure-disk
kubernetes.io/azure-file
kubernetes.io/portworx-volume
kubernetes.io/scaleio
kubernetes.io/storageos
kubernetes.io/no-provisioner
注:在1.20里修改kube-apiserver.yaml
- --feature-gates=RemoveSelfLink=false
利用nfs创建动态卷供应
前面已经用 nfs 配置过共享文件夹了,因为配置起来相对简单,所以这里以 nfs 作为后端存 储来配置动态卷供应。
步骤1.:自行在储存服务器上创建一个目录/vdisk,并共享这个目录。
[root@cka-nfs nfstest]# vim /etc/exports
[root@cka-nfs nfstest]# cat /etc/exports
/nfstest *(rw,async,no_root_squash)
/vdisk *(rw,async,no_root_squash)
[root@cka-nfs nfstest]# exportfs -arv
exporting *:/vdisk
exportfs: Failed to stat /vdisk: No such file or directory
exporting *:/nfstest
因为kubernetes里,nfs没有内置分配器,所以需要下载相关插件来创建nfs 外部分配器。
步骤2:安装git 客户端工具,并克隆项目进入到目录
[root@cka-master volume]# yum -y install git
[root@cka-master volume]# git clone https://github.com/kubernetes-incubator/external-storage.git
cd external-storage-master/nfs-client/deploy/
... ...
##我把需要的包都放在了服务器上,这里可以直接下载
wget http://1.116.86.11/k8s/nfs-client/external-storage-master.zip
wget http://1.116.86.11/k8s/nfs-client/nfs-client-provisioner.tar
docker load -i nfs-client-provisioner.tar #所有节点导入
unzip external-storage-master.zip
cd /root/volume/external-storage-master/nfs-client/deploy
步骤3部署rpac
#因为我是在命名空间 volume 里的,所以需要把 rbac.yaml 里指定的命名空间更换为 volume,然后部署 rbac
sed -i 's/namespace: default/namespace: volume/g' rbac.yaml
[root@cka-master deploy]# kubectl apply -f rbac.yaml
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
部署nfs分配器
[root@cka-master deploy]# ls
class.yaml deployment-arm.yaml deployment.yaml objects rbac.yaml test-claim.yaml test-pod.yaml
[root@cka-master deploy]# vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: volume #命名空间之前给权限的
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: 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: fuseim.pri/ifs #默认就行,改的话,class.yaml 也需要修改对应的
- name: NFS_SERVER
value: 192.168.4.100 #nfs服务地址
- name: NFS_PATH
value: /vdisk #共享目录
volumes:
- name: nfs-client-root
nfs:
server: 192.168.4.100 #你nfs服务器地址
path: /vdisk #共享的目录
[root@cka-master deploy]# vim class.yaml
kind: StorageClass
metadata:
name: mysc
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
archiveOnDelete: "false"
#验证此时直接创建pvc,可以直接创建了
[root@cka-master volume]# vim pvc2.yaml
##########################################
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 100M
storageClassName: mysc #指定之前创建的sc
##############################################
[root@cka-master volume]# kubectl apply -f pvc2.yaml
persistentvolumeclaim/mypvc created
[root@cka-master volume]#
[root@cka-master volume]# kubectl get pvc mypvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
mypvc Bound pvc-3705dde2-58ea-4180-b7ef-699911660adc 100M RWO mysc 5s