本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
在 VPC 中連接 Amazon ECS 服務的最佳實務
您可以在 VPC 中使用 Amazon ECS 任務,將單體式應用程式分割成可在安全環境中獨立部署與擴展的獨立元件。此架構即稱為服務導向架構 (SOA) 或微服務。然而,要確保 VPC 內外的所有元件都能相互通訊,可能具有挑戰性。實現通訊的方法有多種,每種方法都有不同的優勢與劣勢。
使用 Service Connect
建議使用 Service Connect,其可提供 Amazon ECS 組態,用於服務探索、連線與流量監控。透過 Service Connect,您的應用程式可以使用短名稱與標準連接埠,連線至相同叢集、其他叢集 (包括同一區域內跨 VPC 的叢集) 中的服務。如需詳細資訊,請參閱 Amazon ECS Service Connect。
當您使用 Service Connect 時,Amazon ECS 將管理服務探索的所有環節:建立可被探索的名稱、在任務啟動與停止時動態管理每個任務的項目、在每個已設定為可探索這些名稱的任務中執行代理程式。應用程式可透過 DNS 名稱的標準功能查詢這些名稱並建立連線。若應用程式已具備此能力,則您無需修改應用程式即可使用 Service Connect。
變更僅會在部署期間發生
您需在每個服務與任務定義內提供完整的組態。Amazon ECS 會在每次服務部署時管理此組態的變更,確保統一部署中的所有任務行為一致。例如,使用 DNS 作為服務探索機制時,常見問題在於遷移過程難以控制。若變更 DNS 名稱指向的新替代 IP 位址,可能需要等待最長 TTL 時間,所有用戶端才會開始使用新服務。而透過 Service Connect,用戶端部署會透過取代用戶端任務來更新組態。您可以設定部署斷路器及其他部署組態,使 Service Connect 的變更與任何其他部署一樣受到同等管控。
使用服務探索
服務間通訊的另一種方法是使用服務探索進行直接通訊。在此方法中,您可以使用 AWS Cloud Map 服務探索與 Amazon ECS 的整合。使用服務探索,Amazon ECS 會將啟動的任務清單同步至 AWS Cloud Map,這會維護 DNS 主機名稱,以解析該特定服務中一或多個任務的內部 IP 地址。Amazon VPC 中的其他服務可使用此 DNS 主機名稱,透過容器的內部 IP 位址直接向另一個容器傳送流量。如需詳細資訊,請參閱服務探索。
上圖中共有三個服務。service-a-local 包含一個容器,需與包含兩個容器的 service-b-local 通訊。service-b-local 必須與包含一個容器的 service-c-local 通訊。所有三個服務中的每個容器都可以使用來自 的內部 DNS 名稱 AWS Cloud Map ,從其需要通訊的下游服務尋找容器的內部 IP 地址。
這種服務間通訊方法的延遲較低。乍看之下,這種方式同樣簡單,因為容器之間沒有額外元件。流量會從一個容器直接傳送至另一個容器。
此方法適用於採用 awsvpc 網路模式的場景,該模式下每個任務都有專屬的唯一 IP 位址。大多數軟體僅支援使用 DNS A 記錄,這些記錄會直接解析為 IP 位址。使用 awsvpc 網路模式時,每個任務的 IP 位址都是 A 記錄。不過,如果您使用 bridge 網路模式,多個容器可能會共用同一個 IP 位址。此外,動態連接埠映射會導致容器在該單一 IP 位址上隨機指派連接埠號碼。至此,僅靠 A 記錄已不足以滿足服務探索需求。您必須同時使用 SRV 記錄。這種類型的記錄可以追蹤 IP 位址與連接埠號碼,但要求對應用程式進行相應設定。您使用的某些預先建置的應用程式可能不支援 SRV 記錄。
awsvpc 網路模式的另一項優勢,是每個服務都會擁有唯一的安全群組。您可以設定此安全群組,使其僅允許需要與該服務通訊的特定上游服務建立連入連線。
使用服務探索實現服務間直接通訊的主要劣勢在於,您必須實作額外邏輯來處理重試機制與連線失敗問題。DNS 記錄具有存留時間 (TTL) 設定,可控制記錄的快取存留時長。DNS 記錄的更新與快取失效需要一定時間,才能讓應用程式取得最新版本的 DNS 記錄。因此,應用程式最終可能會將 DNS 記錄解析至已不存在的另一個容器。應用程式需要處理重試,並具有忽略不良後端的邏輯。
使用內部負載平衡器
服務間通訊的另一種方法是使用內部負載平衡器。內部負載平衡器完全存在於 VPC 內,且僅供 VPC 內部的服務存取。
負載平衡器透過將備援資源部署至每個子網路來維持高可用性。當 serviceA 中的容器需要與 serviceB 中的容器通訊時,會開啟與負載平衡器的連線。然後,負載平衡器會開啟與 service B 中容器的連線。負載平衡器可作為管理每個服務之間所有連線的集中位置。
如果 serviceB 中的容器停止,則負載平衡器可以從集區中移除該容器。負載平衡器也會針對其集區中的每個下游目標執行運作狀態檢查,並可自動從集區中移除不良目標,直至這些目標恢復正常運作。應用程式不再需要知道有多少個下游容器,只要開啟與負載平衡器的連線。
此方法對所有網路模式都具有優勢。負載平衡器可以在使用 awsvpc 網路模式時追蹤任務 IP 位址,也可以在使用 bridge 網路模式時追蹤更進階的 IP 位址與連接埠組合。其將流量平均分配發至所有 IP 位址與連接埠組合,即使多個容器實際上託管於同一 Amazon EC2 執行個體上,只是使用不同的連接埠。
此方法的一個劣勢是成本較高。若要做到高度可用,負載平衡器需要在每個可用區域中擁有資源。這會增加額外成本,因為需負擔負載平衡器本身的開銷,以及流經負載平衡器的流量所產生的費用。
不過,您可透過讓多個服務共用一個負載平衡器來降低間接成本。這種做法特別適合使用 Application Load Balancer 的 REST 服務。您可以建立路徑型路由規則,將流量路由至不同的服務。例如,/api/user/* 可能會路由至屬於 user 服務的容器,而 /api/order/* 可能會路由至相關聯的 order 服務。使用此方法,您只需支付一個 Application Load Balancer 的費用,並為您的 API 準備一個一致的 URL。不過,您仍可將流量分流至後端的各個微服務。