研发工程师玩转Kubernetes——PVC通过storageClassName进行延迟绑定

news/2024/7/4 7:43:58 标签: kubernetes, 容器, 云原生

不同的PV可以使用相同的StorageClass,它们是一对多的关系。
在这里插入图片描述
PV可以设置节点亲和性。比如下图,local-storage-class-waitforfirstconsumer-pv-ubuntuc只能在节点ubuntuc上;local-storage-class-waitforfirstconsumer-pv-ubuntud只能在节点ubuntud上。
在这里插入图片描述

如果我们使用《研发工程师玩转Kubernetes——PVC使用storageClassName选择PV》一文中的“立即绑定”型的StorageClass。

# local_storage_class_immediate.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage-class-immediate
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: Immediate

则在创建PVC时,立即会选择一个PV。这样这个PVC可能绑定到节点ubuntuc对应的PV上,也可能绑定到节点ubuntud对应的PV上。现在我们假定它绑定到ubuntuc对应的PV——local-storage-class-immediate-pv-ubuntuc上。
假如PVC的使用者——Pod在调度时,清单文件要求它只能在ubuntud上使用。而其PVC却在ubuntuc上,则会调度失败。

立即绑定导致Pod调度失败的案例

StorageClass

注意volumeBindingMode是Immediate,即PVC创建时立即绑定PV。

# local_storage_class_immediate.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage-class-immediate
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: Immediate

PersistentVolume

ubuntuc

# local_storage_class_immediate_pv_ubuntuc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-storage-class-immediate-pv-ubuntuc
spec:
  capacity:
    storage:  1Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage-class-immediate
  local:
    path: /tmp
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - ubuntuc

ubuntud

# local_storage_class_immediate_pv_ubuntud.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-storage-class-immediate-pv-ubuntud
spec:
  capacity:
    storage:  1Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage-class-immediate
  local:
    path: /tmp
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - ubuntud

PersistentVolumeClaim

# local_storage_class_immediate_pvc_600k.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: local-storage-class-immediate-pvc-600k
spec:
  resources:
    requests:
      storage: 600Ki
  accessModes:
    - ReadWriteOnce
  storageClassName: local-storage-class-immediate

创建完上述组件,我们查看下PVC的状态。

kubectl describe persistentvolumeclaims local-storage-class-immediate-pvc-600k 
Name:          local-storage-class-immediate-pvc-600k
Namespace:     default
StorageClass:  local-storage-class-immediate
Status:        Bound
Volume:        local-storage-class-immediate-pv-ubuntuc
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      1Mi
Access Modes:  RWO
VolumeMode:    Filesystem
Used By:       <none>
Events:        <none>

可以看到这个PVC处于绑定状态。

Deployment

# local_deployment_immediate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: local-pv-app-immediate-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: local-pv-app-immediate
  template:
    metadata:
      labels:
        app: local-pv-app-immediate
    spec:
      containers:
      - name: local-pv-app-immediate
        image: busybox
        command: ["/bin/sh", "-c", "if [ -f /tempdir/lockfile ] && ! { set -C; 2>/dev/null >/tempdir/lockfile; }; then tail -f /tempdir/lockfile; else exec 3>/tempdir/lockfile; if [ -n \"$POD_NAME\" ]; then name=$POD_NAME; else name=\"unknown\"; fi; while true; do echo \"this is $name.$name write something to lockfile\"; echo \"$name write something to lockfile\" >&3; sleep 1; done; fi"]  
        volumeMounts:
        - name: local-pvc-volume
          mountPath: /tempdir
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
      volumes:
      - name: local-pvc-volume
        persistentVolumeClaim:
          claimName: local-storage-class-immediate-pvc-600k
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                - ubuntud    

这个清单要求Pod使用local-storage-class-immediate-pvc-600k这个PVC,但是要求自己只能被部署在节点ubuntud上。

错误表现

