Consul与外部服务
HashiCorp Consul是一個服務網格,用于服務發現、運行時配置和微服務應用程序和基礎設施的服務分割。Consul允許注冊和發現“內部”服務到您的基礎設施,以及“外部”服務,例如第三方SaaS提供的服務,以及其他不可能直接運行Consul代理的環境。
這篇博文解釋了如何與Consul的外部服務合作,以及如何使用Consul ESM(外部服務監視器)來對這些服務進行健康檢查。我們將介紹:
- 這個主題的關鍵術語的術語表
- 內部服務注冊和健康檢查
- 外部服務注冊和健康檢查
- 拉/推健康檢查
- 使用Consul ESM監控外部服務的健康狀況
本文中的所有示例都使用Consul agent(下載)1.2.1版本在本地以Consul ui啟用的-dev模式運行,并使用-enable-script-check標志來支持簡單的基于ping的健康檢查。我們還規定了節點名為web,而不是主機名的默認名稱,以使示例更清晰。
$ consul agent -dev -enable-script-checks -node=web -ui隨著Consul dev agent的運行,本文中的示例使用curl與Consul的HTTP API以及Consul的Web UI進行交互,在http://127.0.0.1:8500上可訪問。
這個主題的關鍵術語的術語表
- 代理(Agent): Consul集群的每個成員上的長時間運行的守護進程。代理可以在client或server模式下運行。
- 節點(Node): 節點表示運行代理的“物理”機器。這可能是一個裸露的金屬設備、VM或容器。
- 服務(Service): 服務是應用程序或進程,注冊在Consul目錄中以供發現。服務可以是內部的(在您的數據中心內)或外部的(如RDS集群),并且可以選擇與之相關聯的健康檢查。
- 檢查(Check):?檢查是一個本地運行的命令或操作,它返回附加對象的狀態。檢查可以附加到節點和服務上。
- 目錄(Catalog): 目錄是所有已注冊節點、服務和檢查的注冊中心。
內部服務注冊和健康檢查
首先,我們來看看如何注冊內部服務。在Consul的上下文中,內部服務是由Consul代理可以直接運行的節點(機器)提供的。
內部服務通過服務定義注冊。服務定義可以由Consul代理啟動時加載的配置文件提供,也可以通過/agent/service/register的本地HTTP API端點提供。
我們將用以下配置注冊一個內部web示例,web.json:
{"id": "web1","name": "web","port": 80,"check": {"name": "ping check","args": ["ping","-c1","www.google.com"],"interval": "30s","status": "passing"} }這個示例web服務將具有惟一的id web1、邏輯名稱web、運行在端口80上并進行一次健康檢查。
通過使用PUT請求調用HTTP API來注冊示例web服務:
$ curl --request PUT --data @web.json localhost:8500/v1/agent/service/register要驗證示例web服務已注冊上去,請查詢/catalog/service/:service 端點:
$ curl localhost:8500/v1/catalog/service/web [{"ID": "a2ebf70e-f912-54b5-2354-c65e2a2808de","Node": "web","Address": "127.0.0.1","Datacenter": "dc1","TaggedAddresses": {"lan": "127.0.0.1","wan": "127.0.0.1"},"NodeMeta": {"consul-network-segment": ""},"ServiceID": "web1","ServiceName": "web","ServiceAddress": "","ServiceMeta": {},"ServicePort": 80,"ServiceEnableTagOverride": false,"CreateIndex": 7,"ModifyIndex": 7} ]向 agent/service/register 端點注冊服務定義將本地節點注冊為服務提供者。節點上的本地Consul代理負責為注冊的服務進行健康檢查,并相應地更新目錄。
在我們的示例web服務中,我們使用以下配置定義了一個健康檢查:
"check": {"name": "ping check","args": ["ping","-c1","www.google.com"],"interval": "30s","status": "passing"}這個健康檢查驗證我們的web服務可以通過每30秒ping一次 google.com連接到公共互聯網。對于實際的web服務,應該配置更有用的健康檢查。Consul提供幾種健康檢查方式,包括:腳本,HTTP, TCP,存活時間(TTL), Docker,和gPRC。
要檢驗為注冊到給定本地節點的服務配置的所有健康檢查,請使用/agent/checks/ 端點:
$ curl localhost:8500/v1/agent/checks {"service:web1": {"Node": "web","CheckID": "service:web1","Name": "ping check","Status": "passing","Notes": "","Output": "PING www.google.com (172.217.3.164): 56 data bytes\n64 bytes from 172.217.3.164: icmp_seq=0 ttl=52 time=21.902 ms\n\n--- www.google.com ping statistics ---\n1 packets transmitted, 1 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 21.902/21.902/21.902/0.000 ms\n","ServiceID": "web1","ServiceName": "web","ServiceTags": ["rails"],"Definition": {},"CreateIndex": 0,"ModifyIndex": 0} }可以使用/health/service/:service 查詢單個服務的健康狀況,使用/health/node/:node 查詢單個節點的健康狀態。
健康檢查也可以在Consul UI上查看:
外部服務注冊和健康檢查
在Consul的上下文中,外部服務是由不能運行Consul代理的節點提供的服務。這些節點可能位于基礎設施內部(例如大型機、虛擬設備或不支持的平臺)或基礎設施外部(例如SaaS平臺)。
因為根據定義,外部服務在沒有運行Consul代理的節點上運行,因此無法向本地代理注冊。相反,它們必須使用/catalog/register端點 ?直接與目錄一起注冊。這個端點的對象上下文是節點,而不是像/agent/service/register 端點那樣的服務。當使用/catalog/register端點時,將注冊整個節點。而使用/agent/service/register 端點(這是我們在上面的第一個例子中使用的端點),本地節點上下文中的單個服務被注冊。
直接通過目錄注冊的外部服務的配置與通過代理注冊的內部服務的配置略有不同:
- 節點(Node)和地址(Address)都是必需的,因為它們不能從本地節點Consul代理自動確定。
- 服務(Service)和健康檢查(Checks)是分開定義的。
- 如果提供的ServiceID與該節點上的服務ID匹配,則該檢查將被視為服務級健康檢查,而不是節點級健康檢查。
- 可以為Definition 字段提供TCP或HTTP健康檢查的詳細信息。有關更多信息,請參閱健康檢查。
要演示外部服務注冊是如何工作的,請考慮谷歌提供的外部搜索服務。我們用以下配置來注冊這個服務,extern.json:
{"Node": "google","Address": "www.google.com","NodeMeta": {"external-node": "true","external-probe": "true"},"Service": {"ID": "search1","Service": "search", "Port": 80},"Checks": [{"Name": "http-check","status": "passing","Definition": {"http": "https://www.google.com","interval": "30s"}}] }該配置定義了一個名為google 的節點,可以在地址www.google.com上訪問,該節點提供一個search服務,ID為search1,運行在端口80上。它還定義了每30秒運行一次的http類型健康檢查,并設置了該檢查的初始狀態 passing。
通常,外部服務是通過專門用于此目的的節點注冊的,因此我們將繼續使用Consul dev代理(localhost)進行示例,就好像它是在和內部web服務(例如“Web”)不同的另一個節點(例如“External Services”)上運行一樣。
下面這張圖顯示了向Consul注冊內部和外部服務之間的區別:
使用PUT請求注冊外部服務:
$ curl --request PUT --data @external.json localhost:8500/v1/catalog/register true與通過代理端點注冊的內部服務一樣,我們可以通過查詢/catalog/service/:service 端點來驗證外部服務的注冊:
$ curl localhost:8500/v1/catalog/service/search [{"ID": "","Node": "google","Address": "www.google.com","Datacenter": "dc1","TaggedAddresses": null,"NodeMeta": {"external-node": "true","external-probe": "true"},"ServiceID": "search1","ServiceName": "search","ServiceTags": [],"ServiceAddress": "","ServiceMeta": {},"ServicePort": 80,"ServiceEnableTagOverride": false,"CreateIndex": 246,"ModifyIndex": 246} ]在我們的內部web服務示例中,我們通過查詢本地代理端點 /agent/checks 來驗證健康檢查是活躍的。如果在添加外部服務之后再次查詢此內容,我們將不會看到列出的健康檢查,因為它是在服務目錄中注冊的,而不是本地代理。相反,我們需要查詢目錄級端點,例如/health/service/:service、/health/node/:node、/health/state/:state。
我們還可以看到Consul UI中列出的服務和健康檢查:
從上面可以看到,目錄中有一個健康檢查條目。但是,因為這個節點和服務是直接在目錄中注冊的,所以沒有設置實際的健康檢查,也不會監視節點的健康狀況。
為了演示直接通過目錄注冊的健康檢查與通過本地代理注冊的健康檢查之間的區別,可以在模擬停機前后查詢節點健康狀況。
要模擬停機,請斷開與internet的連接,稍等片刻,并檢查Consul UI:
在上面的輸出中,我們看到內部web服務的不再通過健康檢查,但是在不應該看到外部search服務通過健康檢查時,卻看到健康檢查通過了(passing)。在斷開internet連接時,這兩個服務的健康檢查都應該失敗,但只有對內部web服務的檢查顯示為失敗。
拉和推健康檢查
傳統健康檢查的一個問題是拉動式模型的使用。定期,監視服務器詢問所有節點是否健康,節點以狀態響應。這就造成了瓶頸,因為隨著節點數量的增加,監視服務的流量也在增加。這會阻塞本地網絡流量,并給集群帶來不必要的負載。
Consul使用一個基于推送的模型,其中代理僅在狀態更改時發送事件。因此,即使是大型集群也只有很少的請求。邊緣觸發監測的問題是沒有活性心跳。也就是說,在沒有任何更新的情況下,Consul不知道檢查是否處于穩定狀態,或者服務器是否死亡。Consul通過使用基于gossip協議的故障檢測器來解決這個問題。所有集群成員都參與一個后臺gossip,不管集群大小如何,這個gossip都有一個恒定的負載。gossip和edge觸發的更新的組合允許Consul擴展到非常大的集群大小,而不需要重載。
因為Consul monitoring 要求Consul代理在被監視的服務上運行,所以不會對外部服務執行健康檢查。要啟用外部服務的健康監視,請使用Consul External Service Monitor(ESM)。
使用Consul ESM監控外部服務
Consul ESM是一個與Consul一起運行的守護進程,用于運行外部節點的健康檢查并更新目錄中那些健康檢查的狀態。ESM的多個實例可以運行以獲得可用性,并且ESM將通過持有一個Consul中的鎖來執行領導人選舉。然后,領導者將繼續監視Consul對目錄的更新,并執行在它發現的任何外部節點上定義的健康檢查。這允許外部注冊的服務和檢查訪問與Consul代理在本地注冊相同的功能。
與先前的圖表更新顯示Consul ESM如何與Consul合作監測外部服務的健康狀況:
Consul ESM是作為一個單一的二進制文件提供的。要安裝,請下載適合您系統的版本,并使其在您的路徑中可用。本文中的示例使用Consul ESM v0.2.0。
打開一個新的終端,執行 consul-esm啟用Consul ESM。
$ consul-esm2018/06/14 12:50:44 [INFO] Connecting to Consul on 127.0.0.1:8500... Consul ESM running!Datacenter: (default)Service: "consul-esm"Leader Key: "consul-esm/lock" Node Reconnect Timeout: "72h0m0s"Log data will now stream in as it occurs:2018/06/14 12:50:44 [INFO] Waiting to obtain leadership... 2018/06/14 12:50:44 [INFO] Obtained leadership如果您的internet提供者不允許UDP ping,為了使本文中的示例正常工作,您可能需要在配置文件中設置ping_type = "socket",并使用該配置文件啟動consult -esm。如果你正在使用macOS,你將需要執行sudo:
$ sudo consul-esm -config-file=./consul-esm.hcl示例外部服務定義中包含以下節點元數據(NodeMeta),這些元數據使Consul ESM能夠進行健康監視:
- “external-node”標識該節點是Consul ESM應該監視的外部節點。
? - “external-probe”:“true”告訴Consul ESM定期對節點執行ping,并維護節點的外部節點健康檢查(類似于Consul代理使用的serfHealth檢查)。
一旦Consul ESM運行,再次模擬從互聯網連接中斷。現在,在Consul UI中,可以看到我們的外部服務的健康檢查更新為critical 狀態:
Consul ESM支持HTTP和TCP健康檢查。Ping健康檢查自動添加了"external-probe": "true".
總結
Consul內部服務是由直接運行Consul代理的節點提供的服務。外部服務是由不能運行Consul代理的節點提供的服務。
內部服務通過本地Consul代理在服務定義中注冊。節點上的本地Consul代理負責運行為服務注冊的任何健康檢查,并相應地更新目錄。外部服務必須直接與目錄注冊,因為根據定義,它們在沒有Consul代理的節點上運行。
內部和外部服務都可以進行健康檢查。Consul的健康檢查使用基于推送的模型,其中代理僅在狀態更改時發送事件。Consul提供幾種健康檢查,包括:腳本,HTTP, TCP,TTL, Docker,和gPRC。因為Consul監視要求Consul代理在被監視的服務上運行,所以不會對外部服務執行健康檢查。要啟用外部服務的健康監視,請使用Consul External Service Monitor (ESM)。
總結
以上是生活随笔為你收集整理的Consul与外部服务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用HashiCorp Nomad按需分
- 下一篇: Consul负载均衡策略