使用Gateway API訪問(wèn)服務(wù)
Gateway API是Kubernetes中用于對(duì)服務(wù)網(wǎng)絡(luò)流量進(jìn)行建模的一系列資源。它的目標(biāo)是建立一套表現(xiàn)力強(qiáng)、易擴(kuò)展、面向角色的服務(wù)網(wǎng)絡(luò)模型。本文介紹如何使用Gateway API訪問(wèn)服務(wù)。
前提條件
確保集群為1.24及以上版本。
已安裝Gateway API組件。具體操作,請(qǐng)參見(jiàn)管理組件。
說(shuō)明1.24及以上版本的集群已默認(rèn)安裝Gateway API組件。
背景信息
ACK 1.24及以上版本集群默認(rèn)安裝Gateway API組件相關(guān)的CRD資源。您可以通過(guò)安裝支持Gateway API的網(wǎng)關(guān)來(lái)使用Gateway API的相關(guān)特性。關(guān)于Gateway API的更多說(shuō)明,請(qǐng)參見(jiàn)Gateway API。
使用流程
準(zhǔn)備工作
創(chuàng)建測(cè)試應(yīng)用go-httpbin。
使用以下內(nèi)容,創(chuàng)建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
執(zhí)行以下命令,創(chuàng)建go-httpbin應(yīng)用。
kubectl apply -f httpbin.yaml
安裝Kong Kubernetes Ingress Controller。
ACK中未提供支持Gateway API的網(wǎng)關(guān)組件,本文以kubernetes-ingress-controller網(wǎng)關(guān)為例。
執(zhí)行以下命令,安裝Kong Kubernetes Ingress Controller。
說(shuō)明Kong Kubernetes Ingress Controller會(huì)使用LoadBalancer類(lèi)型的kong-proxy Service向外暴露服務(wù),創(chuàng)建的CLB實(shí)例會(huì)產(chǎn)生額外的費(fèi)用。關(guān)于CLB實(shí)例的計(jì)費(fèi)說(shuō)明,請(qǐng)參見(jiàn)CLB計(jì)費(fèi)概述。
kubectl create -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v2.8.0/deploy/single/all-in-one-dbless.yaml
創(chuàng)建完成的資源將會(huì)放置在kong命名空間下。
驗(yàn)證Kong Kubernetes Ingress Controller是否安裝成功。
執(zhí)行以下命令,查看Service的LoadBalancer IP。
kubectl get svc -n kong kong-proxy
預(yù)期輸出:
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
在返回結(jié)果中獲取
EXTERNAL IP
。執(zhí)行以下命令,訪問(wèn)Kong Kubernetes Ingress Controller。
curl http://<EXTERNAL-IP>
預(yù)期輸出:
{"message":"no Route matched with those values"}
訪問(wèn)Kong Kubernetes Ingress Controller時(shí),返回
{"message":"no Route matched with those values"}
,表明安裝Kong Kubernetes Ingress Controller成功。
創(chuàng)建GatewayClass和Gateway。
使用以下內(nèi)容,創(chuàng)建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
執(zhí)行以下命令,創(chuàng)建GatewayClass和Gateway。
kubectl apply -f gateway.yaml
執(zhí)行以下命令,查看Gateway外部端點(diǎn)。
kubectl get gateway kong
預(yù)期輸出:
NAME CLASS ADDRESS PROGRAMMED AGE kong kong 47.14.**.** 68s
返回以上結(jié)果,表明創(chuàng)建GatewayClass和Gateway成功。
使用HTTPRoute
以下介紹如何使用HTTPRoute,
功能一:創(chuàng)建前綴匹配路由
使用HTTPRoute的前綴匹配路由能力,使僅前綴正確的請(qǐng)求路由到應(yīng)用。
使用以下內(nèi)容,創(chuàng)建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設(shè)置為example.com rules: - matches: # 匹配規(guī)則為前綴匹配路徑。 - path: type: PathPrefix value: / backendRefs: # 后端為類(lèi)型為Service,名稱(chēng)go-httpbin,端口80。 - kind: Service name: go-httpbin port: 80
執(zhí)行以下命令,創(chuàng)建HTTPRoute資源。
kubectl apply -f demo-route.yaml
執(zhí)行以下命令,訪問(wèn)go-httpbin應(yīng)用。
curl http://example.com/version --resolve example.com:80:<EXTERNAL-IP>
預(yù)期輸出:
version:v1
返回以上結(jié)果,表明訪問(wèn)go-httpbin應(yīng)用成功,創(chuàng)建前綴匹配路由成功。
功能二:創(chuàng)建權(quán)重路由
使用HTTPRoute的權(quán)重路由能力,使流量按照權(quán)重比例路由到應(yīng)用。
創(chuàng)建測(cè)試應(yīng)用new-nginx和old-nginx。
使用以下內(nèi)容,創(chuàng)建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
執(zhí)行以下命令,創(chuàng)建new-nginx和old-nginx。
kubectl apply -f nginx.yaml
創(chuàng)建HTTPRoute資源。
執(zhí)行以下命令,創(chuàng)建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設(shè)置為weight.example.com rules: - matches: # 匹配規(guī)則為前綴匹配路徑。 - path: type: PathPrefix value: / backendRefs: # 設(shè)置后端以及對(duì)應(yīng)權(quán)重,權(quán)重不為百分比形式,無(wú)需等于100。 - kind: Service name: old-nginx port: 80 weight: 1 # 設(shè)置old-nginx的權(quán)重為1。 - kind: Service name: new-nginx port: 80 weight: 1 # 設(shè)置new-nginx的權(quán)重為1。
weight:權(quán)重比例,例如本文設(shè)置old-nginx的weight為1,new-nginx的weight為1,表明流量按照1∶1的比例路由到old-nginx和new-nginx。
執(zhí)行以下命令,創(chuàng)建HTTPRoute資源。
kubectl apply -f demo-weight.yaml
多次執(zhí)行以下命令,訪問(wèn)new-nginx和old-nginx應(yīng)用。
curl http://weight.example.com/ --resolve weight.example.com:80:<EXTERNAL-IP>
預(yù)期輸出:
old new old new old new
可以看到流量按照1∶1的比例路由到new-nginx和old-nginx兩個(gè)應(yīng)用中,表明創(chuàng)建權(quán)重路由成功。
功能三:修改請(qǐng)求頭
使用HTTPRoute的filter能力,可以在請(qǐng)求或者回復(fù)階段對(duì)請(qǐng)求頭進(jìn)行額外處理。本文以給發(fā)送到后端的請(qǐng)求添加請(qǐng)求頭為例。關(guān)于filter能力的更多介紹,請(qǐng)參見(jiàn)HTTPRoute。
創(chuàng)建HTTPRoute資源。
執(zhí)行以下命令,創(chuàng)建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設(shè)置為filter.example.com。 rules: - matches: # 匹配規(guī)則為前綴匹配路徑。 - path: type: PathPrefix value: / filters: - type: RequestHeaderModifier # 添加請(qǐng)求頭my-header: foo。 requestHeaderModifier: add: - name: my-header value: foo backendRefs: # 后端為類(lèi)型為Service,名稱(chēng)go-httpbin,端口80。 - kind: Service name: go-httpbin port: 80
執(zhí)行以下命令,創(chuàng)建HTTPRoute資源。
kubectl apply -f demo-filter.yaml
執(zhí)行以下命令,訪問(wèn)go-httpbin應(yīng)用。
curl http://filter.example.com/ --resolve filter.example.com:80:<EXTERNAL-IP>
預(yù)期輸出:
headers: { // ... "My-Header": [ "foo" ], // ... }
可以看到訪問(wèn)go-httpbin應(yīng)用時(shí),返回結(jié)果中包含
My-Header:foo
請(qǐng)求頭,表明修改請(qǐng)求頭成功。
配置TLS證書(shū)
執(zhí)行以下命令,通過(guò)OpenSSL創(chuàng)建自簽名證書(shū)。
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
生成的證書(shū)和私鑰位于當(dāng)前目錄的server.crt和server.key文件中。
執(zhí)行以下命令,使用server.crt和server.key文件創(chuàng)建TLS Secret。
kubectl create secret tls example.com --key server.key --cert server.crt
預(yù)期輸出:
secret/example.com created
將證書(shū)配置到Gateway。
執(zhí)行以下命令,創(chuàng)建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: # 引用所創(chuàng)建的secret。 - kind: Secret name: example.com
執(zhí)行以下命令,將證書(shū)配置到Gateway。
kubectl apply -f gateway1.yaml
執(zhí)行以下命令,驗(yàn)證配置TLS證書(shū)是否成功。
openssl s_client -servername example.com -connect <EXTERNAL-IP>:443
返回結(jié)果中包含
CN = example.com
,表明配置TLS證書(shū)成功。