kubectl describe pod local-pv-app-immediate-deployment-6dd57d98f5-s5vpz 
Name:             local-pv-app-immediate-deployment-6dd57d98f5-s5vpz
Namespace:        default
Priority:         0
Service Account:  default
Node:             <none>
Labels:           app=local-pv-app-immediate
                  pod-template-hash=6dd57d98f5
Annotations:      <none>
Status:           Pending
IP:               
IPs:              <none>
Controlled By:    ReplicaSet/local-pv-app-immediate-deployment-6dd57d98f5
Containers:
  local-pv-app-immediate:
    Image:      busybox
    Port:       <none>
    Host Port:  <none>
    Command:
      /bin/sh
      -c
      if [ -f /tempdir/lockfile ] && ! { set -C; 2>/dev/null >/tempdir/lockfile; }; then tail -f /tempdir/lockfile; else exec 3>/tempdir/lockfile; if [ -n "$POD_NAME" ]; then name=$POD_NAME; else name="unknown"; fi; while true; do echo "this is $name.$name write something to lockfile"; echo "$name write something to lockfile" >&3; sleep 1; done; fi
    Environment:
      POD_NAME:  local-pv-app-immediate-deployment-6dd57d98f5-s5vpz (v1:metadata.name)
    Mounts:
      /tempdir from local-pvc-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-r48fn (ro)
Conditions:
  Type           Status
  PodScheduled   False 
Volumes:
  local-pvc-volume:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  local-storage-class-immediate-pvc-600k
    ReadOnly:   false
  kube-api-access-r48fn:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  8s    default-scheduler  0/5 nodes are available: 1 node(s) didn't match Pod's node affinity/selector. preemption: 0/5 nodes are available: 1 Preemption is not helpful for scheduling, 4 No preemption victims found for incoming pod..

可以看到Pod调度失败,处于Pending状态。
在这里插入图片描述

延迟绑定导致Pod调度成功的案例

StorageClass

注意volumeBindingMode是WaitForFirstConsumer,即PVC创建时不绑定PV。而在PVC被使用(Pod被调度到)时绑定PV。

# local_storage_class_waitforfirstconsumer.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage-class-waitforfirstconsumer
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

PersistentVolume

和之前的PV设置相似,核心就是storageClassName不同,使用了延迟绑定的StorageClass。

ubuntuc

# local_storage_class_waitforfirstconsumer_pv_ubuntuc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-storage-class-waitforfirstconsumer-pv-ubuntuc
spec:
  capacity:
    storage:  1Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage-class-waitforfirstconsumer
  local:
    path: /tmp
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - ubuntuc

ubuntud

# local_storage_class_waitforfirstconsumer_pv_ubuntud.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-storage-class-waitforfirstconsumer-pv-ubuntud
spec:
  capacity:
    storage:  1Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage-class-waitforfirstconsumer
  local:
    path: /tmp
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - ubuntud

PersistentVolumeClaim

和之前例子的区别就是storageClassName选择了延迟绑定的local-storage-class-waitforfirstconsumer。

# local_storage_class_waitforfirstconsumer_pvc_600k.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: local-storage-class-waitforfirstconsumer-pvc-600k
spec:
  resources:
    requests:
      storage: 600Ki
  accessModes:
    - ReadWriteOnce
  storageClassName: local-storage-class-waitforfirstconsumer

我们先创建上述组件,然后观察PVC的状态。

kubectl describe persistentvolumeclaims local-storage-class-waitforfirstconsumer-pvc-600k
Name:          local-storage-class-waitforfirstconsumer-pvc-600k
Namespace:     default
StorageClass:  local-storage-class-waitforfirstconsumer
Status:        Pending
Volume:        
Labels:        <none>
Annotations:   <none>
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      
Access Modes:  
VolumeMode:    Filesystem
Used By:       <none>
Events:
  Type    Reason                Age               From                         Message
  ----    ------                ----              ----                         -------
  Normal  WaitForFirstConsumer  2s (x2 over 11s)  persistentvolume-controller  waiting for first consumer to be created before binding

可以看到这次PVC没有立即绑定,而是处于Pending状态,且原因是等待第一个使用者触发绑定。

Deployment

# local_deployment_waitforfirstconsumer.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: local-pv-app-waitforfirstconsumer-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: local-pv-app-waitforfirstconsumer
  template:
    metadata:
      labels:
        app: local-pv-app-waitforfirstconsumer
    spec:
      containers:
      - name: local-pv-app-waitforfirstconsumer
        image: busybox
        command: ["/bin/sh", "-c", "if [ -f /tempdir/lockfile ] && ! { set -C; 2>/dev/null >/tempdir/lockfile; }; then tail -f /tempdir/lockfile; else exec 3>/tempdir/lockfile; if [ -n \"$POD_NAME\" ]; then name=$POD_NAME; else name=\"unknown\"; fi; while true; do echo \"this is $name.$name write something to lockfile\"; echo \"$name write something to lockfile\" >&3; sleep 1; done; fi"]  
        volumeMounts:
        - name: local-pvc-volume
          mountPath: /tempdir
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
      volumes:
      - name: local-pvc-volume
        persistentVolumeClaim:
          claimName: local-storage-class-waitforfirstconsumer-pvc-600k
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname
                operator: In
                values:
                - ubuntud    

创建完我们查看Pod的状态。

kubectl describe pod local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx
Name:             local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx
Namespace:        default
Priority:         0
Service Account:  default
Node:             ubuntud/172.22.244.197
Start Time:       Wed, 09 Aug 2023 17:07:01 +0000
Labels:           app=local-pv-app-waitforfirstconsumer
                  pod-template-hash=84449895c4
Annotations:      cni.projectcalico.org/containerID: cb10dba20771f872b242bc6284eb9d790565b7f2c1a2fbb096ff1581a73d4de5
                  cni.projectcalico.org/podIP: 10.1.202.206/32
                  cni.projectcalico.org/podIPs: 10.1.202.206/32
Status:           Running
IP:               10.1.202.206
IPs:
  IP:           10.1.202.206
Controlled By:  ReplicaSet/local-pv-app-waitforfirstconsumer-deployment-84449895c4
Containers:
  local-pv-app-waitforfirstconsumer:
    Container ID:  containerd://3fda11a2670236dc37409dd1fd6c5efae36d48bbcf1ce71266f72bd7b0b55b98
    Image:         busybox
    Image ID:      docker.io/library/busybox@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/sh
      -c
      if [ -f /tempdir/lockfile ] && ! { set -C; 2>/dev/null >/tempdir/lockfile; }; then tail -f /tempdir/lockfile; else exec 3>/tempdir/lockfile; if [ -n "$POD_NAME" ]; then name=$POD_NAME; else name="unknown"; fi; while true; do echo "this is $name.$name write something to lockfile"; echo "$name write something to lockfile" >&3; sleep 1; done; fi
    State:          Running
      Started:      Wed, 09 Aug 2023 17:07:04 +0000
    Ready:          True
    Restart Count:  0
    Environment:
      POD_NAME:  local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx (v1:metadata.name)
    Mounts:
      /tempdir from local-pvc-volume (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-52426 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  local-pvc-volume:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  local-storage-class-waitforfirstconsumer-pvc-600k
    ReadOnly:   false
  kube-api-access-52426:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  8s    default-scheduler  Successfully assigned default/local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx to ubuntud
  Normal  Pulling    8s    kubelet            Pulling image "busybox"
  Normal  Pulled     5s    kubelet            Successfully pulled image "busybox" in 2.266071612s (2.266078813s including waiting)
  Normal  Created    5s    kubelet            Created container local-pv-app-waitforfirstconsumer
  Normal  Started    5s    kubelet            Started container local-pv-app-waitforfirstconsumer

可以看到Pod按清单要求被成功调度到ubuntud上。

kubectl describe persistentvolumeclaims local-storage-class-waitforfirstconsumer-pvc-600k 
Name:          local-storage-class-waitforfirstconsumer-pvc-600k
Namespace:     default
StorageClass:  local-storage-class-waitforfirstconsumer
Status:        Bound
Volume:        local-storage-class-waitforfirstconsumer-pv-ubuntud
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      1Mi
Access Modes:  RWO
VolumeMode:    Filesystem
Used By:       local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx
Events:
  Type    Reason                Age                    From                         Message
  ----    ------                ----                   ----                         -------
  Normal  WaitForFirstConsumer  2m23s (x16 over 6m2s)  persistentvolume-controller  waiting for first consumer to be created before binding

这个Pod使用的PVC也被分配到ubuntud上。
在这里插入图片描述

参考资料

  • https://www.qikqiak.com/k8strain/storage/local/

http://www.niftyadmin.cn/n/4927279.html

相关文章

【云原生】Pod详讲

目录 一、Pod基础概念1.1//在Kubrenetes集群中Pod有如下两种使用方式&#xff1a;1.2pause容器使得Pod中的所有容器可以共享两种资源&#xff1a;网络和存储。1.3kubernetes中的pause容器主要为每个容器提供以下功能&#xff1a;1.4Kubernetes设计这样的Pod概念和特殊组成结构有…

【从零学习python 】09.Python 中的条件判断语句

文章目录 if语句的使用一、if判断语句介绍 if-else进阶案例 if语句的使用 一、if判断语句介绍 if语句是用来进行判断的&#xff0c;其使用格式如下&#xff1a; if 要判断的条件:条件成立时&#xff0c;要做的事情demo1: age 30print("------if判断开始------")if…

使用mybatis plus的各种注意事项(实时更新)

TableName("supplies_master") Data public class SuppliesItem extends Page {//如需使用mybatis plus的xxxById方法就必须指定id&#xff0c;否则就无法使用TableId(value "item_code", type IdType.NONE) //type IdType.NONE表示不做任何处理&#…

Vue3.2+TS通过i18n实现国际化全流程,使用Vue3.2+TS+i18n来给大家实现一下项目的国际化,并且单独封装一个切换语种的组件,解决出现的bug

前端开发项目时&#xff0c;很多的时候都会用到国际化&#xff0c;今天我使用Vue3.2TSi18n来给大家实现一下项目的国际化&#xff0c;并且单独封装一个切换语种的组件&#xff0c;解决出现的bug&#xff0c;大家一步一步往下看。 1.安装i18n npm install vue-i18n --save //我…

paddle

文章目录 一、paddle 一、paddle 官网 github gitee 下载安装Linux预测库

plsql设置id自增

plsql如何设置id自增 首先先创表。创建序列创建触发器 首先先创表。 在目录(tables)中选择新建&#xff1a;我创建的表明为SYS_TEST 创建序列 在目录sequences选择新建,我创建的名称为SYS_TEST_SEQ 在点击下方的应用即可。 创建触发器 在目录Triggers选择新建&#xff…

就业前的准备:web前端面试题及答案

今天小编来发布一些收集到的常见web前端面试题以及很多同学在面试过程中遇到的一些不知道如何回答的难题&#xff0c;通过对这些问题的整理&#xff0c;大家也要重新的巩固自身的基础&#xff0c;为日后的就业提前做好准备&#xff1a; 1、什么是盒子模型? 在网页中&#xff…

公网环境Windows系统,远程桌面控制树莓派《内网穿透》

远程桌面控制树莓派&#xff0c;我们可以用xrdp协议来实现&#xff0c;它内部使用的是windows远程桌面的协议。我们只需要在树莓派上安装xrdp&#xff0c;就可以在同个局域网下远程桌面控制树莓派。 而如果需要在公网下远程桌面控制树莓派&#xff0c;可以通过cpolar内网穿透&a…