Serverlss 应用开发之子账号最佳实践以及 Q&A (函数计算篇)

云栖号:https://yqh.aliyun.com
第一手的上云资讯,不同行业精选的上云企业案例库,基于众多成功案例萃取而成的最佳实践,助力您上云决策!

Serverlss 应用开发之子账号最佳实践以及 Q&A (函数计算篇)

在通过子账号上手使用函数计算的过程中,往往会疑惑为什么在为子账号配置了 AliyunFCFullAccess 后,在登录函数计算控制台以及使用函数计算命令行工具 Fun 时,有时仍旧会遇到权限相关的报错。

本文将分析通过子账号使用函数计算时遇到的权限问题以及对应解决方法,并提供子账号使用函数计算的最佳实践。

通常,子账号在使用函数计算时会在三个方面遇到权限相关的问题:

  1. 子账号本身的权限
  2. 为服务配置的服务角色的权限
  3. 为触发器配置的触发器角色的权限

免费开通服务

  1. 免费开通函数计算,按量付费,函数计算有很大的免费额度。

相关知识

在介绍子账号最佳实践前,让我们先来了解下上面提到的服务角色、触发器角色的作用分别是什么。

服务角色
服务角色授予了该函数计算服务下的所有函数访问阿里云服务和资源的权限,具体的权限由授予给该服务角色的权限决定。当函数被调用时,函数计算会代入该角色,如果在函数中有访问其他服务的操作(如访问日志服务 SLS),则需要该服务角色有相关的权限,否则无法访问成功。

触发器角色
函数计算提供了一种事件驱动的计算模型。在事件驱动的计算模型中,事件源是事件的生产者,函数是事件的处理者,而触发器提供了一种集中的和统一的方式来管理不同的事件源。事件源需要扮演一个角色来触发函数的执行,要求这个角色有触发函数执行的权限

最佳实践

接下来我们会通过结合场景来介绍子账户的开发函数计算的最佳实践。

假设现在有 A 公司,A 公司的技术负责人 L 在阿里云有一个主账号,现在有新的业务需要架设在函数计算上,该业务的开发人员为新来的 N 同学。

那么,现在技术负责人 L 需要如何为 N 同学配置阿里云账号从而使 N 同学可以开发函数计算呢?

新建子账号并添加 FC 相关权限
首先 L 需要做的是在 RAM 控制台上创建一个新的用户,配置该用户是否可以登录控制台、是否可以编程访问。此处我们假设 N 同学使用阿里云函数计算命令行工具 Fun 进行本地开发的,因此 L 需要为 N 配置编程访问。当 L 为 N 配置了 AliyunFCFullAccess 权限后,N 就可以在本地开发函数计算并进行远端部署了。

假设 N 在本地开发了一个简单的 HelloWorld 程序。

  • Fun 工程的模版文件 template.yml 内容

    ROSTemplateFormatVersion: '2015-09-01'
    Transform: 'Aliyun::Serverless-2018-04-03'
    Resources:
      demo:
        Type: 'Aliyun::Serverless::Service'
        Properties:
          Description: This is demo service
        func01:
          Type: 'Aliyun::Serverless::Function'
          Properties:
            Handler: index.handler
            Runtime: nodejs8
            Timeout: 60
            MemorySize: 512
            CodeUri: demo/func01
  • 函数的入口文件 demo/func01/index.js 的文件内容

    'use strict';
    module.exports.handler = function(event, context, callback) {
      console.log(new String(event));
      callback(null, 'hello world');
    }

此时,N 可以通过 fun deploydemo/func01 函数部署到远端。

假设 N 想让该函数的日志能够持久化保存下来,N 这个时候需要为 demo 服务配置日志项目和日志仓库。假设 A 公司在日志服务 SLS 有 logProject01 日志项目和 logStore01 日志仓库。N 在模版文件 template.yml 中为 demo 服务配置了如下内容:

  • 模版文件 template.yml 内容

    ROSTemplateFormatVersion: '2015-09-01'
    Transform: 'Aliyun::Serverless-2018-04-03'
    Resources:
      demo:
        Type: 'Aliyun::Serverless::Service'
        Properties:
          Description: This is demo service
          LogConfig:
            Project: logProject01 # 日志项目
            Logstore: logStore01 # 日志仓库
        func01:
          Type: 'Aliyun::Serverless::Function'
          Properties:
            Handler: index.handler
            Runtime: nodejs8
            Timeout: 60
            MemorySize: 512
            CodeUri: demo/func01

