亚马逊AWS官方博客

顾盼自如:基于 Amazon AppStream 2.0 打造数据分析师安全灵活的工作平台

背景

当今跨国企业对于数据资产安全程度的需求日趋严格,尤其涉及到跨多个组织架构,企业内部对于数据敏感保护意识都非常高。而作为数据分析师或工程师,日常工作接触到敏感数据的概率较大,企业提供一个安全合规的工作管理工具显得尤为重要。Amazon SageMaker 作为托管的机器学习平台提供了从构建,训练,部署,监控等端到端的功能特性,帮助机器学习工程师,数据分析师更高效的完成数据探索、算法实验、部署验证的工作。而如何保证企业敏感数据不外泄同时又方便分析师们获取数据,下载工程依赖成为了很多企业客户的诉求。Amazon AppStream 2.0 提供了一个安全、可靠、可扩展的应用程序流和低成本虚拟桌面服务,用户可以利用客户端或者浏览器非常便捷的远程访问应用,Amazon AppStream 2.0 作为一个托管的服务,用户无法远程登录查看后端服务器,因此大大降低了数据外泄的风险。本篇 blog 介绍了如何利用 Amazon AppStream 2.0 结合单点登录,使分析师方便灵活安全地访问 Amazon SageMaker Studio 的同时,又降低了数据外泄的风险。

目标

客户希望使用 Amazon SageMaker 服务来处理他们最敏感的数据,但需要:

  1. 确保一致、安全的环境和友好的使用体验,开发人员和数据分析师在任意地点、任何时间都可以方便流畅地使用 Amazon SageMaker 服务。
  2. 隔离敏感数据,只有合适的人员才能访问属于所属业务团队的数据。
  3. 防止敏感数据在处理过程和最终结果中发生泄露:
    • 确保没有通过身份认证/获得授权的用户不能从互联网访问环境。
    • 确保环境中的任何实例都不能访问互联网,或者只允许访问指定的互联网资源。
    • 确保所有用户都无法将数据从环境中复制出去。
  4. 对环境中用户活动访问进行端到端的审计追溯。

方案介绍

本方案旨在使用 Amazon AppStream 2.0 为数据科学团队提供高安全性和隔离性的环境,以允许开发人员和数据科学家在连接到网络隔离/网络受限的环境时使用 Amazon SageMaker Studio 处理数据集,以下为本次需要用到的 AWS 服务:

  • Amazon AppStream 2.0 是一项完全托管的非持久性应用程序和桌面流媒体服务,可使用兼容 HTML5 的桌面浏览器从任何地方访问桌面应用程序。每次启动 Amazon AppStream 2.0 会话时,都会使用预先构建的映像提供一个全新构建、预配置的实例。一旦您关闭会话并达到断开连接超时时间,实例就会终止。AppStream 2.0 还支持管理员自定义会话策略,例如禁用使用剪贴板、文件传输或打印等。
  • 使用 AWS IAM Identity Center (successor to AWS Single Sign-On)  为 Amazon AppStream 2.0 用户提供联合身份凭证。借助 AWS IAM Identity Center,管理员可以集中管理用户 AWS 账户的登录安全和应用程序的访问权限,支持与 AWS 应用程序、AWS 提供预集成的云应用程序以及自定义 SAML 2.0 应用程序进行集成。
  • Amazon SageMaker Studio 提供了一个可以完全访问、控制和查看构建、训练和部署模型所需的每个步骤的 Web 可视化界面。数据科学团队可以通过 Studio 快速上传数据、创建新的笔记本、训练和调整模型、在步骤之间来回移动以调整实验、比较结果以及将模型部署到生产环境中,所有这些都集中在一个地方,从而大大提高工作效率。
  • Amazon Network Firewall 是一项运行在 VPC 内托管的有状态的网络防火墙以及入侵检测和防御服务,使用网络防火墙可以过滤进出 VPC 的流量。

部署架构

实施步骤

网络设置

首先,我们需要构建一个独立的 VPC,然后创建并关联互联网网关(IGW)。本文会使用 Network Firewall 来过滤进出 VPC 的流量,如上图所示,VPC 的一个可用区内包含 3 个子网:

  • NFW Subnet:用于部署 Amazon Network Firewall 的 Endpoint
  • Public Subnet:用于部署 NAT 网关和部署 Amazon AppStream 2.0 构建镜像的实例
  • Private Subnet:用于部署 Amazon SageMaker 在本 VPC 内的 ENI,以及 Amazon AppStream 2.0 Fleet 的实例

