在 Kubernetes 中使用 JuiceFS

JuiceFS 可以作为存储卷(Volume)挂载到 Kubernetes Pod 中作为持久化存储。

相比于相比普通云盘(如 AWS EBS,阿里云弹性云盘等),JuiceFS 支持更多适合云环境使用的特性:

  • 支持 ReadWriteMany 访问模式,可以同时挂载到多个 Pod 作为共享存储并发读写
  • 支持 ReadOnlyMany 访问模式,可以同时以只读模式挂载到多个 Pod
  • 文件系统挂载不受可用区限制,在单可用区失效情况下,支持工作负载的跨可用区迁移,实现高可用
  • 弹性容量高达 10Pi,无需进行扩容操作
  • 支持快速拷贝,生成数据副本用于离线调测(内测中)

在 Kubernetes 中使用 JuiceFS 可以通过以下三种方式:

  • CSI (推荐用于 Kubernetes v1.13 及以上版本)
  • flexVolume (适用于 Kubernetes v1.2 及以上版本)
  • hostPath (可用于所有 Kubernetes 版本)

针对不同的使用场景,可以选择合适的集成方式。

通过 CSI 存储卷

JuiceFS CSI 驱动 实现了 容器存储接口(CSI) 规范,用于在容器编排器中管理 JuiceFS 文件系统生命周期。

更多 JuiceFS CSI 驱动的文档请参考:JuiceFS CSI 驱动文档

在 Kubernetes v1.13 中, CSI 的支持已被提升为 GA 。CSI 支持在 Kubernetes v1.9 里作为 alpha 特性引入,在 Kubernetes v1.10 中提升为 beta。 如果要在更早的版本里使用 JuiceFS,可以考虑通过 flexVolumehostPath 挂载。

通过 flexVolume 存储卷

脚本 juicefs 同时也是 Flex 卷的驱动,支持 init, mount and unmount 操作。

你需要把 juicefs 放到所有主机的 /usr/libexec/kubernetes/kubelet-plugins/volume/exec/juicedata~juicefs/juicefs 位置, 并且将它改成可执行的(需要 Python2.6+ 或者 Python3)。

  1. $ wget https://juicefs.com/static/juicefs
  2. $ chmod +x juicefs
  3. $ cp juicefs /usr/libexec/kubernetes/kubelet-plugins/volume/exec/juicedata~juicefs/juicefs

在配置文件中使用明文密钥

你可以像下面这样定义一个 Flex 卷并使用 juicedata/juicefs 作为驱动:

  1. volumes:
  2. - name: test
  3. flexVolume:
  4. driver: "juicedata/juicefs"
  5. options:
  6. name: "my-jfs"
  7. token: "TOKEN"
  8. accesskey: "ACCESSKEY"
  9. secretkey: "SECRETKEY"

你还可以把其他挂载参数加入到 options 里,比如 cacheSizecacheDir 完整的参数列表请参考 juicefs mount -h

每个 Pod 会使用一个独立的挂载点,跟 Pod 有相同的生命周期。

Kubernetes 密钥管理

或许你不想把密钥的明文放到 Pod 配置文件中,使用 Kubernetes 的密钥管理可以做到。

先创建一个:

  1. apiVersion: v1
  2. kind: Secret
  3. metadata:
  4. name: my-jfs
  5. type: juicedata/juicefs
  6. data:
  7. token: BASE64(TOKEN)
  8. accesskey: BASE64(ACCESSKEY)
  9. secretkey: BASE64(SECRETKEY)

用下面的方法可以生成秘密的 base64 编码:

  1. $ echo -n TOKEN | base64

然后你可以在 Pod 配置文件中使用它:

  1. volumes:
  2. - name: test
  3. flexVolume:
  4. driver: "juicedata/juicefs"
  5. secretRef:
  6. name: my-jfs
  7. options:
  8. name: "my-jfs"

使用 JuiceFS 的配置文件

不管是使用明文还是 Kubernetes 密钥,Flex 卷都会把它们通过命令行参数的方式传递给驱动,比如:

  1. /usr/libexec/kubernetes/kubelet-plugins/volume/exec/juicedata~juicefs/juicefs mount /var/lib/kubelet/pods/aa8ef19f-ba1f-11e7-ab55-0800279245af/volumes/juicedata~juicefs/test '{"kubernetes.io/fsType":"","kubernetes.io/pod.name":"test","kubernetes.io/pod.namespace":"default","kubernetes.io/pod.uid":"aa8ef19f-ba1f-11e7-ab55-0800279245af","kubernetes.io/pvOrVolumeName":"test","kubernetes.io/readwrite":"rw","kubernetes.io/secret/accesskey":"","kubernetes.io/secret/secretkey":"","kubernetes.io/secret/token":"TOKEN","kubernetes.io/serviceAccount.name":"default","name":"NAME"}'

这样看起来也不是很安全,其他人通过 ps 等方法可以看到密钥明文或者编码后的, 通过 JuiceFS 的配置文件(/root/.juicefs/my-jfs.conf)我们可以把这些从命令行中隐藏起来, 它是一个有如下内容的 JSON 文件:

  1. {“token”: TOKEN”, accesskey”: ACCESSKEY”, secretkey”: SECRETKEY“}

一旦你把这个配置文件部署到所有主机的 /root/.juicefs/my-jfs.conf, 就不需要在 Pod 配置文件中使用明文或者密码了,如下:

  1. volumes:
  2. - name: test
  3. flexVolume:
  4. driver: "juicedata/juicefs"
  5. options:
  6. name: "NAME"

通过 hostPath 存储卷

可以把 JuiceFS 在所有主机中挂载到同一个挂载点(比如 /jfs), 然后使用 HostPath 驱动把它(或者某个子目录)绑定到容器中:

  1. volumes:
  2. - name: test-volume
  3. hostPath:
  4. path: /jfs
  5. # this field is optional
  6. type: Directory

所有在同一个主机中的容器会共享同一个客户端(以及文件系统缓存等)。

注意: HostPath 未来可能会在未来 Kubernetes 版本中被本地卷(Local volume)取代。

更多特性

更多支撑 Kuberentes 中应用的特性正在开发内测中,如有需求请通过浏览器右下角的客户支持与我们即时沟通: