从v1.11开始,kubernetes默认开启resize feature 和 PersistentVolumeClaimResize admission controller,如果用户创建的存储卷容量不够,可以进行扩容,原有数据不会丢失。目前支持resize的存储卷AWS-EBS, GCE-PD, Azure Disk, Azure File, Glusterfs, Cinder, Portworx, 以及 Ceph RBD。其中:

  • 块文件系统,如 GCE-PD, AWS-EBS, Azure Disk, Cinder, and Ceph RBD 需要文件系统扩容。当Pod重启时,k8s会自动完成扩容的工作
  • NAS文件系统,如 Glusterfs and Azure File) 不需要重启Pod,因为他们不需要文件系统扩容

以下以基于Ceph RBD的Storage class为例,具体说明PVC扩容功能。

1、扩容前准备

1、管理员需要配置storage class,开启允许扩容选项 allowVolumeExpansion

allowVolumeExpansion: true
kind: StorageClass
metadata:
  name: sata

2、制作 kube-controller-manager 镜像,增加rbd命令

由于扩容是kube-controller-manager完成的,而我们平台上是以容器形式运行的,因此需要容器镜像中附带rbd命令,否则扩容时会遇到如下错误提示:

  Warning  VolumeResizeFailed  3m (x75 over 4h)  volume_expand  Error expanding volume "default/resize" of plugin kubernetes.io/rbd : rbd info failed, error: executable file not found in $PATH

我制作了kubernetes v1.11.1 + ceph 10版本的controller-manager镜像 silenceshell/kube-controller-manager-amd64:v1.11.1-ceph-10,您也可以自行制作。

制作方法很简单:

  • 基于centos7基础镜像
  • COPY kube-controller-manager 二进制文件到 /usr/local/bin 目录
  • yum install ceph-common ceph-fs-common 即可。注意要使用ceph集群对应的版本。

3、更新 kube-controller-manager 编排文件的image以升级 controller-manager Pod

2、扩容操作

1、修改PVC的size

命令行使用kubectl edit pvc xxx,直接修改PVC的容量即可。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    volume.beta.kubernetes.io/storage-provisioner: ceph.com/rbd
  name: resize
spec:
  resources:
    requests:
      storage: 5Gi
  storageClassName: sata

之后PVC会进入 FileSystemResizePending 状态,等待Pod重启。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    volume.beta.kubernetes.io/storage-provisioner: ceph.com/rbd
  name: resize
spec:
  resources:
    requests:
      storage: 6Gi
  storageClassName: sata
status:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 5Gi
  conditions:
  - lastProbeTime: null
    lastTransitionTime: 2019-04-14T03:51:36Z
    message: Waiting for user to (re-)start a pod to finish file system resize of
      volume on node.
    status: "True"
    type: FileSystemResizePending
  phase: Bound

2、重启挂载该PVC的Pod

之后,controller manager 会调用 rbd resize命令,更新rbd image的大小,并重新挂载卷到Pod上去。

3、登录新的Pod的shell,查看挂载的rbd卷大小;查看PVC的status.capacity.storage 字段,已更新为新的容量。

3、在线扩容

1.11.1版本还提供了一个alpha的特性: ExpandInUsePersistentVolumes,即不需要容器即可扩容PVC扩容。当然了,PVC还是要管理Pod的,即需要被Pod挂载。

支持在线扩容的PVC有:GCE-PD, AWS-EBS, Cinder, and Ceph RBD。

该特性默认不开启,需要手工打开,增加如下kubelet启动参数即可。

--feature-gates ExpandInUsePersistentVolumes=true

打开后,修改RBD pvc的size,之后容器内可以看到,rbd容量自动更新为新的size了。

在线扩容本质上是利用了ext4, xfs这些文件系统可以在线扩容的功能。

4、cephfs可以扩容吗?

除了RBD,我们还会用cephfs PVC,但kubernetes本身是不支持对cephfs的PVC做扩容操作的。

实际上cephfs本身是支持扩容的,可以 setfattr -n ceph.quota.max_bytes 方式设置目录的quota。

这个功能需要修改kubernetes本身的代码,我已经实现了这块,cephfs存储卷可以在线扩容,不需要容器重启。

  1. 需要修改cephfs的属性,打开其expand功能,涉及 apiserver(admission)、controller
  2. 需要在kubelet的reconcile流程中做resize,其实就是设置目录的 ceph.quota.max_bytes

有时间了我详细写一下。

kubernetes的bug

另外发现了一个kubernetes本身的bug,kubelet重启的时候,会造成该节点上的ceph-fuse挂载的卷失效,表现为容器中df命令会提示 ‘Transport endpoint is not connected’,原有挂载卷也无法看到了。

我提了一个 issue

如果你跟我一样使用centos这种systemd管理的操作系统,解决办法就是使用 systemd-run 来执行 ceph-fuse

kubernetes在PR49640中对mount命令的挂载做了处理,会将mount fork出来的用户态进程移交给systemd管理;但是后来支持 ceph-fuse 的时候,并没有考虑这个问题,造成了这个bug。

如果想利旧,我试了下还挺麻烦的,原有架构很难做到。anyway,先提issue让社区解决吧,特别是storage方面的问题(狗头)

Ref: