【51CTO.com原创稿件】如今,身份验证对绝大多数应用程序而言至关重要。Auth0 可以为任何堆栈上的各类(移动、Web 和原生)应用程序提供身份验证、授权和单点登录服务。
我们设计的 Auth0 一开始就可以在任何地方运行:我们的云、你的云,甚至在你自己的私有基础设施上。
在本文中我们将详细探讨我们的公共 SaaS 部署,并简要介绍 auth0.com 背后的基础设施,以及用来确保它顺畅运行的高可用性策略。
我们曾在 2014 年撰文介绍了 Auth0 的架构,自那以来 Auth0 已发生了很大的变化,下面是几大要点:
· 我们从每月处理数百万次登录升级至每月处理逾 15 亿次登录,为成千上万的客户提供服务,包括 FuboTV、Mozilla 和 JetPrivilege 等。
· 我们实施了新功能,比如自定义域、扩展的 bcrypt 操作以及大大改进的用户搜索等。
· 为了扩展我们组织的规模并处理流量的增加,我们产品的服务数量从不到 10 个增加到了 30 多个。
· 云资源的数量也大幅增长,我们过去在一个环境(美国)中有几十个节点,现在我们在四个环境(美国、美国-2、欧盟和澳大利亚)有 1000 多个节点。
· 我们决定为自己的每个环境使用单一云提供商,并将所有公共云基础设施迁移到了 AWS。
核心服务架构
图 1:Auth0.com 的核心服务架构
我们的核心服务包括如下不同的层:
· 核心应用程序:可自动扩展的服务器组,这些服务器运行我们堆栈的不同服务(身份验证、管理 API 和多因子身份验证 API 等)。
· 数据存储:MongoDB、Elasticsearch、Redis 和 PostgreSQL 集群,为不同的应用程序和功能特性存储众多数据集。
· 传输/队列:Kinesis 数据流以及 RabbitMQ、SNS 和 SQS 队列。
· 基础服务:针对速率限制、bcrypt 集群和功能标志等其他的服务。
· 路由:AWS 负载均衡系统(来自 AWS 的 ALB、NLB 和 ELB)以及一些运行 Nginx 充当代理的节点。
高可用性
2014 年,我们使用了多云架构(使用 Azure 和 AWS,还有谷歌云上的一些额外资源),多年来该架构为我们提供了良好的服务。随着使用量(和负载)迅速增加,我们发现自己越来越依赖 AWS 资源。
最初,我们将环境中的主区域切换到 AWS,Azure 留作故障切换区域。我们开始使用更多的 AWS 资源(比如 Kinesis 和 SQS)时,将同样的功能特性放在这两家提供商处开始遇到了麻烦。
随着移动(和扩展)的速度越来越快,我们选择继续支持 Azure,但功能同等性(feature parity)有限。
如果 AWS 上的一切出现故障,我们仍可以使用 Azure 集群来支持身份验证等核心功能,但是不支持我们一直在开发的许多新功能。
2016 年出现几次严重宕机后,我们决定最终集中到 AWS 上。我们停止了与确保服务和自动化平台无关的全部工作,而是专注于:
· 在 AWS 内部提供更好的故障切换机制,使用多个区域,每个区域至少 3 个可用区。
· 增加使用 AWS 特有的资源,比如自动扩展组(而不是使用固定的节点集群)和应用程序负载均衡系统(ALB)等。
· 编写更好的自动化:我们改进了自动化,完全采用基础设施即代码,使用 TerraForm 和 SaltStack 来配置新的 Auth0 环境(以及替换现有环境)。
这让我们从每秒处理约 300 次登录的部分自动化环境升级到每秒处理逾 3400 次登录的全自动化环境;使用新工具更容易向上扩展(必要的话还可以向下扩展)。
我们实现的自动化水平并不***,但让我们极其方便地扩大到新的区域、创建新的环境。
· 编写更好的剧本(playbook):随着时间的推移,我们发现除了自动化外,还需要更好的剧本,以便了解、管理和响应与我们越来越庞大的服务网格相关的事件。
这极大地提高了可扩展性和可靠性,同时加快了新员工的入职。
比如说,不妨看看我们的美国环境架构。我们有这个总体结构,如下图:
图 2:Auth0 美国环境架构
下图是单一可用区内部的结构:
图 3:Auth0 单一可用区
在这种情况下,我们使用两个 AWS 区域:
· us-west-2(我们的主区域)
· us-west-1(故障切换区域)
正常情况下,所有请求都流向 us-west-2,由三个独立的可用区处理请求。
这就是我们实现高可用性的方式:所有服务(包括数据库)在每个可用区(AZ)上都有运行中的实例。
如果一个可用区因数据中心故障而宕机,我们仍有两个可用区来处理请求;如果整个区域宕机或出现错误,我们可以通知 Route53 故障切换到 us-west-1、恢复操作。
我们在服务故障切换方面有不同的成熟度级别:一些服务(比如在 Elasticsearch 上构建缓存的用户搜索 v2)可正常运行,但数据稍显陈旧,不过核心功能按预期运行。
在数据层中,我们使用:
· 面向 MongoDB 的跨区域集群。
· 面向 PostgreSQL 的 RDS 复制。
· 面向 Elasticsearch 的每个区域的集群,自动快照和恢复定期运行,以解决缺少跨区域集群的问题。
我们每年至少进行一次故障切换演练,我们有剧本和自动化,帮助新的基础设施工程师尽快了解如何演练以及由此带来的影响。
我们的部署通常由 Jenkins 节点触发;视服务而定,我们使用 Puppet、SaltStack 及/或 Ansible 来更新单个节点或一组节点,或者我们更新 AMI,为不可变的部署创建新的自动扩展组。
我们为新旧服务部署了不同类型的环境;由于我们需要为应该统一的系统维护自动化、文档和监控,结果证明这基本上很低效。
我们目前在为一些核心服务推出蓝/绿部署(blue/green deployment),我们打算为每个核心的支持服务实施同样的一套。
自动化测试
除了每个项目的单元测试覆盖外,我们还有在每个环境中运行的多个功能测试套件。
我们在部署到生产环境之前先在试运行环境上运行,完成部署后再在生产环境中运行,以确保一切正常。
我们的自动化测试要点:
· 在不同的项目中有数千个单元测试。
· 使用每分钟运行的 Pingdom 探针(probe)来检查核心功能。
· 在每次部署前后结合使用基于 Selenium 的功能测试和基于 CodeceptJS 的功能测试。功能测试套件测试不同的 API 端点、身份验证流程和身份提供者等。
CDN
2017 年之前我们运行自己专门定制的 CDN,在多个区域运行 Nginx、Varnish 和 EC2 节点。
2017 年以后,我们改用 CloudFront,它为我们带来了几个好处,包括:
· 更多的边缘位置,这意味着为我们的客户缩短了延迟。
· 降低维护成本。
· 配置起来更轻松。
但同时也有几个缺点,比如我们需要运行 Lambdas 来执行一些配置(比如将自定义标头添加到 PDF 文件等等)。不过,好处绝对压倒缺点。
Extend
我们提供的功能之一是能够通过身份验证规则或自定义数据库连接,运行自定义代码,作为登录事务的一部分。
这些功能由 Extend(https://goextend.io/)提供支持,Extend 是一个可扩展性平台,由 Auth0 发展而来,现在还被其他公司所使用。
有了 Extend,我们的客户就可以用那些脚本和规则编写所需的任何服务,扩展配置文件、规范属性和发送通知等。
我们有专门针对 Auth0 的 Extend 集群,它们结合使用 EC2 自动扩展组、Docker 容器和自定义代理,以处理来自我们用户的请求,每秒处理数千个请求,并快速响应负载变化。
想了解这如何构建和运行的更多信息,请参阅这篇介绍如何构建自己的无服务器平台的文章(https://tomasz.janczuk.org/2018/03/how-to-build-your-own-serverless-platform.html)。
监控
我们结合使用不同的工具来监控和调试问题:
· CloudWatch
· DataDog
· Pingdom
· SENTINL
我们的绝大多数警报来自 CloudWatch 和 DataDog。
我们往往通过 TerraForm 来配置 CloudWatch 警报,用 CloudWatch 来监控的主要问题有:
· 来自主负载均衡系统的 HTTP 错误。
· 目标组中不健康的实例。
· SQS 处理延迟。
CloudWatch 是基于 AWS 生成的指标(比如来自负载均衡系统或自动扩展组的指标)来监控警报的***工具。
CloudWatch 警报通常发送给 PagerDuty,再从 PagerDuty 发送给 Slack/手机。
DataDog 是我们用来存储时间序列指标并采取相应操作的服务。我们发送来自 Linux 系统、AWS 资源和现成服务(比如 Nginx 或 MongoDB)的指标,还发送来自我们构建的自定义服务(比如 Management API)的指标。
我们有许多 DataDog 监控指标,举几个例子:
· $environment 上的 $service 响应时间增加。
· $instance 中的 $volume($ ip_address)空间不足。
· $environment / $ host 上的 $process($ ip_address)出现问题。
· $environment 上的 $service 处理时间增加。
· $host($ip_address)上出现 NTP 漂移/时钟问题。
· $environment 上的 MongoDB 副本集变更。
从上面例子中可以看出,我们监控低级指标(如磁盘空间)和高级指标(如 MongoDB 副本集变更,这提醒我们主节点定义是否发生了变化)。我们做了大量的工作,设计了一些相当复杂的指标来监控一些服务。
DataDog 警报的输出非常灵活,我们通常将它们全部发送给 Slack,只把那些“引人注意”的警报发送给 PagerDuty,比如错误高峰,或者我们确信对客户产生影响的大多数事件。
至于日志记录方面,我们使用 SumoLogic 和 Kibana;我们使用 SumoLogic 来记录审计跟踪记录和 AWS 生成的许多日志,我们使用 Kibana 存储来自我们自己的服务和其他“现成”服务(如 Nginx 和 MongoDB)的应用程序日志。
未来设想
我们的平台经历了很大的变化,以处理额外负载和对客户来说很重要的众多使用场景,但我们仍有优化的空间。
不仅我们的平台在扩大,我们的工程部门规模也在扩大:我们有许多新团队构建自己的服务,而且需要自动化、工具和可扩展性方面的指导。
有鉴于此,我们落实了这些计划,不仅扩展平台,还夯实工程实践:
· 构建类似 PaaS 的平台:如前所述,今天我们有不同的自动化和部署流程,这导致了混乱,给工程师设置了门槛,因为很难在不接触众多代码库的情况下进行试验和扩展。
我们正在为目前在 ECS 上运行的平台开发概念证明(PoC)代码,工程师们可以配置 YAML 文件,只需部署它,即可获取计算资源、监控、日志记录和备份等。
所有这一切都无需明确配置。这项工作还处于早期阶段,可能会发生很大变化。然而,鉴于我们不断扩大的规模和可扩展性方面的限制,我们认为我们的方向正确。
· 针对每个新的合并请求实施冒烟测试(smoke test):除了单元测试(已经在每个新的 PR 上运行)外,我们希望尽可能在短暂环境上进行集成测试。
· 将我们的日志记录解决方案集中到一家提供商。这可能意味着远离 Kibana,只使用 SumoLogic,但我们仍需要评估功能集和数据量等。
· 自动衡量指标:现在我们的指标好多都是手动的――部署时添加与指标有关的代码调用,以及使用 DataDog 接口来构建仪表板和监控器。
如果我们使用标准格式和命名,可以实现一些任务,比如自动构建仪表板/监控器,从日志提取指标而不是明确添加代码调用等。
· 确保我们针对每个核心服务都有自动扩展和蓝/绿部署。这应该是我们新平台的默认功能,但在构建和测试时,我们需要为这方面仍然不足的核心服务改进扩展/部署/回滚机制。
【51CTO原创稿件,合作站点转载请注明原文作者和出处为51CTO.com】
【责任编辑:关崇 TEL:(010)68476606】