Fluid 助力阿里云 Serverless 容器极致提速
作者:东伝
背景
数据对于当今互联网业务的重要性不言而喻,它几乎渗透到了当今这个世界的每一个角落。但单有数据是不够的,真正让数据产生价值的,是针对各业务场景运行的对大量数据的密集分析与计算,如机器学习、大数据分析、OLAP 聚合分析等等。近些年,随着数据规模的增大,这些对于资源有着更高要求的数据密集应用自然地导向了以弹性资源著称的云服务。
在这种数据密集应用上云的趋势下,Serverless 似乎并不是这个趋势的明显受益者。尽管几乎所有人都对这种计算资源无限扩容、弹性敏捷交付、低运维成本的架构不吝赞美之词,但由于它将计算存储分离的架构推向了一个更纯粹的极端,具有强数据依赖的数据密集应用想要高效运行于 Serverless 环境变得极其困难。
举例来说,如果我们想将 AI 推理服务应用部署在 Serverless 架构下,每个服务应用启动前必须将存放在外部存储系统的 AI 模型首先拉取到本地内存中。考虑到近年来 AI 大模型已经成为业界主流,让我们假设这个 AI 模型的大小为 30GB,并且存储于 OSS 对象存储服务中,如果需要同时启动 100 个这样的 AI 推理服务应用,那么总共的数据读取量就是 3000GB。OSS 存储默认的数据访问限速是 10Gbps,这就意味着 100 个应用都需要等待 2400 秒(3000GB * 8 / 10Gbps)才可以真正开始对外提供服务。如果每个服务我们创建一个 ecs.gn7i-c32g1.16xlarge 的实例(按每小时单价折算每秒 0.008 元),这意味着光在等待数据上就已经花掉了 1920 元(0.008 元/秒 * 2400 秒 * 100)。总结来说,我们大量的费用没有花在产生价值的计算上,这显然不是我们想要的。(*实际价格以阿里云官网显示为准)
那么,有没有什么方法可以优化上述过程?这就引入了本文的主角:Fluid。Fluid 是一个 Kubernetes 原生的分布式数据集编排和加速引擎。Fluid 诞生的初衷即是为应用的数据访问延时问题提供云原生的解决方案。对于困扰着 Serverless 数据密集应用的上述相关问题,Fluid 在保证用户简单易用的使用体验前提下,给出了一套 Serverless 环境新的数据访问架构方案,帮助用户提升数据访问效率。
本文将 step by step 地介绍 Fluid 的运行示例,帮助大家了解如何在阿里云 ASK(Alibaba Serverless Kubernetes)环境中使用 Fluid,展示如何借助 Fluid 实现 zero to zero 的(从零资源使用开始到全部资源释放结束)规模化数据密集型任务执行模式,并取得降本提速的效果。
Fluid on ASK 运行示例
Fluid 数据编排加速 Serverless Kubernetes 功能尚处于公测阶段,可点击阅读原文申请体验席位。
Fluid 部署
在运行以下示例前,首先需要搭建一个 ASK 集群,并配置好连接该集群的 Kubeconfig。相关步骤可参考文末文档《如何创建 ASK 集群》。在使用 Fluid 的各项功能前,需要将 Fluid 的各控制面组件部署到 ASK 集群中。这个部署过程可以通过阿里云容器服务-Kubernetes 控制台轻松完成。
如下图所示:
- 选择 ASK 集群面板右侧的“应用-Helm”子面板
- 点击"创建"按钮
- 在 Chart 市场中搜索 ack-fluid 即可找到 Fluid 对应的 Helm Chart,填写“应用名”(例:ack-fluid)。
- 点击“下一步”后,选择使用默认的 fluid-system 作为部署的命名空间
- 接着无需对 Chart Values 进行任何修改,直接点击“确定”,即可将 Fluid 部署到 ASK 集群中。
在配置完 ASK 集群对应的 Kubeconfig 信息后,输入以下命令:
$ kubectl get pod -n fluid-system
可以观察到 Fluid 的几个组件已经正常运行起来:
NAME READY STATUS RESTARTS AGE
dataset-controller-d99998f79-dgkmh 1/1 Running 0 2m48s
fluid-webhook-55c6d9d497-dmrzb 1/1 Running 0 2m49s
其中:
- Dataset Controller:负责维护各个 Fluid 所引入的 Dataset CRs 的完整生命周期。
- Fluid Webhook: 负责对用户需要访问数据的应用 Pod 进行自动化变换(Mutation),无感知地帮助用户实现 Serverless 场景的数据访问功能。
除了上述描述的两个组件外,Fluid 的控制面仍然包含了一些与各类缓存系统(例如:JindoFS、JuiceFS、Alluxio 等)紧密关联的控制器组件,这些组件在初始部署状态下不会创建,仅当用户指定需要使用某种缓存系统时,与其相关联的缓存系统控制器组件 Pod 才会按需扩容,从而在按量付费的 ASK 环境中尽可能地帮助用户节省成本。
数据缓存部署
Fluid 世界中的一切都以 Dataset 这一自定义资源为中心:无论是对外部存储中已有数据的抽象管理还是应用 Pod 的数据访问,用户都需要和 Dataset 资源进行交互。每当用户创建一个 Dataset CR 并指定了它的缓存系统后端,Fluid 就会自动地将数据缓存部署到 Kubernetes 集群中。
在下面的实践过程中,我们以阿里云 OSS 对象存储作为外部存储系统为例,模拟一个完整的 “缓存部署-数据访问-资源回收”的标准数据使用过程。
- 数据文件准备
首先,准备一个待访问的文件。例如,这里我们使用 dd 命令快速创建一个大小约为 30G 的文件:
$ cd $(mktemp -d)
$ dd if=/dev/zero of=./largefile-30G bs=10M count=3072
3072+0 records in
3072+0 records out
32212254720 bytes (32 GB) copied, 108.189 s, 298 MB/s
$ ls -lh ./largefile-30G
-rw-r--r-- 1 root root 30G Sep 7 21:11 ./largefile-30G
接着,把上述创建的待访问文件上传到 OSS Bucket 中,这里以一个位于 Beijing Region 的名为 fluid-demo 的 OSS Bucket 为例。
$ ossutil cp -i <access_key_id> -k <access_key_secret> -e oss-cn-beijing-internal.aliyuncs.com ./largefile-30G oss://fluid-demo/
- 创建 Fluid Dataset 和 Runtime 资源
数据准备和上传后,即可在 Fluid 中声明上述待访问的数据。具体而言,我们需要提交一个 Dataset CR 和一个 Runtime CR。Dataset CR 中描述数据在外部存储系统中的 URL 位置,Runtime CR 描述缓存系统及系统具体配置。
首先,把访问 OSS Bucket 所需的身份凭证信息存储于 Secret 中:
$ kubectl create secret generic oss-access-key \
--from-literal=fs.oss.accessKeyId=<access_key_id> \
--from-literal=fs.oss.accessKeySecret=<access_key_secret>
接着,定义 Dataset CR 和 Runtime CR。这里我们选择 JindoFS 作为缓存系统后端,Fluid Runtime 资源为 JindoRuntime:
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
name: demo-dataset
spec:
mounts:
- mountPoint: oss://fluid-demo # OSS Bucket URL
name: demo
path: /
options:
fs.oss.endpoint: oss-cn-beijing-internal.aliyuncs.com # OSS Bucket内网访问端点
encryptOptions:
- name: fs.oss.accessKeyId
valueFrom:
secretKeyRef:
name: oss-access-key
key: fs.oss.accessKeyId
- name: fs.oss.accessKeySecret
valueFrom:
secretKeyRef:
name: oss-access-key
key: fs.oss.accessKeySecret
---
apiVersion: data.fluid.io/v1alpha1
kind: JindoRuntime
metadata:
name: demo-dataset
spec:
# 缓存Worker节点数量
replicas: 5
podMetadata:
annotations:
# 选择JindoFS Pod使用的实例规格
k8s.aliyun.com/eci-use-specs: ecs.d1ne.6xlarge
# 启用实例镜像缓存,加速Pod启动过程
k8s.aliyun.com/eci-image-cache: "true"
tieredstore:
levels:
# 以40GiB的内存作为每个缓存Worker节点的缓存介质
- mediumtype: MEM
volumeType: emptyDir
path: /dev/shm
quota: 40Gi
high: "0.99"
low: