joeの小窝

Loading...

k8s 存储详解

k8s存储详解

博客主要介绍本地存储,网络存储,pv,pvc,nfs动态制备pv

k8s存储就是指的pod的存储,持久化存储,数据不会丢失

一、本地存储

1、emptydir类型

  • 在pod所在的物理主机上生成一个随机目录,临时目录

  • 主要用于缓存的,pod被删除后,临时目录也会被删除

[root@master01 pv]# kubectl run b1-emptydir --image=busybox --image-pull-policy=IfNotPresent --dry-run=client -o yaml  -- /bin/sh -c "sleep 3600"  > emptydir.yml

[root@master01 pv]# cat emptydir.yml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: b1-emptydir
  name: b1-emptydir
spec:
  volumes:
    - name: data  # 指定卷的名字
      emptyDir: {}  # 临时目录类型
  containers:
  - args:
    - /bin/sh
    - -c
    - sleep 3600
    image: busybox
    imagePullPolicy: IfNotPresent
    name: b1-emptydir
    resources: {}
    volumeMounts:
    - name: data  # 将卷挂载到容器内部,名字需要一致
      mountPath: /data # 挂载到容器的/data目录下面
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

  • 可以查看到这个临时目录的位置的
[root@master01 pv]# kubectl get pod -o wide
NAME          READY   STATUS    RESTARTS   AGE     IP              NODE   NOMINATED NODE   READINESS GATES
b1-emptydir   1/1     Running   0          4m35s   10.246.73.179   node   <none>           <none>

# pod调度在node节点上,docker查看

[root@node data]# docker inspect b909ada5544a

# 进入挂载目录
[root@node data]# cd /var/lib/kubelet/pods/421b2bf8-5315-47de-9f67-40485d874191/volumes/kubernetes.io~empty-dir/data

# 查看数据
[root@node data]# ls
1.txt

  • 删除pod
# 进不去了,发现被删除了
[root@node pods]# cd /var/lib/kubelet/pods/421b2bf8-5315-47de-9f67-40485d874191/volumes/kubernetes.io~empty-dir/data
-bash: cd: /var/lib/kubelet/pods/421b2bf8-5315-47de-9f67-40485d874191/volumes/kubernetes.io~empty-dir/data: No such file or directory

2、hostPath类型

  • 这个就是在宿主机上面创建一个目录,然后挂载到pod里面

  • 有一个致命的缺陷,就是pod被再次调度到另外一个节点上面,这个节点上面没有这个目录,那就无法实现存储

  • 因此这个hostPath类型需要与标签选择器一起使用,指定在某个节点上调度

  • 或者是这个目录,所有节点都存在

[root@master01 pv]# cat hostpath.yml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: b2-hostpath
  name: b2-hostpath
spec:
  nodeName: master02  # 标签选择器,指定节点进行调度
  volumes:
  - name: hostpath  
    hostPath:  # hostPath 类型
      path: /data  # 宿主机目录
  containers:
  - image: nginx:1.25
    name: b2-hostpath
    resources: {}
    volumeMounts:
    - name: hostpath
      mountPath: /data  # 挂载到容器的/data目录下面
  dnsPolicy: ClusterFirst


# 在容器里面写入数据,宿主机上面也会存储数据
[root@master02 data]# ls
1.txt

二、网络存储

1、nfs存储

  • 为了解决上面的一些问题,pod需要被指定调度在某个节点

  • nfs就不需要指定节点了,只要网络是好的,就能任意共享

img

1、配置nfs服务器

yum -y install nfs-utils
mkdir /nfsdata
chmod o+w /nfsdata
[root@master01 pv]# cat /etc/exports
/nfsdata *(rw)

systemctl enable nfs-server --now
systemctl enable rpcbind --now

# 测试
[root@master01 pv]# showmount -e localhost
Export list for localhost:
/nfsdata *

2、使用nfs作为后端存储

[root@master01 pv]# cat nfs.yml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: b3-nfs
  name: b3-nfs
spec:
  volumes:
  - name: nfs-data
    nfs:
      path: /nfsdata   # nfs存储目录
      server: 192.168.50.20  # nfs服务器地址
  containers:
  - image: nginx:1.25
    name: b3-nfs
    resources: {}
    volumeMounts:
    - name: nfs-data
      mountPath: /nfs  # 挂载到容器nfs目录
  dnsPolicy: ClusterFirst
  restartPolicy: Always

