Kubernetes Gateway API v1.1 解讀,你看懂了嗎?
幾天前,K8s Network SIG 發布了 Gateway API(簡稱 gwapi)的 v1.1 版本[1],這個版本的發布包含了多項重要功能的 GA(一般可用),以及一些實驗功能的引入。這兩部分分別通過標準渠道和實驗渠道發布。
發布渠道用于指示網關 API 內的功能的穩定性。所有新功能和資源都是先從實驗發布渠道開始,在后續迭代演進的過程中可能會升級到標準發布渠道,也有可能完全從 API 中廢除。
通過下圖可以對 gwapi 的發布渠道有個清晰的了解。
圖片
在這些更新中,在我看來當屬服務網格的支持 GA 最為重要,這意味著服務網格標準 API 向著統一又邁進了一步。差不多兩年前,我曾寫過 SMI 與 Gateway API 的 GAMMA 倡議意味著什么, 在 gwapi 差不多 1.0 的時候,SMI 在停止更新的幾個月后歸檔了。
標準發布渠道
GRPCRoute GA
GRPCRoute API 的 v1 版本發布,標志著其可以在生產環境中穩定使用,并得到長期的支持的維護。同時 v1alpha2 版本被標記為廢棄,在未來的版本中將會被移除。
Service Mesh Support GA
gwapi 對服務網格的支持正式畢業,并進入標準發布渠道。實現了對網格的支持后,可以使用同樣的 API 來管理東西向(服務間)的流量,也因此基于 gwapi 構建的策略可以在網格中復用。有興趣的可以看一下去年寫的 探索 Gateway API 在 Service Mesh 中的工作機制,也可參考 官方文檔[2]。
從 v1.1 開始 xRoute 的可以 attach 到(父資源) Gateway 和 Service 上,具體表現為 parentRef.kind 可以是 Gateway(默認) 和 Service。比如:
HTTPRoute 用于網關: 省略 kind: Gateway。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-app-1
spec:
parentRefs:
- name: my-gateway
rules:
...
HTTPRoute 用于服務網格:
kind: HTTPRoute
metadata:
name: smiley-route
namespace: faces
spec:
parentRefs:
- name: smiley
kind: Service
group: ""
port: 80
rules:
...
一致性檢查的配置文件和報告 GA
一致性報告 API 和相應的測試套件已升級為 GA v1 版本。
關于一致性報告:
符合 Gateway API 規范的實現是指通過每個 gwapi 捆綁版本(如 gateway.networking.k8s.io/bundle-version: v1.1.0)發布中包含的一致性測試的實現。 所有的 gwapi 實現必須通過一致性測試,且不能跳過任何一個測試。
在 v1 版本中,ConformanceReport API 擴展了 mode 和 gatewayAPIChannel 兩個字段。前者用于指定實現的工作模式,后者標識該報告適用的發布渠道:標準發布 standard 或實驗發布 experimental。
報告也以更結構化的方式重新組織,實現現在可以添加有關測試運行方式的信息并提供復現步驟。
ParentRef 的 Port 字段 GA
之前,當一個 Gateway 上配置了多個監聽器時,如果想要將路由 attach 到指定的端口,
listeners:
- name: foo
protocol: HTTP
port: 8080
...
- name: bar
protocol: HTTP
port: 8090
...
- name: baz
protocol: HTTP
port: 8090
...
可以使用 sectionName 指定監聽器的名字,因此需要為監聽器通過 name 字段設置名字。
spec:
parentRefs:
- name: acme-lb
sectionName: foo
現在可以通過 port 字段來實現了,因為端口在網關上也是唯一的,這樣就無需使用 name 字段。
spec:
parentRefs:
- name: acme-lb
port: 8080
實驗發布渠道
通過 BackendLBPolicy 支持會話持久性
通過 BackendLBPolicy 引入會話持久性(session persistence)支持,該功能來自 網關增強提案 GEP-1619[3]。
會話持久性是指客戶端請求在“會話”持續時間內定向到同一后端服務器。
當客戶端直接提供信息(例如請求頭中的 cookie)時,代理將其用作將流量定向到特定服務器的參考。持久性是負載均衡的一個例外:持久性客戶端請求繞過代理的負載平衡算法,直接到達之前與之建立會話的后端服務器。
見官方的 會話持久性定義[4]。
gwapi 的會話持久性,可以作用于服務粒度,也可以作用與單個路由。后者的優先級更高,會覆蓋服務粒度的會話持久性配置。
路由粒度的會話持久性,通過路由規則中 sessionPersistence 配置。
kind: HTTPRoute
metadata:
name: routeX
spec:
rules:
- matches:
- path:
value: /a
backendRefs:
- name: servicev1
sessionPersistence:
name: session-a
服務粒度的會話持久性則是通過 BackendLBPolicy 來配置。
kind: BackendLBPolicy
metadata:
name: lbp
spec:
targetRef:
kind: Service
Name: servicev1
sessionPersistence:
sessionName: service-cookie
type: Cookie
注:核心 API 中的 type 是 Cookie,在實現可以擴展支持任意請求頭,類型為 Header。
客戶端證書校驗
網關增強提案 GEP-91[5] 討論了如何驗證前端客戶端在 TLS 握手協議期間向服務器提供的 TLS 證書,可以看作是 mTLS 中的客戶端認證。
在官方的核心 API 設計中,使用監聽器的 tls.frontendValidation 指定的 ConfigMap 中的 CA 證書來對客戶端進行認證。核心 API 只支持一個 ConfigMap,在實現是可擴展支持多個 ConfigMap 或者其他類型如 Service。
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: client-validation-basic
spec:
gatewayClassName: acme-lb
listeners:
- name: foo-https
protocol: HTTPS
port: 443
hostname: foo.example.com
tls:
certificateRefs:
- kind: Secret
group: ""
name: foo-example-com-cert
frontendValidation:
caCertificateRefs:
- kind: ConfigMap
group: ""
name: foo-example-com-ca-cert
BackendTLSPolicy
BackendTLSPolicy[6] 是 gwapi 中的一種類型,用于指定通過 Service API 對象從網關到后端 Pod(或多個 Pod)的連接的 TLS 配置。與客戶端認證正好相反,是對后端服務的認證。
對后端服務的認證有兩種:
- 由網關對后端服務進行認證,即在網關配置用于認證的 CA 證書。
- 有客戶端進行認證,也就是網關的透傳(passthrough)模式。
圖片
相比 v1.0 里的 v1alpha2,v1.1 中的 v1alpha3 發生的重大變化:
- targetRef 字段現在變為 targetRefs 列表,并且這些引用不再包含命名空間字段。
- tls 字段已更名為 validation。
- caCertRefs 字段已更名為 caCertificateRefs。
- wellKnownCACerts 字段已更名為 wellKnownCACertificates。
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
name: tls-upstream-auth
spec:
targetRefs:
- kind: Service
name: auth
group: ""
validation:
caCertificateRefs:
- kind: ConfigMap
name: auth-cert
group: ""
hostname: auth.example.com
網關參數
不同的 gwapi 實現使用了不同的負載均衡器,比如 Envoy Gateway 使用 Envoy,FSM Gateway 使用 Pipy。不同負載均衡器自身的配置各不相同,而 gwapi 無法提供通用的接口。因此在 GatewayClass API 上通過 spec.parametersRef 字段提供了配置接口。
不過 GatewayClass 的配置是全局的,針對所有的 Gateway 實例,無法針對特定的 Gateway 實例進行配置,難以滿足需求。然后就有了 網關增強提案 GEP-1867[7]。
與 GatewayClass 類似的方式,該提案中 Gateway API 通過 infrastructure.parametersRef 字段配置 `LocalParametersReference`[8],具體由各 gwapi 實現來定義。
其他更新
除了兩個發布渠道的功能外,還有其他的更新就不一一介紹了。
- gwctl:
get 命令擴展以支持 gateways、gatewayclasses 和 namespaces。
describe 命令現在支持描述 policycrds 和 namespaces。
增加了使用標簽過濾資源的能力(通過 -l 選項)。
修復了描述 gatewayclasses 時未描述的錯誤。
- 驗證變更:不再需要在 Gateway Listeners 上配置 TLS,以實現更靈活的 TLS 配置。
- 一致性測試:一致性配置文件已重命名,并新增了 Mesh-GRPC 配置文件。
- 依賴項更新:Gateway API 升級到 Go v1.22 和 Kubernetes v1.30。
- 清理:刪除了驗證 webhook,CEL 驗證現在內置在 CRDs 中替代 webhook。
更多內容可以參考 v1.1.0 更新說明[9]。
參考資料
[1] v1.1 版本: https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.1.0
[2] 官方文檔: https://gateway-api.sigs.k8s.io/mesh/
[3] 網關增強提案 GEP-1619: https://gateway-api.sigs.k8s.io/geps/gep-1619
[4] 會話持久性定義: https://gateway-api.sigs.k8s.io/geps/gep-1619/?h=backendlbpolicy#defining-session-persistence
[5] 網關增強提案 GEP-91: https://gateway-api.sigs.k8s.io/geps/gep-91/
[6] BackendTLSPolicy: https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy
[7] 網關增強提案 GEP-1867: https://gateway-api.sigs.k8s.io/geps/gep-1867
[8] LocalParametersReference: https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.LocalParametersReference
[9] v1.1.0 更新說明: https://github.com/kubernetes-sigs/gateway-api/releases/tag/v1.1.0