创建自定义镜像函数

当函数计算平台的内置运行时无法满足您的业务需求时,可以选择自定义镜像函数。本文介绍如何在函数计算控制台或使用Serverless Devs工具创建自定义镜像函数。

注意事项

  • 在函数计算中,创建自定义镜像函数必须使用同一账号下相同地域内阿里云镜像服务仓库中的镜像。针对搭载Apple芯片的Mac电脑(或其他ARM架构的机器),构建镜像时需要指定镜像的编译平台为Linux/Amd64,示例命令如docker build --platform linux/amd64 -t $IMAGE_NAME .

  • 函数计算在解析ACR企业版镜像域名时,使用镜像仓库实例配置的专有网络默认解析或云解析PrivateZone自动解析的访问IP地址。具体场景如下:

    • 场景一:如果ACR企业版实例的访问控制页面的访问 IP中不存在默认解析标识时,该列表下的所有IP地址均为云解析PrivateZone自动解析的IP地址,任意一个VPC配置均可使用。

      image

    • 场景二:如果ACR企业版实例的访问控制页面的访问 IP中存在默认解析标识的IP地址为专有网络默认解析的IP地址,以下图为例,只能选择第一个VPC。

      image

  • 使用企业版实例时只能选择非加速镜像,并且每次更新函数的镜像配置时,都会基于最新选择的原始镜像生成最新的加速镜像(如果加速镜像已存在会覆盖生成)。请不要删除原始镜像以及加速镜像,否则会影响函数调用。

  • 请确保您在函数配置中的镜像在发生任何变化后,及时更新您的函数,否则函数调用会失败。

    • 请确保原始镜像存在,否则函数会进入Failed状态,并且无法调用。函数计算虽然对您的函数做了缓存以加速冷启动速度,但是在调用过程中依然依赖您的原始镜像的存在。

    • 请确保您在任何函数中使用的镜像不要被覆盖,如果被覆盖为其他的Digest,请及时使用最新的镜像信息重新部署您的函数。函数计算会同时记录您在创建和更新配置时所选择的镜像版本Tag和Digest,如果您的镜像版本在别的地方被更新为其他的Digest,函数将调用失败。

前提条件

