1. 外部资源框架到底做了什么
整体就两件事:
1)改写资源请求(Resource Request)
- 你在 Flink 配置里声明要什么资源、要多少
- Flink 会把这些外部资源需求映射进底层资源管理系统(Kubernetes/YARN)的容器或 Pod 资源请求中
- 最终确保 TaskManager 所在的容器/Pod 真的带着你要的外部资源启动
2)把'可用资源信息'提供给算子(Operator)
- TaskManager 启动后,由'外部资源驱动(driver)'生成 ExternalResourceInfo(资源信息集合)
- 算子通过 RuntimeContext.getExternalResourceInfos(resourceName) 拿到资源的关键属性(比如 GPU index),然后就可以在算子里绑定对应设备去用
一句话:框架负责'申请 + 告知',至于'怎么用'取决于具体插件。
2. 适用场景与边界
适合的典型场景
- GPU 推理(TensorRT / ONNX Runtime / PyTorch inference)作为 RichFunction/AsyncFunction 的一部分
- GPU 加速特征工程或向量计算
- 需要 FPGA、专用加速卡的自定义计算
- 同一套作业在 Kubernetes/YARN 上希望'按需申请资源'
当前边界(很关键)
- 外部资源是'机器级/进程级共享'的:同一 TaskManager 上运行的所有算子拿到的 ExternalResourceInfos 目前是同一份集合
- 也就是说:没有 operator 级别的资源隔离(同 TM 内算子理论上能看到同一批 GPU)
如果你希望'每个算子/每个 subtask 独占一张卡',需要你在算子内部做更严格的绑定策略,或用脚本协调模式避免同机多 TM 抢同一 GPU(后面讲)。
3. 启用流程:三步走
3.1 准备外部资源插件(plugins/)
外部资源通过 Flink 插件机制加载,你需要把对应 jar 放到 Flink 的 plugins/ 目录下的某个子目录中,例如:
- GPU 插件:放到
plugins/external-resource-gpu/(或你自定义目录,但要保证 jar 能被加载) - 自定义资源插件:创建一个目录,比如
plugins/fpga/,把你打出来的 jar 放进去
插件隔离非常重要:每个 plugin 目录是独立 classloader,避免依赖冲突;同时 SPI(ServiceLoader)文件必须保留(META-INF/services)。
3.2 配置 external-resources 与每个资源的参数
核心配置有两层:
A)先声明启用哪些资源(白名单)
external-resources: gpu;fpga
只有这里列出来的 <resource_name> 才会生效。
B)为每个资源配置 amount、k8s/yarn 映射、driver、driver 参数 常见配置项含义:
external-resource.<name>.amount:每个 TaskManager 需要的资源数量external-resource.<name>.yarn.config-key:YARN 容器资源 profile 的映射 key(可选)external-resource.<name>.kubernetes.config-key:K8s 容器 resources.requests/limits 的 key(可选)external-resource.<name>.driver-factory.class:驱动工厂(可选但强烈建议)- 不配置也能'申请到资源',但算子拿不到 ExternalResourceInfo(RuntimeContext 里会没有信息)
- :传给驱动工厂的自定义参数(插件自定义解释)

