如何使用 Docker、ECS、Terraform 重建基礎(chǔ)架構(gòu)?

早期 Segment 基礎(chǔ)架構(gòu)普遍組合在一起。我們通過(guò) AWS 界面設(shè)定實(shí)例,使用許多閑散的 AMI,并且采用三種不同的部署方式。

然而隨著商業(yè)的飛速發(fā)展,工程師團(tuán)隊(duì)的規(guī)模不斷擴(kuò)大,基礎(chǔ)架構(gòu)的復(fù)雜度也不斷提高。提高生產(chǎn)效率的方法仍舊只在一小部分人中間傳播,雖然生產(chǎn)效率在不斷提高,但是如果想一直保持高速增長(zhǎng),還要全面修整基礎(chǔ)架構(gòu)。

因此,幾個(gè)月前,我的團(tuán)隊(duì)一起討論:「如果今天重新設(shè)計(jì)基礎(chǔ)架構(gòu),會(huì)是怎樣一種結(jié)構(gòu)?」。

10個(gè)星期后,我們徹底重構(gòu)了基礎(chǔ)架構(gòu)。我們放棄了幾乎所有實(shí)例與舊的配置,將我們的服務(wù)轉(zhuǎn)移到 Docker 容器中運(yùn)行,并且轉(zhuǎn)而使用全新的 AWS 賬號(hào)。

在此我們花了很長(zhǎng)時(shí)間思考如何將產(chǎn)品架構(gòu)變得簡(jiǎn)單、易用且可審計(jì),同時(shí)保留擴(kuò)展的靈活性。

以下是我們的解決方法。

使用不同的 AWS 賬號(hào)

我們并不使用 Region 和 Tag 來(lái)區(qū)分不同的階段如預(yù)發(fā)布環(huán)境和生產(chǎn)環(huán)境,而是使用完全不同的 AWS 賬號(hào)。我們必須保證設(shè)定腳本不會(huì)影響正在運(yùn)行的服務(wù)。同時(shí),新的賬號(hào)就像白紙一樣,可以重新開(kāi)始。

此處,ops 賬號(hào)作為跳躍點(diǎn)和集中登陸點(diǎn)。公司內(nèi)的每個(gè)人有一個(gè) IAM 賬號(hào)用于登陸。

其他環(huán)境有一組 IAM 角色可以相互切換。這意味著,管理賬號(hào)只有一個(gè)登陸點(diǎn),也只有一個(gè)位置限制訪問(wèn)。

比如:Alice 可能擁有所有三個(gè)環(huán)境的訪問(wèn)權(quán),但 Bob 只能訪問(wèn) dev(如果他刪除生產(chǎn)負(fù)載均衡器的話)。但是,他倆都可以進(jìn)入 ops 賬號(hào)。

現(xiàn)在,不需要復(fù)雜的 IAM 設(shè)定以限制訪問(wèn)權(quán)限,我們可以通過(guò)環(huán)境查看用戶通 role 進(jìn)行分組。在界面使用各個(gè)賬戶就像切換當(dāng)前活躍用戶一樣簡(jiǎn)單。

我們無(wú)償?shù)貙?shí)現(xiàn)了真正的隔離,不需額外的配置,無(wú)須擔(dān)心預(yù)發(fā)布環(huán)境的安全性,或它對(duì)生產(chǎn)環(huán)境數(shù)據(jù)庫(kù)的改動(dòng)。

能夠共享配置代碼的另一個(gè)好處是現(xiàn)在的 預(yù)發(fā)布環(huán)境成為了一個(gè)鏡像。在配置上唯一的不同是實(shí)例的大小和容器的數(shù)量。

最后,我們也啟用了各個(gè)賬戶之間統(tǒng)一計(jì)費(fèi)。每個(gè)月我們用同一張發(fā)票付費(fèi),同時(shí)能按照環(huán)境查看費(fèi)用明細(xì)。

Docker 與 ECS

賬戶設(shè)定完畢后,就該設(shè)置服務(wù)的運(yùn)行方式了。為此,我們使用了 DockerEC2 容器服務(wù)(ECS)。

現(xiàn)如今,我們大多數(shù)的服務(wù)都運(yùn)行在 Docker 容器內(nèi),包括 API 與數(shù)據(jù)管道。容器每秒鐘接受成千上萬(wàn)次請(qǐng)求,每個(gè)月處理500億事件。

Docker 的最大好處在于它使團(tuán)隊(duì)能夠從零開(kāi)始搭建服務(wù)。我們不再有一套復(fù)雜的設(shè)定腳本或 AMI ,我們只要給生產(chǎn)集群提供一張鏡像就行了。無(wú)需狀態(tài)性的實(shí)例,我們能保證在預(yù)發(fā)布環(huán)境和生產(chǎn)環(huán)境運(yùn)行一模一樣的代碼。