在控制台创建函数

  1. 登录函数计算控制台,在左侧导航栏,单击函数

  2. 在顶部菜单栏,选择地域,然后在函数页面,单击创建函数

  3. 创建函数页面,选择创建函数的方式,按需设置以下配置项,然后单击创建

    • 基本设置:设置函数名称。

    • 函数代码:配置创建函数的镜像。

      配置项

      说明

      运行环境

      • 使用示例镜像:选择函数计算提供的示例镜像,快速体验部署镜像函数。您需要从配置项容器镜像下方镜像列表中选择目标镜像。

      • 使用 ACR 中的镜像:选择ACR中的镜像创建函数时,需单击配置项容器镜像下方的选择 ACR 中的镜像,在弹出的选择容器镜像面板,选择已创建的容器镜像实例ACR 镜像仓库,然后在下方镜像版本列表找到目标镜像并单击其右侧操作列的选择

        说明
        • 不支持使用跨账户ACR中的公开镜像创建函数。

        • 请确保您在函数配置中的镜像在发生任何变化后,及时更新您的函数,否则函数调用会失败。具体请参见注意事项

        • 使用企业版实例时,只能选择非加速镜像,请不要删除原始镜像以及加速镜像,否则会影响函数调用。具体请参见注意事项

        • 使用企业版实例时,不支持自定义域名格式的镜像地址。

        • 不支持使用ACR企业版(标准版和高级版)实例中开启仅索引模式镜像加速的仓库中的镜像创建函数。

        • 自ACR新增仅索引模式功能起,企业版(基础版)实例中新建的开启镜像加速开关的镜像仓库中的镜像不支持用来创建函数,存量企业版(基础版)实例中存量镜像加速仓库中的镜像仍然支持用来创建函数。关于仅索引模式,请参见按需加载容器镜像

      启动命令

      容器的启动命令。如果不填写,则默认使用镜像中的Entrypoint或者CMD。

      监听端口

      容器镜像中的HTTP Server所监听的端口。默认端口为9000。

    • 高级配置:配置函数的实例相关信息、执行超时时间和网络设置等。

      配置项

      说明

      是否使用GPU

      根据您的业务情况,选择是否使用GPU实例。默认使用CPU实例,不使用GPU实例。更多信息,请参见实例类型及使用模式。关于各种实例类型的计费详情,请参见计费概述

      • 使用GPU

      • 不使用GPU

      说明

      仅当您选择创建事件函数Web函数任务函数时,需要设置此配置项。

      GPU 卡型

      选择GPU卡型,关于GPU卡型介绍,请参见实例类型及使用模式

      规格方案

      • 选择使用GPU

        根据您的业务情况,选择合理的GPU规格函数计算将根据您选择的GPU规格自动选定vCPU规格内存规格,不支持灵活配比。

      • 选择不使用GPU

        根据您的业务情况,选择或手动输入合理的vCPU规格内存规格组合。

      关于各资源使用的计费详情,请参见计费概述

      说明

      vCPU大小(单位为核)与内存大小(单位为GB)的比例必须设置在1∶1到1∶4之间。

      临时硬盘大小

      根据您的业务情况,选择硬盘大小。函数计算为您提供512 MB以内的磁盘免费使用额度。更多信息,请参见计费概述

      执行超时时间

      设置超时时间。默认为60秒,最长为86400秒,推荐您设置为600秒。

      说明

      超过设置的超时时间,函数将以执行失败结束。如需更长的超时时间限制,请加入钉钉用户群(钉钉群号64970014484)申请。

      单实例并发度

      设置函数实例的并发度。具体信息,请参见设置实例并发度

      时区

      选择函数的时区。此处设置函数的时区后,将自动为函数添加一条环境变量TZ,其值为您设置的目标时区。

      函数角色

      如果您的代码逻辑需访问其他云服务,请创建角色并为角色最小化授予访问其他云服务的权限。更多信息,请参见授予函数计算访问其他云服务的权限

      允许访问 VPC

      是否允许函数访问VPC内资源。更多信息,请参见配置网络

      专有网络

      允许访问 VPC选择时必填。创建新的VPC或在下拉列表中选择要访问的VPC ID。

      交换机

      允许访问 VPC选择时必填。创建新的交换机或在下拉列表中选择交换机ID。

      安全组

      允许访问 VPC选择时必填。创建新的安全组或在下拉列表中选择安全组。

      允许函数默认网卡访问公网

      是否允许函数可以通过默认网卡访问公网。关闭后,当前函数将无法通过函数计算的默认网卡访问公网。

      重要

      使用固定公网IP地址功能时,您必须关闭允许函数默认网卡访问公网,否则配置的固定公网IP地址不生效。更多信息,请参见配置固定公网IP地址

      日志功能

      是否启用日志功能,取值说明如下:

      • 启用:启用后,您可以查看函数的调用日志,函数的调用日志将通过日志服务存储和查询。

      • 禁用:不启用日志功能。

    • 环境变量:设置函数运行环境中的环境变量。更多信息,请参见配置环境变量

    创建完成后,您可以在函数列表中查看和更新已创建的函数。

说明

更新函数时,只能变更已设置的监听端口,不能删除或添加额外的监听端口。如果创建函数时,配置了监听端口,更新该函数时,不指定监听端口,将保留创建函数时的监听端口。

使用Serverless Devs创建函数