创建服务角色并为子账号配置 PassRole 权限

此时,N 无法通过 fun deploy 成功部署。为什么呢? 因为此时 N 缺少 RAM 相关权限,无法创建角色并授予 demo 服务。此时,有两种做法可以完成该操作:

  • 第一种方法:向技术负责人 L 申请为 N 的子账号授予 AliyunRAMFullAccess 的权限。这样 N 在使用 fun deploy 的时候,可以成功创建出拥有对 logProject01logStore01 进行操作的 RAM 角色,并将该角色配置给 demo 服务。
  • 第二种方法

    • 由技术负责人 L 创建一个 RAM 角色(假设角色名为 demo-service-role),该角色拥有对 logProject01logStore01 进行操作的权限,并且该角色的受信实体为函数计算。
    • 技术负责人 L 为 N 配置 ram:PassRole 权限,使得 N 有权限为服务配置角色。
    • N 在模版文件 template.yml 中为 demo 服务配置角色 demo-service-role

在子账号实践中,更加推荐使用第二种方法,相比第一种方法来说更加安全。假设 L 创建了 RAM 角色(demo-service-role),并且给 N 配置了 ram:PassRole。此时,N 在模版文件 template.yml 中为 demo 服务配置角色 demo-service-role

  • 模版文件 template.yml 内容

    ROSTemplateFormatVersion: '2015-09-01'
    Transform: 'Aliyun::Serverless-2018-04-03'
    Resources:
      demo:
        Type: 'Aliyun::Serverless::Service'
        Properties:
          Description: This is demo service
          Role: acs:ram:::role/demo-service-role
          LogConfig:
            Project: logProject01
            Logstore: logStore01
        func01:
          Type: 'Aliyun::Serverless::Function'
          Properties:
            Handler: index.handler
            Runtime: nodejs8
            Timeout: 60
            MemorySize: 512
            CodeUri: demo/func01

此时,N 因为有了 ram:PassRole 权限,可以成功的将 demo-service-role 配置给 demo 服务,部署到线上。这时,demo/func01 函数就可以将日志持久化记录在 SLS 日志服务中了。

假设,N 此时希望为函数 demo/func01 配置一个 OSS 触发器,N 编写的模版文件 template.yml 内容如下:

  • 模版文件 template.yml 内容

    ROSTemplateFormatVersion: '2015-09-01'
    Transform: 'Aliyun::Serverless-2018-04-03'
    Resources:
      demo:
        Type: 'Aliyun::Serverless::Service'
        Properties:
          Description: This is demo service
          Role: acs:ram:::role/demo-service-role
          LogConfig:
            Project: logProject01
            Logstore: logStore01
        func01:
          Type: 'Aliyun::Serverless::Function'
          Properties:
            Handler: index.handler
            Runtime: nodejs8
            Timeout: 60
            MemorySize: 512
            CodeUri: demo/func01
          Events:
            ossTrigger:
              Type: OSS
              Properties:
                BucketName: ossBucketName
                Events: ["oss:ObjectCreated:*"]
                Filter:
                  Key:
                    Prefix: source/
                    Suffix: .png

创建触发器角色
此时,N 同样无法通过 fun deploy 完成部署。因为 N 想创建的 OSS 触发器,需要为该触发器配置一个有权限调用函数的角色。而在模版文件中未显式声明该角色,Fun 同样会尝试去创建角色,而 N 用的子账户只有 ram:PassRole 权限,没有其他关于 RAM 的权限,所以无法创建成功。这时的解决方法和最初的服务角色差不多:

  • 由技术负责人 L 创建一个 RAM 角色(假设角色名为 oss-trigger-invocation-role),该角色拥有对函数计算中的函数进行调用的权限,并且该角色的受信实体为 OSS 对象存储服务。
  • 技术负责人 L 为 N 配置 AliyunOSSFullAccess 权限,使得 N 可以访问 OSS。

上述配置完成后,N 可以修改模版文件内容为:

  • 模版文件 template.yml 内容

    ROSTemplateFormatVersion: '2015-09-01'
    Transform: 'Aliyun::Serverless-2018-04-03'
    Resources:
      demo:
        Type: 'Aliyun::Serverless::Service'
        Properties:
          Description: This is demo service
          Role: acs:ram:::role/demo-service-role
          LogConfig:
            Project: logProject01
            Logstore: logStore01
        func01:
          Type: 'Aliyun::Serverless::Function'
          Properties:
            Handler: index.handler
            Runtime: nodejs8
            Timeout: 60
            MemorySize: 512
            CodeUri: demo/func01
          Events:
            ossTrigger:
              Type: OSS
              Properties:
                BucketName: ossBucketName
                Events: ["oss:ObjectCreated:*"]
                Filter:
                   Key:
                     Prefix: source/
                     Suffix: .png
                InvocationRole: acs:ram:::role/oss-trigger-invocation-role