設(shè)定服務(wù)在容器中運(yùn)行后,我們選擇 ECS 為調(diào)度器。

在一個(gè)高水平上,ECS 實(shí)際負(fù)責(zé)在生產(chǎn)環(huán)境下運(yùn)行容器。它負(fù)責(zé)調(diào)度服務(wù)、將它們置于不同的主機(jī)中,在與 ELB 關(guān)聯(lián)時(shí)零宕機(jī)重載。它甚至可以跨多個(gè) AZs,從而達(dá)到更佳可用性。如果一個(gè)容器宕機(jī)了,ECS 會(huì)確保該容器在集群中的新實(shí)例上重啟。

切換到 ECS 之后,極大地簡(jiǎn)化了運(yùn)行服務(wù)的過(guò)程,無(wú)需再擔(dān)心啟動(dòng)任務(wù)或設(shè)定實(shí)例。因?yàn)樗芎?jiǎn)單,只需要添加一個(gè) Dockerfile,設(shè)定 task,再將其與集群關(guān)聯(lián)即可。

在我們的配置中,Docker 鏡像由 CI(持續(xù)集成) 構(gòu)建,之后推送到 Docker Hub。當(dāng)某項(xiàng)服務(wù)啟動(dòng)時(shí),它從 Docker Hub 獲取鏡像,之后 ECS 在各個(gè)機(jī)器間調(diào)度之。

我們依照集群涉及的組件與負(fù)載間檔對(duì)他們分組(不同的集群用于不同的 API、CDN、App 等)。不同的集群意味著我們可見(jiàn)性更高,能為其配置不同的實(shí)例類型( ECS 沒(méi)有實(shí)例關(guān)聯(lián)度的概念)。

每項(xiàng)服務(wù)都包含一個(gè)特別的任務(wù)用于指明容器版本,運(yùn)行的實(shí)例數(shù)量,以及該選擇的集群類型。

在運(yùn)行時(shí),服務(wù)會(huì)自行注冊(cè) ELB,同時(shí)使用健康檢查確定容器是否可以運(yùn)行。我們?cè)?ELB 指定一個(gè)本地的 Route53,因此各個(gè)服務(wù)能相互通信,通過(guò) DNS 就能相互引用。

因?yàn)椴恍枰?strong>任何服務(wù)搜索,所以設(shè)置非常順利。本地的 DNS 幫助我們記錄一切。

ECS 運(yùn)行所有服務(wù),我們通過(guò) ELB 就能獲取免費(fèi)的云監(jiān)控測(cè)量數(shù)據(jù)。這比在啟動(dòng)時(shí)就要在中央注冊(cè)服務(wù)要簡(jiǎn)單的多。而且,更棒的是,我們中央不需要再面對(duì)狀態(tài)沖突了。

使用 Terraform 模板

Docker 與 ECS 負(fù)責(zé)實(shí)現(xiàn)運(yùn)行每一項(xiàng)服務(wù),Terraform 是將他們聯(lián)合在一起的膠水。在高水平上,一系列腳本負(fù)責(zé)創(chuàng)建并更新基礎(chǔ)架構(gòu)。你可以將其想作一個(gè) Cloudformaition 模版,除了它不會(huì)讓你想自戳雙目。

現(xiàn)在,無(wú)需運(yùn)行一系列服務(wù)器以維護(hù)狀態(tài),只需一些腳本用來(lái)描述集群。配置在本地運(yùn)行(未來(lái)通過(guò) CI 運(yùn)行),提交到 git 上。因此,我們能得到一系列記錄,能夠了解生產(chǎn)環(huán)境中基礎(chǔ)構(gòu)架的實(shí)際情況。

以下是我們的 Terraform 模板中設(shè)置 bastion 結(jié)點(diǎn)的樣本代碼。該代碼創(chuàng)建所有的安全組,實(shí)例和 AMI,因此我們可以簡(jiǎn)單地為未來(lái)的環(huán)境設(shè)定跳躍點(diǎn)。

// 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
}

我們?cè)陬A(yù)發(fā)布環(huán)境與生產(chǎn)環(huán)境中使用同樣的模板設(shè)置單個(gè) bastion。唯一需要修改的是 IAM 鍵。

修改也非常簡(jiǎn)單,不需要修改整個(gè)基礎(chǔ)架構(gòu),Terraform 會(huì)在需要的時(shí)候更新內(nèi)容。