使用Serverless Devs可以一键构建、推送容器镜像并部署函数。

  1. 执行以下命令,初始化项目。

    sudo s init

    根据界面提示,依次选择阿里云账号、自定义镜像模板和具体的语言(本文以Node.js为例),设置工程名称、选择项目部署地域并输入您的ACR镜像等。

    image

  2. 执行以下命令,进入项目目录。

    cd start-fc3-custom-container-nodejs
  3. 编辑s.yaml文件。关于YAML文件的参数解释,请参见YAML规范

    示例如下。

    示例中image为您的ACR镜像,需要分别将<your namespace>、<your image>和<your tag>替换为实际的命名空间名称、镜像仓库名称和镜像版本。如果您在步骤1初始化项目时已填入正确的ACR镜像,此处无需修改。

    edition: 3.0.0
    name: hello-world-app
    # access 是当前应用所需要的密钥信息配置:
    # 密钥配置可以参考:https://www.serverless-devs.com/serverless-devs/command/config
    # 密钥使用顺序可以参考:https://www.serverless-devs.com/serverless-devs/tool#密钥使用顺序与规范
    access: "default"
    
    vars: # 全局变量
      region: "cn-hangzhou"
    
    resources:
      hello_world:
        # 如果只想针对 hello_world 下面的业务进行相关操作,可以在命令行中加上 hello_world,例如:
        # 只对 hello_world 进行构建:s hello_world build
        # 如果不带有 hello_world ,而是直接执行 s build,工具则会对当前Yaml下,所有和 hello_world 平级的业务模块(如有其他平级的模块,例如下面注释的next_function),按照一定顺序进行 build 操作
        component: fc3 # 组件名称
        actions:       # 自定义执行逻辑
          pre-deploy: # 在deploy之前运行
            - component: fc3 build --dockerfile ./code/Dockerfile  # 要运行的组件,格式为“component: 组件名 命令 参数”
        props:
          region: ${vars.region}              # 关于变量的使用方法,可以参考:https://docs.serverless-devs.com/serverless-devs/yaml#%E5%8F%98%E9%87%8F%E8%B5%8B%E5%80%BC
          functionName: "start-nodejs-ufrz"
          runtime: "custom-container"
          description: 'hello world by serverless devs'
          timeout: 30
          memorySize: 512
          cpu: 0.5
          diskSize: 512
          code: ./code
          customContainerConfig:
            image: 'registry.${vars.region}.aliyuncs.com/<your namespace>/<your image>:<your tag>'  # 您的ACR镜像,需要分别将<your namespace>、<your image>和<your tag>替换为实际的命名空间名称、镜像仓库名称和镜像版本
          # triggers:
          #   - triggerName: httpTrigger # 触发器名称
          #     triggerType: http # 触发器类型
          #     description: 'xxxx'
          #     qualifier: LATEST # 触发服务的版本
          #     triggerConfig:
          #       authType: anonymous # 鉴权类型,可选值:anonymous、function
          #       disableURLInternet: false # 是否禁用公网访问 URL
          #       methods: # HTTP 触发器支持的访问方法,可选值:GET、POST、PUT、DELETE、HEAD
          #         - GET
          #         - POST
  4. 执行以下命令,部署项目。

    sudo s deploy

    输出示例:

      Steps for [deploy] of [hello-world-app]
    ====================
    
    DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
                BuildKit is currently disabled; enable it by removing the DOCKER_BUILDKIT=0
                environment-variable.
    
    Sending build context to Docker daemon   5.12kB
    Step 1/7 : FROM node:14-buster
    14-buster: Pulling from library/node
    2ff1d7c41c74: Already exists 
    b253aeafeaa7: Already exists 
    3d2201bd995c: Already exists 
    1de76e268b10: Already exists 
    d9a8df589451: Already exists 
    6f51ee005dea: Already exists 
    5f32ed3c3f27: Already exists 
    0c8cc2f24a4d: Already exists 
    0d27a8e86132: Already exists 
    Digest: sha256:a158d3b9b4e3fa813fa6c8c590b8f0a860e015ad4e59bbce5744d2f6fd8461aa
    Status: Downloaded newer image for node:14-buster
     ---> 1d12470fa662
    Step 2/7 : WORKDIR /usr/src/
     ---> Running in 70a8e2e4d1ea
    Removing intermediate container 70a8e2e4d1ea
     ---> 0d67b8fa2901
    Step 3/7 : COPY package*.json ./
     ---> 09eb15f8770a
    Step 4/7 : RUN npm install
     ---> Running in 8ae492be973b
    Step 5/7 : COPY . .
     ---> 7560c7b14431
    Step 6/7 : EXPOSE 9000
     ---> Running in 66b38e54ced0
    Removing intermediate container 66b38e54ced0
     ---> f73cce48d2ae
    Step 7/7 : ENTRYPOINT [ "node", "server.js" ]
     ---> Running in 2fb2f83fd6c0
    Removing intermediate container 2fb2f83fd6c0
     ---> fe51ae71448c
    Successfully built fe51ae71448c
    Successfully tagged registry.cn-hangzhou.aliyuncs.com/z****/z****:latest
    
    [2024-01-29 16:33:06][INFO][hello_world] get instanceName= and region=cn-hangzhou from registry.cn-hangzhou.aliyuncs.com/z****/z****
    [2024-01-29 16:33:06][INFO][hello_world] try to docker push registry.cn-hangzhou.aliyuncs.com/z****/z**** ...
    
    WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
    Configure a credential helper to remove this warning. See
    https://docs.docker.com/engine/reference/commandline/login/#credentials-store
    
    Login Succeeded
    
    
    Using default tag: latest
    The push refers to repository [registry.cn-hangzhou.aliyuncs.com/z****/z****]
    85c1ec915b45: Pushed 
    37c36543a431: Pushed 
    e4afd7f70434: Pushed 
    0d5f5a015e5d: Layer already exists 
    3c777d951de2: Layer already exists 
    f8a91dd5fc84: Layer already exists 
    cb81227abde5: Layer already exists 
    e01a454893a9: Layer already exists 
    c45660adde37: Layer already exists 
    fe0fb3ab4a0f: Layer already exists 
    f1186e5061f2: Layer already exists 
    b2dba7477754: Layer already exists 
    latest: digest: sha256:6bf1ed4119d197a46c99082577632957056cb625f2ee0276d2af53f60d22837d size: 2841
    
    
    
      [hello_world] completed (688.45s)
    
      Result for [deploy] of [hello-world-app]
    ====================
    region:                cn-hangzhou
    cpu:                   0.5
    customContainerConfig: 
      image:            registry.cn-hangzhou.aliyuncs.com/z****/z****
      resolvedImageUri: registry.cn-hangzhou.aliyuncs.com/z****/z****@sha256:6bf1ed4119d197a46c99082577632957056cb625f2ee0276d2af53f60d22837d
    description:           hello world by serverless devs
    diskSize:              512
    functionName:          start-nodejs-ufrz
    handler:               handler
    instanceConcurrency:   1
    internetAccess:        true
    lastUpdateStatus:      Successful
    memorySize:            512
    role:                  
    runtime:               custom-container
    state:                 Active
    timeout:               30
    
    A complete log of this run can be found in: /root/.s/logs/0129162246
  5. 执行以下命令,调试函数。

    sudo s invoke -e "{\"key\":\"val\"}"

    输出示例:

     Steps for [invoke] of [hello-world-app]
    ====================
    ========= FC invoke Logs begin =========
    FC Invoke Start RequestId: 1-65b764db-15eb737f-0c67ab5cd968
    FC Invoke Start RequestId: 1-65b764db-15eb737f-0c67ab5cd968
    hello world!
    
    FC Invoke End RequestId: 1-65b764db-15eb737f-0c67ab5cd968
    
    Duration: 42.27 ms, Billed Duration: 43 ms, Memory Size: 512 MB, Max Memory Used: 47.77 MB
    ========= FC invoke Logs end =========
    
    Invoke instanceId: c-65b764db-15fa2aa8-bc50f7839399
    Code Checksum: undefined
    Qualifier: LATEST
    RequestId: 1-65b764db-15eb737f-0c67ab5cd968
    
    Invoke Result:
    OK
      [hello_world] completed (4.96s)
    
    A complete log of this run can be found in: /root/.s/logs/0129164202

相关文档