一、Volumes
Container(容器)中的磁盘文件是短暂的,当容器崩溃时,kubelet会重新启动容器,但最初的文件将丢失,Container会以最干净的状态启动。另外,当一个Pod运行多个Container时,各个容器可能需要共享一些文件。Kubernetes Volume可以解决这两个问题。
一些需要持久化数据的程序才会用到Volumes,或者一些需要共享数据的容器需要volumes。
Redis-Cluster:nodes.conf
日志收集的需求:需要在应用程序的容器里面加一个sidecar,这个容器是一个收集日志的容器,比如filebeat,它通过volumes共享应用程序的日志文件目录。
Volumes:官方文档 https://kubernetes.io/zh/docs/concepts/storage/volumes/
http://docs.kubernetes.org.cn/429.html
背景
Docker也有卷的概念,但是在Docker中卷只是磁盘上或另一个Container中的目录,其生命周期不受管理。虽然目前Docker已经提供了卷驱动程序,但是功能非常有限,例如从Docker 1.7版本开始,每个Container只允许一个卷驱动程序,并且无法将参数传递给卷。
另一方面,Kubernetes卷具有明确的生命周期,与使用它的Pod相同。因此,在Kubernetes中的卷可以比Pod中运行的任何Container都长,并且可以在Container重启或者销毁之后保留数据。Kubernetes支持多种类型的卷,Pod可以同时使用任意数量的卷。
从本质上讲,卷只是一个目录,可能包含一些数据,Pod中的容器可以访问它。要使用卷Pod需要通过.spec.volumes字段指定为Pod提供的卷,以及使用.spec.containers.volumeMounts 字段指定卷挂载的目录。从容器中的进程可以看到由Docker镜像和卷组成的文件系统视图,卷无法挂载其他卷或具有到其他卷的硬链接,Pod中的每个Container必须独立指定每个卷的挂载位置。
1、emptyDir
和上述volume不同的是,如果删除Pod,emptyDir卷中的数据也将被删除,一般emptyDir卷用于Pod中的不同Container共享数据。它可以被挂载到相同或不同的路径上。
默认情况下,emptyDir卷支持节点上的任何介质,可能是SSD、磁盘或网络存储,具体取决于自身的环境。可以将emptyDir.medium字段设置为Memory,让Kubernetes使用tmpfs(内存支持的文件系统),虽然tmpfs非常快,但是tmpfs在节点重启时,数据同样会被清除,并且设置的大小会被计入到Container的内存限制当中。
使用emptyDir卷的示例,直接指定emptyDir为{}即可:
# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2020-09-19T02:41:11Z"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts: # 挂载在容器内
- mountPath: /opt
name: share-volume
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx2
command: # 同一命名空间内nginx80端口冲突
- sh
- -c
- sleep 3600
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /mnt
name: share-volume
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: share-volume
emptyDir: {} #emptyDir配置
#medium: Memory # 配置使用内存
启动pod,并查看状态
# kubectl apply -f pod_emptydir.yaml
pod/pod-emptydir created
#
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-emptydir 2/2 Running 0 10s 10.244.2.166 k8s-node02 <none> <none>
#
# kubectl describe pod pod-emptydir
Name: pod-emptydir
Namespace: default
Priority: 0
Node: k8s-node02/172.16.1.112
Start Time: Fri, 12 Jun 2020 22:49:11 +0800
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"pod-emptydir","namespace":"default"},"spec":{"containers":[{"image":"...
Status: Running
IP: 10.244.2.166
IPs:
IP: 10.244.2.166
Containers:
myapp-pod:
Container ID: docker://d45663776b40a24e7cfc3cf46cb08cf3ed6b98b023a5d2cb5f42bee2234c7338
Image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1
Image ID: docker-pullable://10.0.0.110:5000/k8s-secret/myapp@sha256:9eeca44ba2d410e54fccc54cbe9c021802aa8b9836a0bcf3d3229354e4c8870e
Port: <none>
Host Port: <none>
State: Running
Started: Fri, 12 Jun 2020 22:49:12 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/cache from cache-volume (rw) ##### 挂载信息
/var/run/secrets/kubernetes.io/serviceaccount from default-token-v48g4 (ro)
busybox-pod:
Container ID: docker://c2917ba30c3322fb0caead5d97476b341e691f9fb1990091264364b8cd340512
Image: registry.cn-beijing.aliyuncs.com/google_registry/busybox:1.24
Image ID: docker-pullable://registry.cn-beijing.aliyuncs.com/ducafe/busybox@sha256:f73ae051fae52945d92ee20d62c315306c593c59a429ccbbdcba4a488ee12269
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
sleep 3600
State: Running
Started: Fri, 12 Jun 2020 22:49:12 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/test/cache from cache-volume (rw) ##### 挂载信息
/var/run/secrets/kubernetes.io/serviceaccount from default-token-v48g4 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
cache-volume:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
default-token-v48g4:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-v48g4
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3s default-scheduler Successfully assigned default/pod-emptydir to k8s-node02
Normal Pulled 2s kubelet, k8s-node02 Container image "registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1" already present on machine
Normal Created 2s kubelet, k8s-node02 Created container myapp-pod
Normal Started 2s kubelet, k8s-node02 Started container myapp-pod
Normal Pulled 2s kubelet, k8s-node02 Container image "registry.cn-beijing.aliyuncs.com/google_registry/busybox:1.24" already present on machine
Normal Created 2s kubelet, k8s-node02 Created container busybox-pod
Normal Started 2s kubelet, k8s-node02 Started container busybox-pod
emptyDir验证
在pod中的myapp-pod容器内操作
# kubectl exec -it pod-emptydir -c myapp-pod -- sh
/ # cd /cache
/cache # pwd
/cache
/cache # date >> data.info
/cache # ls -l
total 4
-rw-r--r-- 1 root root 29 Jun 12 14:53 data.info
/cache # cat data.info
Fri Jun 12 14:53:27 UTC 2020
在pod中的busybox-pod容器内操作
# kubectl exec -it pod-emptydir -c busybox-pod -- sh
/ # cd /test/cache
/test/cache # ls -l
total 4
-rw-r--r-- 1 root root 29 Jun 12 14:53 data.info
/test/cache # cat data.info
Fri Jun 12 14:53:27 UTC 2020
/test/cache # echo "===" >> data.info
/test/cache # date >> data.info
/test/cache # cat data.info
Fri Jun 12 14:53:27 UTC 2020
===
Fri Jun 12 14:56:05 UTC 2020
由上可见,一个Pod中多个容器可共享同一个emptyDir卷。
2、hostPath
hostPath卷可将节点上的文件或目录挂载到Pod上,用于Pod自定义日志输出或访问Docker内部的容器等。
hostPath 的一些用法有
- 运行一个需要访问 Docker 引擎内部机制的容器;请使用 hostPath 挂载 /var/lib/docker 路径。
- 在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys。
- 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。
使用hostPath卷的示例。将主机的/data目录挂载到Pod的/test-pd目录:
# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2020-09-19T02:41:11Z"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt
name: share-volume
- mountPath: /etc/timezone # 挂载时间
name: timezone
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx2
command:
- sh
- -c
- sleep 3600
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /mnt
name: share-volume
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: timezone
hostPath:
path: /etc/timezone
type: File
hostPath卷常用的type(类型)如下:
类型 | 说明 |
---|---|
空字符串 | 默认选项,意味着挂载hostPath卷之前不会执行任何检查 |
DirectoryOrCreate | 如果给定的path不存在任何东西,那么将根据需要创建一个权限为0755的空目录,和Kubelet具有相同的组和权限 |
Directory | 目录必须存在于给定的路径下 |
FileOrCreate | 如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为0644,和Kubelet具有相同的组和所有权 |
File | 文件,必须存在于给定路径中 |
Socket | UNIX套接字,必须存在于给定路径中 |
CharDevice | 字符设备,必须存在于给定路径中 |
BlockDevice | 块设备,必须存在于给定路径中 |
启动pod,并查看状态
# kubectl apply -f pod_hostpath.yaml
pod/pod-hostpath created
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-hostpath 1/1 Running 0 17s 10.244.4.133 k8s-node01 <none> <none>
# kubectl describe pod pod-hostpath
Name: pod-hostpath
Namespace: default
Priority: 0
Node: k8s-node01/172.16.1.111
Start Time: Sat, 13 Jun 2020 16:12:15 +0800
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"pod-hostpath","namespace":"default"},"spec":{"containers":[{"image":"...
Status: Running
IP: 10.244.4.133
IPs:
IP: 10.244.4.133
Containers:
myapp-pod:
Container ID: docker://8cc87217fb483288067fb6d227c46aa890d02f75cae85c6d110646839435ab96
Image: registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1
Image ID: docker-pullable://registry.cn-beijing.aliyuncs.com/google_registry/myapp@sha256:9eeca44ba2d410e54fccc54cbe9c021802aa8b9836a0bcf3d3229354e4c8870e
Port: <none>
Host Port: <none>
State: Running
Started: Sat, 13 Jun 2020 16:12:17 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/test-k8s/hostpath-dir from hostpath-dir-volume (rw)
/test/hostpath-file/test.conf from hostpath-file-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-v48g4 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
hostpath-dir-volume:
Type: HostPath (bare host directory volume)
Path: /k8s/hostpath-dir
HostPathType: DirectoryOrCreate
hostpath-file-volume:
Type: HostPath (bare host directory volume)
Path: /k8s2/hostpath-file/test.conf
HostPathType: FileOrCreate
default-token-v48g4:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-v48g4
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/pod-hostpath to k8s-node01
Normal Pulled 12m kubelet, k8s-node01 Container image "registry.cn-beijing.aliyuncs.com/google_registry/myapp:v1" already present on machine
Normal Created 12m kubelet, k8s-node01 Created container myapp-pod
Normal Started 12m kubelet, k8s-node01 Started container myapp-pod
宿主机操作
根据pod,在k8s-node01节点宿主机操作【因为Pod分配到了该节点】
# 对挂载的目录操作
# pwd
/k8s/hostpath-dir
# echo "dir" >> info
# date >> info
# cat info
dir
Sat Jun 13 16:22:37 CST 2020
# 对挂载的文件操作
# pwd
/k8s2/hostpath-file
# echo "file" >> test.conf
# date >> test.conf
# cat test.conf
file
Sat Jun 13 16:23:05 CST 2020
在Pod 容器中操作
# 进入pod 中的指定容器【如果只有一个容器,那么可以不指定容器】
# kubectl exec -it pod-hostpath -c myapp-pod -- /bin/sh
##### 对挂载的目录操作
/ # cd /test-k8s/hostpath-dir
/test-k8s/hostpath-dir # ls -l
total 4
-rw-r--r-- 1 root root 33 Jun 13 08:22 info
/test-k8s/hostpath-dir # cat info
dir
Sat Jun 13 16:22:37 CST 2020
/test-k8s/hostpath-dir # date >> info
/test-k8s/hostpath-dir # cat info
dir
Sat Jun 13 16:22:37 CST 2020
Sat Jun 13 08:26:10 UTC 2020
##### 对挂载的文件操作
# cd /test/hostpath-file/
/test/hostpath-file # cat test.conf
file
Sat Jun 13 16:23:05 CST 2020
/test/hostpath-file # echo "file====" >> test.conf
/test/hostpath-file # cat test.conf
file
Sat Jun 13 16:23:05 CST 2020
file====
3、NFS
NFS 是Network File System的缩写,即网络文件系统。Kubernetes中通过简单地配置就可以挂载NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持同时写操作。Pod被删除时,Volume被卸载,内容被保留。这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递。
所有节点
yum install nfs-utils -y
安装nfs服务, node01
systemctl start nfs
sudo systemctl enable nfs
mkdir -p /data/nfs
vim /etc/exports
/data/nfs/ 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
exportfs -rv
systemctl reload nfs-server
权限 | 说明 |
---|---|
rw | read-write,可读写 |
sync | 文件同时写入硬盘和内存 |
async | 文件暂存于内存,而不是直接写入内存 |
no_root_squash | NFS客户端连接服务端时如果使用的是root的话,那么对服务端分享的目录来说,也拥有root权限。显然开启这项是不安全的 |
root_squash | NFS客户端连接服务端时如果使用的是root的话,那么对服务端分享的目录来说,拥有匿名用户权限,通常他将使用nobody或nfsnobody身份 |
all_squash | 不论NFS客户端连接服务端时使用什么用户,对服务端分享的目录来说都是拥有匿名用户权限 |
anonuid | 匿名用户的UID值,通常是nobody或nfsnobody,可以在此处自行设定 |
anongid | 匿名用户的GID值 |
insecure | 当mount监听端口大于1024时需要使用此参数 |
master01
showmount -e xx.xx.xx.xx # xx.xx.xx.xx为服务端IP,有返回信息说明成功
mount -t nfs 192.168.0.204:/data/nfs /mnt/
cd /mnt/
touch 123
unmount /mnt
volumes挂载
案例https://www.cnblogs.com/xiajq/p/11395211.html
生产环境不用nfs,也不直接用NFS,用PV来连接
可以用云服务商的来存储
# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2020-09-19T02:41:11Z"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt
name: share-volume
- mountPath: /etc/timezone
name: timezone
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx2
command:
- sh
- -c
- sleep 3600
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /mnt
name: share-volume
- mountPath: /opt
name: nfs-volume
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: nfs-volume
nfs:
server: 192.168.0.204
path: /data/nfs/test-dp
二、PV&PVC
1、PV、PVC
PersistentVolume:简称PV,是由Kubernetes管理员设置的存储,可以配置Ceph、NFS、GlusterFS等常用存储配置,相对于Volume配置,提供了更多的功能,比如生命周期的管理、大小的限制。PV分为静态和动态。没有命名空间限制。
PersistentVolumeClaim:简称PVC,是对存储PV的请求,表示需要什么类型的PV,需要存储的技术人员只需要配置PVC即可使用存储,或者Volume配置PVC的名称即可。有命名空间限制。
官方文档:https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/
2、存储配置
1、PV回收策略
PV回收策略 | 说明 |
---|---|
Retain | 保留,该策略允许手动回收资源,当删除PVC时,PV仍然存在,PV被视为已释放,管理员可以手动回收卷 |
Recycle | 回收,如果Volume插件支持,Recycle策略会对卷执行rm -rf清理该PV,并使其可用于下一个新的PVC,但是本策略将来会被弃用,目前只有NFS和HostPath支持该策略 |
Delete | 删除,如果Volume插件支持,删除PVC时会同时删除PV,动态卷默认为Delete,目前支持Delete的存储后端包括AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder等 |
可以通过persistentVolumeReclaimPolicy: Recycle字段配置
官方文档:https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#reclaim-policy
2、PV访问策略
PV访问策略 | 说明 |
---|---|
ReadWriteOnce | 可以被单节点以读写模式挂载,命令行中可以被缩写为RWO |
ReadOnlyMany | 可以被多个节点以只读模式挂载,命令行中可以被缩写为ROX |
ReadWriteMany | 可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX |
ReadWriteOncePod | 只允许被单个Pod访问,需要K8s 1.22+以上版本,并且是CSI创建的PV才可使用 |
官方文档:https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#access-modes
3、存储分类
存储分类 | 说明 |
---|---|
文件存储 | 一些数据可能需要被多个节点使用,比如用户的头像、用户上传的文件等,实现方式:NFS、NAS、FTP、CephFS等 |
块存储 | 一些数据只能被一个节点使用,或者是需要将一块裸盘整个挂载使用,比如数据库、Redis等,实现方式:Ceph、GlusterFS、公有云 |
对象存储 | 由程序代码直接实现的一种存储方式,云原生应用无状态化常用的实现方式,实现方式:一般是符合S3协议的云存储,比如AWS的S3存储、Minio、七牛云等 |
4、PV配置示例
1、NFS/NAS
# cat nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0001
spec:
capacity:
storage: 5Gi # 定义内存大小,PVC的要比这个小
volumeMode: Filesystem # 文件系统类型
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle # 策略上面有介绍
storageClassName: nfs-slow # 这个名字是PVC创建的时候要对应的名字
mountOptions:
- hard
- nfsvers=4.1
nfs: #对应上nfs服务器的 ip 共享的文件夹
path: /data/nfs
server: 192.168.1.104
# CREATE pv
# kubectl create -f nfs-pv.yaml
persistentvolume/pv0001 created
# 查看PV
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv0001 5Gi RWO Recycle Available nfs-slow 2m3s
参数 | 说明 |
---|---|
capacity | 容量配置 |
volumeMode | 卷的模式,目前支持Filesystem(文件系统) 和 Block(块),其中Block类型需要后端存储支持,默认为文件系统 |
accessModes | 该PV的访问模式 |
storageClassName | PV的类,一个特定类型的PV只能绑定到特定类别的PVC,PVC和PV的这个名字一样,才能被绑定 |
persistentVolumeReclaimPolicy | 回收策略 |
mountOptions | 非必须,新版本中已弃用 |
nfs | NFS服务配置,包括以下两个选项 |
path:NFS上的共享目录 /server:NFS的IP地址 |
2、NFS配置
NFS服务器安装服务端
yum install nfs* rpcbind -y
所有K8s节点安装NFS客户端
yum install nfs-utils -y
NFS服务端
mkdir /data/k8s -p
NFS服务器创建共享目录
# vim /etc/exports
/data/k8s/ *(rw,sync,no_subtree_check,no_root_squash)
# exportfs -r
# systemctl restart nfs rpcbind
挂载测试
mount -t nfs nfs-serverIP:/data/k8s /mnt/
Pv的状态 | 说明 |
---|---|
Available | 空闲的PV,没有被任何PVC绑定 |
Bound | 已经被PVC绑定 |
Released | PVC被删除,但是资源未被重新使用 |
Failed | 自动回收失败 |
3、HostPath
kind: PersistentVolume
apiVersion: v1
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: hostpath
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath: # hostPath服务配置
path: "/mnt/data" # 宿主机路径
4、CephRBD
apiVersion: v1
kind: PersistentVolume
metadata:
name: ceph-rbd-pv
spec:
capacity:
storage: 1Gi
storageClassName: ceph-fast
accessModes:
- ReadWriteOnce
rbd:
monitors:
- 192.168.1.123:6789
- 192.168.1.124:6789
- 192.168.1.125:6789
pool: rbd
image: ceph-rbd-pv-test
user: admin
secretRef:
name: ceph-secret
fsType: ext4
readOnly: false
参数 | 说明 |
---|---|
monitors | Ceph的monitor节点的IP |
pool | 所用Ceph Pool的名称,可以使用ceph osd pool ls查看 |
image | Ceph块设备中的磁盘映像文件,可以使用rbd create POOL_NAME/IMAGE_NAME --size 1024创建,使用rbd list POOL_NAME查看 |
user | Rados的用户名,默认是admin |
secretRef | 用于验证Ceph身份的密钥 |
fsType | 文件类型,可以是ext4、XFS等 |
readOnly | 是否是只读挂载 |
5、挂载PVC
创建一个PVC
# 绑定到指定类型的PV
# cat test-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pvc-claim # PVC的名字,可自取
spec:
storageClassName: nfs-slow # 名字要对应上想绑定的PV上
accessModes:
- ReadWriteMany
# volumeMode: Filesystem
resources:
requests:
storage: 3Gi
# create PVC
# kubectl create -f test-pvc.yaml
persistentvolumeclaim/myclaim created
# 查看PVC
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myclaim Bound pv0001 5Gi RWX nfs-slow 34s
# 再次查看PV,可看到状态已经发生改变
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv0001 5Gi RWX Recycle Bound default/myclaim nfs-slow 13m
绑定到指定类型的PV
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pvc-claim
containers:
- env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
image: nginx
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage # 名字要对应上想绑定的PV上
6、更改deployment使用PVC类型的volume
# 更改后的yaml,在对应位置加上以下参数调用PVC
volumeMounts:
- mountPath: /opt/pvc
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
# 然后进入容器查看是否挂载成功
# kubectl exec -it nginx-5bb6d88dfb-w78k8 -c nginx2 -- bash
root@nginx-5bb6d88dfb-w78k8:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 37G 4.3G 33G 12% /
tmpfs 64M 0 64M 0% /dev
tmpfs 985M 0 985M 0% /sys/fs/cgroup
/dev/mapper/centos-root 37G 4.3G 33G 12% /mnt
192.168.1.104:/data/nfs 37G 3.0G 35G 9% /opt/pvc # 这就是刚刚挂载的PVC
# 文件能共享
root@nginx-5bb6d88dfb-w78k8:/opt/pvc# ls
pvc qqq test
root@nginx-5bb6d88dfb-w78k8:/opt/pvc# echo 11 > test
root@nginx-5bb6d88dfb-w78k8:/opt/pvc# cat test
11
7、PVC创建和挂载失败的原因
PVC一直Pending的原因:
- lPVC的空间申请大小大于PV的大小
- lPVC的StorageClassName没有和PV的一致
- lPVC的accessModes和PV的不一致
挂载PVC的Pod一直处于Pending:
- lPVC没有创建成功/PVC不存在
- lPVC和Pod不在同一个Namespace
删除PVC后k8s会创建一个用于回收的Pod,根据PV的回收策略进行pv的回收,回收完以后PV的状态就会变成可被绑定的状态也就是空闲状态,其他的Pending状态的PVC如果匹配到了这个PV,他就能和这个PV进行绑定。
作者: 杜宽
链接: https://ke.qq.com/course/2738602
评论区