# 查看pod详细,也可以看到挂载的详细信息
  • 写入数据
# 发现有数据
[root@master01 pv]# ls /nfsdata/
1.txt  nfs.txt

2、ceph存储

  • 可以使用rbd,cephfs这些作为后端的存储

  • 在下一篇的博客会详细的介绍

  • 只不过是写法不一样而已

三、pv和pvc

1、什么是pv和pvc?

  • 是k8s的资源对象,namespace级别的,pv不是ns级别的,pv全局可见的

  • 专门用来作为pod的后端存储的,pv是实际的存储,pvc是申请

  • pv和pvc进行绑定,pod直接使用pvc存储

  • pv的后端还是nfs或者rbd存储,所以底层还是之前学过的

  • 这样做的一个好处就是

    • pod直接使用pvc进行存储,不需要管后端使用的什么存储

    • 实现了存储的提供方和使用方的分离,方便管理,迁移

2、pv和pvc实验

  • pv的后端使用的是nfs存储

1、创建pv

[root@master01 pv]# cat b1-pvc.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
spec:
  capacity:
    storage: 5Gi  # 大小为5G
  accessModes:  # 访问模式,声明,没有实际的意义
  - ReadWriteOnce
  nfs:   # 使用的nfs作为后端存储
    path: /nfsdata
    server: 192.168.50.20

# pv全局可见的
[root@master01 pv]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Retain           Available                                   104s

# RWO权限

# Retain 默认策略,还有delete,recyle策略

# claim 为空,表示还没有pvc进行绑定

# 状态是avaliable 可用的

1、pv的状态

  • available 没有被pvc绑定,可以被使用的

  • bound 已经与pvc进行绑定了

  • released 绑定的pvc被删除了,但是这个pv里面的数据还在,pv还在,但pv的策略是Retain时,触发这种,无法被pvc绑定,因此需要删除pv才能再次使用

2、pv的策略(persistentVolumeReclaimPolicy)

  • Retain 保留策略,删除pvc后,pv里面的数据保留,但是pv的状态变成了released状态,就不可用了,pvc无法进行绑定,必须是available状态才行,需要删除pv,重新创建,才能再次使用

  • Delete 删除策略,pvc删除,pv也被删除,动态制备这个是默认策略,

  • Recyle 回收策略,删除数据,nfs或者hostpath支持

3、pv的访问模式

跟后面的pvc访问模式都是一样的意思, 就是一个声明的意思,没有任何意义

  • ReadWriteOnce RWO 单节点读写

  • ReadOnlyMany ROX 多节点只读

  • ReadWriteMany RWX 多节点读写

  • ReadWriteOncePod 单节点pod读写

2、创建一个pvc


apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc01
spec:
  accessModes:
  - ReadWriteOnce # 访问模式需要保持一样的
  resources:
    requests:
      storage: 5Gi  # 申请的大小

[root@master01 pv]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM           STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Retain           Bound    default/pvc01                           20m

# 发现pv被绑定了
[root@master01 pv]# kubectl get pvc
NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc01   Bound    pv01     5Gi        RWO                           4s

1、为什么会自动绑定了

  • 通过权限进行匹配

  • pvc的容器大小 小于等与 pv的大小即可

  • 如果有多个pvc的话,随机匹配,谁创建的快就优先匹配

  • 一个pvc只能绑定一个pv,一个pv也是一样的,只能绑定一个pv

  • 还受到storagename的影响,这个优先级是最高的,pv和pvc里面写这个字段,指定绑定的pv

2、pvc的状态

  • pending pvc没有被绑定

  • bound 成功被绑定

  • lost 删除了pv

  • terminating pvc正在被删除

3、pod使用pvc

apiVersion: v1
kind: Pod
metadata:
  name: b1-pvc
spec:
  volumes:
  - name: pvc  
    persistentVolumeClaim:  # 使用的pvc  
      claimName: pvc01  # pvc是哪一个
  containers:
  - name: b1-pvc
    image: nginx:1.25
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: pvc
      mountPath: /pvc  # 挂载到容器里面

  • 写入数据
[root@master01 pv]# kubectl exec -ti b1-pvc -- /bin/bash

