https://onedayxyy.cn/docs/GatewayAPI/
实战名称 |
---|
🚩 实战:配置请求路由-2023.12.27 |
🚩 实战:路由到指定版本-2023.12.27 |
🚩 实战:基于用户身份路由-2023.12.27 |
🚩 实战:基于权重的路由-2023.12.27 |
🚩 实战:使用 TLS 暴露服务-2023.12.27 |
接下来我们来了解下如果通过 Gateway API 将请求动态路由到微服务的多个版本。
同样我们这里以 Bookinfo 示例为例(首先要部署 Bookinfo 应用),我们首先将所有流量路由到微服务的 v1 (版本 1),然后将应用规则根据 HTTP 请求 header 的值路由流量。
🚩 实战:配置请求路由-2023.12.27
🔱 说明:
此部分实战因自己Gatway API部署失败导致无法进一步测试,这里仅维护文档。
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
首先要部署 Bookinfo 应用(部署方式见之前文章)
首先专门为 Bookinfo 应用创建一个 Gateway
资源对象,如下所示:
# bookinfo-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
gatewayClassName: istio
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: Same
上面的 Gateway
资源对象与之前的示例类似,只是这里我们将 allowedRoutes
设置为 Same
,表示允许同一命名空间中的所有路由资源对象都可以连接到这个网关。
HTTPRoute
资源对象,如下所示:# productpage-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: bookinfo
spec:
parentRefs:
- name: bookinfo-gateway # 引用上面定义的 Gateway 对象
rules:
- matches:
- path:
type: Exact
value: /productpage
- path:
type: PathPrefix
value: /static
- path:
type: Exact
value: /login
- path:
type: Exact
value: /logout
- path:
type: PathPrefix
value: /api/v1/products
backendRefs:
- name: productpage # 引用的后端服务
port: 9080
和以前 VirtualService 的类似,我们为 Productpage 应用配置了几个路由规则,这样我们就可以在页面上正常访问应用了。
kubectl apply -f bookinfo-gateway.yaml
kubectl apply -f productpage-route.yaml
Gateway
对象后,会自动在 default 命名空间中部署一个 gateway-istio
的 Deployment 和 对应的 Service:$ kubectl get pods -l istio.io/gateway-name=bookinfo-gateway
NAME READY STATUS RESTARTS AGE
bookinfo-gateway-istio-548556df95-kggs2 1/1 Running 0 112s
$ kubectl get svc bookinfo-gateway-istio
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
bookinfo-gateway-istio LoadBalancer 10.111.86.147 <pending> 15021:30357/TCP,80:30749/TCP 2m19s
30749
这个 NodePort 端口来访问 Productpage 应用了:测试结束。😘
同样的页面上的评论区域会出现 3 种不同的状态,因为我们背后有 3 个不同的版本的评论服务。
🚩 实战:路由到指定版本-2023.12.27
🔱 说明:
此部分实战因自己Gatway API部署失败导致无法进一步测试,这里仅维护文档。
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
HTTPRoute
资源对象,首先将流量路由到 v1 版本:# route-reviews-v1.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: reviews
spec:
parentRefs: # 这里我们引用的是 reviews 这个 Service 对象
- group: ""
kind: Service
name: reviews
port: 9080
rules:
- backendRefs:
- name: reviews-v1
port: 9080
注意上面的资源对象中我们是通过 parentRefs
字段引用的是 reviews
这个 Service 对象,而不是 Gateway
对象了,因为我们流量并不是从 Gateway
直接过来的,而是通过 Productpage 访问 reviews 服务,也就是 Service 对象。然后背后的我们会将流量全部路由到 v1 版本的 reviews 服务 reviews-v1
。
kubectl apply -f route-reviews-v1.yaml
不过这里需要注意不同于 Istio API 使用 DestinationRule
子集来定义服务的版本, Kubernetes Gateway API 将为此使用后端 Service 服务来进行定义。
reviews
服务创建后端服务定义:kubectl apply -f samples/bookinfo/platform/kube/bookinfo-versions.yaml
reviews:v1
,而此版本的服务不访问星级评分服务。测试结束。😘
接下来我们来更改路由配置,将来自特定用户的所有流量路由到特定服务版本,比如将来自名为 Jason
的用户的所有流量被路由到服务 reviews:v2
(包含星级评分功能的版本)。
🚩 实战:基于用户身份路由-2023.12.27
🔱 说明:
此部分实战因自己Gatway API部署失败导致无法进一步测试,这里仅维护文档。
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
HTTPRoute
资源对象:# route-reviews-jason-v2.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: reviews
spec:
parentRefs:
- group: ""
kind: Service
name: reviews
port: 9080
rules:
- matches:
- headers: # 匹配请求头 end-user: jason
- name: end-user
value: jason
backendRefs:
- name: reviews-v2
port: 9080
- backendRefs:
- name: reviews-v1
port: 9080
在上面的 HTTPRoute
资源对象中,我们将访问 reviews
的流量分为两个规则,第一个规则匹配请求头 end-user: jason
,然后将流量路由到 reviews-v2
服务,第二个则是如果不匹配将流量路由到 reviews-v1
服务。
kubectl apply -f route-reviews-jason-v2.yaml
jason
身份进行登录,登录后无论如何刷新浏览器,我们将始终在页面上看到黑色的星级评分,也就是 reviews 的 v2 版本。我们也可以切换成其他用户,或者不登录,刷新浏览器,那么就不会显示星级评分了。
测试成功。😘
接下来我们再来测试下基于权重的路由,常常我们有将流量从微服务的一个版本逐步迁移到另一个版本的需求,同样使用 Gateway API 来实现也非常简单。
下面我们将会把 50% 的流量发送到 reviews:v1
,另外,50% 的流量发送到 reviews:v3
。接着,再把 100% 的流量发送到 reviews:v3
来完成迁移。
🚩 实战:基于权重的路由-2023.12.27
🔱 说明:
此部分实战因自己Gatway API部署失败导致无法进一步测试,这里仅维护文档。
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
kubectl apply -f route-reviews-v1.yaml
reviews:v1
转移到 reviews:v3
:# route-reviews-50-v3.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: reviews
spec:
parentRefs:
- group: ""
kind: Service
name: reviews
port: 9080
rules:
- backendRefs:
- name: reviews-v1
port: 9080
weight: 50
- name: reviews-v3
port: 9080
weight: 50
上面的对象中在 backendRefs
中我们使用了一个 weight
字段,用于设置权重,这里我们将 reviews-v1
和 reviews-v3
的权重都设置为 50,也就是说将流量平均分配到这两个版本的服务上。
kubectl apply -f route-reviews-50-v3.yaml
等待几秒钟,等待新的规则传播到代理中生效,然后我们再次刷新浏览器中的 productpage 页面,大约有 50% 的几率会看到页面中带红色星级的评价内容。 这是因为 reviews 的 v3 版本可以访问带星级评价,但 v1 版本不能。
如果你认为 reviews:v3
微服务已经稳定,那么接下来我们就可以将 100% 的流量路由 reviews:v3
:
# route-reviews-v3.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: reviews
spec:
parentRefs:
- group: ""
kind: Service
name: reviews
port: 9080
rules:
- backendRefs:
- name: reviews-v3
port: 9080
kubectl apply -f route-reviews-v3.yaml
测试成功😘。
接下来我们来看下如何通过 TLS 来暴露服务,这里我们以 httpbin 示例进行说明。
🚩 实战:使用 TLS 暴露服务-2023.12.27
🔱 说明:
此部分实战因自己Gatway API部署失败导致无法进一步测试,这里仅维护文档。
k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
istio v1.19.3(--set profile=demo)
实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)
kubectl apply -f samples/httpbin/httpbin.yaml
然后接下来生成客户端和服务器证书和密钥,这里我们使用 openssl 工具来生成。
$ mkdir example_certs1
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs1/example.com.key -out example_certs1/example.com.crt
httpbin.example.com
创建证书和私钥:$ openssl req -out example_certs1/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
$ openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 0 -in example_certs1/httpbin.example.com.csr -out example_certs1/httpbin.example.com.crt
kubectl create -n istio-system secret tls httpbin-credential \
--key=example_certs1/httpbin.example.com.key \
--cert=example_certs1/httpbin.example.com.crt
# httpbin-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: mygateway
namespace: istio-system
spec:
gatewayClassName: istio
listeners:
- name: https
hostname: "httpbin.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
在上面的对象中我们配置了 HTTPS
协议,并在 tls
中配置使用 Terminate
模式,也就是说我们将在网关上终止 TLS 连接,然后在 certificateRefs
中引用了之前创建的 Secret 对象,用于配置网关的凭据。最后通过 allowedRoutes
字段配置了允许的路由,这里我们配置的是将流量路由到 default
命名空间中的所有路由资源对象。
HTTPRoute
配置网关的入口流量路由:# httpbin-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- name: mygateway
namespace: istio-system
hostnames: ["httpbin.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /status
- path:
type: PathPrefix
value: /delay
backendRefs:
- name: httpbin
port: 8000
这里最重要的就是在 parentRefs
字段中引用了之前创建的 Gateway
对象。
kubectl apply -f httpbin-gateway.yaml
kubectl apply -f httpbin-route.yaml
gateway-istio
的 Deployment 和对应的 Service:$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
mygateway-istio-64676bfc88-q8nft 1/1 Running 0 32s
$ kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mygateway-istio LoadBalancer 10.111.175.36 <pending> 15021:31206/TCP,443:32597/TCP 74s
32597
这个 NodePort 端口向 httpbin
服务发送 HTTPS 请求:$ curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:32597:192.168.0.100" --cacert example_certs1/example.com.crt "https://httpbin.example.com:32597/status/418"
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: example_certs1/example.com.crt
CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* subject: O=httpbin organization,CN=httpbin.example.com
* start date: Dec 22 07:13:47 2023 GMT
* expire date: Dec 21 07:13:47 2024 GMT
* common name: httpbin.example.com
* issuer: CN=example.com,O=example Inc.
# ......
-=[ teapot ]=-
_...._
.' _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
| ;/
\_ _/
`"""`
* Connection #0 to host httpbin.example.com left intact
正常我们就可以看到输出一个茶壶,这样我们完成了通过 TLS 来暴露服务。
测试成功。😘
除了 HTTP 路由外,Gateway API 还支持 TCP 和 UDP 路由,配置 TCP 的路由规则,需要使用单独的资源对象 TCPRoute
,如下所示:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tcp-echo-gateway
spec:
gatewayClassName: istio
listeners:
- name: tcp-31400
protocol: TCP
port: 31400
allowedRoutes: # 只允许 TCPRoute 资源对象连接到这个网关
kinds:
- kind: TCPRoute
---
apiVersion: v1
kind: Service
metadata:
name: tcp-echo-v1
spec:
ports:
- port: 9000
name: tcp
selector:
app: tcp-echo
version: v1
---
apiVersion: v1
kind: Service
metadata:
name: tcp-echo-v2
spec:
ports:
- port: 9000
name: tcp
selector:
app: tcp-echo
version: v2
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute # TCPRoute 资源对象
metadata:
name: tcp-echo
spec:
parentRefs: # 引用定义的 Gateway 对象
- name: tcp-echo-gateway
sectionName: tcp-31400
rules:
- backendRefs:
- name: tcp-echo-v1
port: 9000
weight: 80
- name: tcp-echo-v2
port: 9000
weight: 20
其他的流量管理比如故障注入、熔断这些,Gateway API 尚不支持。
但是支持请求超时,比如对 reviews 服务的调用增加一个半秒的请求超时,可以使用下面的资源对象:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: reviews
spec:
parentRefs:
- group: ""
kind: Service
name: reviews
port: 9080
rules:
- backendRefs:
- name: reviews-v2
port: 9080
timeouts:
request: 500ms
上面的对象中我们添加了一个 timeouts
字段,用于设置请求超时时间。
同样还支持流量镜像,如下的资源对象:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- group: ""
kind: Service
name: httpbin
port: 8000
rules:
- filters:
- type: RequestMirror
requestMirror:
backendRef:
name: httpbin-v2
port: 80
backendRefs:
- name: httpbin-v1
port: 80
在上面的资源对象中我们添加了一个 RequestMirror
过滤器,该过滤器用于将流量镜像到另外的服务上去。
我的博客主旨:
🍀 微信二维码
x2675263825 (舍得), qq:2675263825。
🍀 微信公众号
《云原生架构师实战》
🍀 个人博客站点
http://onedayxyy.cn/
🍀 语雀
https://www.yuque.com/xyy-onlyone
🍀 csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421
🍀 知乎
https://www.zhihu.com/people/foryouone
好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!