k8s存储卷和动态创建pv

发布于:2024-12-19 ⋅ 阅读:(34) ⋅ 点赞:(0)

1、kubernetes中的存储卷

1、为什么需要存储卷

  • 在部署pod的时候,启动时需要配置文件

  • 还有产生的临时的数据,需要多个容器共享

  • 还有数据库的持久化数据

  • 还有一个最重要的一点就是默认情况下,容器的文件在磁盘上是临时存放的,如果这个容器需要删除的话,这些数据也就会消失,之前的配置就没有了,所以需要存储卷来存储之前的配置

2、emptyDir(临时存储卷)

  • 顾名思义,就是一个临时存储数据的,可以实现pod中的容器之间共享目录数据,但是没有持久化的数据,存储卷会随着pod的结束而结束
# 这个字段
kubectl explain pod.spec.volumes.emptyDir

medium # 指定emptydir卷的存储位置,Default和Memory

sizeLimit # 用于指定存储卷的大小

1、emptydir实现

[root@master mnt]# cat n1.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: n1
  name: n1
spec:
  nodeName: node1
  containers:
  - image: docker.io/library/nginx:latest
    imagePullPolicy: IfNotPresent
    name: n1
    resources: {}
    volumeMounts:
    - name: empty
      mountPath: /var/empty
  volumes:
  - name: empty
    emptyDir: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}


[root@master pods]# kubectl get pod n1 -o jsonpath='{.metadata.uid}'
1c580bb2-23ab-4116-9996-065fa87a03dd

# 进入到/var/lib/kubelet/pods/这个目录,就可以看到临时存储挂载的目录了

3、hostPath(节点存储卷)

  • 就是将node节点上面的目录以文件挂载到pod容器指定目录上面去

  • 但是有一个缺点,如果这个pod调度在别的节点上面的话,那么就不能实现跨node节点的pod共享资源了,但是可以指定这个pod一直调度在这个节点上面去即可

  • 能在单独的一个节点上面持久化存储数据

1、hostPath字段

[root@master mnt]# kubectl explain pod.spec.volumes.hostPath

type # 字段的取值为DirectoryOCreate 如果给定的路径上面什么都不存在的话,那么就需要创建空目录,默认是这个

# Directory 就是路径上面必须存在目录

2、hostPath实现

[root@master mnt]# cat n1.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: n1
  name: n1
spec:
  nodeName: master
  containers:
  - image: docker.io/library/nginx:latest
    imagePullPolicy: IfNotPresent
    name: n1
    resources: {}
    volumeMounts:
    - name: hostpath
      mountPath: /var/hostpath
  volumes:
  - name: hostpath
    hostPath:
      path: /var/hostpath
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

4、nfs(网络共享)

  • 就是搭建一个NFS,然后利用共享目录提供出去,这样的话,不需要关心pod调度在哪一个节点上面去了,都可以获取到之前的配置了
[root@master mnt]# cat /etc/exports
/mnt/nfs *(rw)


[root@master mnt]# cat n1.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: n1
  name: n1
spec:
  nodeName: master
  containers:
  - image: docker.io/library/nginx:latest
    imagePullPolicy: IfNotPresent
    name: n1
    resources: {}
    volumeMounts:
    - name: nfs
      mountPath: /var/nfs
  volumes:
  - name: nfs
    nfs:
      server: 10.104.43.227  # nfs的ip地址
      path: /mnt/nfs   # nfs提供的挂载的目录
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

2、kubernetes中的数据卷pv和pvc

1、基本介绍pv和pvc

  • pv是一个从存储设备空间中逻辑划分创建出来的可持久化的存储对象,也就是磁盘中分出来一部分用于做成pv,就是一些硬盘等

  • 持久卷声明PVC,对pv存储资源的请求和和绑定,相当于是格式化吧,pod使用的一种存储卷的类型

1、pv的状态

生命周期 描述
Available(可用) pv的创建,直接创建pv的静态方式,还没有被pvc绑定
binding pv和pvc绑定后即可
Released(已释放) 表示PVC被删除了,但是PV还没被回收
failed(失败) 表示pv自动回收失败

2、accessModes字段

访问模式 描述
ReadWriteOnce(rwo) 读写的权限,但是只能被单个的node挂载
ReadOnMany(rox) 只读的,允许被多个node挂载
ReadWriteMany(rwx) 读写的权限,允许被多个node挂载

3、回收策略

  • 就是pv的一些策略

  • Retain的话就是PVC删除的时候,pv会被保留在集群中,不会被删除,也不会自动的清理里面的数据,但是pvc被删除后,pv仍然存在,需要手动删除pv或者清理里面的数据,就可以再次使用

  • Recycle 当PVC被删除时,pv中的所有文件会被清除掉,这个策略只有NFS和HostPath的PV支持,就是清理存储中的文件,然后就能使用了

  • Delete 当删除pvc的时候,pv会被自动删除,相关的数据也会被删除掉

