kubernetes学习笔记06(存储)
  aNy5PUCye2R8 2023年11月02日 40 0

Kubernetes存储管理

容器中的磁盘生命周期是短暂的,也带来了一系列的问题:

  • 当一个容器损坏后,Kubernetes会重启容器,但是文件会丢失
  • 很多容器在同一Pod中运行的时候,数据文件需要共享

Kubernetes Volume的到来解决了上述问题,Kubernetes集群中的存储跟Docker的存储卷有些类似,只不过Docker的存储卷作用范围为一个容器,Kubernetes的作用范围是Pod,每个Pod中声明的存储卷由Pod中的所有容器共享

kubernetes学习笔记06(存储)_Kubernetes学习笔记

1、EmptyDir

emptyDir:当Pod分配到Node上时,将会创建emptyDir,pod中的容器都可以读写这个目录,这个目录可以被挂载到各个容器相同或不同的路径下,并且只要Node上的Pod一直运行,Volume就会一直存在,当Pod从Node上被删除时,emptyDir也会被同时删除,存储的数据也将永久删除。(容器损坏不影响emptyDir

1.1 创建命名空间

创建名为nsvolume的命名空间,使用kubens切换命名空间

[root@master ~]# kubectl create namespace nsvolume
[root@master ~]# kubens nsvolume

1.2 创建并进入新的目录

[root@master ~]# mkdir volume
[root@master ~/volume]# cd volume/

1.3 创建一个pod的yaml文件

[root@master ~/volume]# kubectl run demo --image=busybox --image-pull-policy=IfNotPresent --dry-run=client -o yaml -- sh -c 'sleep 5000' > emp.yaml

查看该文件

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: demo
  name: demo
spec:
  containers:
  - args:
    - sh
    - -c
    - sleep 5000
    image: busybox
    imagePullPolicy: IfNotPresent
    name: demo
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

修改该文件至如下

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: demo
  name: demo
spec:
  # 创建一个Volume1和Volume2
  volumes:
    - name: volume1
      emptyDir: {}
    - name: volume2
      emptyDir: {}
  containers:
  # 两个容器命名为demo1、demo2并且使用volume1的卷
  - command: ['sh','-c','sleep 5000;']
    image: busybox
    imagePullPolicy: IfNotPresent
    name: demo1
    volumeMounts:
    - mountPath: /mmx
      name: volume1
  - command: ['sh','-c','sleep 5000;']
    image: busybox
    imagePullPolicy: IfNotPresent
    name: demo2
    volumeMounts:
    - mountPath: /mmx
      name: volume1
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

1.4 执行编排文件

[root@master ~/volume]# kubectl apply -f emp.yaml 
pod/demo configured
[root@master ~/volume]# kubectl get pods 
NAME   READY   STATUS    RESTARTS   AGE
demo   2/2     Running   2          134m

1.5 查看pod具体位置

根据命令,发现pod在node3上

[root@master ~/volume]# kubectl get pods -o wide 
NAME   READY   STATUS    RESTARTS   AGE    IP              NODE    NOMINATED NODE   READINESS GATES
demo   2/2     Running   2          135m   10.244.135.16   node3   <none>           <none>

查看容器

[root@node3 ~]# docker ps --format "{{.ID}} {{.Names}}" | grep nsvolume 
d4d2106b6983 k8s_demo2_demo_nsvolume_d3d5c156-76ca-437f-9a29-ee11a897eb96_1
ba418b395532 k8s_demo1_demo_nsvolume_d3d5c156-76ca-437f-9a29-ee11a897eb96_1
ab6552464c41 k8s_POD_demo_nsvolume_d3d5c156-76ca-437f-9a29-ee11a897eb96_0

查看是否存在挂载目录/mmx,发现容器共享一个卷

[root@node3 ~]# docker inspect ba418b395532 | grep /mmx 
                "/var/lib/kubelet/pods/d3d5c156-76ca-437f-9a29-ee11a897eb96/volumes/kubernetes.io~empty-dir/volume1:/mmx:Z",
                "Destination": "/mmx",
[root@node3 ~]# docker inspect d4d2106b6983 | grep /mmx             
                "/var/lib/kubelet/pods/d3d5c156-76ca-437f-9a29-ee11a897eb96/volumes/kubernetes.io~empty-dir/volume1:/mmx:Z",
                "Destination": "/mmx",

1.6 使用kubectl命令复制操作

[root@master ~/volume]# kubectl cp /etc/hosts demo:/mmx -c demo1 
[root@master ~/volume]# kubectl cp /etc/fstab demo:/mmx -c demo2

1.7 查看pod上是否存在文件

由于容器是共享一个目录的,所以hosts和fstab文件均存在

[root@master ~/volume]# kubectl exec demo -c demo1 -- ls /mmx 
fstab
hosts

进入特定目录查看

[root@node3 ~]# ls /var/lib/kubelet/pods/d3d5c156-76ca-437f-9a29-ee11a897eb96/volumes/kubernetes.io~empty-dir/volume1
fstab  hosts

1.8 移除Pod

[root@master ~/volume]# kubectl delete -f emp.yaml --force 
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "demo" force deleted

查看挂载卷

# 由于其特性,挂载目录也随之消失
[root@node3 ~]# ls /var/lib/kubelet/pods/d3d5c156-76ca-437f-9a29-ee11a897eb96/volumes/kubernetes.io~empty-dir/volume1
ls: cannot access '/var/lib/kubelet/pods/d3d5c156-76ca-437f-9a29-ee11a897eb96/volumes/kubernetes.io~empty-dir/volume1': No such file or directory

2、HostPath

hostPath允许挂载Node上的文件系统到Pod里面去。如果Pod需要使用Node上的文件,可以使用hostPath。相比于EmptyDir,此方式在删除Pod后,数据依旧保留,需要给挂载目录指定对应的物理目录,很类似于Docker中的挂载操作。

2.1 创建编排文件

[root@master ~/volume]# kubectl run demo --image=busybox --image-pull-policy=IfNotPresent --dry-run=client -o yaml -- sh -c 'sleep 5000' > host.yml

编排文件默认如下所示

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: demo
  name: demo
spec:
  containers:
  - args:
    - sh
    - -c
    - sleep 5000
    image: busybox
    imagePullPolicy: IfNotPresent
    name: demo
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

修改成hostPath方式

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: demo
  name: demo
spec:
  # 指定本地目录为/root/mmx
  volumes:
    - name: volume
      hostPath:
        path: /root/mmx
  containers:
  # 两个容器命名为demo1、demo2并且使用volume1的卷
  - command: ['sh','-c','sleep 5000;']
    image: busybox
    imagePullPolicy: IfNotPresent
    name: demo1
    volumeMounts:
    - mountPath: /mmx
      name: volume
  - command: ['sh','-c','sleep 5000;']
    image: busybox
    imagePullPolicy: IfNotPresent
    name: demo2
    volumeMounts:
    - mountPath: /mmx
      name: volume
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

2.2 执行编排文件

[root@master ~/volume]# kubectl apply -f host.yml 
pod/demo created

查看编排文件具体位置

[root@master ~]# kubectl get pods -o wide 
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES
demo   2/2     Running   0          41s   10.244.135.17   node3   <none>           <none>

查看node3上是否已经创建/root/mmx目录

[root@node3 ~]# ls /root/mmx/

2.3 使用kubectl命令复制操作

[root@master ~/volume]# kubectl cp /etc/hosts demo:/mmx -c demo1 
[root@master ~/volume]# kubectl cp /etc/fstab demo:/mmx -c demo2

2.4 验证操作是否成功

本地目录查看

[root@node3 ~]# ls mmx/
fstab  hosts

容器挂载点查看

[root@master ~]# kubectl exec demo -c demo1 -- ls /mmx/
fstab
hosts
[root@master ~]# kubectl exec demo -c demo2 -- ls /mmx/ 
fstab
hosts

2.5 删除Pod并验证

[root@master ~]# kubectl delete pod demo --force 
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "demo" force deleted

验证本地目录文件是否被删除

# 由于hostpath特性,本地文件并未删除
[root@node3 ~]# ls mmx/
fstab  hosts

3、NFS存储

NFS网络文件系统(network file system)服务可以将远程Linux系统上的文件共享资源挂载到本地主机的目录上,从而使得本地主机(Linux客户端)基于TCP/IP协议,像使用本地主机上的资源那样读写远程Linux系统上的共享文件。

Kubernetes中通过简单地配置就可以挂载NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持同时写操作。Pod被删除时,Volume被卸载,内容被保留。这就意味着NFS能够允许我们提前对数据进行处理,而且这些数据可以在Pod之间相互传递。

NFS卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir那样会在删除 Pod 的同时也会被删除,NFS卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 NFS卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

3.1 配置NFS服务器

使用master节点作为nfs服务器

# 安装软件包
yum -y install nfs-utils 
# 开启NFS服务
systemctl enable nfs-server.service --now
# 放行防火墙
firewall-cmd --add-service=nfs --permanent 
firewall-cmd --reload 
# 创建共享文件夹
mkdir /nfs_share
# 编辑nfs配置文件
echo "/nfs_share 192.168.0.0/24(rw,sync,no_root_squash)" > /etc/exports

3.2 配置NFS客户端

在node1~node3上配置

# 安装软件包
yum -y install nfs-utils 
# 编辑挂载文件
mkdir /share
echo "192.168.0.100:/nfs_share /share nfs defaults 0 0" >> /etc/fstab
mount -a 
# 验证
df -Th /share

3.3 通过Pod访问NFS

[root@master ~]# kubectl run nfs --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml -- sh -c 'echo hello; sleep 10' > nfs.yaml

生成编排文件如下

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nfs
  name: nfs
spec:
  containers:
  - args:
    - sh
    - -c
    - echo hello; sleep 10
    image: nginx
    imagePullPolicy: IfNotPresent
    name: nfs
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

修改成如下格式

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nfs
  name: nfs
spec:
  volumes:
  - name: volume1
    nfs:
      server: 192.168.0.100
      path: '/nfs_share'
  containers:
  - command: ['sh','-c','echo hello; sleep 5000']
    image: busybox
    imagePullPolicy: IfNotPresent
    name: nfs
    volumeMounts:
    - mountPath: /mmx
      name: volume1
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

3.4 应用编排文件

[root@master ~/nfs]# kubectl apply -f nfs.yaml 
pod/nfs created
# 查看pod具体位置
[root@master ~/nfs]# kubectl get pod -o wide 
NAME   READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES
nfs    1/1     Running   1          30s   10.244.104.20   node2   <none>           <none>

验证是否在nfs目录下

[root@master ~/nfs]# kubectl cp /etc/fstab nfs:/mmx 
[root@master ~/nfs]# kubectl cp /etc/hosts nfs:/mmx -c nfs 
[root@master ~/nfs]# ls /nfs_share/
fstab  hosts

验证在pod中是否能查看该文件

[root@master ~/nfs]# kubectl exec nfs -- ls /mmx
fstab
hosts

3.5 移除Pod

[root@master ~/nfs]# kubectl delete -f nfs.yaml 
pod "nfs" deleted

验证Pod移除后nfs共享目录文件是否存在

# 由于NFS是网络共享文件系统,移除Pod文件依旧存在
[root@master ~/nfs]# ls /nfs_share/
fstab  hosts

4、持久性存储

PV和PVC使得K8s集群具备了存储的逻辑抽象能力,使得在配置Pod的逻辑里可以忽略对实际后台存储技术的配置,而把这项配置的工作交给PV的配置者,即集群的管理者。存储的PV和PVC的这种关系,跟计算的Node和Pod的关系是非常类似的;PV和Node是资源的提供者,根据集群的基础设施变化而变化,由K8S集群管理员配置;而PVC和Pod是资源的使用者,根据业务服务的需求变化而变化,有K8s集群的使用者即服务的管理员来配置。

4.1 PV(PersistentVolume)

持久卷(PersistentVolume,PV)是集群中的一块存储,可以由管理员事先制备,或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的Volume一样,也是使用卷插件来实现的,只是它们拥有独立于任何使用PV的Pod的生命周期。

4.2 PVC(PersistentVolumeClaim)

持久卷申领(PersistentVolumeClaim,PVC) 表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而PVC申领会耗用PV资源。Pod可以请求特定数量的资源(CPU 和内存);同样PVC申领也可以请求特定的大小和访问模式(例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载)。

访问模式

说明

ReadWriteOnce

单节点读写映射

ReadOnlyMany

多节点只读映射

ReadWriteMany

多节点读写映射

4.3 各个生命周期说明

PV和PVC之间的相互作用遵循这个生命周期:

  • Provisioning(供应
  • Binding(绑定
  • Using(使用
  • Releasing(发布
  • Recycling(回收

Provisioning

Provisioning

有两种PV提供的方式:静态和动态

静态PV:集群管理员创建多个PV,它们携带着真实存储的详细信息,这些存储对于集群用户是可用的。它们存在于Kubernetes API中,并可用于存储使用。

kubernetes学习笔记06(存储)_Kubernetes学习笔记_02

动态PV:当管理员创建的静态PV都不匹配用户的PVC时,集群可能会尝试专门地供给volume给PVC。这种供给基于StorageClass,PVC必须请求一个类,并且管理员必须已创建并配置该类才能进行动态配置。

kubernetes学习笔记06(存储)_Kubernetes_03

PVC与PV的绑定是一对一的映射。没找到匹配的PV,那么PVC会无限期的处于unbound未绑定状态。

Binding

在动态配置的情况下,用户创建或已经创建了具有特定数量的存储请求和特定访问模式的PVC。 主机中的控制回路监视新的PVC,找到匹配的PV(如果可能),并将它们绑定在一起。 如果为新的PVC动态配置PV,则循环将始终将该PV绑定到PVC。

Using Pod使用PVC就像使用volume一样。集群检查PVC,查找绑定的PV,并映射PV给Pod。对于支持多种访问模式的PV,用户可以指定想用的模式。一旦用户拥有了一个PVC,并且PVC被绑定,那么只要用户还需要,PV就一直属于这个用户。用户调度Pod,通过在Pod的volume块中包含PVC来访问PV。

Pod使用PVC作为卷, 集群检查声明以找到绑定的卷并挂载该卷的卷。 对于支持多种访问模式的卷,用户在将其声明用作pod中的卷时指定所需的模式。

Releasing

当用户使用PV完毕后,他们可以通过API来删除PVC对象。当PVC被删除后,对应的PV就被认为是已经是“released”了,但还不能再给另外一个PVC使用。

Recycling

PV的回收策略告诉集群,在PV被释放之后集群应该如何处理该PV。当前,PV可以被Retained(保留)、 Recycled(再利用)或者Deleted(删除)。保留允许手动地再次声明资源。对于支持删除操作的PV卷,删除操作会从Kubernetes中移除PV对象,还有对应的外部存储(如AWS EBS,GCE PD,Azure Disk,或者Cinder volume)。动态供给的卷总是会被删除。

4.4 创建PV卷

使用NFS共享文件系统,分配一个大小为10G的空间

# 生成编排文件
kubectl run pv1 --image=nginx --dry-run=client -o yaml > pv1.yml

生成编排文件如下

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pv1
  name: pv1
spec:
  containers:
  - image: nginx
    name: pv1
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

将yaml文件修改如下所示

apiVersion: v1
# 将kind修改为PersistentVolume(持久卷)
kind: PersistentVolume
metadata:
  name: pv1
spec:
  # 定义容量
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  # 持久卷回收策略:回收
  persistentVolumeReclaimPolicy: Recycle
  # 使用NFS提供服务
  nfs:
    path: /nfs_share
    server: 192.168.0.100

创建PV卷并验证

[root@master ~]# kubectl apply -f pv1.yml 
persistentvolume/pv1 created
[root@master ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv1    10Gi       RWO            Recycle          Available                                   11s

4.5 创建PVC

通过PVC来调用已经存在的PV空间

# 生成编排文件
kubectl run pvc1 --image=nginx --dry-run=client -o yaml > pvc1.yaml

将生成yaml文件修改如下所示

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  # 设置访问方式为单节点读写
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  # 请求存储容量为5G,还剩5G
  resources:
    requests:
      storage: 5Gi

查看PVC

[root@master ~]# kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc1   Bound    pv1      10Gi       RWO                           15s

4.6 storageClassName

该参数用于给PV打上标记,通过该标记,可以让pod通过标记使用PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  # 打上标记mmx
  storageClassName: mmx
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /nfs_share
    server: 192.168.0.100

对应的PVC文件

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
spec:
  # 使用对应的标记mmx
  storageClassName: mmx
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 5Gi

执行并查看

[root@master ~]# kubectl apply -f pv2.yml 
persistentvolume/pv2 created
[root@master ~]# kubectl apply -f pvc2.yml 
persistentvolumeclaim/pvc2 created
# 此时发现mmx的标记能够查看到
[root@master ~]# kubectl get pv 
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM           STORAGECLASS   REASON   AGE
pv1    10Gi       RWO            Recycle          Bound    nsvolume/pvc1                           4m1s
pv2    5Gi        RWO            Recycle          Bound    nsvolume/pvc2   mmx                     78s
[root@master ~]# kubectl get pvc 
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc1   Bound    pv1      10Gi       RWO                           3m53s
pvc2   Bound    pv2      5Gi        RWO            mmx            7s

4.8 删除PV、PVC

先删除PVC再删除PV(重要!

# 删除pvc
kubectl delete -f pvc2.yml
kubectl delete -f pvc1.yml
# 删除pv
kubectl delete -f pv2.yml 
kubectl delete -f pv1.yml

4.9 Pod使用持久化存储

# 生成编排文件
kubectl run pv_pod --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml > pv_pod.yml

生成文件如下

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  volumes:
  - name: mypv
    persistentVolumeClaim:
      claimName: pvc1
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: mmx
    volumeMounts:
    - mountPath: /mnt
      name: mypv

执行yaml编排文件

[root@master ~]# kubectl apply -f pv1.yml 
[root@master ~]# kubectl apply -f pvc1.yml 
[root@master ~]# kubectl apply -f pv_pod.yml 
# 验证pv、pvc、pod是否均已创建
[root@master ~]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM           STORAGECLASS   REASON   AGE
pv1    10Gi       RWO            Recycle          Bound    nsvolume/pvc1                           14m
[root@master ~]# kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc1   Bound    pv1      10Gi       RWO                           13m
[root@master ~]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          9m13s

Pod放入文件并验证

# 放入常用的测试文件
[root@master ~]# kubectl cp /etc/hosts nginx:/mnt 
[root@master ~]# kubectl cp /etc/fstab nginx:/mnt

# 查看NFS提供的目录
[root@master ~]# cat /etc/exports
/nfs_share 192.168.0.0/24(rw,sync,no_root_squash)
# 查看文件是否存在
[root@master ~]# ls /nfs_share/                  
fstab  hosts


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  O704k6GYsxMM   2023年11月13日   21   0   0 rkeDockerkubernetes