阅读 63

k8s-存储卷

一,简介

我们知道默认情况下容器的数据都是非持久化的,在容器消亡以后数据也跟着丢失,所以 Docker 提供了 Volume 机制以便将数据持久化存储。类似的,Kubernetes 提供了更强大的 Volume 机制和丰富的插件,解决了容器数据持久化和容器间共享数据的问题。
与 Docker 不同,Kubernetes Volume 的生命周期与 Pod 绑定容器挂掉后 Kubelet 再次重启容器时,Volume 的数据依然还在而 Pod 删除时,Volume 才会清理。数据是否丢失取决于具体的 Volume 类型,比如 emptyDir 的数据会丢失,而 PV 的数据则不会丢

1,volume类型

目前kubernetes支持一下volume类型:


image.png

注意,这些 volume 并非全部都是持久化的,比如 emptyDir、secret、gitRepo 等,这些 volume 会随着 Pod 的消亡而消失。

二,示例

1,emptyDir
概念:

emptyDir是最基础的Volume类型,用于存储临时数据的简单空目录。如果Pod设置了emptyDir类型Volume,Pod被分配到Node上时候,会创建emptyDir,只要Pod运行在Node上,emptyDir都会存在(容器挂掉不会导致emptyDir丢失数据),但是如果Pod从Node上被删除(Pod被删除,或者Pod发生迁移),emptyDir也会被删除,并且永久丢失。

面将用emptyDir卷实现在同一pod中两个容器之间的文件共享


image.png
[root@k8s-master volumes]# cat pod-volume.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-volume
  namespace: default
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    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"
    - "-c"
    - "while true; do echo $(date) >>/data/index.html; sleep 2; done"
  volumes:
  - name: html
    emptyDir: {}

查看pod

[root@k8s-master volumes]# kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
pod-volume                      2/2     Running   0          2m13s   10.244.1.74   k8s-node1   <none>           <none>
#使用curl 命令查看我们重定向到网页文件的内容
[root@k8s-master volumes]# curl 10.244.1.74
Thu Mar 18 08:26:58 UTC 2021
Thu Mar 18 08:27:00 UTC 2021
Thu Mar 18 08:27:02 UTC 2021
Thu Mar 18 08:27:04 UTC 2021

2,hostPath
概念:

hostPath允许挂载Node上的文件系统到Pod里面去。如果Pod需要使用Node上的文件,可以使用hostPath。在同一个节点上运行并在其hostPath卷中使用相同路径的pod可以看到相同的文件。


image.png

hostPath指定的type:


image.png
#在node 上创建存储目录
mkdir -p /data/volume 
echo "hello" >/data/volume/index.html
[root@k8s-master volumes]# cat pod-volume-hostpath.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-volume-hostpath
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80 
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: html
    hostPath:
      path: /data/volume
      type: DirectoryOrCreate
#创建pod
kubectl apply -f pod-volume-hostpath.yaml

[root@k8s-master volumes]# kubectl get pods  -o wide
NAME                            READY   STATUS    RESTARTS   AGE    IP            NODE        NOMINATED NODE   READINESS GATES
pod-volume-hostpath             1/1     Running   0          10s    10.244.1.75   k8s-node1   <none>           <none>
#访问网页文件
[root@k8s-master volumes]# curl 10.244.1.75
hello
#hostpath类型删除pod后重新创建pod被调度到该node节点上数据依然不会变,如果node节点宕了则存储卷也会删除,数据会消失,

3,NFS
概念:

NFS是Network File System的缩写,即网络文件系统。Kubernetes中通过简单地配置就可以挂载NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持同时写操作。
 emptyDir可以提供不同容器间的文件共享,但不能存储;hostPath可以为不同容器提供文件的共享并可以存储,但受制于节点限制,不能跨节点共享;这时需要网络存储 (NAS),即既可以方便存储容器又可以从任何集群节点访问,本文以NFS为例做测试

首先准备一台机器同一局域网的机器做为nfs-server(关闭firewalld.service和selinux)
安装nfs软件

[root@docker-ce ~]# yum install -y nfs-utils

创建共享目录:

mkdir -p /data/volumes
[root@docker-ce ~]# cat /etc/exports
/data/volumes 10.0.0.0/24(rw,no_root_squash)

在node节点上安装nfs-utils

[root@k8s-node2 ~]# yum install -y nfs-utils

创建NFS的pods

[root@k8s-master volumes]# cat volume-nfs.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-nfs
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/
  volumes:
  - name: html
    nfs:
      path: /data/volumes
      server: 10.0.0.100
