近期发布的 JuiceFS CSI Driver v0.18 版本中,我们提供了一种全新的方式访问文件系统,即 JuiceFS 客户端以 Sidecar 方式运行于应用 Pod 中,且客户端与应用同生命周期。
这个全新的功能将帮助用户在 Serverless Kubernetes 环境中使用 JuiceFS;与传统的 Mount Pod 模式相比,问题排查更方便、客户端管理更简单。
今天在这篇文章中,将为大家介绍 Sidecar 模式的工作原理以及应用场景, 另外在文末还附上了用户关心的问题与解答。
What is a sidecar in cloud?
Sidecar 是一种常见的设计模式,这个概念在容器和微服务的领域中非常流行。回到 sidecar 的字面意思,如下图所示,就是指摩托车边上安装的这个小车,以增加摩托车的承载能力,它非常形象地表达了Sidecar 容器和应用容器的关系。在云环境中,他们成为一体,共享 Kubernetes pod 的环境,并且同一 pod 内的所有容器生命周期一致。
基础介绍
一些名词解释
- Pod:可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元
- Deployment / DaemonSet / StatefulSet / Job:声明式资源,对 Pod 的不同管理方式
- PV(PersistentVolume):集群中的一块存储
- PVC(PersistentVolumeClaim):表达的是用户对存储的请求
- StorageClass:为管理员提供了描述存储 "类" 的方法
- CSI(Container Storage Interface):容器存储接口
如何使用
存储的管理是一个与计算实例的管理完全不同的问题。PV 表示的是集群中的一块存储,可以由管理员事先创建;或者使用 StorageClass 来动态创建,然后用户在 Pod 中通过指定 PVC 来使用。根据 PV 的创建方式,可以分为静态配置和动态配置两种使用方式,下面一一介绍。
静态配置
由系统管理员创建若干 PV,在 PV 中声明包含了 JuiceFS 系统参数的 Secret,以备用户使用。用户创建 PVC,声明使用具体的 PV,在应用 Pod 中配置使用 PVC 即可。
资源间的关系如下图所示:
静态配置每一个应用使用都需要系统管理员对应创建一个 PV,在简单测试场景或者应用间数据共享时使用比较广泛。
动态配置
由系统管理员创建 StorageClass,在 StorageClass 中声明包含了 JuiceFS 系统参数的 Secret;然后用户创建 PVC,声明使用具体的 StorageClass,PVC 创建之后,Kubernetes 会根据 StorageClass 自动创建出一个 PV 与 PVC 进行绑定,最后用户在应用 Pod 中配置使用 PVC。
资源间的关系如下图所示:
在动态配置模式下,只需要创建一份 StorageClass 资源,就可以让多个应用使用,大大减少了系统管理员的配置工作。另外,对于 JuiceFS 来说,使用动态配置还能够实现应用间的数据隔离。
JuiceFS CSI Driver 的工作原理
用户通过在 PV / StorageClass 中指定 JuiceFS 的参数,进而在集群中使用 JuiceFS。JuiceFS CSI Driver 则负责挂载 JuiceFS 文件系统。
JuiceFS CSI Driver 提供了两种方式挂载文件系统,一种是现有的 Mount Pod 模式,另一种则是本次发布的版本中提供的 Sidecar 容器的方式。下面一一介绍两种模式以及二者的对比。
Mount Pod 模式
组件
Mount Pod 模式涉及到的组件包括 CSI Controller Service 和 CSI Node Service,职责分别为:
- Controller Service:以 PV id 为名,在 JuiceFS 文件系统中创建子目录。
- Node Service:创建 Mount Pod(JuiceFS 客户端),并挂载应用 Pod。下文会详细介绍其工作机制。
这种模式对环境的要求:
- 可以使用 FUSE 设备,在容器中体现为需要特权(Privilege);
- 可以运行 DaemonSet ,默认每台机器上都需要运行一个 CSI Node pod。
工作原理
CSI Node Service 的工作机制如下图所示:
- 用户创建应用 Pod,Pod 中声明使用 JuiceFS 的 PVC;
- CSI Node 负责在应用 Pod 所在节点创建 Mount Pod;
- Mount Pod 启动,执行 JuiceFS 客户端挂载,运行 JuiceFS 客户端,挂载路径暴露在宿主机上;
- CSI Node 等待 Mount Pod 启动成功后,将 PV 对应的 JuiceFS 子目录 bind 到容器内,路径为其声明的 VolumeMount 路径;
- Kubelet 创建应用 Pod。
PVC 与 Mount Pod 的关系
PVC、PV 和 Pod 的关系可以用下图表示,即在同一个节点上,一个 PVC 会对应一个 Mount Pod。
Sidecar 模式
组件
JuiceFS FUSE 客户端以 sidecar 容器的方式与应用容器一起运行在同一个 Pod 中。
CSI Driver 组件只有 CSI Controller Service。其职责为:
- 1. 以 PV id 为名在 JuiceFS 文件系统中创建子目录;
- 2. 向 ApiServer 注册 webhook,在 pod 中注入 JuiceFS 客户端的 sidecar 容器。
工作原理
工作机制如下图所示:
- CSI Controller 启动时向 ApiServer 注册 webhook;
- 应用 Pod 指定使用 JuiceFS 的 PVC;
- ApiServer 在创建应用 Pod 前调用 CSI Controller 的 webhook 接口;
- CSI Controller 向应用 Pod 中注入 JuiceFS 客户端容器(sidecar);
- ApiServer 创建 Pod,sidecar 容器启动后执行挂载,并运行 JuiceFS 客户端,客户端则按需访问元数据引擎和对象存储;应用容器启动后可直接访问文件系统。
PVC 与 Sidecar 的关系
PVC、PV 和 Pod 的关系可以用下图表示,即每个应用 pod 单独拥有自己的 JuiceFS 客户端,应用的挂载点相互隔离。
这种模式下,对环境的要求是可以使用 FUSE 设备,在容器中体现为需要特权(Privilege)容器。
Sidecar 容器的资源请求默认为 1 CPU 和 1GiB 内存,资源约束默认为 2 CPU 和 5GiB 内存。当集群资源紧俏时,我们还可以在 PV/StorageClass 中对 Sidecar 容器的使用资源进行配置。
另外,Sidecar 容器和应用容器的挂载点共享是通过 HostPath 实现的,不是直接共享,所以当 Sidecar 容器发生意外重启后,应用容器中的挂载点不会自行恢复,需要整个 Pod 重新创建。
两种模式的优缺点及使用场景
Sidecar 模式:
- 优势:故障排查简单;所有环境都可用;
- 缺点:资源开销大,每个应用 Pod 独享 JuiceFS 客户端;
- 使用场景:Serverless Kubernetes 环境(可以使用 FUSE);应用任务量不大的标准 Kubernetes 环境。
Mount Pod 模式:
- 优势:资源开销小,使用相同 PVC 的所用应用 Pod 共享同一个 JuiceFS 客户端;
- 缺点:故障排查复杂;Serverless 环境不可用。
- 使用场景:应用任务较多、标准的 Kubernetes 环境。
Q & A
Q1:Sidecar 模式创建的 pod,大概会占多少资源?默认分配多少?
A:资源限制是在容器这一层的,sidecar 容器的资源限制可以在 PV/StorageClass 中配置,参考文档,资源请求默认为 1 CPU 和 1GiB 内存,资源约束默认为 2 CPU 和 5GiB 内存。
Q2:FUSE 客户端是怎么升级的?
A:客户端的版本取决于 Sidecar 容器用的镜像,可以在 PV/StorageClass 中配置,参考文档,更换镜像实现升级。
Q3:Limit 达到上限后是否会影响文件读取性能?
A:CPU 达到 Limit 上限后文件的读写会变慢,Memory 达到 Limit 上限后客户端进程被会系统 OOM。
Q4:Sidecar和业务容器的启动结束的顺序有控制么?
A:Sidecar 容器默认在业务容器前面启动。
Q5:在 Sidecar 模式下,如果 FUSE 客户端出错 crash了,使用挂载点的其他容器里IO是不是就出错了?后面 FUSE 客户端所在的容器重启,其他容器里的 IO 重试能成功吗?
A:在 Sidecar 模式下,如果 FUSE 客户端 crash,挂载点会不可用;FUSE 客户端重启后,挂载点不可恢复,业务容器的 IO 也会失败,重启整个 Pod 重新挂载可以恢复。
Q6:在 Sidecar 模式下,FUSE 客户端本身是没有状态的,所以新起来的 FUSE 客户端是可以继续服务的?
A:在 Sidecar 模式下,FUSE 客户端是有状态的,重启后挂载点不可恢复。
使用示例
Sidecar 模式在安装时与 Mount Pod 有所不同,因为 webhook 与 ApiServer 通信需要鉴权,所以在安装前需要生成自签名证书。官方提供了一个可以自动生成自签名证书的脚本,实现一键安装。首先,在官网下载安装脚本,并设置执行权限:
wget https://raw.githubusercontent.com/juicedata/juicefs-csi-driver/master/scripts/juicefs-csi-webhook-install.sh
chmod +x ./juicefs-csi-webhook-install.sh
然后,用脚本安装 JuiceFS CSI:
./juicefs-csi-webhook-install.sh install
第三步,本文实例中的应用 pod 在 default namespace 下,需要为 default 打上以下标签:
kubectl label namespace default juicefs.com/enable-injection=true --overwrite
最后与 Mount Pod 模式的使用方式一样,配置 Secret、PVC、PV,在应用 Pod 中使用 PVC:
apiVersion: v1
kind: Pod
metadata:
name: juicefs-app
namespace: default
spec:
containers:
- args:
- -c
- while true; do echo $(date -u) >> /data/out.txt; sleep 5; done
command:
- /bin/sh
image: registry.cn-hangzhou.aliyuncs.com/juicefs/juicefs-fuse:v1.0.0-beta2
name: app
volumeMounts:
- mountPath: /data
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: ce-static
创建后结果如下,可以看到 juicefs-app 这个 pod 有两个容器:
$ kubectl get po
NAME READY STATUS RESTARTS AGE
juicefs-app 2/2 Running 0 45s
在 pod 的应用容器中也可以看到 JuiceFS 的挂载点:
$ kubectl exec -it juicefs-app -c app bash
root@juicefs-app:/app#
root@juicefs-app:/app# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 97G 23G 71G 24% /
tmpfs 64M 0 64M 0% /dev
tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup
JuiceFS:minio 1.0P 4.0K 1.0P 1% /data
/dev/mapper/ubuntu--vg-ubuntu--lv 97G 23G 71G 24% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 3.8G 12K 3.8G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 2.0G 0 2.0G 0% /proc/acpi
tmpfs 2.0G 0 2.0G 0% /proc/scsi
tmpfs 2.0G 0 2.0G 0% /sys/firmware
Sidecar模式的使用演示,还可查看B站视频