kubernetes
  • Introduction
  • 安装
    • 组件端口
    • 二进制安装
    • Kubeadm
      • 安装单Master集群
      • 安装高可用集群(手动分发证书)
      • 安装高可用集群(自动上传证书)
      • 安装ETCD集群
      • 安装高可用集群(外部ETCD)
    • 启动参数解析
      • ETCD相关参数
  • 负载均衡
    • Service
    • Ingress
    • 安装MetalLB
    • Nginx-ingress-controller
      • 转发TCP与UDP服务
      • 启动参数
      • 自定义Nginx模板
  • 存储
    • Volume
    • PV与PVC
    • StorageClass
    • Local-PV
      • Static-Provisioner
    • 实践
      • Ceph-RBD
      • NFS
  • 有状态服务
    • Mysql实践
    • Operator
      • Etcd
      • Zookeeper
      • Mysql
  • 认证与授权
    • 认证
      • 实践
    • 授权
  • Helm
    • 安装
    • Chart
      • 依赖
    • Helm命令
    • Repository
  • 日志
  • 监控
    • Prometheus体系
      • Prometheus
        • 内置函数
        • 配置
          • 规则文件
        • PromQL
      • Exporter
        • Metrics
      • Grafana
        • 配置
      • AlertManager
        • 配置
    • 容器监控
      • Cadvisor的指标
      • k8s中部署Prom与Cadvisor
  • Istio
  • 资源预留
    • imagefs与nodefs
    • 总结
  • 集群联邦
    • 联邦DNS原理
    • 联邦DNS安装
    • 安装federation-v1
  • Other
    • ImagePullSecret
    • QOS
    • Apiserver的代理
    • 资源配额
Powered by GitBook
On this page

Was this helpful?

  1. 存储

Local-PV

当我们在kubernetes中引入RBD、NFS这些分布式存储后,环境的部署就会变得复杂,因为要额外部署这些分布式存储系统,而本地存储是最简单的存储方式。本文将为大家介绍本地持久卷(Local Persistent Volume)

我们知道,RBD-PV是将Ceph中的一个RBD块抽象成一个PV。类似,Local-PV的设计理念就是,将主机上的一块磁盘抽象成一个PV。

那么问题来了

第一,Local-PV关联的是一块本地磁盘,如何保证使用这个PV的Pod能够被调度到这台主机上呢?

所以,在Local-PV的Yaml文件中,必须填写NodeAffinity内容,指定该磁盘是属于哪个节点的,如下:

上面的Yaml文件定义了一个Local-PV。我们要重点关注一下NodeAffinity中内容,它实际的效果是:使用这个PV的Pod只能被调度到节点node1上,也说是说,如果Pod使用的PVC绑定的是这个PV,那么Kube-Scheduler在调度这个Pod时,会把它调度到node1上。

这个时候,有人可能会问,Local-PV用HostPath加NodeSelector也可以实现吗?那为什么还要它呢?

对于这个问题,其实本质就是:有了Volume,为什么还要PV+PVC?

PV+PVC的本质就是,使用者无需关注具体的后端存储,只需要通过PVC声明自已对存储的需求。比如说考虑如下的一个场景:

有十个使用者要在集群中各发布一个Mysql服务,集群主机上有十块磁盘,如果用Volume(HostPath),那么k8s集群管理员得提前分配好,然后告诉使用者他们在Pod中该使用哪块磁盘。

很明显,这个过程非常的麻烦,当使用Local-PV,集群管理员只需要提前创建一批Local-PV,然后使用者只需要通过PVC声明自已需要多大的磁盘,k8s会自动给使得者分配一块磁盘。

第二,延迟绑定的问题

当创建一个PVC后,一般来说kube-controller-manager会立即为它寻找一个合适的PV进行绑定。但是,这种即时绑定对于Local-PV会有一些问题。

我们来看这样子的一个场景:假设k8s集群有三台主机A、B、C,每台主机上有一块空磁盘,我们创建了三个Local-PV pv-a、pv-b和pv-c,分别关联到主机A、B、C的磁盘。然后我们要发布一个Pod,而且限制了这个Pod只能调度到B、C主机上。Pod中使用了一个PVC,假设是即时绑定,那么在创建Pod前,该PVC就已经绑定好了一个PV,而假设该PVC绑定的PV所关联的磁盘刚好又在A主机上,那么根据Local-PV的NodeAffinity,该Pod只能被调度到A主机上。那么这个时候,Pod就会找不到合适的主机,最终的结果就是调度失败。

所以,为了解决这个问题。我们可以为Local-PV定义一个StorageClass,声明绑定策略为延迟绑定,如下:

上面的WaitForFirstConsumer的意思是:当创建一个local类型的PVC时,不马上进行绑定,而是等待第一个使用它的Pod被创建后等待调度时,由kube-scheduler对PVC进行绑定。

接下来,我们再来看上面的场景:

当创建一个local类型的PVC后,kube-controller-manager不会为PVC绑定一个PV。然后我们再创建Pod,使用该PVC。此时,kube-scheduler准备对这个Pod进行调度,但发现它使用了一个local类型的PVC,于是kube-scheduler会先为这个PVC绑定一个PV。kube-scheduler发现Pod中限制了其只能被调度到B、C主机中,于是会为该PVC在pv-b与pv-c中选择一个进行绑定,假设为pv-b。绑定后,那么Pod也会被调度到主机B上。

通过这种延迟绑定机制,可以尽量避免Pod调度失败的机率。

最佳实践

最后,我们来讲一下Local-PV的最佳实践

(1)虽然可以把一个目录抽象为一个Local-PV,但我们最好把一块磁盘抽象为一个Local-PV,因为这样子每个PV的磁盘空间就能得到很好的控制,不会相互干扰

(2)虽然在NodeAffinity中可以指定多个主机,但千万不要这么做

(3)使用Local-PV的服务,实例之间本身要具有同步数据的能力,因为一但某个节点挂了,这个节点上的Loval-PV的数据就找不回来了

PreviousStorageClassNextStatic-Provisioner

Last updated 5 years ago

Was this helpful?