2、创建的pvc的思路

  • 首先需要搭建一个MFS服务器,提供一个对外的共享文件夹,然后创建pv,以这个文件夹为例,这样PV就创建出来了,然后创建一个PVC,绑定即可,就能使用了PVC了
[root@master mnt]# cat pv-pvc.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  nfs:
    path: /mnt/nfs
    server: 10.104.43.227
  accessModes:
  - ReadWriteMany 
  capacity:
    storage: 2Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  accessModes:  # pvc的访问模式,需要与上面保持的一致即可
  - ReadWriteMany
  resources:  # pvc需要的大小
    requests:
      storage: 2Gi

[root@master mnt]# cat n1.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: n1
  name: n1
spec:
  nodeName: master
  containers:
  - image: docker.io/library/nginx:latest
    imagePullPolicy: IfNotPresent
    name: n1
    resources: {}
    volumeMounts:  
    - name: pvc1 
      mountPath: /usr/share/nginx/html
  volumes: 
  - name: pvc1
    persistentVolumeClaim: # 使用pvc挂载
      claimName: pvc1
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

3、动态的创建PV

  • 上面的静态有一个缺点,就是如果需要大量的pv,就需要创建很多的pv,因此的话,就会有一个动态的创建pv的出来,创建出来

1、自动创建的思路

# 因为安装这个自动创建pv的插件,也就是供应商,所以的话就需要sa和权限
  • 首先创建一个nfs服务器

  • 然后创建sa和账户

  • 然后创建供应商,绑定sa和nfs服务器,这样的话自动创建pvc,这个供应商就会自动的创建pv出来,与pvc进行绑定,然而,这个pv就是从这个nfs服务器提供的目录里面进行划分的

  • 这样的话就实现了自动创建pv的操作

2、动态创建的实现

1、创建一个nfs服务器和账户和绑定权限
# 创建一个nfs服务器
[root@master mnt]# cat /etc/exports
/mnt/nfs *(rw)

# 这样的话,这个账户就创建出来了,并且赋予了权限
[root@master pvc]# cat s1.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: null
  name: s1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: s1-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: ""
  kind: ServiceAccount
  name: s1
  namespace: default

2、创建一个供应商
[root@master pvc]# cat nfs-provisioner.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nfs-provisioner
  name: nfs-provisioner
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-provisioner
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nfs-provisioner
    spec:
      serviceAccountName: s1
      containers:
      - image: uhub.service.ucloud.cn/k8s-q7/nfs-subdir-external-provisioner:v4.0.0  # 供应商镜像
        name: nfs-client-provisioner
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: nfs-client-root
          mountPath: /persistentvolumes
        env:
        - name: PROVISIONER_NAME  # 配置provisioner的name,这个名字需要与后面创建动态类一样名字
          value: nfs-storage
        - name: NFS_SERVER  # 配置绑定NFS的服务器
          value: 10.104.43.227
        - name: NFS_PATH  # NFS服务器目录
          value: /mnt/nfs
      volumes:
      - name: nfs-client-root
        nfs:
          server: 10.104.43.227
          path: /mnt/nfs 
3、创建一个存储类(storage class)
[root@master pvc]# cat storage.yaml 
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: storage1
provisioner: nfs-storage  # 名字与provisioner的一致

[root@master pvc]# kubectl get storageclasses.storage.k8s.io 
NAME       PROVISIONER   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
storage1   nfs-storage   Delete          Immediate           false                  9m52s


4、创建一个pvc的pod
[root@master pvc]# cat pvc1.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
  storageClassName: storage1


[root@master pvc]# kubectl get pvc
NAME   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc1   Bound    pvc-e4280b84-cc41-45b8-bf33-8773b18a3e9d   2Gi        RWX            storage1       9m8s
[root@master pvc]# kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   REASON   AGE
pvc-e4280b84-cc41-45b8-bf33-8773b18a3e9d   2Gi        RWX            Delete           Bound    default/pvc1   storage1                9m10s

# 这个nfs目录也会创建一个目录来使用
[root@master nfs]# pwd
/mnt/nfs
[root@master nfs]# ls
default-pvc1-pvc-e4280b84-cc41-45b8-bf33-8773b18a3e9d

3、总结

  • 动态的创建pv,就是先创建一个底座,也就是提供存储的NFS,然后创建一个供应商,连接这个NFS,创建一个动态的存储类连接这个供应商,这样的话,就能创建pvc的时候,自动的创建pv了

  • 查看pod的uid

[root@master nfs]# kubectl get pod n1 -o jsonpath='{.metadata.uid}'

网站公告

今日签到

点亮在社区的每一天
去签到