k8s 持久化存储

1、为什么需要持久化存储?

  • k8s部署的应用都是以Pod形式运行的,mysql和redis这些数据库的话,需要存储数据

  • pod是有生命周期的,删除的话,数据也被删除了,所以需要做数据持久化存储

1、持久化存储

#可以查看pod支持的存储类型
[root@master ~]# kubectl explain pod.spec.volumes

1、临时目录类型的存储(emptydir)

  • pod分配到node主机上面时创建,会自动分配一个目录,无需在指定的node上面创建目录文件,随机分配一个目录,目录初始为空

  • pod被删除的话,临时目录里面数据也会被删除

  • 适用于不需要永久存储数据的程序

  • 一般存储在/var/lib/kubelet/pods

#临时目录挂在到容器/cache目录
[root@master volumes]# cat v1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: v1
  namespace: dev
spec:
  containers:
  - name: v1
    image: docker.io/library/tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: v1
      mountPath: /cache
  volumes:
  - emptyDir: {}
    name: v1


#在临时目录上面创建一个文件,进入pod里面的容器,查看数据
[root@master volumes]# kubectl get pod -n dev v1 -o yaml | grep -i uid
  uid: e4e613e6-5dc2-4d94-a5c8-9bc9900357ba
[root@node1 v1]# pwd
/var/lib/kubelet/pods/e4e613e6-5dc2-4d94-a5c8-9bc9900357ba/volumes/kubernetes.io~empty-dir/v1
[root@node1 v1]# touch test
#进入pod查看
[root@master volumes]# kubectl exec -ti -n dev v1 -- /bin/bash
bash-4.4# pwd
/usr/local/tomcat
bash-4.4# cd /cache/
bash-4.4# ls
test

#删除pod,临时目录也会被删除
[root@master volumes]# kubectl delete pod -n dev v1
pod "v1" deleted
[root@node1 pods]# ls
06fb2b78-d02e-40ec-b460-5ad19430258e  c6481ac9-520a-4ea7-96c7-80b6bcf4036e
1e2b7336-481e-44f5-9d50-da2c4a5a24ad

2、宿主机目录类型存储(hostPath)

  • 指定节点上面的目录,然后挂在到pod里面去,pod被删除的话,目录还在

  • 缺点,创建的pod每次调度的时候,需要在同一个节点上面,否则调度到其他节点,没有这个/data1目录

  • 有一个坑就是容器的挂在点的名字需要和hostpath挂在点的名字一样,相匹配才行

  • 有一个致命的缺点,每次都需要确保挂在到了同一个节点上面才行,否则数据不会持久化保存

  • node节点上的目录为主

#创建2个容器,宿主机目录/data1,2个容器共享这个data1目录
[root@master volumes]# cat v2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-test
  namespace: dev
spec:
  containers:
  - name: test-tomcat
    image: docker.io/library/tomcat:8.5-jre8-alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: pod-test 
      mountPath: /test-tomcat
  - name: test-nginx
    image: docker.io/library/nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: pod-test
      mountPath: /test-nginx
  volumes:
  - name: pod-test
    hostPath:
      type: DirectoryOrCreate  #宿主机挂在目录不存在的话,会自动的创建出来
      path: /data1

#在node1上面进行调度了,所以的话这个/data1被自动创建了
[root@master volumes]# kubectl get pod -n dev -o wide
NAME       READY   STATUS    RESTARTS      AGE     IP               NODE    NOMINATED NODE   READINESS GATES
pod-test   2/2     Running   0             2m58s   10.244.166.136   node1   <none>           <none>
pod1       1/1     Running   1 (67m ago)   14h     10.244.166.134   node1   <none>           <none>

[root@node1 data1]# pwd
/data1
[root@node1 data1]# mkdir test

#进入容器里面进行查看
[root@master volumes]# kubectl exec -it -n dev pod-test -c test-tomcat -- /bin/bash
bash-4.4# cd /test-tomcat/
bash-4.4# ls
test
bash-4.4# mkdir tomcat
#进入到nginx容器
[root@master volumes]# kubectl exec -ti -n dev pod-test -c test-nginx  -- /bin/bash
root@pod-test:/# cd /test-nginx/
root@pod-test:/test-nginx# ls
test  tomcat
root@pod-test:/test-nginx# mkdir nginx

#都是挂载在/data1上面
[root@node1 data1]# ls
nginx  test  tomcat

3、nfs网络文件存储

  • 弥补了上面必须确保在同一个节点上面的问题了

  • nfs支持多个客户端挂在同一个nfs共享目录出来,但是nfs宕机了,数据也就被丢失了,所以需要分布式存储,cephfs等

#每一个节点上面安装nfs-utils,启动
#master节点上面,/data/volumes作为nfs服务器,然后挂在即可
#