當(dāng)我們要將 ELB 超時(shí)時(shí)間改為60秒時(shí),只需通過(guò) terraform apply 簡(jiǎn)單地查找/替換就好。兩分鐘之后,我們的 ELB 生產(chǎn)環(huán)境就完全改變了。

而且,這是可復(fù)制、可審計(jì)且自文檔化的,每一步都是可見(jiàn)的白盒操作。

我們將所有配置都放在一個(gè)中心的 infrastructure 庫(kù),這樣很容易看清某一項(xiàng)給定的服務(wù)是如何配置的。

到目前為止,我們還未講到核心部分。我們希望利用模板轉(zhuǎn)變更多的 Terraform 配置,聯(lián)合獨(dú)立文件從而減少共享文件的數(shù)量。

同時(shí),我們也發(fā)現(xiàn)了有關(guān) .tfstate 的一些陷阱。Terraform 總是先從現(xiàn)存的基礎(chǔ)架構(gòu)讀取數(shù)據(jù),如果狀態(tài)不同步就會(huì)報(bào)錯(cuò)。最后,我們將 .tfstate 放到庫(kù)中。我們希望能通過(guò) Atlas 或使用 CI 來(lái)解決該問(wèn)題。

使用 Datadog 監(jiān)控

至此,我們已經(jīng)搭好了基礎(chǔ)架構(gòu),開(kāi)通了服務(wù),做好了必要的隔離。最后要做的是監(jiān)控生產(chǎn)環(huán)境中所有運(yùn)行程序。

在新環(huán)境中,我們將所有的監(jiān)控和指標(biāo)都用 Datadog 進(jìn)行。不夸張的說(shuō) Datadog 真的棒極了!

我們對(duì) Datadog 的界面,API 以及其和 AWS 的整合都非常滿意。但是,想要完全利用這個(gè)工具,還需要一些關(guān)鍵的設(shè)置。

首先,我們與 AWS 和 Cloudtrail 進(jìn)行整合。這能使我們?nèi)媪私猸h(huán)境中的所有情況。由于我們已經(jīng)與 ECS 整合過(guò)了,Datadog feed 會(huì)在任務(wù)內(nèi)容更新時(shí)自動(dòng)更新,于是我們能在部署放生改變時(shí)得到免費(fèi)通知。搜索 feed 的過(guò)程也異??旖荩茌p松找到最近一次的服務(wù)部署或重新調(diào)度。

接下來(lái),我們確保將 Datadog-agent 作為 AMI 基礎(chǔ)容器(datadog/docker-dd-agent)。它不僅會(huì)從主機(jī)( CPU,內(nèi)存等)收集測(cè)量數(shù)據(jù),也作為存儲(chǔ) statsd 測(cè)量數(shù)據(jù)的容器。每一項(xiàng)服務(wù)都會(huì)收集關(guān)于查詢、潛伏、錯(cuò)誤的自定義指標(biāo),因此我們可以在 Datadog 中進(jìn)行探索,獲得警告等。我們的 go 工具箱(很快就會(huì)開(kāi)源)會(huì)自動(dòng)收集并在 ticker 輸出 pprof,因此達(dá)到監(jiān)控內(nèi)存與 goroutines 的目的。

更酷的是,該探針能夠圖形化展示環(huán)境中多個(gè)主機(jī)間的實(shí)例利用情況,因此我們能從更高角度了解可能出問(wèn)題的實(shí)例或集群:

此外,我的隊(duì)友 Vince 寫(xiě)了一個(gè)針對(duì) Datadog 的 Terraform,因此我們可以針對(duì)實(shí)際的生產(chǎn)配置設(shè)置報(bào)警腳本。我們的報(bào)警會(huì)被記錄,同時(shí)與生產(chǎn)環(huán)境中運(yùn)行的程序保持同步。

按照慣例,我們會(huì)設(shè)定兩種報(bào)警級(jí)別:預(yù)警重要警告預(yù)警使線上的工程師了解任何可疑的問(wèn)題,會(huì)在潛在問(wèn)題發(fā)生以前發(fā)出。重要警告則是會(huì)在半夜把你喊起來(lái)的嚴(yán)重系統(tǒng)宕機(jī)。

此外,當(dāng)我們完成向 Terraform 模塊的轉(zhuǎn)移,將 Datadog 提供程序加到服務(wù)描述層之后,所有的服務(wù)都會(huì)免費(fèi)獲得告警。這些數(shù)據(jù)都是由內(nèi)部工具箱與 Cloudwatch 指標(biāo)驅(qū)動(dòng)的。

讓好時(shí)光在 Docker 中繼續(xù)

