原文鏈接: https://trainyao.github.io/post/gloo/gloo_in_non_kubernetes_env_gateway_01/
本系列文章主要介紹了在非 kubernetes 環(huán)境,使用 gloo 搭建服務(wù)網(wǎng)關(guān)的過程靠汁,以及 gloo 的簡單的使用指南。
系列文章目錄如下:
- 使用 gloo 在非 kubernetes 環(huán)境搭建服務(wù)網(wǎng)關(guān)指南 - 初識 gloo(本篇)
- 使用 gloo 在非 kubernetes 環(huán)境搭建服務(wù)網(wǎng)關(guān)指南 - 路由能力: tcp / http
- 使用 gloo 在非 kubernetes 環(huán)境搭建服務(wù)網(wǎng)關(guān)指南 - 路由能力: grpc
- 使用 gloo 在非 kubernetes 環(huán)境搭建服務(wù)網(wǎng)關(guān)指南 - envoy 高可用、錯誤注入苏章、超時控制请垛、熔斷
- 使用 gloo 在非 kubernetes 環(huán)境搭建服務(wù)網(wǎng)關(guān)指南 - 指標(biāo)監(jiān)控暑椰、報警
- 使用 gloo 在非 kubernetes 環(huán)境搭建服務(wù)網(wǎng)關(guān)指南 - 鏈路跟蹤
- 使用 gloo 在非 kubernetes 環(huán)境搭建服務(wù)網(wǎng)關(guān)指南 - 權(quán)限餐抢、流控
首先: 使用非 kubernetes 環(huán)境意義何在?
-
調(diào)試快速
gloo 文檔內(nèi)的教程內(nèi)容比較多的偏重在 kubernetes 環(huán)境下操作 gloo堵幽,而在調(diào)試 gloo 功能特性的過程中搭建個人 kubernetes 集群還是有一定成本的。
然而弹澎,docker-compose/docker run 的方式很直接也比較快速,而且在實踐過程中也發(fā)現(xiàn)努咐,基于 gloo 官方文檔內(nèi)的 kubernetes 操作是可以等價遷移過去 docker-compose + consul 的操作的苦蒿。 -
技術(shù)方案過渡
實際使用場景中并非都能在 k8s 集群上部署服務(wù)(雖然使用 k8s 作為容器編排是大勢所趨),docker-compose + consul 提供一種另外的解決方案作為技術(shù)方案過渡渗稍。
-
學(xué) envoy
gloo 的強大功能基于 envoy 的能力佩迟。在使用 gloo 的過程中驗證配置是否正常团滥,很多時候需要去看最后作用于 envoy 的配置是否正常,借此可以熟悉 envoy 的配置报强。
那么灸姊,就來開始系列的第一篇: 初識 gloo :-)。
本系列文章的源碼將放在這里
1. gloo 是什么
gloo 是 solo 公司的一個開源產(chǎn)品秉溉,它可以看作是 envoy 的一個控制面板力惯。
envoy 是一個功能強大的4層&7層代理,它性能較好召嘶、可擴展性強父晶,也比較穩(wěn)定。由于它基于 http2 協(xié)議弄跌,所以它在7層上支持 rest甲喝、grpc 協(xié)議的路由功能。它能夠被用作服務(wù)的邊界網(wǎng)關(guān)铛只,而且由于比較穩(wěn)定埠胖,且系統(tǒng)資源占用較少,也被用作微服務(wù)里的服務(wù)邊車(比如在 istio 里)淳玩,與業(yè)務(wù)服務(wù)一起部署直撤。
envoy 的功能如此強大,以致它的配置也比較復(fù)雜凯肋。gloo 在 envoy 的上層建立了一個控制面板谊惭,將自己抽離的一些業(yè)務(wù)對象(比如下面會提及的 proxy virtualserivce 等)轉(zhuǎn)換成 envoy 的配置并且加以維護(hù)。用戶只需操作 gloo 抽離的這些對象即可配置網(wǎng)關(guān)侮东,而不需要考慮 envoy 的復(fù)雜配置圈盔。這樣的中間層是有好處的,比如后續(xù)想要更換代理實現(xiàn)(比如 nginx悄雅,或者 mosn)驱敲,也可以將 envoy 更換掉,而翻譯配置的模塊只需改寫成從翻譯 envoy 的配置為翻譯新代理實現(xiàn)即可宽闲。
在真實工程環(huán)境中众眨,使用 envoy 作為網(wǎng)關(guān)或者邊車是一個不錯的選擇。但 envoy 的復(fù)雜配置增加了不少使用維護(hù)成本容诬,最終你有可能會建立一個類似 gloo 的控制面板娩梨,滿足工程需求。既然如此何不使用和擴展 gloo 呢览徒?:)
2. gloo 里的概念
xds
為了與 envoy 交互狈定,gloo 里帶有了一個 xds 服務(wù)。xds 是配置 envoy 的協(xié)議,如上文所屬纽什,gloo 會將內(nèi)部業(yè)務(wù)對象翻譯成 envoy 的配置措嵌,翻譯后的配置就是通過 xds 協(xié)議與 envoy 交互的。
gateway
gateway 是服務(wù)的入口芦缰,可以看做代理服務(wù)里的 listener企巢,具體表現(xiàn)為監(jiān)聽某個端口作為流量的入口,進(jìn)行4让蕾、7層的路由分發(fā)浪规。
gateway 對象是用戶可以配置的蝙泼。
virtual service
virtual service 可以理解成代理提供的虛擬服務(wù)针史,它是一個7層概念。virtual service 對象可以配置 "host" 字段的流量分發(fā)挠将,當(dāng)流量從 gateway 監(jiān)聽的端口進(jìn)來再姑,帶不同的 "host" 字段的流量能被路由到不同的后端服務(wù)中萌抵,對外看起來就像不同域名提供了不同的服務(wù)。
在 gloo 中元镀,virtual service 對象也可以配置不同功能的路由绍填,比如根據(jù) path 路由、根據(jù) header 路由栖疑,也可以配置錯誤注入讨永、熔斷等功能,可以說7層功能的配置基本上都在 virtual service 對象上完成遇革。
virtual service 對象也是用戶可以配置的卿闹。
proxy
proxy 對象是 gloo 翻譯組件根據(jù) gateway 和 virtual service 對象翻譯出來的。被用作 xds 服務(wù)讀取并翻譯成 envoy 配置萝快。
對于 proxy 對象锻霎,用戶是不需要也不應(yīng)該配置的。
它的內(nèi)容實際上等價于 gateway + virtual service 對象的內(nèi)容揪漩。
在架構(gòu)設(shè)計角度上旋恼,proxy 對象也可以看作是 gloo 翻譯組件和 xds 服務(wù)的中間層:翻譯組件應(yīng)該將待翻譯的內(nèi)容(比如 gateway、virtual service等)翻譯成 proxy 對象奄容,而 xds 服務(wù)以 proxy 對象為標(biāo)準(zhǔn)冰更,翻譯 envoy 配置。這意味著昂勒,在 gloo 里蜀细,gateway、virtual service 這類與用戶打交道的配置是可以擴展和替換的戈盈,gloo 只要求奠衔,擴展替換后與翻譯組件合作的結(jié)果 = proxy 對象即可。
downstream
downstream 可以理解為請求方。
gloo 里沒有 downstream 對象涣觉。
upstream
upstream 可以理解為后端真正提供業(yè)務(wù)邏輯的服務(wù)。
upstream 對象也是無需用戶配置的血柳,gloo 內(nèi)置服務(wù)發(fā)現(xiàn)組件官册,通過監(jiān)聽服務(wù)注冊(如 k8s 內(nèi)的 service、consul 里的 service)來生成 upstream 對象难捌,供 xds 服務(wù)讀取并生成 envoy 配置膝宁。
3. gloo 的架構(gòu)
(上圖來自 gloo 文檔)
上述架構(gòu)圖基本上能和第二部分講到的概念對應(yīng)上:
- xds server = xds 組件
- translation engine + config watcher = 翻譯組件,它監(jiān)聽存儲層的配置根吁,翻譯成 proxy 對象供 xds 服務(wù)使用员淫。用戶通過操作存儲層(如經(jīng)過 glooctl 命令行工具,或者直接修改存儲層配置)配置 gateway击敌、virtual service 等與用戶打交道的配置對象介返。
- endpoint discovery = 服務(wù)發(fā)現(xiàn)組件
4. 非 k8s 環(huán)境運行 gloo 與在 k8s 環(huán)境運行的異同
首先,本系列文章在非 k8s 環(huán)境下使用 gloo 主要是基于 gloo 源碼下的 install/docker-compose-consul 安裝方式來使用沃斤,可以看出圣蝎,是基于 docker-compose + consul 來運行的。
在使用上很多地方其實可以對應(yīng)到 k8s 環(huán)境下的實現(xiàn)衡瓶。
異同點分下列點講述:
-
存儲層 & 用戶操作
在 k8s 環(huán)境里徘公,配置存儲主要依賴 k8s 本身的配置存儲,即 etcd + k8s crd 概念哮针。而在非 k8s 環(huán)境下关面,consul 就成為了配置中心的位置。
那么在 k8s 環(huán)境下通過操作 crd 來修改配置十厢,對應(yīng)過來就是修改 consul 里的 kv 對象了等太。
在 consul 作為存儲層的實現(xiàn)中,gloo 也為我們規(guī)劃好了文件目錄寿烟。
consul-kv.jpg從上圖看到澈驼,gloo 的配置信息在 consul kv 里用不同的文件目錄進(jìn)行規(guī)劃,與用戶打交道的放在
gateway.solo.io
筛武,而 xds 服務(wù)用到的放在gloo.solo.io
(其實也可以看作是根據(jù)監(jiān)聽的組件來安排文件目錄缝其,在 docker-compose + consul 實現(xiàn)中,gateway.solo.io
目錄會被 gateway 組件監(jiān)聽徘六,而 gateway 組件就是上文說的 "翻譯組件"内边,gloo.solo.io
目錄會被 gloo 組件監(jiān)聽,而 gloo 組件就是上文說的 "xds 服務(wù)")待锈。 -
服務(wù)注冊 & 服務(wù)發(fā)現(xiàn)
在 k8s 環(huán)境里漠其,服務(wù)發(fā)現(xiàn)自然是監(jiān)聽 k8s 的 service crd 的變化,而在 consul 實現(xiàn),利用的是 consul 的服務(wù)注冊功能和屎。
gloo 的服務(wù)發(fā)現(xiàn)組件會監(jiān)聽 consul 的服務(wù)注冊拴驮,并生成對應(yīng)的 upstream 對象。而對于服務(wù)注冊柴信,k8s 環(huán)境下就是自然的創(chuàng)建 service 對象套啤,在 consul 環(huán)境下就是將服務(wù)注冊到 consul 里。
-
envoy 高可用
對于 envoy 的高可用随常,在 k8s 環(huán)境下可以利用 k8s 的容器編排潜沦,擴容多個 envoy 的 pod,而在非 k8s 環(huán)境下就相對麻煩些了绪氛。
gloo 啟動 envoy 需要配置 gloo xds 服務(wù)唆鸡,而開啟多個 envoy 實例則需要在其他機器啟動 envoy,并配置同一個 gloo xds 服務(wù)作為 xds 協(xié)議內(nèi)容的接收服務(wù)枣察,并且還可能需要在上層再搭建一個 LB 作為對外流量的入口或者 DNS 解析的 endpoint争占,雖然這在 k8s 環(huán)境下也是類似的,但是在 非 k8s 環(huán)境下需要自己去做询件。
-
網(wǎng)絡(luò)模型
在 k8s 環(huán)境下燃乍,網(wǎng)絡(luò)模型作為基礎(chǔ)設(shè)施被實現(xiàn)了,service 對象在 pod 內(nèi)可以直接網(wǎng)絡(luò)互通和域名解析宛琅,
而在非 k8s 環(huán)境下刻蟹,網(wǎng)絡(luò)互通、域名解析等嘿辟,都要自己實現(xiàn)舆瘪。
5. 將 gloo 跑起來
gloo 文檔里的 petstore 例子是能跑通的,上面附上的項目也是基于這個 petstore demo 改動的红伦。
-
運行初始化腳本
? ~ cd path/to/gloo/source/install/docker-compose-consul ? docker-compose-consul git:(master) ? cat prepare-directories.sh #!/usr/bin/env bash mkdir -p ./data/artifacts/gloo-system ? docker-compose-consul git:(master) ? bash prepare-directories.sh
這個腳本主要是初始化一個 artifacts 文件夾
-
docker-compose 啟動
可以先看看 docker-compose.yml 里面有什么:
version: '3' services: # consul # note: this consul instance is being run in dev mode # and should not be used in production consul: ... # vault # note: this vault instance is being run in dev mode # and should not be used in production vault: ... # example application, the swagger petstore petstore: ... # Gloo components gloo: ... discovery: ... gateway: ... gateway-proxy: image: ${GLOO_REPO:-quay.io/solo-io}/gloo-envoy-wrapper:${GLOO_VERSION:-1.2.4} entrypoint: ["envoy"] ...
其中
petstore
是業(yè)務(wù)容器英古,consul
、vault
負(fù)責(zé)服務(wù)注冊和密鑰管理昙读,gateway-proxy
實際上是一個 envoy 容器召调。其他的
gloo
、discovery
蛮浑、gateway
都是 gloo 的組件唠叛,
其中gloo
是 gloo 實現(xiàn)的 xds 服務(wù),gateway
是上文說的"翻譯組件"沮稚,discovery
是上文說的"服務(wù)發(fā)現(xiàn)組件"艺沼。運行
docker-compose up &
啟動:? docker-compose-consul git:(master) ? docker-compose up & ? docker-compose-consul git:(master) ? Creating network "docker-compose-consul_default" with the default driver Creating docker-compose-consul_gloo_1 ... done Creating docker-compose-consul_vault_1 ... done Creating docker-compose-consul_gateway-proxy_1 ... done Creating docker-compose-consul_consul_1 ... done Creating docker-compose-consul_gateway_1 ... done Creating docker-compose-consul_petstore_1 ... done Creating docker-compose-consul_discovery_1 ... done Attaching to docker-compose-consul_vault_1, docker-compose-consul_discovery_1, docker-compose-consul_gateway_1, docker-compose-consul_gloo_1, docker-compose-consul_petstore_1, docker-compose-consul_gateway-pro xy_1, docker-compose-consul_consul_1 vault_1 | Couldn't start vault with IPC_LOCK. Disabling IPC_LOCK, please use --privileged or --cap-add IPC_LOCK discovery_1 | {"level":"info","ts":"2020-01-31T07:02:09.470Z","logger":"uds","caller":"setuputils/main_setup.go:108","msg":"using filesystem for settings","version":"1.2.4","directory":"/data/"} discovery_1 | {"level":"info","ts":"2020-01-31T07:02:09.470Z","logger":"fds","caller":"setuputils/main_setup.go:108","msg":"using filesystem for settings","version":"1.2.4","directory":"/data/"} gateway_1 | {"level":"info","ts":"2020-01-31T07:02:10.583Z","logger":"gateway","caller":"setuputils/main_setup.go:108","msg":"using filesystem for settings","version":"1.2.4","directory":"/data/"} gloo_1 | {"level":"warn","ts":"2020-01-31T07:02:10.628Z","caller":"setup/setup.go:22","msg":"Could not create metrics storage loader - will not report usage: %s","error":"invalid configuration: no co nfiguration has been provided","errorCauses":[{"err ...
看到上文信息即啟動成功。
-
服務(wù)注冊到 consul
首先我們要獲取 petstore 的內(nèi)網(wǎng) ip 地址
? gloo git:(master) ? PETSTORE_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-compose-consul_petstore_1) ? gloo git:(master) ? echo ${PETSTORE_IP} 172.24.0.5 ? gloo git:(master) ? cat > petstore-service.json <<EOF { "ID": "petstore1", "Name": "petstore", "Address": "${PETSTORE_IP}", "Port": 8080 } EOF ? gloo git:(master) ? cat petstore-service.json { "ID": "petstore1", "Name": "petstore", "Address": "172.24.0.5", "Port": 8080 } ? gloo git:(master) ? ? gloo git:(master) ? cat petstore-service.json { "ID": "petstore1", "Name": "petstore", "Address": "172.24.0.5", "Port": 8080 } ? gloo git:(master) ? curl -v \ -XPUT \ --data @petstore-service.json \ "http://127.0.0.1:8500/v1/agent/service/register" * Trying 127.0.0.1... * TCP_NODELAY set * Connected to 127.0.0.1 (127.0.0.1) port 8500 (#0) > PUT /v1/agent/service/register HTTP/1.1 > Host: 127.0.0.1:8500 > User-Agent: curl/7.54.0 > Accept: */* > Content-Length: 83 > Content-Type: application/x-www-form-urlencoded > * upload completely sent off: 83 out of 83 bytes < HTTP/1.1 200 OK < Vary: Accept-Encoding < Date: Fri, 31 Jan 2020 07:35:15 GMT < Content-Length: 0 < * Connection #0 to host 127.0.0.1 left intact ? gloo git:(master) ?
看到 consul 返回 200蕴掏,服務(wù)注冊成功障般。
通過
glooctl
可以看到 upstream 已被 gateway 捕捉到调鲸,consul kv 也看到 upstream 對象已經(jīng)創(chuàng)建了。? gloo git:(master) ? glooctl get upstream --use-consul +----------+--------+----------+--------------------+ | UPSTREAM | TYPE | STATUS | DETAILS | +----------+--------+----------+--------------------+ | consul | Consul | Accepted | svc name: consul | | | | | svc tags: [] | | | | | | | petstore | Consul | Accepted | svc name: petstore | | | | | svc tags: [] | | | | | | +----------+--------+----------+--------------------+
upstream.jpg從
dicovered_by: consulplugin
可以看出挽荡,這個 upstream 對象是 discovery 組件創(chuàng)建的藐石,
而status=accepted reportedBy gloo
能看出,這個對象創(chuàng)建后 gloo 組件(xds 服務(wù))發(fā)現(xiàn)了這個對象的創(chuàng)建定拟,并附加了一個status=accepted
的屬性贯钩。 -
增加路由
使用 glooctl 增加到 petstore 的服務(wù)的路由
? gloo git:(master) ? glooctl add route \ --path-exact /all-pets \ --dest-name petstore \ --prefix-rewrite /api/pets \ --use-consul {"level":"info","ts":"2020-01-31T18:53:56.585+0800","caller":"selectionutils/virtual_service.go:99","msg":"Created new default virtual service","virtualService":"virtual_host:<domains:\"*\" > status:<> metadata:<name:\"default\" namespace:\"gloo-system\" > "} +-----------------+--------------+---------+------+---------+-----------------+--------------------------------+ | VIRTUAL SERVICE | DISPLAY NAME | DOMAINS | SSL | STATUS | LISTENERPLUGINS | ROUTES | +-----------------+--------------+---------+------+---------+-----------------+--------------------------------+ | default | | * | none | Pending | | /all-pets -> | | | | | | | | gloo-system.petstore | | | | | | | | (upstream) | +-----------------+--------------+---------+------+---------+-----------------+--------------------------------+
用 curl 驗證請求正常
? gloo git:(master) ? curl localhost:8090/api/pets -v * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8090 (#0) > GET /api/pets HTTP/1.1 > Host: localhost:8090 > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < Content-Type: application/xml < Date: Fri, 31 Jan 2020 10:55:47 GMT < Content-Length: 86 < [{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}] * Connection #0 to host localhost left intact ? gloo git:(master) ? curl localhost:8080/all-pets -v * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8080 (#0) > GET /all-pets HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < content-type: application/xml < date: Fri, 31 Jan 2020 10:55:53 GMT < content-length: 86 < x-envoy-upstream-service-time: 3 < server: envoy < [{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}] * Connection #0 to host localhost left intact
localhost:8090 提供是 petstore 服務(wù)提供的,8080 是經(jīng)過 gloo 路由的請求办素,可以看到 http 返回頭里有
server: envoy
的信息。vs.jpg這時候查看 consul kv 查看 virtual service 有一個對應(yīng)的對象被創(chuàng)建了祸穷,其中
matchers
屬性里和我們填寫的路由信息很相似性穿,而 gloo 組件也對此附加了 accepted status。我們還能查看到 proxy 對象的內(nèi)容和通過 envoy 的 debug 端口查看到翻譯過來的配置雷滚。
? gloo git:(master) ? curl localhost:19000/config_dump { "configs": [ { "@type": "type.googleapis.com/envoy.admin.v2alpha.BootstrapConfigDump", "bootstrap": { "node": { "id": "docker-compose-node", "cluster": "gateway", "metadata": { "role": "gloo-system~gateway-proxy" }, "build_version": "3bf7d19b3405ebf85dbc6aac3fc15214a190b970/1.12.0-dev/Distribution/RELEASE/BoringSSL" }, ....
6. 總結(jié)
本篇是系列文章的第一篇需曾,主要介紹了 gloo 的基本情況和簡單跑起了非 k8s 環(huán)境下的 gloo,為后續(xù)的其他功能介紹做個鋪墊祈远。
后續(xù)文章就可以更多涉及網(wǎng)關(guān)能力的介紹呆万。