如何使用 Docker、ECS、Terraform 重建基础架构?
早期 Segment 基础架构普遍组合在一起。我们通过 AWS 界面设定实例,使用许多闲散的 AMI,并且采用三种不同的部署方式。
然而随着商业的飞速发展,工程师团队的规模不断扩大,基础架构的复杂度也不断提高。提高生产效率的方法仍旧只在一小部分人中间传播,虽然生产效率在不断提高,但是如果想一直保持高速增长,还要全面修整基础架构。
因此,几个月前,我的团队一起讨论:「如果今天重新设计基础架构,会是怎样一种结构?」。
10个星期后,我们彻底重构了基础架构。我们放弃了几乎所有实例与旧的配置,将我们的服务转移到 Docker 容器中运行,并且转而使用全新的 AWS 账号。
在此我们花了很长时间思考如何将产品架构变得简单、易用且可审计,同时保留扩展的灵活性。
以下是我们的解决方法。
使用不同的 AWS 账号
我们并不使用 Region 和 Tag 来区分不同的阶段如预发布环境和生产环境,而是使用完全不同的 AWS 账号。我们必须保证设定脚本不会影响正在运行的服务。同时,新的账号就像白纸一样,可以重新开始。
此处,ops
账号作为跳跃点和集中登陆点。公司内的每个人有一个 IAM 账号用于登陆。
其他环境有一组 IAM 角色可以相互切换。这意味着,管理账号只有一个登陆点,也只有一个位置限制访问。
比如:Alice 可能拥有所有三个环境的访问权,但 Bob 只能访问 dev(如果他删除生产负载均衡器的话)。但是,他俩都可以进入 ops
账号。
现在,不需要复杂的 IAM 设定以限制访问权限,我们可以通过环境查看用户通 role 进行分组。在界面使用各个账户就像切换当前活跃用户一样简单。
我们无偿地实现了真正的隔离,不需额外的配置,无须担心预发布环境的安全性,或它对生产环境数据库的改动。
能够共享配置代码的另一个好处是现在的 预发布环境成为了一个镜像。在配置上唯一的不同是实例的大小和容器的数量。
最后,我们也启用了各个账户之间统一计费。每个月我们用同一张发票付费,同时能按照环境查看费用明细。
Docker 与 ECS
账户设定完毕后,就该设置服务的运行方式了。为此,我们使用了 Docker 与 EC2 容器服务(ECS)。
现如今,我们大多数的服务都运行在 Docker 容器内,包括 API 与数据管道。容器每秒钟接受成千上万次请求,每个月处理500亿事件。
Docker 的最大好处在于它使团队能够从零开始搭建服务。我们不再有一套复杂的设定脚本或 AMI ,我们只要给生产集群提供一张镜像就行了。无需状态性的实例,我们能保证在预发布环境和生产环境运行一模一样的代码。
设定服务在容器中运行后,我们选择 ECS 为调度器。
在一个高水平上,ECS 实际负责在生产环境下运行容器。它负责调度服务、将它们置于不同的主机中,在与 ELB 关联时零宕机重载。它甚至可以跨多个 AZs,从而达到更佳可用性。如果一个容器宕机了,ECS 会确保该容器在集群中的新实例上重启。
切换到 ECS 之后,极大地简化了运行服务的过程,无需再担心启动任务或设定实例。因为它很简单,只需要添加一个 Dockerfile,设定 task,再将其与集群关联即可。
在我们的配置中,Docker 镜像由 CI(持续集成) 构建,之后推送到 Docker Hub。当某项服务启动时,它从 Docker Hub 获取镜像,之后 ECS 在各个机器间调度之。
我们依照集群涉及的组件与负载间档对他们分组(不同的集群用于不同的 API、CDN、App 等)。不同的集群意味着我们可见性更高,能为其配置不同的实例类型( ECS 没有实例关联度的概念)。
每项服务都包含一个特别的任务用于指明容器版本,运行的实例数量,以及该选择的集群类型。
在运行时,服务会自行注册 ELB,同时使用健康检查确定容器是否可以运行。我们在 ELB 指定一个本地的 Route53,因此各个服务能相互通信,通过 DNS 就能相互引用。
因为不需要任何服务搜索,所以设置非常顺利。本地的 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 真的棒极了!
我们对 Datadog 的界面,API 以及其和 AWS 的整合都非常满意。但是,想要完全利用这个工具,还需要一些关键的设置。
首先,我们与 AWS 和 Cloudtrail 进行整合。这能使我们全面了解环境中的所有情况。由于我们已经与 ECS 整合过了,Datadog feed 会在任务内容更新时自动更新,于是我们能在部署放生改变时得到免费通知。搜索 feed 的过程也异常快捷,能轻松找到最近一次的服务部署或重新调度。
接下来,我们确保将 Datadog-agent 作为 AMI 基础容器(datadog/docker-dd-agent)。它不仅会从主机( CPU,内存等)收集测量数据,也作为存储 statsd 测量数据的容器。每一项服务都会收集关于查询、潜伏、错误的自定义指标,因此我们可以在 Datadog 中进行探索,获得警告等。我们的 go 工具箱(很快就会开源)会自动收集并在 ticker 输出 pprof
,因此达到监控内存与 goroutines 的目的。
更酷的是,该探针能够图形化展示环境中多个主机间的实例利用情况,因此我们能从更高角度了解可能出问题的实例或集群:
此外,我的队友 Vince 写了一个针对 Datadog 的 Terraform,因此我们可以针对实际的生产配置设置报警脚本。我们的报警会被记录,同时与生产环境中运行的程序保持同步。
按照惯例,我们会设定两种报警级别:预警
与重要警告
。预警
使线上的工程师了解任何可疑的问题,会在潜在问题发生以前发出。重要警告
则是会在半夜把你喊起来的严重系统宕机。
此外,当我们完成向 Terraform 模块的转移,将 Datadog 提供程序加到服务描述层之后,所有的服务都会免费获得告警。这些数据都是由内部工具箱与 Cloudwatch 指标驱动的。
让好时光在 Docker 中继续
当所有的组件都准备就绪后,切换的日子终于到来了。
首先,我们会在新的生产环境与原有环境间建立 VPC 对等连接——从而集群化数据库并在两者间进行复制。
其次,我们预热新环境中的 ELB 使之能够承受新的负载。亚马逊无法提供自动更改大小的 ELB,因此我们不得不提前为其扩容以应对增加后的负载。
之后,我们只需使用加权的 Route53 路由平稳地将流量从旧环境导向新环境,并且持续监控确保一切正常。
现在,我们的 API 每秒处理成千上万次请求,并且完全运行在 Docker 容器内。
但是还没完,我们还在优化服务的创建方式,减少引用,使得团队中的任何人都能简便地创建服务,同时包含适度的监控与预警系统。此外,我们还想优化容器周边的工具,因为现在的服务已不再围绕实例进行了。
我们还会关注这一领域颇有发展的技术。Convox 团队真正创建围绕 AWS 基础架构的强大工具。尽管我们很喜欢 ECS 的简单与集成,但 Kubernetes 、Mesosphere、 Nomad 与 Fleet 这些都是非常不错的调度器。我们很期待看到他们的后续发展,并会考虑选择一二进行使用。
经历所有这些编排变化之后,我们比以前更加相信将基础构架外包至 AWS 的策略。他们产品化了许多核心服务,完全改变了游戏规则,而且维持了一个极具竞争力的价格。这使得越来越多的初创企业能够高效、低成本低开发产品,同时在维护上节省时间。我们相当看好这些建立在基础生态系统之上的工具。
原文 Rebuilding Our Infrastructure with Docker, ECS, and Terraform 作者 Calvin French-Owen,本文由 OneAPM 工程师翻译整理。
OneAPM 能够帮你查看 Python 应用程序的方方面面,不仅能够监控终端的用户体验,还能监控服务器性能,同时还支持追踪数据库、第三方 API 和 Web 服务器的各种问题。想阅读更多技术文章,请访问 OneAPM 官方技术博客。
本文转自 OneAPM 官方博客
如何使用 Docker、ECS、Terraform 重建基础架构?的更多相关文章
- 基础架构之Docker私有库
由于项目要容器化,所有搭建自己的镜像库也是很有必要的,不然发到直接使用官方的镜像库,速度绝对能让你头疼,这篇文章就介绍搭建自己的镜像私有库. (一) 环境要求 Centos 7.5.1804 Doc ...
- AWS EC2+Docker+JMeter构建分布式负载测试基础架构
目录 概述及范围 前提条件 Part 1: Local setup-本地配置 Part 2: Cloud端基础架构--Infrastructure 总结: 原文链接 @ 概述及范围 本文介绍有关如何使 ...
- Docker底层架构之基础架构
Docker 采用了 C/S架构,包括客户端和服务端. Docker daemon 作为服务端接受来自客户 的请求,并处理这些请求(创建.运行.分发容器). 客户端和服务端既可以运行在一个机器上,也可 ...
- b2c项目基础架构分析(二)前端框架 以及补漏的第一篇名词解释
继续上篇,上篇里忘记了也很重要的前端部分,今天的网站基本上是以一个启示页,然后少量的整页切换,大量的浏览器后台调用web服务局部.动态更新页面显示状态这种方式在运作的,从若干年前简单的ajax流行起来 ...
- b2c项目基础架构分析(一)b2c 大型站点方案简述 已补充名词解释
我最近一直在找适合将来用于公司大型bs,b2b b2c的基础架构. 实际情况是要建立一个bs架构b2b.b2c的网站,当然还包括wap站点.手机app站点. 一.现有公司技术人员现状: 1.熟悉asp ...
- Docker容器学习梳理 - 基础知识(1)
Docker是PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0协议开源.Docker是通过内核虚拟化技 ...
- 【转帖】使用容器化和 Docker 实现 DevOps 的基础知识
使用容器化和 Docker 实现 DevOps 的基础知识 https://www.kubernetes.org.cn/6730.html 2020-02-24 15:20 灵雀云 分类:容器 阅读( ...
- SQL Server数据仓库的基础架构规划
问题 SQL Server数据仓库具有自己的特征和行为属性,有别去其他.从这个意义上说,数据仓库基础架构规划需要与标准SQL Server OLTP数据库系统的规划不同.在本文中,我们将介绍在计划数据 ...
- Docker虚拟化实战学习——基础篇(转)
Docker虚拟化实战学习——基础篇 2018年05月26日 02:17:24 北纬34度停留 阅读数:773更多 个人分类: Docker Docker虚拟化实战和企业案例演练 深入剖析虚拟化技 ...
随机推荐
- MySQLdb安装和使用2
http://blog.chinaunix.net/uid-8487640-id-3183185.html MySQLdb是Python连接MySQL的模块,下面介绍一下源码方式安装MySQLdb: ...
- Java基础知识强化之集合框架笔记55:Map集合之HashMap集合(HashMap<Integer,String>)的案例
1. HashMap集合(键是Integer,值是String的案例) 2. 代码示例: package cn.itcast_02; import java.util.HashMap; import ...
- Java基础知识强化之网络编程笔记03:UDP之UDP协议发送数据 和 接收数据
1. UDP协议发送数据 和 接收数据 UDP协议发送数据: • 创建发送端的Socket对象 • 创建数据,并把数据打包 • 调用Socket对象的发送方法,发送数据包 • 释放资源 UDP协议接 ...
- 如何让android sdk manager飞奔安装sdk
由于国内的gwf的原因,凡是google的服务都是无法正常访问,这两天从android官网上下载sdk不是一般的慢.不过现在有一个好的方法.sdk都是从https://dl-ssl.google.co ...
- 4G上网卡NIDS拨号之Rmnet驱动
4G上网卡一般为双对外通讯口,一个是串口.一个是USB. 但是基于串口的常用波特率为115200,速度过于底下,所以大多使用USB. 1)一般来说常用ppp拨号方式,ppp拨号方式分为应用层pppd与 ...
- Jquery Call WebDav
最近研究了一下WebDav,尝试了一下用Jquery.ajax 发生请求访问WebDav. 代码如下: <!DOCTYPE html> <html xmlns="http: ...
- volatile用处说明
在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程环境下volatile关键字的使用变得非常重要. 在当前 ...
- js实现FileUpload选择图片后预览功能
当asp.net的FileUpload选择一个图片后不需要上传就能显示出图片的预览功能, 代码: <%@ Page Language="C#" AutoEventWireup ...
- python基础知识八
当你的程序中出现某些 异常的 状况的时候,异常就发生了.例如,当你想要读某个文件的时候,而那个文件不存在.或者在程序运行的时候,你不小心把它删除了.上述这些情况可以使用异常来处理. 如你的程序中有一些 ...
- delphi参数传递
delphi参数传递 参数传递 声明/实现一个过程使用的参数称为形式参数(简称形参),调用过程时传入的参数称为实际参数(简称实参). { Info是形参} procedure ShowInfo( ...