如何使用 Docker、ECS、Terraform 重建基礎架構?

早期 Segment 基礎架構廣泛組合在一塊兒。咱們經過 AWS 界面設定實例,使用許多閒散的 AMI,而且採用三種不一樣的部署方式。html

然而隨着商業的飛速發展,工程師團隊的規模不斷擴大,基礎架構的複雜度也不斷提升。提升生產效率的方法仍舊只在一小部分人中間傳播,雖然生產效率在不斷提升,可是若是想一直保持高速增加,還要全面修整基礎架構。python

所以,幾個月前,個人團隊一塊兒討論:「若是今天從新設計基礎架構,會是怎樣一種結構?」。git

10個星期後,咱們完全重構了基礎架構。咱們放棄了幾乎全部實例與舊的配置,將咱們的服務轉移到 Docker 容器中運行,而且轉而使用全新的 AWS 帳號。github

在此咱們花了很長時間思考如何將產品架構變得簡單、易用且可審計,同時保留擴展的靈活性。docker

如下是咱們的解決方法。數據庫

使用不一樣的 AWS 帳號

咱們並不使用 Region 和 Tag 來區分不一樣的階段如預發佈環境和生產環境,而是使用徹底不一樣的 AWS 帳號。咱們必須保證設定腳本不會影響正在運行的服務。同時,新的帳號就像白紙同樣,能夠從新開始。ubuntu

此處,ops 帳號做爲跳躍點和集中登錄點。公司內的每一個人有一個 IAM 帳號用於登錄。安全

其餘環境有一組 IAM 角色能夠相互切換。這意味着,管理帳號只有一個登錄點,也只有一個位置限制訪問。服務器

好比:Alice 可能擁有全部三個環境的訪問權,但 Bob 只能訪問 dev(若是他刪除生產負載均衡器的話)。可是,他倆均可以進入 ops 帳號。架構

如今,不須要複雜的 IAM 設定以限制訪問權限,咱們能夠經過環境查看用戶通 role 進行分組。在界面使用各個帳戶就像切換當前活躍用戶同樣簡單。

咱們無償地實現了真正的隔離,不需額外的配置,無須擔憂預發佈環境的安全性,或它對生產環境數據庫的改動。

可以共享配置代碼的另外一個好處是如今的 預發佈環境成爲了一個鏡像。在配置上惟一的不一樣是實例的大小和容器的數量。

最後,咱們也啓用了各個帳戶之間統一計費。每月咱們用同一張發票付費,同時能按照環境查看費用明細。

Docker 與 ECS

帳戶設定完畢後,就該設置服務的運行方式了。爲此,咱們使用了 DockerEC2 容器服務(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 的簡單與集成,但 KubernetesMesosphereNomadFleet 這些都是很是不錯的調度器。咱們很期待看到他們的後續發展,並會考慮選擇一二進行使用。

經歷全部這些編排變化以後,咱們比之前更加相信將基礎構架外包至 AWS 的策略。他們產品化了許多核心服務,徹底改變了遊戲規則,並且維持了一個極具競爭力的價格。這使得愈來愈多的初創企業可以高效、低成本低開發產品,同時在維護上節省時間。咱們至關看好這些創建在基礎生態系統之上的工具。

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

OneAPM 可以幫你查看 Python 應用程序的方方面面,不只可以監控終端的用戶體驗,還能監控服務器性能,同時還支持追蹤數據庫、第三方 API 和 Web 服務器的各類問題。想閱讀更多技術文章,請訪問 OneAPM 官方技術博客

本文轉自 OneAPM 官方博客

相關文章
相關標籤/搜索