1. 创建需要用到的服务的 Endpoint

接下来创建 VPC 终端节点并将其关联到 VPC,以使部署在 Private Subnet 内的资源可以在不连接互联网的情况下连接到 AWS 服务(例如 Amazon S3、CloudWatch Logs、SageMaker API、SageMaker Studio、SageMaker Notebook、SageMaker Runtime 等)。

更多 VPC only 模式下的 SageMaker Studio 需要的 endpoint

2. 创建 Amazon Network Firewall 的 Endpoint

Amazon Network Firewall 是 AWS 提供的云原生的网络安全服务,它具有第 7 层入侵防御系统(IPS)规则,并具有应用 TLS 指纹识别以防止伪造 IP 或 FQDN 的能力。通过在路由级别提供有状态和无状态规则,从 OSI 模型的第 3 到第 7 层,扩展了安全组和 NACL 的保护范围。

创建 Network Firewall,将 endpoint 部署在 NFW Subnet,等待 5 分钟左右状态 Ready。

此时可以看到 Network Firewall endpoint 部署完成:

3. 创建路由表并关联到子网

创建路由表关联 NFW Subnet

  • 所有流量(0.0.0/0)指向 IGW

创建路由表关联 Public Subnet

  • 所有流量(0.0.0/0)指向 Network Firewall Endpoint

创建路由表关联 Private Subnet

  • 配置 S3 Gateway Endpoint 生成一条将 S3 前缀列表的 ID 作为目的地的路由
  • 所有流量(0.0.0/0)指向 NAT Gateway

创建路由表关联 IGW

  • 配置路由使流量经过 NFW 过滤规则,即目标地址为 NAT Gateway 所在的 Public Subnet 的 CIDR,下一条(Target)为 Network Firewall Endpoint
  • 路由表中选择“Edge associations” 关联到 IGW

SAML 身份源配置

Amazon AppStream 2.0 支持通过 SAML 2.0 的身份提供商(IdP)进行联合身份认证,本文使用 AWS IAM Identity Center (successor to AWS Single Sign-On) 为 Amazon AppStream 2.0 用户提供身份凭证,并向 IAM Identity Center 中的用户授予对 Amazon AppStream 2.0 应用程序的单点登录访问权限。

请先按照以下文档的步骤创建 IAM Identity Center:

https://docs.thinkwithwp.com/singlesignon/latest/userguide/getting-started.html

部署 Amazon AppStream 2.0

1. IAM 设置

1.1 创建 IAM Policy

Amazon SageMaker 支持使用 IAM User/Role 通过请求为 Domain 创建 presigned url,为了防止用户从互联网使用该 IAM User/Role 创建 presigned url,我们需要为 User/Role 关联的 Policy 添加 Condition 限制,只允许来源于 Amazon AppStream 2.0 实例所在 VPC 的请求。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "SageMakerPresignedUrl",
            "Effect": "Allow",
            "Action": [
                "sagemaker:CreatePresignedDomainUrl",
                "sagemaker:ListDomains",
                "sagemaker:DescribeUserProfile"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:sourceVpc": [
                        "vpc-01e7c8985c678a020"
                    ]
                }
            }
        }
    ]
}

1.2 创建 IAM User

创建一个专门用来创建 presigned url 的 IAM user,关联 SageMakerPresignedUrlPolicy,并为其创建 AK/SK,用于在 Amazon AppStream 2.0 中自定义可执行程序。

2. 构建 AppStream 镜像

2.1 发布构建镜像实例

首先,选择一个基础镜像,这里我们选择 Windows Server 2019 作为基础镜像。在 Amazon AppStream 2.0 的 Console 左边栏选择 Images,点击 Launch Image builder 创建镜像构建实例,添加筛选条件如下:

Platform = Microsoft Windows Server 2019 base
Instance family = General purpose

输入构建镜像的实例的名称

为构建镜像的实例选择合适的机型

可以将构建镜像的实例放在 Public Subnet 或者 NFW Subnet,便于从互联网下载需要的软件

