如何使用 Docker、ECS、Terraform 重建基础架构?

早期 Segment 基础架构普遍组合在一起。我们通过 AWS 界面设定实例,使用许多闲散的 AMI,并且采用三种不同的部署方式。

然而随着商业的飞速发展,工程师团队的规模不断扩大,基础架构的复杂度也不断提高。提高生产效率的方法仍旧只在一小部分人中间传播,虽然生产效率在不断提高,但是如果想一直保持高速增长,还要全面修整基础架构。

因此,几个月前,我的团队一起讨论:「如果今天重新设计基础架构,会是怎样一种结构?」。

10个星期后,我们彻底重构了基础架构。我们放弃了几乎所有实例与旧的配置,将我们的服务转移到 Docker 容器中运行,并且转而使用全新的 AWS 账号。

在此我们花了很长时间思考如何将产品架构变得简单、易用且可审计,同时保留扩展的灵活性。

以下是我们的解决方法。

使用不同的 AWS 账号

我们并不使用 Region 和 Tag 来区分不同的阶段如预发布环境和生产环境,而是使用完全不同的 AWS 账号。我们必须保证设定脚本不会影响正在运行的服务。同时,新的账号就像白纸一样,可以重新开始。

-----2016-01-15---11-00-51.png

此处,ops 账号作为跳跃点和集中登陆点。公司内的每个人有一个 IAM 账号用于登陆。

其他环境有一组 IAM 角色可以相互切换。这意味着,管理账号只有一个登陆点,也只有一个位置限制访问。

比如:Alice 可能拥有所有三个环境的访问权,但 Bob 只能访问 dev(如果他删除生产负载均衡器的话)。但是,他俩都可以进入 ops 账号。

现在,不需要复杂的 IAM 设定以限制访问权限,我们可以通过环境查看用户通 role 进行分组。在界面使用各个账户就像切换当前活跃用户一样简单。

-----2016-01-15---11-10-37.png

我们无偿地实现了真正的隔离,不需额外的配置,无须担心预发布环境的安全性,或它对生产环境数据库的改动。

能够共享配置代码的另一个好处是现在的 预发布环境成为了一个镜像。在配置上唯一的不同是实例的大小和容器的数量。

最后,我们也启用了各个账户之间统一计费。每个月我们用同一张发票付费,同时能按照环境查看费用明细。

Docker 与 ECS

账户设定完毕后,就该设置服务的运行方式了。为此,我们使用了 DockerEC2 容器服务(ECS)

现如今,我们大多数的服务都运行在 Docker 容器内,包括 API 与数据管道。容器每秒钟接受成千上万次请求,每个月处理500亿事件。

Docker 的最大好处在于它使团队能够从零开始搭建服务。我们不再有一套复杂的设定脚本或 AMI ,我们只要给生产集群提供一张镜像就行了。无需状态性的实例,我们能保证在预发布环境和生产环境运行一模一样的代码。

设定服务在容器中运行后,我们选择 ECS 为调度器。

在一个高水平上,ECS 实际负责在生产环境下运行容器。它负责调度服务、将它们置于不同的主机中,在与 ELB 关联时零宕机重载。它甚至可以跨多个 AZs,从而达到更佳可用性。如果一个容器宕机了,ECS 会确保该容器在集群中的新实例上重启。

切换到 ECS 之后,极大地简化了运行服务的过程,无需再担心启动任务或设定实例。因为它很简单,只需要添加一个 Dockerfile,设定 task,再将其与集群关联即可。

在我们的配置中,Docker 镜像由 CI(持续集成) 构建,之后推送到 Docker Hub。当某项服务启动时,它从 Docker Hub 获取镜像,之后 ECS 在各个机器间调度之。

-----2016-01-15---11-29-46.png

我们依照集群涉及的组件与负载间档对他们分组(不同的集群用于不同的 API、CDN、App 等)。不同的集群意味着我们可见性更高,能为其配置不同的实例类型( ECS 没有实例关联度的概念)。

