etcd 笔记(04)— etcd 网关与 gRPC 网关
1. etcd 網關
etcd 網關是一個簡單的 TCP 代理,可將網絡數據轉發到 etcd 集群。網關是無狀態且透明的,它既不會檢查客戶端請求,也不會干擾集群響應,支持多個 etcd 服務器實例,并采用簡單的循環策略。
etcd 網關將請求路由到可用端點,并向客戶端隱藏故障,使得客戶端感知不到服務端的故障。
1.1 適用場景
我們使用客戶端連接到 etcd 服務器時,每個訪問 etcd 的應用程序必須知道所要訪問的 etcd 集群實例的地址,即用來提供客戶端服務的地址:ETCD_LISTEN_CLIENT_URLS。
如果同一服務器上的多個應用程序訪問相同的 etcd 集群,每個應用程序仍需要知道 etcd 集群的廣播的客戶端端點地址。如果將 etcd 集群重新配置,擁有不同的端點,那么每個應用程序還需要更新其端點列表。在大規模集群環境下,重新配置的操作既造成了重復又容易出錯。
以上問題,都可以通過 etcd 網關來解決:
- 使用
etcd網關作為穩定的本地端點,對于客戶端應用程序來說,不會感知到集群實例的變化。 - 典型的
etcd網關配置是使每臺運行網關的計算機在本地地址上偵聽,并且每個etcd應用程序都連接對應的本地網關,發生etcd集群實例的變更時,只需要網關更新其端點,而不需要更新每個客戶端應用程序的代碼實現。
1.2 不適用場景
- 性能提升
etcd 網關不是為提高 etcd 集群性能設計的。它不提供緩存、watch 流合并或批量處理等功能。
- 在集群上運行管理系統
類似 Kubernetes 的高級集群管理系統本身支持服務發現。應用程序可以使用系統默認的 DNS 名稱或虛擬 IP 地址訪問 etcd 集群。例如,負責為 Service 提供 Cluster 內部的服務發現和負載均衡的 Kube-proxy 其實等效于 etcd 網關的職能。
總而言之,為了自動傳播集群端點更改,etcd 網關在每臺機器上都運行,為多個應用提供訪問相同的 etcd 集群服務。
2. gRPC 網關
gRPC-Gateway 為非 gRPC 的客戶端提供 HTTP 接口。
etcd v3 使用 gRPC 作為消息傳輸協議。
etcd 項目中包括了基于 gRPC 的 Go client 和命令行工具 etcdctl,客戶端通過 gRPC 框架與 etcd 集群通訊。對于不支持 gRPC 的客戶端語言,etcd 提供 JSON 的 gRPC-Gateway,通過 gRPC-Gateway 提供 RESTful 代理,轉換 HTTP/JSON 請求為 gRPC 的 Protocol Buffer 格式的消息。
這里你需要注意的是,在 HTTP 請求體中的 JSON 對象,其包含的 key 和 value 字段都被定義成了 byte 數組,因此必須在 JSON 對象中,使用 base64 編碼對內容進行處理。
2.1 etcd 版本與 gRPC-Gateway 接口對應的關系
gRPC-Gateway 提供的接口路徑自 etcd v3.3 已經變更:
-
etcd v3.2及之前的版本只能使用[CLIENT-URL]/v3alpha/*接口; -
etcd v3.3使用CLIENT-URL/v3alpha/*; -
etcd v3.4使用CLIENT-URL/v3beta/,且廢棄了[CLIENT-URL]/v3alpha/; -
etcd v3.5只使用CLIENT-URL/v3beta/;
通過上面的接口與 etcd 版本的對應關系,你可以看到,即使是 v3 版本下的 API,gRPC-Gateway 提供的接口路徑在內部細分的版本下也有不同,所以需要注意當前正在使用的 etcd 版本。
2.2 鍵值對讀寫操作
如果沒有使用 base64 對鍵值對進行編碼,那么會報以下錯誤:
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/kv/put -X POST -d '{"key": "/demo", "value": "AAA"}'
{"error":"illegal base64 data at input byte 4","message":"illegal base64 data at input byte 4","code":3}
對其進行 base64 編碼
demo字符串的base64編碼結果為ZGVtbw==AAA字符串的base64編碼結果為QUFB
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/kv/put -X POST -d '{"key": "ZGVtbw==", "value": "QUFB"}'
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"26","raft_term":"3"}}
接著,我們通過 /v3/kv/range 接口,來讀取剛剛寫入的鍵值對:
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/kv/range -X POST -d '{"key": "ZGVtbw=="}'
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"26","raft_term":"3"},"kvs":[{"key":"ZGVtbw==","create_revision":"26","mod_revision":"26","version":"1","value":"QUFB"}],"count":"1"}
當我們想要獲取前綴為指定值的鍵值對時,可以使用如下請求:
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/kv/range -X POST -d '{"key": "ZGVtbw==", "range_end": "Zm9w"}'
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"26","raft_term":"3"},"kvs":[{"key":"ZGVtbw==","create_revision":"26","mod_revision":"26","version":"1","value":"QUFB"}],"count":"1"}
因為只有一個值,所以返回正確。
2.3 watch 鍵值
etcd 中提供了 /v3/watch 接口來監測 keys,我們來 watch 剛剛寫入的 ZGVtbw==,請求如下所示:
curl -N http://localhost:2379/v3/watch -X POST -d '{"create_request": {"key":"ZGVtbw=="}}'
然后另開一個窗口,執行以下命令
etcdctl put demo 123
查看 watch 結果輸出:
wohu@ubuntu:~$ curl -N http://localhost:2379/v3/watch -X POST -d '{"create_request": {"key":"ZGVtbw=="} }'
{"result":{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"26","raft_term":"3"},"created":true}}
{"result":{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"27","raft_term":"3"},"events":[{"kv":{"key":"ZGVtbw==","create_revision":"26","mod_revision":"27","version":"2","value":"MTIz"}}]}}
當寫入鍵值后,觸發了監測事件的發生,控制臺輸出了時間的細節。HTTP 請求客戶端與 etcd 服務端建立長連接,當監聽的鍵值對發生變更時,便會將事件通知給客戶端。
2.4 HTTP 請求的安全認證
HTTP 的方式訪問 etcd 服務端,需要考慮安全的問題,gRPC-Gateway 中提供的 API 接口支持開啟安全認證。通過 /v3/auth 接口設置認證,需要實現以下 4 個步驟:
- 創建用戶
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/auth/user/add -X POST -d '{"name": "root", "password": "123456"}'
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"27","raft_term":"3"}}
- 創建角色
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/auth/role/add -X POST -d '{"name": "root"}'
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"27","raft_term":"3"}}
- 用戶授予角色
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/auth/user/grant -X POST -d '{"user": "root", "role": "root"}'
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"27","raft_term":"3"}}
- 開啟認證權限
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/auth/enable -X POST -d '{}'
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"27","raft_term":"3"}}
如上的請求中,我們首先創建了 root 用戶和角色,將 root 角色賦予到 root 用戶,這樣就可以開啟用戶的權限。接下來就是進行身份驗證,并進行 HTTP 訪問。流程如下圖所示:
使用 /v3/auth/authenticate API 接口對 etcd 進行身份驗證以獲取身份驗證令牌:
wohu@ubuntu:~$ curl -L http://localhost:2379/v3/auth/authenticate -X POST -d '{"name": "root", "password": "123456"}'
{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"27","raft_term":"3"},"token":"BGQDrdEVPaGQBCGh.51"}
請求獲取到 token 的值為 BGQDrdEVPaGQBCGh.51。接下來,設置請求的頭部 Authorization 為剛剛獲取到的身份驗證令牌,以使用身份驗證憑據設置 key 值:
curl -L http://localhost:2379/v3/kv/put -H 'Authorization:BGQDrdEVPaGQBCGh.51' -X POST -d '{"key": "ZGVtbw==", "value": "QUFB"}'
如果 token 不合法會報錯誤:
{"error":"etcdserver: invalid auth token","message":"etcdserver: invalid auth token","code":16}
etcd gRPC-Gateway 中提供的 API 接口還有諸如 /v3/auth/role/delete、/v3/auth/role/get 等其他接口,請參考 官網
3. 總結
-
etcd網關通常用于etcd集群的門戶,是一個簡單的TCP代理,將客戶端請求轉發到etcd集群,對外屏蔽了etcd集群內部的實際情況,在集群出現故障或者異常時,可以通過etcd網關進行切換; -
gRPC-Gateway則是對于etcd的gRPC通信協議的補充,有些語言的客戶端不支持gRPC通信協議,此時就可以使用gRPC-Gateway對外提供的HTTP API接口。通過HTTP請求,實現與gRPC調用協議同樣的功能。
總結
以上是生活随笔為你收集整理的etcd 笔记(04)— etcd 网关与 gRPC 网关的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国氧化铟锡薄膜行业
- 下一篇: 2022-2028年中国ITO薄膜行业市