点击 Next,然后创建实例,这里会 pending 状态持续 15 分钟左右,实例才会 running

状态为 Running 后点击 Connect ,选择以 Administrator 登录 Windows Server实例

2.2 构建和部署自定义可执行程序

2.2.1 安装 Python3 环境

2.2.2 创建自定义可执行程序

在 Windows 中构建一个可执行程序,用于创建 Amazon SageMaker Studio Domain 的 presigned url 并自动打开浏览器 tab 页。先创建 Python 文件 sagemaker_url.py ,其中:

  • 使用创建的 presigned url 的 IAM user 的 AKSK
  • 建议设置 token 有效期在 1 分钟以内
  • 用户 session 超时时间 8小时
import os
import boto3
import webbrowser

ACCESS_KEY = "xxxxxxxxxxxx"
SECRET_KEY = "xxxxxxxxxxxxxxxxxxx"

def createpresignedurl(client,domain_id):

  userprofile_name = os.environ.get("APPSTREAM_USERNAME").split('@')[0]

  response = client.create_presigned_domain_url(
           DomainId=domain_id,
           UserProfileName=userprofile_name,
           SessionExpirationDurationInSeconds=28800,
           ExpiresInSeconds=15
        )
  
  return  response['AuthorizedUrl']


def getdomainid(client, domain_name):
  
    domain_id = ""
    marker = None
    while True:
        if marker:
            response = client.list_domains(NextToken=marker)
        else:
            response = client.list_domains()
        
        for domain in response["Domains"]:
            if domain['DomainName'] == domain_name:
                domain_id = domain['DomainId']

        try:
            marker = response['NextToken']
        except KeyError:
            break
            
    return domain_id    
   

def main():
  domain_name = input('Enter your Domain Name: ')
  aws_region = os.environ.get("AWS_REGION") 

  client = boto3.client('sagemaker', 
           aws_access_key_id=ACCESS_KEY,
           aws_secret_access_key=SECRET_KEY,
           endpoint_url= 'https://api.sagemaker.{region}.amazonaws.com'.format(region=aws_region),
           region_name= aws_region
        )

  domain_id = getdomainid(client, domain_name)
  if domain_id != "":
     presigned_url = createpresignedurl(client,domain_id)
     print(presigned_url)
     driver = webbrowser.Mozilla("C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe")
     driver.open(presigned_url)
  else:
     print("the domain {name} not exist".format(name=domain_name))


if __name__ == "__main__":
    main()

打包成 exe 可执行程序

python.exe -m pip install boto3 pyinstaller
pyinstaller.exe -F .\sagemaker_url.py -n presigned_url.exe

将打包好的文件放入 C:\Program Files (x86)\ 下

接下来,我们要把 Firefox 和 presigned_url.exe 加入到  Image Assistant 中的 app 列表发布。

2.3 添加软件并构建镜像

打开 Image Assistant,点击 Add App 添加 Firefox 和自定义可执行文件

注意添加 App 时,Launch Path 不要选择成桌面快捷方式,要定位到可执行文件的绝对路径。比如在添加自定义可执行文件时 Launch Path 填写存放 presigned_url.exe 的绝对路径

点击 Next 到 3. Test,切换 Test User 可以看到添加的 app 即可

点击 Next  到 4. Optimize,这里 Image 分析优化启动依赖,需要点击 launch 打开所有添加的 app

点击 Next 到 5.Configure Image,配置镜像名称和描述。

点击 Next,确认镜像信息,点击 Disconnect and Create Image,可以关闭会话

此时 Image Builder 实例正在 Snapshotting,大概要等 15 分钟左右

当 Image Builder 实例 stopped 状态时,可以在镜像仓库查看到构建的镜像

3. 部署 Amazon AppStream 2.0 Fleet

接下来,我们要用构建的镜像发布 Amazon AppStream 2.0 实例。在 Amazon AppStream 2.0 的 console 左边栏选择 Fleets,点击 Create Fleet,首先选择 Fleet 类型,考虑到节约成本,我们推荐选择 on-demand 只有连接会话时才会收费,但每次开启 stream session 需要等待 1-2分钟。然后配置 Fleet 实例的名称和描述。根据需要选择实例类型,我们只用到浏览器和自定义可执行文件,选择通用机型 medium 大小就足够。