當(dāng)所有的組件都準(zhǔn)備就緒后,切換的日子終于到來(lái)了。

首先,我們會(huì)在新的生產(chǎn)環(huán)境與原有環(huán)境間建立 VPC 對(duì)等連接——從而集群化數(shù)據(jù)庫(kù)并在兩者間進(jìn)行復(fù)制。

其次,我們預(yù)熱新環(huán)境中的 ELB 使之能夠承受新的負(fù)載。亞馬遜無(wú)法提供自動(dòng)更改大小的 ELB,因此我們不得不提前為其擴(kuò)容以應(yīng)對(duì)增加后的負(fù)載。

之后,我們只需使用加權(quán)的 Route53 路由平穩(wěn)地將流量從舊環(huán)境導(dǎo)向新環(huán)境,并且持續(xù)監(jiān)控確保一切正常。

現(xiàn)在,我們的 API 每秒處理成千上萬(wàn)次請(qǐng)求,并且完全運(yùn)行在 Docker 容器內(nèi)。

但是還沒(méi)完,我們還在優(yōu)化服務(wù)的創(chuàng)建方式,減少引用,使得團(tuán)隊(duì)中的任何人都能簡(jiǎn)便地創(chuàng)建服務(wù),同時(shí)包含適度的監(jiān)控與預(yù)警系統(tǒng)。此外,我們還想優(yōu)化容器周邊的工具,因?yàn)楝F(xiàn)在的服務(wù)已不再圍繞實(shí)例進(jìn)行了。

我們還會(huì)關(guān)注這一領(lǐng)域頗有發(fā)展的技術(shù)。Convox 團(tuán)隊(duì)真正創(chuàng)建圍繞 AWS 基礎(chǔ)架構(gòu)的強(qiáng)大工具。盡管我們很喜歡 ECS 的簡(jiǎn)單與集成,但 Kubernetes 、Mesosphere、 NomadFleet 這些都是非常不錯(cuò)的調(diào)度器。我們很期待看到他們的后續(xù)發(fā)展,并會(huì)考慮選擇一二進(jìn)行使用。

經(jīng)歷所有這些編排變化之后,我們比以前更加相信將基礎(chǔ)構(gòu)架外包至 AWS 的策略。他們產(chǎn)品化了許多核心服務(wù),完全改變了游戲規(guī)則,而且維持了一個(gè)極具競(jìng)爭(zhēng)力的價(jià)格。這使得越來(lái)越多的初創(chuàng)企業(yè)能夠高效、低成本低開(kāi)發(fā)產(chǎn)品,同時(shí)在維護(hù)上節(jié)省時(shí)間。我們相當(dāng)看好這些建立在基礎(chǔ)生態(tài)系統(tǒng)之上的工具。

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

OneAPM 能夠幫你查看 Python 應(yīng)用程序的方方面面,不僅能夠監(jiān)控終端的用戶體驗(yàn),還能監(jiān)控服務(wù)器性能,同時(shí)還支持追蹤數(shù)據(jù)庫(kù)、第三方 API 和 Web 服務(wù)器的各種問(wèn)題。想閱讀更多技術(shù)文章,請(qǐng)?jiān)L問(wèn) OneAPM 官方技術(shù)博客。

本文轉(zhuǎn)自 OneAPM 官方博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Docker — 云時(shí)代的程序分發(fā)方式 要說(shuō)最近一年云計(jì)算業(yè)界有什么大事件?Google Compute Engi...
    ahohoho閱讀 15,854評(píng)論 15 147
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,641評(píng)論 19 139
  • 寫(xiě)這篇文章主要是為了今后畢業(yè)論文素材上的整理,同時(shí)對(duì)docker進(jìn)行鞏固溫習(xí)。大綱: docker簡(jiǎn)介docker...
    胡圖仙人閱讀 7,775評(píng)論 2 96
  • 我們總是等到失去才會(huì)珍惜,卻不知道這次的擦肩而過(guò),會(huì)不會(huì)再見(jiàn)。 夏小詩(shī)整個(gè)高三時(shí)期都在暗戀那個(gè)男生,那個(gè)笑起來(lái)很陽(yáng)...
    梔子花開(kāi)lpy閱讀 417評(píng)論 0 0
  • 導(dǎo)讀: 1.我校機(jī)器人團(tuán)隊(duì)榮獲2017中國(guó)教育機(jī)器人大賽兩項(xiàng)一等獎(jiǎng) 2.我校召開(kāi)部分中層干部工作調(diào)整宣布會(huì) 3.黃...
    7bc7efaa2f5e閱讀 251評(píng)論 0 2

友情鏈接更多精彩內(nèi)容