持續整合(Continuous Integration,CI) 與 持續交付/部署(Continuous Delivery/Deployment,CD)在目前軟體開發應該算是蠻出名的做法。前者通常指從原始碼到建置成成品(Artifact)的自動化過程;而後者則是功能到達可用階段,乃自於自動/半自動部署到生產環境的過程。
在幾年前主要是在GitLab平臺,其實多數時候仍使用手動編譯建置成品和部署,只有少部分成品的建置和測試透過GitLab Runner自動化進行。
目前主要在進行的專案移到了Azure DevOps進行,不單建置部分完成了自動化(CI),部署部分也透過Azure DevOps Agent和部署群組的設定完成了自動/半自動化,降低部署過程中人為失誤的情況。
CI/CD像是一個工廠流水線(Pipeline)。在流水線前期建置成品部分比較單純(CI),通常一個原始碼分支對應一個成品。但是後期部署部分(CD),就有可能一個成品需要部署到不同地方,甚至不同環境之中。
Apache APISIX對於不管是哪個CD環境,Admin API都可以配合達到滾動式更新(Rolling Update)的結果。也就是仍保留一定數量的服務節點,一次僅進行一部分的節點更新,直至所有節點都完成更新,達成服務不中斷的目的。極端者,更可以一次僅更新一個節點。
就像是在「健康檢查」一章所提到的,如果可以請一個斥候查探百貨公司據點有沒有開業,就不需要每個都自己跑過一趟。
同樣地,如果可以先看看天氣預報,又何必需要先請斥候查探呢?
既然在部署過程中,難免得停用服務節點,不如就先讓Apache APISIX知道這個「天氣預報」。
既然需要通知APISIX,就需要知道怎麼和APISIX溝通。Apache APISIX提供了一組Admin API,通常Base URI會是/apisix/admin/
開頭,並監聽9180
端口。這也是在docker-compsoe.yaml
轉發了9180
端口的原因。
apisix:
container_name: apisix
image: "apache/apisix:3.2.2-debian"
ports:
- 9180:9180 # admin api
- 9080:9080 # HTTP
- 9091:9091 # prometheus
- 9443:9443 # HTTPS
- 9090:9090 # control api
- 389:389 # Proxy AD Service
要變更監聽的端口,可以透過調整apisix_config/config.yaml
中的deployment.admin.admin_listen
設定:
deployment:
role: traditional # 部署模式: traditional, control_plane, or data_plane.
admin:
admin_key:
- name: admin
key: SaiTJp7TEa9K39oy7D5A4ouXmdqHvL9a # 使用預設的 Admin API Key 存在安全風險,部署到生產環境時請及時更新
role: admin
allow_admin: # http://nginx.org/en/docs/http/ngx_http_access_module.html#allow
- 0.0.0.0/0
admin_listen:
ip: 0.0.0.0 # Admin API 監聽的 IP,如果不設定,預設為“0.0.0.0”。
port: 9180 # Admin API 監聽的埠,必須使用與 node_listen 不同的埠。
並且要使用Admin API,APSIX的部署模式也要正確,以上面程式碼片段deployment.role
來說,就是使用traditional
(有部分模式Admin API不起作用)。
此外,雖然apisix.enable_admin
預設就是true
了,但也可以明確在該區段添加該設定。
apisix:
enable_admin: true # Admin API
其實前後應該已經看到過Admin API了,後面章節也還會使用到。Admin API設計大致符合RESTful範式,使用起來還蠻輕鬆的,因此並不會每個都詳詳細細說明,如有疑問也可以自行參考文檔。
這部分就稍微圍繞「路由」相關的API說明一下。
先來看取得路由清單的例子:
curl --request GET \
--url http://localhost:9180/apisix/admin/routes \
--header 'X-API-KEY: SaiTJp7TEa9K39oy7D5A4ouXmdqHvL9a'
如果同樣「新竹百貨公司」、和「APISIX的狀態」的路由已經建立起來,應該會取得兩個路由的資訊。
路由相關的API端點都是由/apisix/admin/routes
開始。在上面的查詢,已經可以查到已存在路由的id
。如果查詢時僅想查詢一個路由,可以透過/apisix/admin/routes/{id}
取得。
另外注意:在請求中添加了一個HEADER字段X-API-KEY
。這個值實際上需要和apisix_config/config.yaml
中的deployment.admin.admin_key.key
匹配。
Admin API設計大致符合RESTful範式。要建立路由,可以簡單將請求方法從GET
調整成POST
,再加上需要建立的路由內容:
curl http://127.0.0.1:9180/apisix/admin/routes -H 'X-API-KEY: SaiTJp7TEa9K39oy7D5A4ouXmdqHvL9a' -X POST -d '
{
"uri": "/apisix/status",
"plugins": {
"public-api": {}
}
}'
而這個結果會自動分配一個路由ID。在Dashboard的Web UI中同樣可以看到這個結果。
在「APISIX的狀態」中見過另外一個例子,這個例子指定了路由ID--ns
,並且方法改成了PUT
:
curl http://127.0.0.1:9180/apisix/admin/routes/ns -H 'X-API-KEY: SaiTJp7TEa9K39oy7D5A4ouXmdqHvL9a' -X PUT -d '
{
"uri": "/apisix/status",
"plugins": {
"public-api": {}
}
}'
Admin API設計大致符合RESTful範式。要刪除路由,只要指定路由ID,並將請求方法改成DELETE
即可:
curl --silent http://192.168.56.3:9180/apisix/admin/routes/00000000000000000438 -H 'X-API-KEY: SaiTJp7TEa9K39oy7D5A4ouXmdqHvL9a' -X DELETE
要做到「天氣預報」的效果,需要在進行服務節點的更新作業之前,通知APISIX該節點進行維護。詳細做法是調整上游權重爲0
或移除該上游節點與清單之中。
如果上游的設定是嵌入在路由之中,可以透過PATCH
更新路由/apisix/admin/routes/{id}/upstream
。如果像是「新竹百貨公司」的例子,則可以透過更新Upstream的設定來達成。下面是一個示範例子:
curl --request PATCH \
--url http://192.168.56.3:9180/apisix/admin/upstreams/583854961993974464/nodes \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: SaiTJp7TEa9K39oy7D5A4ouXmdqHvL9a' \
--data '{
"192.168.56.3:8081": 1,
"192.168.56.3:8082": 1,
"192.168.56.3:8083": 1,
"192.168.56.3:8084": 0
}'
總地來說,透過Admin API的配合、APISIX的動態調整/動態路由,已經對於上游節點的主動/被動健康檢查,來完成服務的高可用與滾動式更新。