此时,N 可以通过 fun deploy 部署成功。

总结

根据上面最佳实践的例子,我们可以总结出如下几点经验:

  1. 若希望函数可以访问其他服务,需要为函数所在的服务配置服务角色,该服务角色其实是 RAM 角色拥有对于其他服务或资源的访问权限,并且受信实体为函数计算。
  2. 若希望为函数配置外部事件源,需要为该事件源触发器配置触发器角色,该角色拥有触发函数的权限,并且受信实体为事件源所在的服务。
  3. 若希望子账号可以为服务配置服务角色或为触发器配置触发器角色,需要授予子账号 ram:PassRole 权限以及对应事件源的权限。

常见问题梳理:

下述的问题梳理都是基于已经为子账号配置了 AliyunFCFullAccess 后,使用函数计算控制台或命令行工具 Fun 时会遇到的问题。

  1. Q: 控制台首页提示 账号缺少AliyunCloudMonitorReadOnlyAccess权限
    A: 函数计算控制台首页的监控数据信息:本月执行次数、本月资源使用量、公网流量是来自于云监控 CloudMonitor 服务的,如果子账号希望查看相关数据信息,需要在 RAM 控制台为当前子账号配置 AliyunCloudMonitorReadOnlyAccess 权限。
  2. Q: 控制台应用中心提示 账号缺少AliyunROSFullAccess权限
    A: 函数计算控制台中应用中心的某些功能是依赖于阿里云资源编排 ROS 服务的,如果子账号希望使用应用中心的功能,需要在 RAM 控制台为当前子账号配置 AliyunROSFullAccess 权限。
  3. Q: 在控制台服务配置中,专有网络配置下的专有网络下拉框没有列举出已有的专有网络。
    A: 这是由于子账号缺少查看 VPC 的权限,在 RAM 控制台中为当前子账号配置 AliyunVPCReadOnlyAccess 即可。
  4. Q: 在控制台服务配置中,日志配置下的日志仓库下拉框没有列举出已有的日志仓库。
    A: 和专有网络配置时遇到的问题相似,是由于子账号缺少查看日志服务 SLS 的权限,在 RAM 控制台中为当前子账号配置 AliyunLogReadOnlyAccess 即可。
  5. Q: 在控制台服务配置中,角色配置展开提示 获取角色列表权限不足,需要 RAM 相关权限
    A: 是由于子账号缺少查看 RAM 角色的权限,在 RAM 控制台中为当前子账号配置 AliyunRAMReadOnlyAccess 即可。
  6. Q: 在 Fun 工程的模版文件中为服务配置了 Policies,部署时提示没有相关 RAM 权限。
    A: Fun 在遇到为服务配置了 Policies 的情况下,会用当前 Fun 配置下的 AK 信息,使用 RAM 服务做创建角色、为角色授权、为服务配置角色等一系列操作,此时需要子账户有相关操作的 RAM 权限。如果希望子账号可以完成这些操作,需要在 RAM 控制台为当前子账号配置 AliyunRAMFullAccess 权限。这不是特别推荐的做法,上文中的最佳实践有讲述到相关内容。
  7. Q: 子账号拥有访问其他服务的权限,但是创建出来的函数运行时无法访问其他服务。
    A: 函数是否能够访问其他服务与子账号本身的权限无关,与该函数所在服务配置的服务角色有关。如果希望函数可以访问 A 服务,则需要为函数所在的服务配置下的服务角色授权访问 A 服务。

参考资料

  1. 函数计算
  2. RAM
  3. Funcraft
  4. Aliyun Serverless VSCode

云栖号在线课堂,每天都有产品技术专家分享
立即加入圈子:https://c.tb.cn/F3.Z8gvnK
与专家面对面,及时了解课程最新动态!

原文发布时间:2020-01-09
本文作者:泽尘
本文来自:“阿里云云栖社区”,了解相关信息可以关注“阿里云云栖社区

上一篇:Aliyun Serverless VSCode Extension v1.1.0 发布


下一篇:Serverless 实战 —— 函数计算 + Typescript 实践