k8s之存储管理

70 阅读4分钟

emptyDir

使用emptyDir的存储方式,就是在物理机上随机地产生一个目录,然后把这个目录挂载到容器目录/xxx(不存在会自动创建)。这种存储是临时性的,是以内存为介质,并非是永久性的。在删除pod的时候,emptyDir对应的目录也会被一起删除。类似docker创建容器时的命令docker run -v /xx

#以下yaml定义了两个emptyDir类型的volume,分别挂载在demo1,demo2两个容器的/data目录下
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    aa: aa
  name: demo
spec:
  volumes:
  - name: volume1
    emptyDir: {}
  - name: volume2
    emptyDir: {}
  containers:
  - args:
    - sh
    - -c
    - echo "hello pod"; sleep 10000
    image: busybox
    imagePullPolicy: IfNotPresent
    name: demo1
    volumeMounts:
    - mountPath: /data
      name: volume1
    resources: {}
  - name: demo2
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh','-c','sleep 5000']
    volumeMounts:
    - mountPath: /data
      name: volume1


  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

hostPath

使用hostPath的存储方式,类似于在创建docker容器时的docker run -v /data:/xx, 把物理机的目录/data映射到容器的/xx目录里,如果删除了这个pod,数据仍然是保留的。如果/xx目录不存在,会自动在容器里创建,同样如果是物理机的/data目录不存在的话也会自动创建。

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    purpose: demonstrate-envars
  name: demo
spec:
  volumes:
  - name: volume1
    hostPath:
      path:  /data
  containers:
  - args:
    - sh
    - -c
    - echo "hello pod"; sleep 10000
    image: busybox
    imagePullPolicy: IfNotPresent
    name: demo1
    volumeMounts:
    - mountPath: /containerdata
      name: volume1
    resources: {}
  - name: demo2
    image: busybox
    imagePullPolicy: IfNotPresent
    command: ['sh','-c','sleep 5000']
    volumeMounts:
    - mountPath: /poddata
      name: volume1
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

nfs存储

用nfs作为共享存储可以实现pod数据的共享。

持久性存储

Persistent Volume(持久性卷,pv)与指定后端存储关联,pv不属于任何namespace,全局可见。用户登录到自己的namespace之后,只要创建pvc(Persistent Volume Claim持久性卷声明),pvc会自动和pv进行绑定。一个pv只能和一个pvc进行绑定。

root@k8sdbamaster:/data/volume# cat pv1.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: /xx
    server: 10.99.00.11

accessModes有以下三种值,一定要确保pvc和pv的accessMode一致

ReadWriteOnce(RWO):仅允许单个节点挂载读写
ReadOnlyMany(ROX): 允许多个节点挂载只读
ReadWriteMany(RWX): 允许多个节点挂载读写

pv的回收策略persistentReclimPolicy,删除pvc之后pc是否会释放

Recycle: 删除pvc之后,会生成一个pod回收数据,删除pv里的数据,删除pvc之后,pv可复用,pv状态由Released变成available. pv中数据也被删除了。
Retain: 不回收数据,删除pvc之后,pv依然不可用,pv状态长期保持为Released。需要手动删除pv,然后重新创建,但是删除pv的时候并不会删除里面的数据
--删除pvc,查看pv状态,先是Release,然后就变成available
root@k8sdbamaster:/data/volume# kubectl delete -f pvc1.yaml
persistentvolumeclaim "pvc01" deleted
root@k8sdbamaster:/data/volume# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM            STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Recycle          Released   nsvolume/pvc01   xx                      42m
root@k8sdbamaster:/data/volume# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Recycle          Available           xx                      43m

查看pv属性

root@k8sdbamaster:~# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv01   5Gi        RWO            Recycle          Available                                   4m4s
root@k8sdbamaster:~# kubectl describe pv pv01

pvc(PersistentVolumeClaim)是基于namespace创建的,不同的namespace里的pvc是相互隔离的。 pvc通过storage的大小和accessModes的值与pv进行绑定,即如果pvc里的storage的大小,accessModes的值与pv里的storage的大小和accessModes的值都一样的话,那么pvc和pv进行绑定。

在pv和pvc的accessModes相同的情况下,只有pv的storage大小大于等于pvc的storage的大小的时候才能绑定。在有多个pvc的情况下,可以通过storageClassName进行控制。

root@k8sdbamaster:/data/volume# kubectl get pvc -n nsvolume
NAME    STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc01   Bound    pv01     5Gi        RWO                           15s

如果要在pod中使用pvc的话,需要在pod的yaml文件中创建pvc类型的卷,然后在pod中的容器中挂载这个卷就可以

kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx1
  name: nginx1
  namespace: nsvolume
spec:
  volumes:
  - name : myv
    persistentVolumeClaim:
      claimName: pvc01
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx1
    volumeMounts:
      - mountPath: "/mnt"
        name: myv
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
创建一个类型为pvc的卷,关联到名字为pvc01的pvc上

如果创建的pod状态一直是ContainerCreating,且通过kubectl describe pod查看有如下报错,可以查看物理机上nfs是否安装,可通过sudo apt install nfs-kernel-server来修复此问题。

Events:
  Type     Reason       Age                  From               Message
  ----     ------       ----                 ----               -------
  Normal   Scheduled    2m25s                default-scheduler  Successfully assigned nsvolume/nginx1 to k8sdbaworker1
  Warning  FailedMount  17s (x9 over 2m25s)  kubelet            MountVolume.SetUp failed for volume "pv01" : mount failed: exit status 32
Mounting command: mount

动态卷供应

在持久性存储的时候需要先创建pv,然后创建pvc。如果在不同的namespace中同时要创建不同的pvc,就需要提前把pv都创建好,这样才能为pvc提供存储。 现在可以通过storageClass(sc)来解决问题。 最终效果是,只要创建好storageClass,用户创建pvc的时候, storageClass会自动创建出一个pv和这个pvc绑定。

创建存储类型为hostPath的持久性存储

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv10
spec:
  capacity:
    storage: 2Gi
  volumeMode: Filesystem
  storageClassName: cka
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  hostPath:
    path: /pv10

通过kubectl在pod的container中写入数据

root@k8sdbamaster:/data/volume# kubectl exec -it pod-pvc  -- bash -c "echo hi > /data/testnew.txt"