假設有如下三個節點的?K8S?集群:
??
k8s31master 是控制節點
k8s31node1、k8s31node2?是工作節點
容器運行時是 containerd
一、Gateway 是什么
-
背景和目的
- 入口(Ingress)目前已停止更新。新的功能正在集成至網關 API 中。
- 在 Kubernetes 環境中,服務的網絡訪問管理至關重要。傳統的 Ingress 資源在功能上存在一定局限性,例如對流量管理的細粒度控制不足、難以滿足復雜的網絡拓撲和多集群場景等需求。Gateway API 的出現就是為了克服這些局限性,提供更通用、更靈活且更具擴展性的網絡流量管理解決方案,以適應現代云原生應用復雜的網絡需求。
-
核心概念
- Gateway:代表了集群內的一個網絡入口點,通常與底層的物理或虛擬網絡設備相對應,定義了流量進入集群的位置以及相關的網絡配置,如 IP 地址、端口等。
- GatewayClass:用于描述 Gateway 的類型和配置參數,它是對一類 Gateway 的抽象定義,例如可以定義基于 Nginx、Istio 等不同技術實現的 GatewayClass,每個 GatewayClass 可以有自己特定的配置選項,如負載均衡算法、TLS 配置等。
- HTTPRoute:用于定義 HTTP 流量的路由規則,通過匹配請求的路徑、方法、頭信息等條件,將流量路由到后端的不同服務或服務版本上,支持豐富的路由功能,如路徑重寫、請求頭修改、流量分流等。
- TLSRoute:專門用于處理 HTTPS 加密流量的路由規則,定義了如何將加密的 TLS 流量路由到后端服務,包括 TLS 證書的管理和配置,以及根據 TLS 握手信息進行流量路由的規則。
- Service:Kubernetes 中的服務資源,是一組提供相同功能的 Pod 的抽象集合,通過 Service 可以實現對后端 Pod 的負載均衡和服務發現,Gateway API 通過與 Service 的結合,將外部流量路由到具體的后端服務上。
-
?請求數據流
以下是使用 Gateway 和 HTTPRoute 將 HTTP 流量路由到服務的簡單示例:
在此示例中,實現為反向代理的 Gateway 的請求數據流如下:
- 客戶端開始準備 URL 為?http://gateway.example.com 的 HTTP 請求
- 客戶端的 DNS 解析器查詢目標名稱并了解與 Gateway 關聯的一個或多個 IP 地址的映射。
- 客戶端向 Gateway IP 地址發送請求;反向代理接收 HTTP 請求并使用 Host: 標頭來匹配基于 Gateway 和附加的 HTTPRoute 所獲得的配置。
- 可選的,反向代理可以根據 HTTPRoute 的匹配規則進行請求頭和(或)路徑匹配。
- 可選地,反向代理可以修改請求;例如,根據 HTTPRoute 的過濾規則添加或刪除標頭。
- 最后,反向代理將請求轉發到一個或多個后端。
-
?資源鏈接
Gateway API 官網:https://gateway-api.sigs.k8s.io
NGINX Gateway Fabric 官網:https://docs.nginx.com/nginx-gateway-fabric
NGC github:https://github.com/nginx/nginx-gateway-fabric
Gateway API github:https://github.com/kubernetes-sigs/gateway-api
二、怎么找資源
Gateway API 是 Ingress API 的后繼者。Gateway API 資源不是由 Kubernetes 原生實現的,而是被定義為受廣泛實現支持的自定義資源(CustomResourceDefinition)。Gateway API CRD 是一個規范,就像 Java JDBC 一樣,具體的實現依賴于各個廠商。
下面是官網列出的實現了?Gateway API 的一些項目,以及所處的階段。
像我們熟悉的?NGINX Gateway Fabric、Istio、Envoy Gateway 都處于 GA 階段。
我們今天來部署?NGINX Gateway Fabric,這個是 F5/Nginx 公司提供的一種?Gateway API 實現。
?
我們基于?NGINX Gateway Fabric 官網安裝文檔,來教大家如何安裝?NGINX Gateway Fabric。
因為?NGINX Gateway Fabric 依賴?Gateway API CRD,所以第一步就是要安裝?Gateway API CRD。
?NGF 與 K8S 的版本依賴關系倒是不大 1.19+即可,與?Gateway API CRD 的版本依賴比較大。
直接運行官網推薦的命令是肯定運行不了的,因為眾所周知的原因,github.com 在國內是訪問不了的。但是我們可以把命令請求的資源文件下載下來,直接在本地集群中運行。
kubectl kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v1.6.2" | kubectl apply -f -
- kubectl kustomize:命令用于根據指定的配置生成 Kubernetes 資源清單。這里指定的是一個來自 GitHub 倉庫 nginx/nginx-gateway-fabric 的配置路徑,ref=v1.6.2 表示使用該倉庫 v1.6.2 版本的配置。kubectl kustomize 會讀取該路徑下的配置文件(如kustomization.yaml等),對其中定義的資源進行定制化處理,生成最終的 Kubernetes 資源清單文件內容。
- | kubectl apply -f -:| 是管道符,將 kubectl kustomize 命令的輸出作為 kubectl apply -f - 的輸入。kubectl apply -f - 中的 -f 表示從文件中讀取資源配置來創建或更新 Kubernetes 資源,- 表示從標準輸入讀取。所以這部分命令會將 kubectl kustomize 生成的資源清單內容在 Kubernetes 集群中應用,即創建或更新對應的 Kubernetes 資源,比如可能會創建與 NGINX Gateway Fabric 相關的自定義資源,這些資源用于配置和管理基于 NGINX Gateway Fabric 的網關功能,像網關的路由規則、服務暴露方式等。
?https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard
https://github.com/kubernetes-sigs/gateway-api/config/crd?
執行這五份就可以,不過?Gateway API 官方也有提供一份統一的 yaml。
https://github.com/kubernetes-sigs/gateway-api/releases
我這里也提供給大家?standard-install.yaml。
三、部署
1)部署?Gateway API CRDs
[root@k8s31master gateway]# kubectl apply -f standard-install.yaml
# 查看是否安裝到位
kubectl get crds | grep gateway.networking.k8s.io
2)部署 NGF?CRDs
NGF 也有一些自定義資源,所以也要執行 crds.yaml。
[root@k8s31master gateway]# kubectl apply -f crds.yaml
?3)部署 NGF
因為是本地自建集群,所以沒有云服務商 LoadBalancer?提供公網 IP,選擇 NodePort 的方式暴露端口。
整個部署依賴兩個鏡像:
ghcr.io/nginx/nginx-gateway-fabric:1.6.2
ghcr.io/nginx/nginx-gateway-fabric/nginx:1.6.2
-
下載鏡像
找個國內好訪問的鏡像站,在各個工作節點上提前下載好鏡像。
# 在 node1 執行
[root@k8s31node1 ~]# ctr -n=k8s.io images pull ghcr.nju.edu.cn/nginx/nginx-gateway-fabric/nginx:1.6.2
[root@k8s31node1 ~]# ctr -n=k8s.io images pull ghcr.nju.edu.cn/nginx/nginx-gateway-fabric:1.6.2# 在 node2 執行
[root@k8s31node2 ~]# ctr -n=k8s.io images pull ghcr.nju.edu.cn/nginx/nginx-gateway-fabric/nginx:1.6.2
[root@k8s31node2 ~]# ctr -n=k8s.io images pull ghcr.nju.edu.cn/nginx/nginx-gateway-fabric:1.6.2
-
修改 deploy.yaml(提供給大家)
將 deploy.yaml 中?ghcr.io 全部替換為?ghcr.nju.edu.cn
?修改 Deployment 副本數
spec:replicas: 2 # 跟工作節點數量一致
?修改 Deployment Pod 親和性
affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchLabels:app.kubernetes.io/name: nginx-gatewaytopologyKey: kubernetes.io/hostname
?讓每個節點上都安裝 nginx-gateway-controller。官網給的?nginx-gateway-controller 的部署方式是?Deployment,官網也推薦使用 DaemonSet,在每一個節點上安裝一份,對于請求處理的性能更佳。
-
?運行
[root@k8s31master gateway]# kubectl apply -f deploy.yaml
-
?驗證
整個部署會幫我們創建 2 個?nginx-gateway-controller Pod,分別運行在兩個工作節點上,負責監聽請求:
kubectl get pod -n nginx-gateway -owide
創建了 1 個 gatewayclass 資源,引用?nginx-gateway-controller,且 gatewayclass 的名字叫 nginx:
kubectl get gatewayclass -n nginx-gateway
?
創建了一個 NodePort 的 Service,代理了那 2 個?nginx-gateway-controller Pod:
kubectl get svc -n nginx-gateway
kubectl describe svc -n nginx-gateway
?后續請求各個工作節點的 30185 端口,則會被?nginx-gateway-controller 80 端口接管。
?四、將流量路由到應用
? 1)創建應用
apiVersion: apps/v1
kind: Deployment
metadata:name: tomcat-deploy
spec:replicas: 2selector:matchLabels:app: tomcattemplate:metadata:labels:app: tomcatspec:containers:- name: tomcatimage: tomcat:8.5-jre8-alpineimagePullPolicy: IfNotPresentports:- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:name: tomcat-svc
spec:type: ClusterIPselector:app: tomcatports:- port: 8080protocol: TCPtargetPort: 8080
創建了 2 個 tomcat Pod,和一個 Service,Service 暴露 8080 端口。
?2)創建 gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:name: nginx-gatewaynamespace: default
spec:gatewayClassName: nginxlisteners:- name: httpprotocol: HTTPport: 80
gatewayClassName 要使用我們 NGF 為我們創建的名字 nginx。
gateway 監聽 80 端口。
?3)創建 httproute
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:name: example-routenamespace: default
spec:parentRefs:- name: nginx-gatewayhostnames:- "gateway.example.com"rules:- matches:- path:type: PathPrefixvalue: / backendRefs:- name: tomcat-svckind: Serviceport: 8080
- parentRefs:綁定我們新建的 gateway。
- hostnames:定義訪問的主機名。
- rules.matches:定義路由規則,PathPrefix 表示路徑前綴匹配。
- backendRefs:定義后端服務以及服務端口。
?4)訪問
curl -H "Host: gateway.example.com" http://192.168.40.20:30185/
?集群外隨便找臺機子訪問都能訪問到 tomcat。
?修改本機 hosts 也能瀏覽器訪問:
192.168.40.20 gateway.example.com
?五、原理
其實?nginx-gateway-controller 就是一個 nginx,它會監聽 gateway 跟 httproute 的變化,重寫 nginx.conf,重啟 nginx。
# nginx-gateway-64fd456f8-5qh6k
# nginx-gateway-64fd456f8-n9h26
kubectl exec -it -n nginx-gateway nginx-gateway-64fd456f8-5qh6k -c nginx -- nginx -T
六、A/B 測試、金絲雀發布
看這一篇文章。