Gateway API是Kubernetes中用於對服務網路流量進行建模的一系列資源。它的目標是建立一套表現力強、易擴充、面向角色的服務網路模型。本文介紹如何使用Gateway API訪問服務。
前提條件
確保叢集為1.24及以上版本。
已安裝Gateway API組件。具體操作,請參見管理組件。
說明1.24及以上版本的叢集已預設安裝Gateway API組件。
背景資訊
ACK 1.24及以上版本叢集預設安裝Gateway API組件相關的CRD資源。您可以通過安裝支援Gateway API的網關來使用Gateway API的相關特性。關於Gateway API的更多說明,請參見Gateway API。
使用流程
準備工作
建立測試應用go-httpbin。
使用以下內容,建立httpbin.yaml。
apiVersion: apps/v1 kind: Deployment metadata: name: go-httpbin namespace: default spec: replicas: 1 selector: matchLabels: app: go-httpbin template: metadata: labels: app: go-httpbin version: v1 spec: containers: - image: specialyang/go-httpbin:v3 args: - "--port=8090" - "--version=v1" imagePullPolicy: Always name: go-httpbin ports: - containerPort: 8090 --- apiVersion: v1 kind: Service metadata: name: go-httpbin namespace: default spec: ports: - port: 80 targetPort: 8090 protocol: TCP selector: app: go-httpbin
執行以下命令,建立go-httpbin應用。
kubectl apply -f httpbin.yaml
安裝Kong Kubernetes Ingress Controller。
ACK中未提供支援Gateway API的網關組件,本文以kubernetes-ingress-controller網關為例。
執行以下命令,安裝Kong Kubernetes Ingress Controller。
說明Kong Kubernetes Ingress Controller會使用LoadBalancer類型的kong-proxy Service向外暴露服務,建立的CLB執行個體會產生額外的費用。關於CLB執行個體的計費說明,請參見CLB計費概述。
kubectl create -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v2.8.0/deploy/single/all-in-one-dbless.yaml
建立完成的資源將會放置在kong命名空間下。
驗證Kong Kubernetes Ingress Controller是否安裝成功。
執行以下命令,查看Service的LoadBalancer IP。
kubectl get svc -n kong kong-proxy
預期輸出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kong-proxy LoadBalancer 172.16.19.238 47.14.**.** 80:31611/TCP,443:30936/TCP 10s
在返回結果中擷取
EXTERNAL IP
。執行以下命令,訪問Kong Kubernetes Ingress Controller。
curl http://<EXTERNAL-IP>
預期輸出:
{"message":"no Route matched with those values"}
訪問Kong Kubernetes Ingress Controller時,返回
{"message":"no Route matched with those values"}
,表明安裝Kong Kubernetes Ingress Controller成功。
建立GatewayClass和Gateway。
使用以下內容,建立gateway.yaml。
apiVersion: gateway.networking.k8s.io/v1beta1 kind: GatewayClass metadata: name: kong annotations: konghq.com/gatewayclass-unmanaged: 'true' spec: controllerName: konghq.com/kic-gateway-controller --- apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway metadata: name: kong spec: gatewayClassName: kong listeners: - name: proxy port: 80 protocol: HTTP - name: proxy-ssl port: 443 protocol: HTTPS
執行以下命令,建立GatewayClass和Gateway。
kubectl apply -f gateway.yaml
執行以下命令,查看Gateway外部端點。
kubectl get gateway kong
預期輸出:
NAME CLASS ADDRESS PROGRAMMED AGE kong kong 47.14.**.** 68s
返回以上結果,表明建立GatewayClass和Gateway成功。
使用HTTPRoute
以下介紹如何使用HTTPRoute,
功能一:建立首碼匹配路由
使用HTTPRoute的首碼匹配路由能力,使僅首碼正確的請求路由到應用。
使用以下內容,建立demo-route.yaml。
apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: demo-route spec: parentRefs: # 引用Gateway資源。 - group: gateway.networking.k8s.io kind: Gateway name: kong hostnames: - example.com # host設定為example.com rules: - matches: # 匹配規則為首碼匹配路徑。 - path: type: PathPrefix value: / backendRefs: # 後端為類型為Service,名稱go-httpbin,連接埠80。 - kind: Service name: go-httpbin port: 80
執行以下命令,建立HTTPRoute資源。
kubectl apply -f demo-route.yaml
執行以下命令,訪問go-httpbin應用。
curl http://example.com/version --resolve example.com:80:<EXTERNAL-IP>
預期輸出:
version:v1
返回以上結果,表明訪問go-httpbin應用成功,建立首碼匹配路由成功。
功能二:建立權重路由
使用HTTPRoute的權重路由能力,使流量按照權重比例路由到應用。
建立測試應用new-nginx和old-nginx。
使用以下內容,建立nginx.yaml。
apiVersion: apps/v1 kind: Deployment metadata: name: old-nginx spec: replicas: 1 selector: matchLabels: run: old-nginx template: metadata: labels: run: old-nginx spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx imagePullPolicy: Always name: old-nginx ports: - containerPort: 80 protocol: TCP restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: old-nginx spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: run: old-nginx sessionAffinity: None type: NodePort --- apiVersion: apps/v1 kind: Deployment metadata: name: new-nginx spec: replicas: 1 selector: matchLabels: run: new-nginx template: metadata: labels: run: new-nginx spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx imagePullPolicy: Always name: new-nginx ports: - containerPort: 80 protocol: TCP restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: new-nginx spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: run: new-nginx sessionAffinity: None type: NodePort
執行以下命令,建立new-nginx和old-nginx。
kubectl apply -f nginx.yaml
建立HTTPRoute資源。
執行以下命令,建立demo-weight.yaml。
apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: demo-weight spec: parentRefs: # 引用Gateway資源。 - group: gateway.networking.k8s.io kind: Gateway name: kong hostnames: - weight.example.com # host設定為weight.example.com rules: - matches: # 匹配規則為首碼匹配路徑。 - path: type: PathPrefix value: / backendRefs: # 設定後端以及對應權重,權重不為百分比形式,無需等於100。 - kind: Service name: old-nginx port: 80 weight: 1 # 設定old-nginx的權重為1。 - kind: Service name: new-nginx port: 80 weight: 1 # 設定new-nginx的權重為1。
weight:權重比例,例如本文設定old-nginx的weight為1,new-nginx的weight為1,表明流量按照1∶1的比例路由到old-nginx和new-nginx。
執行以下命令,建立HTTPRoute資源。
kubectl apply -f demo-weight.yaml
多次執行以下命令,訪問new-nginx和old-nginx應用。
curl http://weight.example.com/ --resolve weight.example.com:80:<EXTERNAL-IP>
預期輸出:
old new old new old new
可以看到流量按照1∶1的比例路由到new-nginx和old-nginx兩個應用中,表明建立權重路由成功。
功能三:修改要求標頭
使用HTTPRoute的filter能力,可以在請求或者回複階段對要求標頭進行額外處理。本文以給發送到後端的請求添加要求標頭為例。關於filter能力的更多介紹,請參見HTTPRoute。
建立HTTPRoute資源。
執行以下命令,建立demo-filter.yaml。
apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: demo-filter spec: parentRefs: # 引用Gateway資源。 - group: gateway.networking.k8s.io kind: Gateway name: kong hostnames: - filter.example.com # host設定為filter.example.com。 rules: - matches: # 匹配規則為首碼匹配路徑。 - path: type: PathPrefix value: / filters: - type: RequestHeaderModifier # 添加要求標頭my-header: foo。 requestHeaderModifier: add: - name: my-header value: foo backendRefs: # 後端為類型為Service,名稱go-httpbin,連接埠80。 - kind: Service name: go-httpbin port: 80
執行以下命令,建立HTTPRoute資源。
kubectl apply -f demo-filter.yaml
執行以下命令,訪問go-httpbin應用。
curl http://filter.example.com/ --resolve filter.example.com:80:<EXTERNAL-IP>
預期輸出:
headers: { // ... "My-Header": [ "foo" ], // ... }
可以看到訪問go-httpbin應用時,返回結果中包含
My-Header:foo
要求標頭,表明修改要求標頭成功。
配置TLS認證
執行以下命令,通過OpenSSL建立自我簽署憑證。
openssl req -subj '/CN=example.com' -new -newkey rsa:2048 -sha256 \ -days 365 -nodes -x509 -keyout server.key -out server.crt \ -addext "subjectAltName = DNS:example.com" \ -addext "keyUsage = digitalSignature" \ -addext "extendedKeyUsage = serverAuth" 2> /dev/null; openssl x509 -in server.crt -subject -noout
產生的認證和私密金鑰位於目前的目錄的server.crt和server.key檔案中。
執行以下命令,使用server.crt和server.key檔案建立TLS Secret。
kubectl create secret tls example.com --key server.key --cert server.crt
預期輸出:
secret/example.com created
將認證配置到Gateway。
執行以下命令,建立gateway1.yaml。
apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway metadata: name: kong spec: gatewayClassName: kong listeners: - name: proxy port: 80 protocol: HTTP - name: proxy-ssl port: 443 protocol: HTTPS tls: # 配置TLS。 mode: Terminate certificateRefs: # 引用所建立的secret。 - kind: Secret name: example.com
執行以下命令,將認證配置到Gateway。
kubectl apply -f gateway1.yaml
執行以下命令,驗證配置TLS認證是否成功。
openssl s_client -servername example.com -connect <EXTERNAL-IP>:443
返回結果中包含
CN = example.com
,表明配置TLS認證成功。