设置会话超时时间:

  • 会话保持 480 分钟,这里建议大于创建 studio 设置的会话超时时间
  • 断开连接超时 15 分钟
  • 连接空闲超过 15 分钟断开

Fleet 实例的生命周期也是通过 auto scaling group 来维护,这里配置最小和最大实例数量

Stream View 选择您希望用户拥有的直播视图。当您选择 “Application” 时,用户将关注特定于应用程序。当您选择 “Desktop” 时,用户将看到操作系统上提供的标准桌面体验

弹性扩展策略自动调整可用的 stream 实例的数量,比如这里设置容量利用率超过  50% 添加 1 个实例,容量利用率小于 25% 时再缩容 1 个实例

选择上面步骤构建的镜像

选择放在上面步骤创建的 VPC 和 Private Subnet,并添加安全组

4.  定义 AppStream Stack

Stack 的作用是用以控制对 Fleet 的访问。所以接下来,我们还需要创建 Stack 并关联 Fleet,之后就可以通过 AppStream 2.0 用户池、SAML 2.0 向用户提供访问权限,并且控制用户在 Stream 上的行为。

左侧栏选择“Stack”,点击“Create Stack”。 配置 Stack 的名称和描述。如果为用户启用 Home 目录的存储,会使用 S3 作为后端持久存储,桶的路径通常为:appstream2-36fb080bb8-{Region}-{AWS Account} 

user settings 可以控制用户行为,比如 Clipboard、文件传输权限和打印等

设置为只允许从剪贴板粘贴到远程会话和只允许上传文件

在 Stack 创建完成后,选中后点击 Action 选择“Create Streaming URL”。访问 URL 测试确保能够按照预期登陆桌面

Amazon AppStream  2.0 与 AWS SSO 集成

Amazon AppStream 2.0 除了支持与列表中第三方 SAML 2.0 身份提供商解决方案的集成,也支持与企业自建的支持 SAML 2.0 协议身份提供商集成,步骤见 SMAL 2.0 集成。本环节演示 AWS IAM Identity Center 创建和设置 Amazon AppStream 2.0 单点登录访问权限的配置步骤。

1. 添加和配置 Amazon AppStream  2.0 启用身份中心

首先,我们在 IAM Identity Center 的 console 打开 application,点击添加应用,在预集成应用中选择 Amazon AppStream 2.0

下载 IAM Identity Center SAML metadata 文件

2. IAM 身份中心控制台中的应用程序属性

在 IAM Identity Center 中,您可以通过配置应用程序的开始 URL、中继状态和会话持续时间来自定义用户体验。详细解释可参考:

https://docs.thinkwithwp.com/zh_cn/singlesignon/latest/userguide/appproperties.html

  • Relay URL 格式:https://relay-state-region-endpoint?stack=stackname&accountId=aws-account-id-without-hyphens
  • Application ACS URL 将 SAML 断言发布到 AWS 登录 SAML 端点 https://signin.thinkwithwp.com/saml

3. IAM 创建 IdP 和 Role

首先在 IAM 中创建 Identity Provider

  1. 选择身份提供商的类型为 SAML
  2. 上传在 IAM Identity Center 添加 Amazon AppStream 2.0 时下载的 IAM Identity Center SAML metadata 文件

然后为该 SAML IDP 创建 IAM Role appstream_sagemaker_stack_Saml_Idp_Role

  1. 信任实体的类型,选择 SAML 2.0 federation
  2. 选择上一步骤创建的 Identity Provider

如果是第三方的 SAML IDP,还需要去 trust relationship 添加 sts:TagSession 的 action,这里我们可跳过此步骤

这个 Role 创建成功后,我们再为其添加 Inline policy,用于用户在单点登录成功后可以通过此 Role 去打开指定 AppStream Stack 的会话,resource 中限制指定的 AppStream stack。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appstream:Stream",
            "Resource": "arn:aws:appstream:us-west-2:808577411626:stack/sagemaker_stack_0826",
            "Condition": {
                "StringEquals": {
                    "appstream:userId": "${saml:sub}"
                }
            }
        }
    ]
}

4. 配置 AWS SSO 属性映射

