使用容器镜像部署函数
概述
用户在本地环境打包容器镜像,只要符合OCI(Open Container Initiative)标准,都可以上传到FunctionGraph,由平台加载并启动运行。与原来上传代码方式相比,用户可以使用自定义的代码包,不仅灵活也简化了用户的迁移成本。您可以选择“事件函数”类型创建自定义镜像函数,也可以选择“HTTP函数”类型创建自定义镜像函数。
使用容器镜像部署函数,开发HTTP函数示例,请参见开发HTTP函数。
使用容器镜像部署函数,开发事件函数示例,请参见开发事件函数。
前提条件
请参见配置委托权限,创建一个包含“SWR Admin容器镜像服务(SWR)管理员”权限的委托,因为用户镜像储存在SWR服务中,只有拥有“SWR Admin”权限,才能调用与获取,拉取镜像。
操作步骤
- 登录函数工作流控制台,在左侧的导航栏选择“函数 > 函数列表”。
- 单击右上方的“创建函数”,进入“创建函数”页面。
- 选择“容器镜像”,参见表1。
图1 创建容器镜像
表1 配置信息 参数
说明
*函数类型
选择函数类型。
事件函数:通过触发器来触发函数执行。
HTTP函数:用户可以直接发送 HTTP 请求到 URL 触发函数执行。说明:- 自定义容器镜像需包含HTTP Server,监听端口为8000。
- HTTP函数只允许创建APIG/APIC的触发器类型,其他触发器不支持。
- 事件函数需创建一个HTTP Server并实现Method为POST和Path为/invoke的函数执行入口,可实现Method为POST和Path为/init的函数初始化入口。
- 通过APIG服务调用函数服务时,isBase64Encoded的值默认为true,表示APIG传递给FunctionGraph的请求体body已经进行Base64编码,需要先对body内容Base64解码后再处理。
- 函数必须按以下结构返回字符串。
{ "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": {"headerName":"headerValue",...}, "body": "..." }
*区域
选择要部署代码的区域。
*函数名称
函数名称,命名规则如下:
- 可包含字母、数字、下划线和中划线,长度不超过60个字符。
- 以大/小写字母开头,以字母或数字结尾。
*企业项目
选择已创建的企业项目,将函数添加至企业项目中,默认选择“default”。
容器镜像
输入镜像URL,即用于函数的容器镜像的位置。您可以单击“查看镜像”,查看自有镜像及共享镜像。
容器镜像覆盖
- CMD:容器的启动命令,例如"/bin/sh"。该参数为可选参数,不填写,则默认使用镜像中的Entrypoint/CMD。字符串数组,以逗号分开。
- Args:容器的启动参数,例如"-args,value1"。该参数为可选参数,不填写,则默认使用镜像中的CMD。字符串数组,以逗号分开。
- Working Dir:容器的工作目录。该参数为可选参数,不填写,则默认使用镜像中的配置。文件夹路径,以/开头。
- 用户ID:镜像运行时的用户ID,若不填写,默认为1003。
- 用户组ID:镜像运行时的用户组ID,若不填写,默认为1003。
现有委托
选择包含SWR Admin权限的委托,如需创建委托,请参见创建委托。
- Command、Args、Working dir三个参数之和不能超过5120。
- 初次执行时需要从SWR中拉取镜像,且冷启动时需要启动容器,所以自定义镜像冷启动比较慢。后续每次冷启动,如果节点上没有镜像,都需要从SWR中拉取。
- 镜像类型支持公开和私有,具体详情请参考编辑镜像属性。
- 自定义容器镜像开放端口限定为8000。
- 可支持的镜像包最大为10G,当镜像包过大时可以采取一些方式缩容,比如在线题库场景中,可以把原来加载在容器中的题库数据通过外部文件系统挂载盘方式挂载到容器中。
- FunctionGraph通过LTS日志采集容器输出到控制台的所有日志,可以通过标准输出或者开源日志框架重定向到控制台的方式打印业务信息。打印的内容建议包括系统时间、组件名称、代码行、关键数据等来方便定位。
- oom错误时,内存占用大小可以在函数执行结果中查看。
- 用户函数需要返回一个合法的http响应报文。
示例代码
以下示例使用NodeJS Express,在函数实例初始化时函数工作流会使用POST方法访问/init路径(可选),在每次调用时函数工作流会使用POST方法访问/invoke路径。函数通过req.headers获取context,req.body获取event,返回结果通过HTTP Response结构体输出。
const express = require('express'); const app = express(); const PORT = 8000; app.post('/init', (req, res) => { res.send('Hello init\n'); }); app.post('/invoke', (req, res) => { res.send('Hello invoke\n'); }); app.listen(PORT, () => { console.log(`Listening on http://localhost:${PORT}`); });