每项服务都包含一个特别的任务用于指明容器版本,运行的实例数量,以及该选择的集群类型。

在运行时,服务会自行注册 ELB,同时使用健康检查确定容器是否可以运行。我们在 ELB 指定一个本地的 Route53,因此各个服务能相互通信,通过 DNS 就能相互引用。

-----2016-01-15---11-36-13.png

因为不需要任何服务搜索,所以设置非常顺利。本地的 DNS 帮助我们记录一切。

ECS 运行所有服务,我们通过 ELB 就能获取免费的云监控测量数据。这比在启动时就要在中央注册服务要简单的多。而且,更棒的是,我们中央不需要再面对状态冲突了。

使用 Terraform 模板

Docker 与 ECS 负责实现运行每一项服务,Terraform 是将他们联合在一起的胶水。在高水平上,一系列脚本负责创建并更新基础架构。你可以将其想作一个 Cloudformaition 模版,除了它不会让你想自戳双目。

现在,无需运行一系列服务器以维护状态,只需一些脚本用来描述集群。配置在本地运行(未来通过 CI 运行),提交到 git 上。因此,我们能得到一系列记录,能够了解生产环境中基础构架的实际情况。

以下是我们的 Terraform 模板中设置 bastion 结点的样本代码。该代码创建所有的安全组,实例和 AMI,因此我们可以简单地为未来的环境设定跳跃点。

// Use the Ubuntu AMI
module "ami" {
    source = "github.com/terraform-community-modules/tf_aws_ubuntu_ami/ebs"
    region = "us-west-2"
    distribution = "trusty"
    instance_type = "${var.instance_type}"
}

// Set up a security group to the bastion
resource "aws_security_group" "bastion" {
    name = "bastion"
    description = "Allows ssh from the world"
    vpc_id = "${var.vpc_id}"

    ingress {
        from_port = 22
        to_port   = 22
        protocol  = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
    }

    egress {
        from_port = 0
        to_port = 0
        protocol = "-1"
        cidr_blocks = ["0.0.0.0/0"]
    }

    tags {
        Name = "bastion"
    }
}

// Add our instance description
resource "aws_instance" "bastion" {
    ami = "${module.ami.ami_id}"
    source_dest_check = false
    instance_type = "${var.instance_type}"
    subnet_id = "${var.subnet_id}"
    key_name = "${var.key_name}"
    security_groups = ["${aws_security_group.bastion.id}"]
    tags  {
        Name = "bastion-01"
        Environment = "${var.environment}"
    }
}

// Setup our elastic ip
resource "aws_eip" "bastion" {
    instance = "${aws_instance.bastion.id}"
    vpc = true
}

我们在预发布环境与生产环境中使用同样的模板设置单个 bastion。唯一需要修改的是 IAM 键。

修改也非常简单,不需要修改整个基础架构,Terraform 会在需要的时候更新内容。

当我们要将 ELB 超时时间改为60秒时,只需通过 terraform apply 简单地查找/替换就好。两分钟之后,我们的 ELB 生产环境就完全改变了。

而且,这是可复制、可审计且自文档化的,每一步都是可见的白盒操作。

我们将所有配置都放在一个中心的 infrastructure 库,这样很容易看清某一项给定的服务是如何配置的。

到目前为止,我们还未讲到核心部分。我们希望利用模板转变更多的 Terraform 配置,联合独立文件从而减少共享文件的数量。

同时,我们也发现了有关 .tfstate 的一些陷阱。Terraform 总是先从现存的基础架构读取数据,如果状态不同步就会报错。最后,我们将 .tfstate 放到库中。我们希望能通过 Atlas 或使用 CI 来解决该问题。

使用 Datadog 监控

至此,我们已经搭好了基础架构,开通了服务,做好了必要的隔离。最后要做的是监控生产环境中所有运行程序。

在新环境中,我们将所有的监控和指标都用 Datadog 进行。不夸张的说 Datadog 真的棒极了!

-----2016-01-15---11-46-12.png