[root@master volumes]# cat v3.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nfs
  namespace: dev
spec:
  containers:
  - name: nfs
    image: docker.io/library/nginx 
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: nfs-v
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nfs-v  #名字要与volumemounts一样才行
    nfs:
      path: /data/volumes  #将这个目录挂在到了nginx里面去了
      server: master

#这样的话,就解决了创建的pod必须在同一个节点上面的问题,只要节点能够访问nfs服务器即可实现数据的持久化存储

4、pvc和pv资源

  • pv是一块存储,pvc持久化存储卷,绑定pv上面,才能进行使用

  • pvc创建成功后,pod使用的pvc必须与pvc在同一个名称空间下面

  • pv是资源,pvc是对这些资源的请求

  • pv相当于是磁盘的分区,pvc相当于是app向某个分区申请多少空间,安装wps时,需要申请1G的空间来进行安装

  • pv与pvc绑定后,pod就可以使用这个pvc了,如果没有满足pvc的要求的pv的话,pvc处于pending状态,

  1. pv和pvc之间的绑定模式

    • 跟pv的访问模式有关,
  2. pv的创建方式有2种(资源供应的模式)

    • 静态模式,先创建各种各样的pv,等待pvc的使用

    • 动态模式,无需先创建pv,通过storageclass动态模式自动完成pv的创建以及pvc的绑定

    • 总的来说都是pv与pvc之间的绑定

  3. 没有pv和pvc之前的对比

    • 没有的时候

      • 各个pod都可以任意的向存储资源中写数据,随便一个pod都可以写,任意磁盘爆掉
    • 有pv和pvc后

      • 引入了pvc个pv后,限制pod写入存储数据的大小

      • 先规划,后申请,在使用

  4. 使用pv和pvc

    • 找一个存储服务器,划分为多个存储空间

    • 将这些存储空间定义为多个pv

    • 先创建pvc,定义需要使用的pv的大小和访问模式,找到合适的pv

    • pvc被创建后,pod就可以使用这个存储卷了

    • pvc与pv之间是一一对应的关系,pv被绑定了就不能被其他的pvc使用了

  5. 回收策略

    • 创建Pod时,使用pvc作为存储卷的话,会与pv绑定,当删除pod时,pvc和pv就会解绑,这个时候的pv里面的数据可以保留或者删除

    • retain模式的话,删除pvc后,pv仍然存在,处于释放的状态,但是不能被其他的pvc绑定使用了,里面的数据还是存在的,下次使用的话,数据还是存在的,默认的回收策略

    • delete模式的话,删除pvc时会从k8s中移除pv,数据也会被删除

  6. 注意事项

    • 每次创建pvc的时候,需要使用有划分好的pv,不方便,那么可以在创建pvc的时候直接动态创建一个pv存储类,pv事项是不存在的

    • 删除pv的话,里面数据不会进行丢失,因为是后端存储做的

    • 删除pod的话,pvc和pv被解绑了,但是pv不能用了,如果用pod来使用pv的处于pending的状态

    • 必须要删除pv才行,才能使用pv

kubectl explain pvc
kubectl explain pv
1、静态的创建pv
#创建一个共享文件nfs
[root@master volume_test]# cat /etc/exports
/data/volume_test/v1 *(rw)
/data/volume_test/v2 *(rw)
[root@master volume_test]# exportfs -arv
exporting *:/data/volume_test/v2
exporting *:/data/volume_test/v1


#创建2个pv,将nfs作为pv
[root@master volumes]# cat pv1.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v1
  namespace: dev
spec:
  capacity:   #pv的大小
    storage: 1Gi
  accessModes:
  -  ReadWriteOnce  #单节点的pv进行读写
  nfs:
    path: /data/volume_test/v1
    server: master
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: v2
  namespace: dev
spec:
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteMany  #多节点pv进行读的模式
  nfs:
    path: /data/volume_test/v2
    server: master

[root@master volumes]# kubectl get pv -n dev
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
v1     1Gi        RWO            Retain(回收策略)           Available(可用的)                                   4s
v2     2Gi        RWX            Retain           Available                                   4s


#创建一个pvc
#pvc的访问模式跟pv的访问模式进行匹配
[root@master volumes]# cat pvc1.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc1
  namespace: dev
spec:
  accessModes:  #访问模式
  - ReadWriteMany
  resources:
    requests:
      storage: 2Gi

#pv和pvc之间进行了绑定
[root@master volumes]# kubectl get pvc -n dev
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc1   Bound    v2       2Gi        RWX                           34s

#pod创建出来,使用pvc作为持久化存储即可
[root@master volumes]# cat pod-pvc.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-pvc
  namespace: dev
spec:
  containers:
  - name: nginx
    image: docker.io/library/nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: nginx-html
      mountPath: /usr/share/nginx/html
  volumes:
  - name: nginx-html
    persistentVolumeClaim:
      claimName: my-pvc1