配置 IDP 在身份认证响应包中返回的 SAML 属性来传递用户登录的数据。

  1. 打开 IAM 身份中心控制台
  2. 选择应用程序
  3. 在应用程序列表中,选择您要映射属性的应用程序。
  4. 在应用程序详细信息页面上,选择属性映射选项卡。
  5. 选择 Add new attribute mapping(添加新属性映射)按如下配置:
    • 在第一个文本框中,输入应用程序属性。

      —————————————-
      User attribute in the application: Subject
      Maps to this string value or user attribute in AWS SSO: ${user:email}
      Format: persistent

    • 在第二个文本框中,在 IAM Identity Center 中输入要映射到应用程序属性的属性。例如,您可能需要将应用程序属性 Username 映射到 IAM Identity Center 用户属性 email。要查看 IAM Identity Center 中允许的用户属性列表,请参阅中的表格属性映射
      —————————————-
      User attribute in the application: https://thinkwithwp.com/SAML/Attributes/RoleSessionName
      Maps to this string value or user attribute in AWS SSO: ${user:email}
      Format: unspecified
    • 在表格的第三列中,从菜单中为属性添加之前步骤创建的 Role ARN 和 Identity Provider ARN。
      —————————————-
      User attribute in the application: https://thinkwithwp.com/SAML/Attributes/Role
      Maps to this string value or user attribute in AWS SSO: arn:aws:iam::808577411626:role/appstream_sagemaker_stack_Saml_Idp_Role,arn:aws:iam::808577411626:saml-provider/AWS_SSO_sagemaker_appstream_stack
      Format: unspecified
  1. 选择 Save changes(保存更改)。

5. 为 IAM 身份中心用户分配对应用程序的访问权限

在 IAM 身份中心控制台中为用户或群组分配访问添加的 Amazon AppStream 2.0 权限

  1. 打开 IAM 身份中心控制台
  2. 选择应用程序
  3. 在应用程序列表中,选择要为其分配访问权限的应用程序名称。
  4. 在应用程序详细信息页面的分配用户部分,选择分配用户
  5. 分配用户对话框中,输入用户名或组名。您还可以搜索用户和群组。您可以指定多个用户或组,方法是当其显示在搜索结果中时选择适用的账户。
  6. 选择 Assign users(分配用户)

6. 单点登录测试打开 AppStream 2.0 应用

在 IAM Identity Center 界面登录成功后,点击 AppStream 2.0 应用

此时 AppStream Fleet 实例启动,可以按照预期打开会话

7. 测试只允许指定 IP 能打开 Stream

为了限制打开 Stream 会话的来源,只能允许是指定的出口 IP 才能够打开 AppStream 2.0 应用,用户需要在办公网环境或者接入 VPN 后再打开。这需要在之前配置的允许打开 Stream 会话的 Inline policy “sagemaker_stack_policy” 中Condition 添加 SourceIP 限制,只允许属于自己的 public IP 地址发起 Stream 请求。如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appstream:Stream",
            "Resource": "arn:aws:appstream:us-west-2:808577411626:stack/sagemaker_stack_0826",
            "Condition": {
                "StringEquals": {
                    "appstream:userId": "${saml:sub}"
                },
                "IpAddress": { "aws:SourceIp": "54.240.199.99/32" }
            }
        }
    ]
}

在 IAM Identity Center 界面登录成功后,点击 AppStream 2.0 应用,依然可以成功打开 Stream 会话。接着我们测试一下,换一个未知的 Public IP,预期是打开会话会报权限问题

在 IAM Identity Center 界面登录成功后,点击 AppStream 2.0 应用,会话打开失败,提示没有合法的权限了

SageMaker Studio 创建 Domain

首先创建 Domain,建议 Domain 名称跟业务领域代码相关

  • 对不同组织拥有各自独立的 Domain,赋予不同 Role 以隔离数据权限,因此需要 Domain 命名使用业务团队名称
  • 因为我们不能允许用户在 VPC 内创建出 presigned url 复制到本地通过互联网访问,在创建 SageMaker Studio Domain 时选择 VPC only 的模式

    然后再在 domain 下创建 UserProfile,建议与用户名一致。

  • UserProfile 中指定的 Role 要有 CreateApp 的权限

完整使用测试