我们对 Datadog 的界面,API 以及其和 AWS 的整合都非常满意。但是,想要完全利用这个工具,还需要一些关键的设置。

首先,我们与 AWS 和 Cloudtrail 进行整合。这能使我们全面了解环境中的所有情况。由于我们已经与 ECS 整合过了,Datadog feed 会在任务内容更新时自动更新,于是我们能在部署放生改变时得到免费通知。搜索 feed 的过程也异常快捷,能轻松找到最近一次的服务部署或重新调度。

接下来,我们确保将 Datadog-agent 作为 AMI 基础容器(datadog/docker-dd-agent)。它不仅会从主机( CPU,内存等)收集测量数据,也作为存储 statsd 测量数据的容器。每一项服务都会收集关于查询、潜伏、错误的自定义指标,因此我们可以在 Datadog 中进行探索,获得警告等。我们的 go 工具箱(很快就会开源)会自动收集并在 ticker 输出 pprof,因此达到监控内存与 goroutines 的目的。

更酷的是,该探针能够图形化展示环境中多个主机间的实例利用情况,因此我们能从更高角度了解可能出问题的实例或集群:

-----2016-01-15---11-50-59.png

此外,我的队友 Vince 写了一个针对 Datadog 的 Terraform,因此我们可以针对实际的生产配置设置报警脚本。我们的报警会被记录,同时与生产环境中运行的程序保持同步。

按照惯例,我们会设定两种报警级别:预警重要警告预警使线上的工程师了解任何可疑的问题,会在潜在问题发生以前发出。重要警告则是会在半夜把你喊起来的严重系统宕机。

此外,当我们完成向 Terraform 模块的转移,将 Datadog 提供程序加到服务描述层之后,所有的服务都会免费获得告警。这些数据都是由内部工具箱与 Cloudwatch 指标驱动的。

让好时光在 Docker 中继续

当所有的组件都准备就绪后,切换的日子终于到来了。

首先,我们会在新的生产环境与原有环境间建立 VPC 对等连接——从而集群化数据库并在两者间进行复制。

其次,我们预热新环境中的 ELB 使之能够承受新的负载。亚马逊无法提供自动更改大小的 ELB,因此我们不得不提前为其扩容以应对增加后的负载。

之后,我们只需使用加权的 Route53 路由平稳地将流量从旧环境导向新环境,并且持续监控确保一切正常。

现在,我们的 API 每秒处理成千上万次请求,并且完全运行在 Docker 容器内。

但是还没完,我们还在优化服务的创建方式,减少引用,使得团队中的任何人都能简便地创建服务,同时包含适度的监控与预警系统。此外,我们还想优化容器周边的工具,因为现在的服务已不再围绕实例进行了。

我们还会关注这一领域颇有发展的技术。Convox 团队真正创建围绕 AWS 基础架构的强大工具。尽管我们很喜欢 ECS 的简单与集成,但 KubernetesMesosphereNomadFleet 这些都是非常不错的调度器。我们很期待看到他们的后续发展,并会考虑选择一二进行使用。

经历所有这些编排变化之后,我们比以前更加相信将基础构架外包至 AWS 的策略。他们产品化了许多核心服务,完全改变了游戏规则,而且维持了一个极具竞争力的价格。这使得越来越多的初创企业能够高效、低成本低开发产品,同时在维护上节省时间。我们相当看好这些建立在基础生态系统之上的工具。

原文 Rebuilding Our Infrastructure with Docker, ECS, and Terraform 作者 Calvin French-Owen,本文由 OneAPM 工程师翻译整理。

OneAPM 能够帮你查看 Python 应用程序的方方面面,不仅能够监控终端的用户体验,还能监控服务器性能,同时还支持追踪数据库、第三方 API 和 Web 服务器的各种问题。想阅读更多技术文章,请访问 OneAPM 官方技术博客

本文转自 OneAPM 官方博客

转载于:https://www.cnblogs.com/oneapm/p/5133313.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值