#删除Pod,然后删除pvc,删除pvc
#共享目录还在,
#删除了pod和pvc后,pv处于释放的状态
[root@master volumes]# kubectl delete -f pvc1.yaml 
[root@master v2]# kubectl get pv -n dev
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM         STORAGECLASS   REASON   AGE
v1     1Gi        RWO            Retain           Available                                         45m
v2     2Gi        RWX            Retain           Released    dev/my-pvc1                           4m38s

#在创建pvc的话,处于pending状态,如果还想要使用pv的话,先要删除pv才行
[root@master volumes]# kubectl apply -f pvc1.yaml 
persistentvolumeclaim/my-pvc1 created
[root@master volumes]# kubectl get pvc -n dev
NAME      STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
my-pvc1   Pending                                                     10s

#所以的话,需要删除pod,pvc,pv,才能使用pv
2、动态创建pv(存储类)
  • 上面静态模式的话,需要事先创建pv,然后一一对应,如果有成千上万的话,就需要很多的pv,维护的成本很高

  • k8s提供了一个自动创建pv的机制,也就是模版,动态生成一个存储卷供pvc使用

  • provisioner 内部供应商提供,也可以有外部提供,划分的pv有什么提供,可以是nfs,是一个外部的供应商

  1. 总结

    • 主要就是先创建一个供应商(nfs,共享文件夹)

    • 创建一个存储类,指定供应商

    • 创建pvc,指定存储类,就能从供应商下面的共享文件里面创建对应的pv,自动的创建出来

kubectl explain storageclass

#nfs为例,需要一个nfs-client自动装载程序,叫provisioner
#会使用我们配置好的nfs服务器自动创建持久卷,自动帮我们创建pv

#创建运行nfs-provisioner需要sa账号,这样的话,nfs就能与k8s交互

#创建nfs-provisioner账户
#方便pod创建出来,pod就有了指定的账户的权限
[root@master volumes]# cat service.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner

#对nfs账户进行授权
[root@master volumes]# kubectl create clusterrolebinding nfs-provisioner-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner
clusterrolebinding.rbac.authorization.k8s.io/nfs-provisioner-clusterrolebinding created

#安装nfs-provisioner程序,nfs供应商
[root@master volumes]# cat nfs-deployment.yaml 
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-provisioner
spec:
  selector:
    matchLabels:
       app: nfs-provisioner
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs  # 这个就是nfs供应商
            - name: NFS_SERVER
              value: 192.168.200.100
            - name: NFS_PATH
              value: /data/nfs_pro/
      volumes:
        - name: nfs-client-root
          nfs:
            server: master 
            path: /data/nfs_pro/  #从这几个目录下面创建pv,这个是nfs目录

#创建存储类,动态供给pv的
[root@master volumes]# cat stoarge.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs
provisioner: example.com/nfs  #供应商是example.com/nfs,

[root@master volumes]# kubectl get storageclasses.storage.k8s.io 
NAME   PROVISIONER       RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION(不允许扩展)   AGE
nfs    example.com/nfs   Delete          Immediate           false                  6s


#创建pvc,通过存储类动态生成pv
[root@master ~]# cat claim.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim1
spec:
  accessModes:  ["ReadWriteMany"]
  resources:
    requests:
      storage: 1Gi
  storageClassName:  nfs

#通过存储类自动的创建出来pv,有供应商创建出来的
[root@master ~]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pvc-51edc6b9-3361-45a0-a31b-c815544581a0   1Gi        RWX            Delete           Bound    default/test-claim1   nfs                     43s
[root@master ~]# kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
test-claim1   Bound    pvc-51edc6b9-3361-45a0-a31b-c815544581a0   1Gi        RWX            nfs            47s

#共享出来的文件夹
[root@master nfs_pro]# pwd
/data/nfs_pro
[root@master nfs_pro]# ls
default-test-claim1-pvc-51edc6b9-3361-45a0-a31b-c815544581a0


#创建pod时,使用pvc.就能直接指定,不需要创建pv
[root@master ~]# cat read-pod.yaml 
kind: Pod
apiVersion: v1
metadata:
  name: read-pod
spec:
  containers:
  - name: read-pod
    image: nginx
    imagePullPolicy: IfNotPresent
    volumeMounts:
      - name: nfs-pvc
        mountPath: /usr/share/nginx/html
  restartPolicy: "Never"
  volumes:
    - name: nfs-pvc
      persistentVolumeClaim:
        claimName: test-claim1

  1. 步骤

    • 供应商,创建一个nfs provisioner,提供pv的, 还是nfs作为底层的

    • 创建存储类,指定供应商,绑定了供应商

    • 创建pvc,指定存储类后,供应商就会创建pv

    • pod绑定pvc即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值