在 IAM Identity Center 界面登录成功后,点击 AppStream 2.0 应用,打开 presigned_url.exe

等待环境置备完成,用户输入团队的 Domain 名称后自动会找到对应 domain id 下属于用户自己的 UserProfile,生成 presigned url

并自动打开 firefox 登录 studio

即使是把 presinged url 复制到本地浏览器也是没权限打开的,因为之前创建 SageMaker Studio domain 的时候选择的是 VPC only 模式

创建 AWS Network Firewall 策略限制互联网访问

防火墙策略中包含有状态和无状态规则组,本文的目标是限制用户从 AppStream 实例和 SageMaker  Notebook 只能访问受到允许的网站,因此需要创建一个有状态规则组(stateful rule group)。

首先在 AWS Network Firewall 创建一个有状态规则组,规则顺序我们选择 Action Order,这样会优先支持 allow 允许的放行流量,最后 deny 其余的所有流量。

接着,在有状态规则组中的 Domain list 中填入允许访问的域名,例如 .youtube.com。action 处选择 Allow

此时从 Amazon AppStream 2.0 实例 outbound 流量只能访问 YouTube 和 GitHub,其他出入互联网的流量都会被阻止。

审计 Amazon AppStream  2.0 会话

通常,企业安全管理员还会希望能够对环境进行端到端审计。需要对所有用户活动进行审计和可追溯性。因此,本方案的审计通过 AWS Athena 查询 Amazon AppStream 2.0 使用情况报告。

  1. 在 Glue 中创建 Crawler 任务爬取 AWS AppStream 日志里的 session 文件,添加数据源为存放 AppStream 日志的 S3 路径,通常为:
    s3://appstream-logs-{REGION}-{AWS ACCOUNT}-*/sessions/schedule=DAILY/
  2. 选择 Crawler 的 AWS IAM Role,存放的库,以及生成的表的前缀。执行 AWS Glue Crawler 任务。
  3. 使用 AWS Athena 查询 session可以获得的字段,如:用户名,认证方式,客户端 IP,开始时间,结束时间,stack 名称,fleet 名称,stream 实例的 IP 等。
    SELECT * FROM "default"."appstream-logs-sessions-schedule_daily"
  4. Amazon AppStream 2.0 使用 AWS 身份和访问管理(IAM)角色授予对其他 AWS 服务的精细访问权限,例如 Amazon S3、Amazon Redshift、Amazon SageMaker 和其他 AWS 服务。这使得管理员既可以控制访问权限,也可以通过 Amazon CloudTrail 进行日志审计。操作记录可以通过 AWS Athena 查询 CloudTrail 来获取,例如查看 SageMaker相关操作记录:
    SELECT * FROM {cloudtrail_table} WHERE awsregion like {region} and eventsource like 'sagemaker%' and useridentity.arn like '%appstream-test'

方案对比

是否支持多租户隔离 运维复杂度 产品集成能力 成本 用户管理
Private windows host 极高 困难,需要自己维护用户状态和数据
VDI 商业产品 较易使用,但欠缺灵活度 license 费用高昂
AppStream 2.0 非常灵活,易于使用 API 和 SDK 来管理甚至嵌入远程桌面 无 license 费用,且根据不同场景拥有不同计费模式 易,提供基于 SAML 2.0 实现单点登录

Reference

[1] https://docs.thinkwithwp.com/appstream2/latest/developerguide/external-identity-providers-setting-up-saml.html

[2] https://thinkwithwp.com/blogs/desktop-and-application-streaming/enable-federation-with-aws-single-sign-on-and-amazon-appstream-2-0/

[3] https://thinkwithwp.com/blogs/machine-learning/launch-amazon-sagemaker-studio-from-external-applications-using-presigned-urls/

本篇作者

吴立虎

亚马逊云科技解决方案架构师,十年以上企业应用开发经验,专注于微服务,异构平台集成,容器虚拟化等技术领域,为客户提供现代化应用上云咨询与方案。平常喜欢竞技运动,忠实的曼联铁杆粉丝。

詹叶

亚马逊云科技技术客户经理,主要支持互联网金融,汽车行业客户的架构优化、成本管理、技术咨询与交付工作。拥有多年企业级产品研发和管理经验,曾经贡献过多项开源项目。目前热衷于 Serverless 领域。