Square 和云
Square 正处于向云迁移的早期阶段。现在,我们的大多数应用程序都运行在自己的数据中心。
我们的平台和基础架构工程(PIE)团队一直负责提供在数据中心构建和运营应用的基础架构和工具。不过,由于 PIE 是 Square 一个较小的部门,因此它的产出存在很多局限。PIE 认为云计算可以为 Square 工程师创造机遇,帮助他们选择更适合自身需求的工具和架构模式。
我们的策略分为两个层面:
首先,让团队以最小的代价将现有应用程序迁移至云端;
其次,为团队提供工具和基础架构,帮助他们使用云原生模式来构建应用程序。
我们的云原生开发一开始关注的是无服务器应用程序。Square 有 160 多个工程团队,关注的问题领域多种多样,包括外部 API、内部 Web 应用程序、支付处理、语音系统等等。
在数据中心内
Square 数据中心中的应用程序通过 Envoy 通信,使用相互传输层安全性(也称为 mTLS)进行身份验证。证书是在物理主机上自动生成和轮换的。服务到服务(s2s)的通信通过 Envoy 控制,其负责同步来自称为注册表(Registry)的内部应用程序提供的应用依赖项信息。
我们很早就决定将 DC 中的 Lambda 函数和部署视为同一应用程序的逻辑组件。团队可以选择将它们进一步分离成单独的应用程序。
数据中心中的 S2s 调用主要依赖自动化和配置。为了让 Lambda 能调用数据中心的应用程序,我们需要弄清楚哪些工具可以重用,哪些内容需要构建。
结果,我们发现要构建的东西有很多。我们选择了自动化优先的思路来实现目标,这样就用不着创建人工流程,之后还得废弃它们了。
开始转向 AWS
团队转向云中构建时,遇到的第一个障碍是帐户、网络和基础架构设置。
我们原本用来在数据中心创建新应用程序的工具在云端无法使用,于是 PIE 中的 Cloud Foundations 团队构建了一个应用程序,团队只需轻点按钮或提交一个简单的表格就能用它为已有的应用程序创建开发和暂存帐户——可以将其看作是一个 AWS 账户自动售货机。生产和第三方开发人员沙箱帐户在创建之前需要获得一些内部批准,我们也在努力简化相关流程。
这意味着团队的每个应用程序将拥有 3 或 4 个 AWS 账户。我们发现这种多帐户模型带来的收益超过了它的开销。
请求新的 AWS 账户和新应用程序的简单表格
默认情况下,所有新帐户均使用共享 VPC 中的子网和连接到 CI/CD 管道的 Terraform 存储库设置。完整的帐户创建过程用时不足 30 分钟,无需任何人工干预,并且帐户准备就绪时会通过 slack 和电子邮件通知开发人员。
提醒新帐户可用的 Slack 通知,其中包括一个立即访问账户的链接
Square 的开发人员不习惯在数据中心中创建或管理自己的基础架构。Cloud Foundations 团队采访了内部客户,了解他们想要使用哪些工具来管理云中的基础架构。AWS 控制台用户界面确实很有用,但依靠它来管理基础架构的路径是无法扩展的。我们将 Terraform 用作基础架构即代码解决方案,该方案已被 Square 的一些团队使用。
我们构建了几个 Terraform 模块,来帮助安全地配置 AWS 账户和 Lambda 函数。这些模块负责处理常见需求,例如设置 IAM 以供我们的 CI 系统使用,以及用 s2 正常工作所需的正确权限和约定来销毁 Lambda 函数。团队使用中心化管理的 Terraform CICD 管道,其中基础架构的更改也会像我们部署的其他内容一样提交代码审查。
Lambda 和 mTLS
我们希望确保 Lambda 可以进入 Envoy 服务网格,并像 Square 上的其他应用程序一样参与工作。具体来说,我们不希望从 Lambda 调用的应用程序需要任何更改——它运作起来应该和其他服务调用一样。
这涉及许多运动部件,因为所有服务到服务的调用都使用 Envoy 和 mTLS。Lambdas 接入 Envoy 需要证书和路径。无法让 Envoy 作为 Lambda 的 sidecar 运行,因此我们需要弄清楚请求是如何到达 Envoy 实例的。
证书
每个 Lambda 需要 TLS 凭据(证书和私钥对)和一组根 CA 证书才能执行 mTLS。根 CA 证书已添加到可供我们 AWS 组织使用的,内部可访问的 s3 存储桶中。
与 Square 的其他应用程序一样,Lambda 函数使用其 TLS 凭据对其他应用程序进行身份验证。Envoy 和服务器应用程序均基于客户端 TLS 证书中的身份验证,检查调用方是否有权进行 API 调用。这意味着凭据是高度敏感的,并且有必要以最小特权的方式访问。
我们通过两种方式做到了这一点。
首先,我们将元数据添加到注册表的应用程序中,以指示应用程序在 AWS 中具有资源,并添加了默认标志来控制证书的生成。团队必须选择在 AWS 中生成证书,这样可以避免生成潜在的高权限凭据,除非云中的应用程序组件需要它们。
该 UI 允许为一组 AWS 账户打开或关闭 Lambda s2s 功能。
其次,在 AWS 内部,安全基础架构团队构建了一个系统,检查注册表中的元数据,然后仅为需要它们的应用程序生成短期证书。这将在后台使用 AWS Private Certificate Authority(PCA)。每个证书都通过资源策略保存到中央 AWS Secrets Manager,其资源策略决定哪些 AWS 帐户和角色可以读取它。Lambda 在其短寿命容器的生命周期内对其进行缓存。证书每 12 个小时生成一次,并且仅生效 24 小时,这样即便证书被盗或无意泄漏,也能限制攻击窗口。
以上就是我们构建证书生成系统的简要概述。关于更详细的内容,我们将在以后的博客文章中介绍它。
进入服务网格
Envoy 还用于服务发现和负载平衡。由于 Lambda 没有 sidecar,并且服务之间的所有通信都是通过 Envoy 进行的,因此我们需要另外一块工具来将通信路由到服务网格。
我们最初尝试构建一个 L7 代理,它将重新签名来自 Lambda 的请求,但这将创建一个能模仿其他任何应用程序身份的强大应用程序。我们认为这种安全风险是无法接受的。我们还研究了在每个需要调用数据中心的 AWS 账户中部署 Envoy 的方法,但意识到这将给应用程序团队和 PIE 中的中央流量团队带来运营负担,并增加成本。
最后,我们部署了一个“网格网关”Envoy 作为 L4 代理,驻留在我们的共享 kubernetes 集群中,前端是网络负载均衡器。网格网关使用 SNI 标头将请求转发到请求的后端服务,但是 TLS 握手仍由调用的 Lambda 处理。这允许 Lambda 将请求发送到 staging.appname.meshproxy.internaldomain.com,并且网状网关会将请求路由到正确的后端。
对我们而言,这是最佳折衷方案:一个 Envoy 无法访问多个应用程序的私钥,所有团队的运营压力都不算大,并且 Lambda 仍然可以利用 Envoy 的功能,因为 Envoy 就在请求的另一端。
架构概述,包括使用 PCA 生成证书的帐户,从机密管理器中提取证书的 Lambda 以及通过 L4 Envoy 代理请求路由的过程。
Lambda 代码
其他基础架构都就绪后,Lambda 就需要使用它了。这意味着下载 s2s 凭据并执行 mTLS 握手。通过与内部客户的交流,我们得知需要支持多个 Lambda 运行时,最初是 Ruby 和 Golang。我们还了解到大家想尽可能减少需要维护的库,尤其是在涉及 mTLS 握手的代码时。由于 Square 具有广阔的技术前景,因此 Lambda 需要自定义的 mTLS 逻辑,并且我们希望尽量避免重复。
我们的解决方案是一个 golang 软件包,它可以检索和缓存证书,并在 Lambda 函数中处理 mTLS 逻辑。使用 go 运行时的任何 Lambda 都可以直接导入这个包。对于其他语言,我们将一个二进制 Lambda 层分发给整个组织。这个层创建了一个反向 HTTP 代理,其在后台使用了与 go http 客户端相同的代码,这样 mTLS 代码只需放在一处即可。对于其他语言,我们还开发了将二进制文件作为后台进程启动的库,并提供了正确配置的 http 客户端供 Lambda 使用。这些特定于语言的库比 go 软件包小得多,这样维护它们和接受内部开发人员社区的贡献也就容易多了。
我们为在 Lambda 内运行而构建的所有内容均依赖于常规库,而不是什么市面可用的无服务器开发框架。我们的目标是与框架无关,以便团队可以选择最能满足其产品、安全性和时间要求的工具。
总结
上述工具链和基础架构的结合使团队可以随意设置自己的 AWS 账户。这套工具链(特别是来自虚拟自动售货机和 Terraform CI/CD 管道的 AWS 账户)能确保团队以一致的方式设置和管理账户。该基础架构有一个单独的 AWS 账户,负责生成证书和作为 kubernetes 中应用程序的 Envoy,整个架构负责创建从 Lambda 到数据中心的安全通信流。
原文链接:
https://developer.squareup.com/blog/enabling-serverless-applications-at-square/
评论