過來人談容器、微服務和服務網格,其實不是新鮮事!

banq發表於2019-05-21

早在像Docker和Kubernetes這樣的容器平臺興起之前的10年,有一個dotCloud平臺,基於100多個微服務構建的平臺,支援數千個以容器執行的生產應用程式,作者將分享構建和執行它時面臨的挑戰與經驗,並討論服務網格到底有沒有用?

dotCloud

它是一個PaaS,允許客戶執行各種各樣的應用程式(Java,PHP,Python ......)。資料服務(MongoDB,MySQL,Redis ......)以及類似於Heroku的工作流程:您可以將程式碼推送到平臺,平臺將構建容器映像,並部署這些容器映像。

如何路由流量呢?部署在dotCloud上的應用程式可能會暴露HTTP和TCP端點。

HTTP端點被動態新增到Hipache負載均衡器叢集的配置中。這類似於我們今天可以通過Kubernetes Ingress資源和Traefik 等負載均衡器實現的目標。客戶端可以使用其關聯的域名連線到HTTP端點,前提是域名將指向dotCloud的負載均衡器。

TCP端點與埠號相關聯,然後通過環境變數傳遞給該堆疊的所有容器。客戶端可以使用指定的主機名(例如gateway-X.dotcloud.com)和埠號連線到TCP端點。

如果您熟悉Kubernetes,這可能會提醒您想起NodePort服務。dotCloud平臺沒有相應的ClusterIP 服務:為簡單起見,服務從平臺的內部和外部以相同的方式訪問。

HTTP和TCP路由網格的初始實現可能只有幾百行Python,使用相當簡單(我敢說,天真)的演算法,但隨著時間的推移演變以處理平臺的增長和其他要求。它不需要對現有應用程式程式碼進行大量重構。特別是十二因子應用程式可以直接使用通過環境變數提供的地址資訊。

與現代服務網格有什麼不同?

1. 可觀察性有限。TCP路由網格根本沒有度量標準。至於HTTP路由網格,後來的版本提供了詳細的HTTP指標,顯示了錯誤程式碼和響應時間; 但是現代服務網格已經超越,並提供與Prometheus等指標收集系統的整合。可觀察性不僅從運維角度(幫助我們解決問題)很重要,而且還提供安全藍/綠部署或 金絲雀部署等功能

2.路由效率也受到限制。在dotCloud路由網格中,所有流量都必須通過一組專用路由節點。這意味著可能跨越幾個AZ(可用區)邊界,並顯著增加延遲。我記得一些程式碼的疑難解答問題,這些程式碼在顯示給定頁面時發出了100多個SQL請求,併為每個請求開啟了與SQL伺服器的新連線。在本地執行時,頁面會立即載入,但在dotCloud上執行時,需要幾秒鐘,因為每個TCP連線(以及後續的SQL請求)都需要幾十毫秒才能完成。在這種特定情況下,使用持久連線就可以了。

現代服務網格比這更好。首先,確保在源處路由連線。邏輯流仍然是client → mesh → service,但現代網格是在本地執行,而不是在遠端節點上執行,因此client → mesh連線是本地連線,因此非常快(微秒而不是毫秒)。

現代服務網格還實現了更智慧的負載平衡演算法。通過監視後端的執行狀況,他們可以在更快的後端上傳送更多流量,從而提高整體效能。

現代服務網格的安全性也更強。dotCloud路由網格完全在EC2 Classic上執行,並沒有對流量進行加密。現代服務網格可以透明地保護我們的所有流量,例如通過相互TLS身份驗證和後續加密。

平臺服務的流量路由

我們已經討論了應用程式如何溝通,但是dotCloud平臺本身又如何呢?

平臺本身由大約100個微服務組成,負責各種功能。其中一些服務接受了其他人的請求,其中一些是後臺工作者,可以連線到其他服務,但不能自己接收連線。無論哪種方式,每個服務都需要知道連線所需的地址的端點。

這些服務以非常簡單粗暴的方式公開:有一個YAML檔案列出了這些服務,將它們的名字對映到它們的地址; 並且這些服務的每個使用者都需要該YAML檔案的副本作為其部署的一部分。

一方面,這非常強大,因為它不涉及維護像Zookeeper這樣的外部鍵/值儲存(記住,當時不存在etcd或Consul)。另一方面,它使得難以移動服務。每次移動服務時,其所有使用者都需要接收更新的YAML檔案(並且可能會重新啟動)。不太方便!

我們開始實施的解決方案是讓每個消費者都連線到本地代理。消費者不需要知道服務的完整地址+埠,而只需知道其埠號,然後連線即可localhost。本地代理將處理該連線,並將其路由到實際後端。現在,當後端需要移動到另一臺機器,或者按比例放大或縮小,而不是更新所有消費者時,我們只需要更新所有這些本地代理; 我們不再需要重新啟動消費者了。

這與AirBNB的SmartStack非常相似; 

我個人認為SmartStack是Istio,Linkerd,Consul Connect等系統的先驅之一......因為所有這些系統都遵循這種模式:

  • 在每個節點上執行代理
  • 消費者連線到代理
  • 控制平面在後端更改時更新代理的配置
  • ......利潤!

今天的服務網格

如果我們今天必須實現類似的網格,我們可以使用類似的原則。例如,我們可以設定內部DNS區域,將服務名稱對映到127.0.0.0/8 空間中的地址。然後在我們叢集的每個節點上執行HAProxy,接受每個服務地址(在該127.0.0.0/8子網中)的連線,並將它們轉發/負載平衡到適當的後端。HAProxy配置可以通過confd進行管理,允許在etcd或Consul中儲存後端資訊,並在需要時自動將更新的配置推送到HAProxy。

這或多或少是Istio如何運作的!但有一些差異:

  • 它使用Envoy Proxy而不是HAProxy
  • 它使用Kubernetes API而不是etcd或Consul來儲存後端配置
  • 服務在內部子網(Kubernetes ClusterIP地址)中分配地址而不是 127.0.0.0/8
  • 它有一個額外的元件(Citadel)來在客戶端和伺服器之間新增相互TLS身份驗證
  • 它增加了對斷路,分散式跟蹤,金絲雀部署等新功能的支援......

Istio vs. Linkerd vs. Consul Connect

到目前為止,我們只討論過Istio,但它並不是唯一的服務網格。Linkerd是另一個受歡迎的選擇,還有Consul Connect

我們應該選哪一個?

實說,我不知道,在這一點上,我認為自己沒有足夠的知識來幫助任何人做出這個決定。有一些有趣的 文章 比較 它們,甚至是基準

一種具有很大潛力的方法是使用像SuperGloo這樣的工具。SuperGloo提供了一個抽象層,用於簡化和統一服務網格公開的API。我們可以使用SuperGloo提供的更簡單的構造,並從一個服務網格無縫切換到另一個服務網格,而不是瞭解各種服務網格的特定(以及我認為相對複雜的)API。有點像我們有一個描述HTTP前端和後端的中間配置格式,並且能夠為NGINX,HAProxy,Traefik,Apache生成實際配置......

 

相關文章