root@b1-pvc:/# cd /pvc/
root@b1-pvc:/pvc# ls
1.txt  nfs.txt
root@b1-pvc:/pvc# echo pvc > pvc.txt

  • 查看后端的存储情况
# 也有数据
[root@master01 pv]# ls /nfsdata/
1.txt  nfs.txt  pvc.txt

4、删除pod,pvc

kubectl delete pod b1-pvc
[root@master01 pv]# kubectl delete pvc pvc01 

# 查看pv状态,发现变成了released
[root@master01 pv]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM           STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Retain           Released   default/pvc01                           36m

# 删除pv,再次创建pv,才能被使用
[root@master01 pv]# kubectl delete pv pv01 


# 这个后端存储的数据还是没有变的,还是存在的

5、总结

  • pv是实际存储的,pvc是申请存储,与pv进行绑定才能被pod使用

  • pv底层的存储可以是nfs,rbd,cephfs

  • pv,pvc都是k8s的资源对象,虚拟出来的

  • nfs映射到pv,pv映射到pvc,最后以卷的形式挂载pod即可

四、nfs动态制备

  • 就是上面创建pvc,pv还是有点麻烦的,每次创建一个pvc,还需要创建一个pv才行,pod只需要pvc即可

  • 那么就有一个动态制备了,就是创建了一个pvc就能自动的创建一个pvc进行绑定,无需手动创建

  • nfs-csi,ceph-csi都可以实现的

  • nfs动态制备原理

    • 创建一个pvc之后,先去找storageClassName

    • 绑定了nfs驱动,里面定义了后端的nfs服务器的一些信息

    • 在nfs服务器的共享目录下创建目录

    • pv使用这个目录,pvc绑定pv

img

  • 存储类怎么关联的nfs驱动呢?

    • 有参数指定的

1、nfs服务器部署

[root@master01 hpa]# cat /etc/exports
/nfsdata *(rw)

systemctl enable nfs-server --now
systemctl enable rpcbind --now

[root@master01 hpa]# showmount -e localhost
Export list for localhost:
/nfsdata *

2、部署nfs驱动

[root@master01 nfs]# git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git

[root@master01 deploy]# pwd
/root/nfs/nfs-subdir-external-provisioner/deploy

  • 都是部署在default下的
[root@master01 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

  • 修改deployment.yaml文件
# 修改镜像
image: registry.cn-hangzhou.aliyuncs.com/cloudcs/nfs-subdir-external-provisioner:v4.0.2

# 对接nfs服务器配置

            - name: NFS_SERVER
              value: 192.168.50.20
            - name: NFS_PATH
              value: /nfsdata
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.50.20
            path: /nfsdata


[root@master01 deploy]# kubectl get pod 
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-5cf5744c5f-78svw   1/1     Running   0          51s

2、创建storageClass

[root@master01 nfs]# cat class.yml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"  # 添加这个为默认的
  name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  archiverOnDelete: "false"


[root@master01 nfs]# kubectl get sc
NAME         PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-client   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  3s


3、创建一个pvc出来

[root@master01 nfs]# cat pvc.yml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: nfs-client  # 使用的存储类是nfs-client,就会自动的创建pv
  resources:
    requests:
       storage: 5Gi

[root@master01 nfs]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
pvc-b8640026-13ec-4cfa-bee8-e6363e634cd3   5Gi        RWO            Delete           Bound    default/pvc3   nfs-client              25s

# 自动创建出了pv
[root@master01 nfs]# kubectl get pvc
NAME   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc3   Bound    pvc-b8640026-13ec-4cfa-bee8-e6363e634cd3   5Gi        RWO            nfs-client     26s

# nfs服务器自动创建了一个目录,用作pv的存储
[root@master01 nfs]# cd /nfsdata/
[root@master01 nfsdata]# ls
default-pvc3-pvc-b8640026-13ec-4cfa-bee8-e6363e634cd3

五、总结

  • 在没有pv,pvc之前,pod需要直接使用存储,各种存储的写法不一样

  • 有了pv,pvc之后,pod直接使用pvc,pv使用后端的存储,各个存储不一样,pod只关心有没有pvc,就可以了

  • pvc创建后,自动的创建pv

ceph

nfs

ceph支撑nfs

posted @ 2026-04-07 20:30  乔的港口  阅读(30)  评论(0)    收藏  举报