创建pod
[root@k8s-master volumekubectl apply -f volume-nfs.yaml 
[root@k8s-master volumes]# kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE    IP            NODE        NOMINATED NODE   READINESS GATES
pod-nfs                         1/1     Running   0          9s     10.244.1.77   k8s-node1   <none>           <none>

去存储节点创建文件:

[root@docker volumes]# cat /data/volumes/index.html 
<h1>NFS docker</h1
#然后去访问pod的文件
[root@k8s-master volumes]# curl 10.244.1.77
<h1>NFS docker</h1
#删掉pod后在重建pod后数据依然在但是如果nfs宕了数据依然会丢失。
4,pv && pvc
概念:

PersistentVolume (持久卷, 简称 PV)和Persistent VolumeClaim(持久卷声明,简称 PVC)使得K8s集群具备了存储的逻辑抽象能力,使得在配置Pod的逻辑里可以忽略对实际后台存储技术的配置,而把这项配置的工作交给PV的配置者,即集群的管理者。存储的PV和PVC的这种关系,跟计算的Node和Pod的关系是非常类似的;PV和Node是资源的提供者,根据集群的基础设施变化而变化,由K8s集群管理员配置;而PVC和Pod是资源的使用者,根据业务服务的需求变化而变化,由K8s集群的使用者即服务的管理员来配置。
当集群用户需要在其pod中使用持久化存储时,他们首先创建PVC清单,指定所需要的最低容量要求和访问模式,然后用户将待久卷声明清单提交给Kubernetes API服务器,Kubernetes将找到可匹配的PV并将其绑定到PVC。PVC可以当作pod中的一个卷来使用,其他用户不能使用相同的PV,除非先通过删除PVC绑定来释放。

image.png
1,创建pv

准备环境
在nfs存储机器上创建目录

[root@docker ~]# mkdir /data/volumes/v{1..5}

[root@docker ~]# cat /etc/exports
/data/volumes/v1 10.0.0.0/24(rw,no_root_squash)
/data/volumes/v2 10.0.0.0/24(rw,no_root_squash)
/data/volumes/v3 10.0.0.0/24(rw,no_root_squash)
/data/volumes/v4 10.0.0.0/24(rw,no_root_squash)
/data/volumes/v5 10.0.0.0/24(rw,no_root_squash)

显示正常导出:
[root@docker ~]# exportfs -avr
exporting 10.0.0.0/24:/data/volumes/v5
exporting 10.0.0.0/24:/data/volumes/v4
exporting 10.0.0.0/24:/data/volumes/v3
exporting 10.0.0.0/24:/data/volumes/v2
exporting 10.0.0.0/24:/data/volumes/v1
#
[root@docker ~]# showmount -e
Export list for docker:
/data/volumes/v5 10.0.0.0/24
/data/volumes/v4 10.0.0.0/24
/data/volumes/v3 10.0.0.0/24
/data/volumes/v2 10.0.0.0/24
/data/volumes/v1 10.0.0.0/24

定义一个nfs的pv

定义pv不能定义在namespace中,应为pv是属于集群级别的资源,同样创建namespace是也不能指定名称空间,这两都是属于集群级别的资源

#创建了5个pv
[root@k8s-master volumes]# cat pv-deom.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv001
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  nfs:
    path: /data/volumes/v1
    server: 10.0.0.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv002
spec:
  capacity:
    storage: 8Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  nfs:
    path: /data/volumes/v2
    server: 10.0.0.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv003
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  nfs:
    path: /data/volumes/v3
    server: 10.0.0.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv004
spec:
  capacity:
    storage: 15Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  nfs:
    path: /data/volumes/v4
    server: 10.0.0.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv005
spec:
  capacity:
    storage: 20Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
    - ReadWriteMany
  nfs:
    path: /data/volumes/v5
    server: 10.0.0.100

查看pv

[root@k8s-master volumes]# kubectl get pv 
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv001   5Gi        RWO,RWX        Retain           Available                                   89s
pv002   8Gi        RWO,RWX        Retain           Available                                   89s
pv003   10Gi       RWO,RWX        Retain           Available                                   89s
pv004   15Gi       RWO,RWX        Retain           Available                                   89s
pv005   20Gi       RWO,RWX        Retain           Available                                   89s

创建pvc
[root@k8s-master volumes]# cat pvc-demo.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mypvc
  namespace: default
spec:
  accessModes: 
  - ReadWriteMany
  resources:
    requests:
      storage: 8Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pvc-pod
  namespace: default
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/
  volumes:
  - name: html
    persistentVolumeClaim:
      claimName: mypvc
#创建pvc
[root@k8s-master volumes]# kubectl apply -f pvc-demo.yaml 
#查看pvc
[root@k8s-master volumes]# kubectl get pvc
NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mypvc   Bound    pv002    8Gi        RWO,RWX                       18s
[root@k8s-master volumes]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON   AGE
pv001   5Gi        RWO,RWX        Retain           Available                                           74m
pv002   8Gi        RWO,RWX        Retain           Bound       default/mypvc                           74m
pv003   10Gi       RWO,RWX        Retain           Available                                           74m
pv004   15Gi       RWO,RWX        Retain           Available                                           74m
pv005   20Gi       RWO,RWX        Retain           Available                                           74m

spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
#access modes 使用参考:
https://v1-19.docs.kubernetes.io/docs/concepts/storage/persistent-volumes/

作者:会倒立的香飘飘

原文链接:https://www.jianshu.com/p/9924340e9ca2

文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