快捷菜单
常用功能一站直达
更多功能请点顶栏「快捷菜单」
更新于:2024年1月5

[toc]
| 实战名称 |
|---|
| 🚩 实战:Gateway API在istio里的安装及测试-2023.12.23(测试成功) |
| 🚩 实战:配置请求路由-2023.12.27(测试成功) |
| 🚩 实战:路由到指定版本-2023.12.27(测试成功) |
| 🚩 实战:基于用户身份路由-2023.12.27(测试成功) |
| 🚩 实战:基于权重的路由-2023.12.27(测试成功) |
| 🚩 实战:使用 TLS 暴露服务-2023.12.27(测试成功) |
Gateway API 是由 SIG-NETWORK 社区管理的开源项目,项目地址:https://gateway-api.sigs.k8s.io/。
主要原因是 Ingress 资源对象不能很好的满足网络需求,很多场景下 Ingress 控制器都需要通过定义 annotations 或者 crd 来进行功能扩展,这对于使用标准和支持是非常不利的,新推出的 Gateway API 旨在通过可扩展的面向角色的接口来增强服务网络。
Gateway API 是 Kubernetes 中的一个 API 资源集合,包括 GatewayClass、Gateway、HTTPRoute、TCPRoute、Service 等,这些资源共同为各种网络用例构建模型。

Gateway API 最初设计用于管理从集群外部客户端到集群内部服务的流量(入口或北/南情况)。随着时间的推移,服务网格用户的兴趣促使 GAMMA(Gateway API for Service Mesh)计划的创建,以定义 Gateway API 如何用于同一集群内的服务间或东/西流量。
Gateway API 的改进比当前的 Ingress 资源对象有很多更好的设计:
还有一些其他值得关注的功能:
GatewayClasses - GatewayClasses 将负载均衡实现的类型形式化,这些类使用户可以很容易了解到通过 Kubernetes 资源可以获得什么样的能力。无论是道路、电力、数据中心还是 Kubernetes 集群,基础设施都是为了共享而建的,然而共享基础设施提供了一个共同的挑战,那就是如何为基础设施用户提供灵活性的同时还能被所有者控制。
Gateway API 通过对 Kubernetes 服务网络进行面向角色的设计来实现这一目标,平衡了灵活性和集中控制。它允许共享的网络基础设施(硬件负载均衡器、云网络、集群托管的代理等)被许多不同的团队使用,所有这些都受到集群运维设置的各种策略和约束。

一个集群运维人员创建了一个基于 GatewayClass 的 Gateway 资源,这个 Gateway 配置了它所代表的基础网络资源,集群运维和特定的团队必须沟通什么可以附加到这个 Gateway 上来暴露他们的应用。 集中的策略,如 TLS,可以由集群运维在 Gateway 上强制执行,同时,Store 和 Site 应用在他们自己的命名空间中运行,但将他们的路由附加到相同的共享网关上,允许他们独立控制他们的路由逻辑。
这种关注点分离的设计可以使不同的团队能够管理他们自己的流量,同时将集中的策略和控制留给集群运维。
在整个 Gateway API 中涉及到 3 个角色:基础设施提供商、集群管理员、应用开发人员,在某些场景下可能还会涉及到应用管理员等角色。Gateway API 中定义了 3 种主要的资源模型:GatewayClass、Gateway、Route。
GatewayClass 定义了一组共享相同配置和动作的网关。每个 GatewayClass 由一个控制器处理,是一个集群范围的资源,必须至少有一个 GatewayClass 被定义。
这与 Ingress 的 IngressClass 类似,在 Ingress v1beta1 版本中,与 GatewayClass 类似的是
ingress-class注解,而在 Ingress V1 版本中,最接近的就是IngressClass资源对象。
Gateway 网关描述了如何将流量转化为集群内的服务,也就是说,它定义了一个请求,要求将流量从不了解 Kubernetes 的地方转换到集群内的服务。例如,由云端负载均衡器、集群内代理或外部硬件负载均衡器发送到 Kubernetes 服务的流量。
它定义了对特定负载均衡器配置的请求,该配置实现了 GatewayClass 的配置和行为规范,该资源可以由管理员直接创建,也可以由处理 GatewayClass 的控制器创建。
Gateway 可以附加到一个或多个路由引用上,这些路由引用的作用是将流量的一个子集导向特定的服务。
路由资源定义了特定的规则,用于将请求从网关映射到 Kubernetes 服务。从 v1alpha2 版本开始,API 中包含四种 Route 路由资源类型。
HTTPRoute
HTTPRoute 是用于 HTTP 或 HTTPS 连接,适用于我们想要检查 HTTP 请求并使用 HTTP 请求进行路由或修改的场景,比如使用 HTTP Headers 头进行路由,或在请求过程中对它们进行修改。
TLSRoute
TLSRoute 用于 TLS 连接,通过 SNI 进行区分,它适用于希望使用 SNI 作为主要路由方法的地方,并且对 HTTP 等更高级别协议的属性不感兴趣,连接的字节流不经任何检查就被代理到后端。
TCPRoute 和 UDPRoute
TCPRoute(和 UDPRoute)旨在用于将一个或多个端口映射到单个后端。在这种情况下,没有可以用来选择同一端口的不同后端的判别器,所以每个 TCPRoute 在监听器上需要一个不同的端口。你可以使用 TLS,在这种情况下,未加密的字节流会被传递到后端,当然也可以不使用 TLS,这样加密的字节流将传递到后端。
GRPCRoute
GRPCRoute 用于路由 gRPC 流量,支持 GRPCRoute 的网关必须支持 HTTP/2,无需从 HTTP/1 进行初始升级,因此可以确保 gRPC 流量正常进行。
GatewayClass、Gateway、xRoute 和 Service 的组合定义了一个可实施的负载均衡器,下图说明了不同资源之间的关系:

使用反向代理实现的网关的典型客户端/网关 API 请求流程如下所示:
客户端向 http://foo.example.com 发出请求
DNS 将域名解析为 Gateway 网关地址
反向代理在监听器上接收请求,并使用 Host Header 来匹配 HTTPRoute
(可选)反向代理可以根据 HTTPRoute 的匹配规则进行路由
(可选)反向代理可以根据 HTTPRoute 的过滤规则修改请求,即添加或删除 headers
最后,反向代理根据 HTTPRoute 的 forwardTo 规则,将请求转发给集群中的一个或多个对象,即服务。
我们这里主要是讲解 Gateway API 在服务网格中的使用,首先我们先了解下 Gateway API 与 Istio API 的区别。
Gateway API 与 Istio API(如 Gateway 和 VirtualService)有很多相似之处。主资源使用相同的 Gateway 名称,并且这些资源服务于相类似的目标。
新的 Gateway API 致力于从 Kubernetes 的各种 Ingress 实现(包括 Istio)中吸取经验,以构建标准化的,独立于供应商的 API。这些 API 通常与 Istio Gateway 和 VirtualService 具有相同的用途,但依然有一些不同的地方:
HTTPRoute 和 TCPRoute。接下来我们就来了解下如何在 Istio z 中使用 Gateway API。默认情况下 Kubernetes 集群中不会安装 Gateway API。
🚩 实战:Gateway API在istio里的安装及测试-2023.12.23(测试成功)
1k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
2istio v1.19.3(--set profile=demo)实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)

experimental-install.yaml文件:
链接:https://pan.baidu.com/s/1pcuEn2DHsqmDTPX_rtNtLQ?pwd=wwhj
提取码:wwhj
实战:Gateway API在istio里的安装及测试-2023.12.23(测试失败)–最后测试成功了。

1[root@master1 GatewayAPI]#kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/experimental-install.yaml
2customresourcedefinition.apiextensions.k8s.io/backendtlspolicies.gateway.networking.k8s.io created
3customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
4customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
5customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io created
6customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
7customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created
8customresourcedefinition.apiextensions.k8s.io/tcproutes.gateway.networking.k8s.io created
9customresourcedefinition.apiextensions.k8s.io/tlsroutes.gateway.networking.k8s.io created
10customresourcedefinition.apiextensions.k8s.io/udproutes.gateway.networking.k8s.io createdstandard-install.yaml 包括所有已升级为 GA 或 Beta 的资源,包括 GatewayClass、Gateway、HTTPRoute 和 ReferenceGrant,由于 Istio 已经对 Gateway API 提供了支持,所以现在我们就可以直接使用了。
experimental.yaml包括其他的路由对象,比如 TLSRoute、TCPRoute、UDPRoute 等。
istio 的 GatewayClass 资源对象,如下所示(另外还有一个名为 istio-remote): 1[root@master1 GatewayAPI]#kubectl get gatewayclass
2NAME CONTROLLER ACCEPTED AGE
3istio istio.io/gateway-controller True 13m
4istio-remote istio.io/unmanaged-gateway True 13m
5[root@master1 GatewayAPI]#kubectl get gatewayclass istio -oyaml
6apiVersion: gateway.networking.k8s.io/v1
7kind: GatewayClass
8metadata:
9……
10spec:
11 controllerName: istio.io/gateway-controller
12 description: The default Istio GatewayClass
13……
14[root@master1 GatewayAPI]#因为大部分场景下在一个 Kubernetes 集群中只会有一个 Istio 集群,所以我们可以直接使用默认的 istio 这个 GatewayClass,如果你有多个 Istio 集群,那么你可以创建多个 GatewayClass 来区分不同的集群。
比如接下来我们来尝试将 httpbin 应用使用 Gateway API 暴露到外部。
1kubectl apply -f samples/httpbin/httpbin.yamlGateway 资源对象Gateway 资源对象,用于将流量从外部负载均衡器转发到集群内的服务,如下所示: 1# default-gateway.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: Gateway
4metadata:
5 name: gateway
6 namespace: istio-ingress # 网关资源对象所在的命名空间
7spec:
8 gatewayClassName: istio # 使用默认的 istio GatewayClass
9 listeners: # 监听器
10 - name: default
11 hostname: "*.example.com"
12 port: 80
13 protocol: HTTP
14 allowedRoutes: # 允许的路由
15 namespaces:
16 from: All # 允许所有命名空间Gateway 代表了逻辑负载均衡器的实例化,它是根据一个 istio 这个 GatewayClass 进行模板化的,网关在 80 端口上监听 HTTP 流量,这个特定的 GatewayClass 在部署后会自动分配一个 IP 地址,该地址会显示在 Gateway.status 中。
🔱 注意:
需要注意的是这里我们声明使用的命名空间为
istio-ingress, 这是因为 Istio Gateway 可以直接使用 istio ingressgateway 的 Deployment,而这个 Deployment 默认是部署在istio-system命名空间中的,我们这里单独将Gateway资源对象创建在istio-ingress命名空间中,那么就会自动在这个命名空间中部署一个网关控制器,用于区分默认的 istio ingressgateway。
istio-ingress 命名空间中创建这个 Gateway 资源对象,这样才能让 istio ingressgateway 通过 Gateway 资源对象来获取配置。1kubectl create namespace istio-ingress 1$ kubectl apply -f default-gateway.yaml
2
3##查看
4[root@master1 Gateway]#kubectl get po,deployment,svc,gateway -nistio-ingress
5NAME READY STATUS RESTARTS AGE
6pod/gateway-istio-7474cd4d9b-mg9qg 1/1 Running 0 91s
7
8NAME READY UP-TO-DATE AVAILABLE AGE
9deployment.apps/gateway-istio 1/1 1 1 91s
10
11NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
12service/gateway-istio LoadBalancer 10.96.149.21 <pending> 15021:31861/TCP,80:31415/TCP 91s
13
14NAME CLASS ADDRESS PROGRAMMED AGE
15gateway.gateway.networking.k8s.io/gateway istio False 91s
16[root@master1 Gateway]#我们也可以去对比下上面生成的 gateway-istio 和 Istio 默认的 istio-ingressgateway 的 Deployment,他们的配置几乎是一样的。
🔰
完了,又报错了(已解决😘)
最终通过升级机器内核解决了。
这里排查记录就放这里把,太坑了,太菜了哦哈哈🤣

1Events:
2 Type Reason Age From Message
3 ---- ------ ---- ---- -------
4 Normal Scheduled 4m23s default-scheduler Successfully assigned istio-ingress/gateway-istio-7474cd4d9b-pkmsr to node2
5 Warning FailedCreatePodSandBox 6s (x20 over 4m21s) kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: open /proc/sys/net/ipv4/ip_unprivileged_port_start: no such file or directory: unknown
6[root@master1 GatewayAPI]# 1[root@master1 GatewayAPI]#kubectl get gateway -nistio-ingress
2NAME CLASS ADDRESS PROGRAMMED AGE
3gateway istio False 5m50s
4[root@master1 GatewayAPI]#kubectl get po -nistio-ingress
5NAME READY STATUS RESTARTS AGE
6gateway-istio-7474cd4d9b-pkmsr 0/1 ContainerCreating 0 5m52s
7[root@master1 GatewayAPI]#kubectl get svc -nistio-ingress
8NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
9gateway-istio LoadBalancer 10.100.204.5 <pending> 15021:32204/TCP,80:31157/TCP 5m54s
10[root@master1 GatewayAPI]#感觉像是底层pod sandbox–pause??问题??;
可能和这个有关系:。。。。例如 containerd 或 runc 的正确版本。


再次gpt
error during container init: open /proc/sys/net/ipv4/ip_unprivileged_port_start: no such file or directory: unknown
这个错误信息表明在容器初始化时发生了问题,具体是无法找到 /proc/sys/net/ipv4/ip_unprivileged_port_start 文件或目录。这个文件通常是 Linux 内核中的一部分,用于设置非特权端口的起始范围。
以下是一些建议的解决方法:
检查文件是否存在:
执行以下命令,确保 /proc/sys/net/ipv4/ip_unprivileged_port_start 文件或目录确实存在:
1bashls /proc/sys/net/ipv4/ip_unprivileged_port_start如果文件不存在,可能是因为内核配置不同或者缺少相关的内核模块。这时,你可以考虑检查内核配置,确保相关功能已启用。
检查内核配置:
检查系统的内核配置,确保启用了相应的网络参数。你可以通过查看 /boot/config-$(uname -r) 文件来检查当前内核的配置:
1bashcat /boot/config-$(uname -r) | grep IPV4确保类似 CONFIG_IPV4=y 或 CONFIG_IP_MULTIPLE_TABLES=y 的配置项是启用的。
重新加载内核模块:
如果涉及到内核模块,尝试重新加载相关的模块。例如,如果涉及到 iptables 相关的问题,你可以尝试重新加载 iptables 模块:
1bashmodprobe iptable_filter这是一个示例,具体命令可能因问题的性质而异。
更新内核:
检查容器运行时配置:
检查 SELinux 或 AppArmor:
通过上述步骤,你可以逐步排除问题并找到解决方案。如果问题仍然存在,可能需要更深入的系统调查或者查看详细的容器运行时日志以获取更多信息。
🔰 看来要升级下内核测试了……

node2节点kubelet有报错

排查方法

我删除下flannel看下把。。。
1[root@master1 ~]#kubectl get po -nkube-flannel -owide
2NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
3kube-flannel-ds-2ndhl 1/1 Running 1 (11d ago) 44d 172.29.9.62 node1 <none> <none>
4kube-flannel-ds-m44dc 1/1 Running 1 (11d ago) 44d 172.29.9.61 master1 <none> <none>
5kube-flannel-ds-s4787 1/1 Running 3 (5m10s ago) 44d 172.29.9.63 node2 <none> <none>
6[root@master1 ~]#kubectl delete po kube-flannel-ds-s4787 -n kube-flannel
7pod "kube-flannel-ds-s4787" deleted
8
9##已重建
10[root@master1 ~]#kubectl delete po kube-flannel-ds-s4787 -n kube-flannel
11pod "kube-flannel-ds-s4787" deleted
12[root@master1 ~]#kubectl get po -nkube-flannel -owide
13NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
14kube-flannel-ds-2ndhl 1/1 Running 1 (11d ago) 44d 172.29.9.62 node1 <none> <none>
15kube-flannel-ds-m44dc 1/1 Running 1 (11d ago) 44d 172.29.9.61 master1 <none> <none>
16kube-flannel-ds-mkh5z 1/1 Running 0 14s 172.29.9.63 node2 <none> <none>
17[root@master1 ~]#还是不行。。。


pause版本
1 Warning FailedCreatePodSandBox 12m (x3 over 14m) kubelet Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image "registry.k8s.io/pause:3.6": failed to pull image "registry.k8s.io/pause:3.6": failed to pull and unpack image "registry.k8s.io/pause:3.6": failed to resolve reference "registry.k8s.io/pause:3.6": failed to do request: Head "https://us-west2-docker.pkg.dev/v2/k8s-artifacts-prod/images/pause/manifests/3.6": dial tcp 173.194.174.82:443: i/o timeout
2
3
4
5sed -i 's/registry.k8s.io\/pause:3.6/registry.aliyuncs.com\/google_containers\/pause:3.9/g' /etc/containerd/config.toml 重启node2后,一直卡在这里。。。

如何在Gatway API官网里查看对应的依赖呢???;–没找到。。。;
这里先把runc给升级到最新版本吧。。。。;
当前node2上runc版本:
1[root@node2 ~]#runc --version
2runc version 1.1.5
3commit: v1.1.5-0-gf19387a6
4spec: 1.0.2-dev
5go: go1.19.7
6libseccomp: 2.5.1
7[root@node2 ~]#但是runc是依赖于contaerind的呀,自己和老师containerd是一致的娃。。。;

结论:k8s里网络问题排查起来好难哦😭
放弃了几天
这里记录下就好,这个问题有点难搞……
1[root@master1 ~]#ssh node2
2Last login: Sat Dec 23 08:48:26 2023 from master1
3[root@node2 ~]#ctr -n k8s.io i ls -q|grep pause
4registry.aliyuncs.com/k8sxio/pause:3.8
5registry.aliyuncs.com/k8sxio/pause@sha256:67cc096c2abe1f29ece08439b509738a5cd11f8ff87851a06d092772d52c090e
6[root@node2 ~]#无非就是容器运行时问题?
runc?
containerd?
pause版本?
k8s版本?(不至于呀……)
记得当时我的环境和老师的是基本一致的哇……。。。;
如果这个gateway部署有问题,那么后续的
灰度测试也是没法正常测试的呀。。。;
该怎么排查呢……啊啊啊(先)
🔰
2023.1.3 升级内核测试(完美解决)
1[root@node2 ~]#uname -r
23.10.0-957.el7.x86_64给当前机器做快照
开始升级
……
1[root@master1 ~]#uname -a
2Linux master1 5.4.265-1.el7.elrepo.x86_64 #1 SMP Wed Dec 20 13:57:20 EST 2023 x86_64 x86_64 x86_64 GNU/Linux
3[root@master1 ~]#ssh node1 uname -a
4Linux node1 5.4.265-1.el7.elrepo.x86_64 #1 SMP Wed Dec 20 13:57:20 EST 2023 x86_64 x86_64 x86_64 GNU/Linux
5[root@master1 ~]#ssh node2 uname -a
6Linux node2 5.4.265-1.el7.elrepo.x86_64 #1 SMP Wed Dec 20 13:57:20 EST 2023 x86_64 x86_64 x86_64 GNU/Linux
7[root@master1 ~]# 1[root@master1 Gateway]#kubectl get po,deployment,svc,gateway -nistio-ingress
2NAME READY STATUS RESTARTS AGE
3pod/gateway-istio-7474cd4d9b-mg9qg 1/1 Running 0 91s
4
5NAME READY UP-TO-DATE AVAILABLE AGE
6deployment.apps/gateway-istio 1/1 1 1 91s
7
8NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
9service/gateway-istio LoadBalancer 10.96.149.21 <pending> 15021:31861/TCP,80:31415/TCP 91s
10
11NAME CLASS ADDRESS PROGRAMMED AGE
12gateway.gateway.networking.k8s.io/gateway istio False 91s
13[root@master1 Gateway]#一般在测试集群实验时,一定要把内核都给升级下,不然会出现很多奇怪的问题的;
HTTPRoute 资源对象来定义路由规则HTTPRoute 资源对象来定义这个路由规则,如下所示: 1# httpbin-route.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: HTTPRoute
4metadata:
5 name: httpbin
6 namespace: default
7spec:
8 parentRefs: # 引用定义的 Gateway 对象
9 - name: gateway
10 namespace: istio-ingress
11 hostnames: ["httpbin.example.com"] # 域名
12 rules: # 具体的路由规则
13 - matches:
14 - path:
15 type: PathPrefix
16 value: /get # 匹配 /get 的请求
17 backendRefs: # 引用的后端服务
18 - name: httpbin
19 port: 8000在上面的 HTTPRoute 对象中我们通过 parentRefs 字段指定要连接到的网关,只要网关允许这种连接,这将允许路由接收来自父网关的流量,在 backendRefs 中定义将要发送流量的后端。但是需要注意我们这里只定义了匹配 /get 这个路径的请求,然后将要访问的域名通过 hostnames 来定义。
1$ kubectl apply -f httpbin-route.yaml
2$ kubectl get httproute
3NAME HOSTNAMES AGE
4httpbin ["httpbin.example.com"] 5shttpbin.example.com 来访问 httpbin 应用了:1# $ export INGRESS_HOST=$(kubectl get gateways.gateway.networking.k8s.io gateway -n istio-ingress -ojsonpath='{.status.addresses[0].value}')
2export GATEWAY_URL=$(kubectl get po -l istio.io/gateway-name=gateway -n istio-ingress -o 'jsonpath={.items[0].status.hostIP}'):$(kubectl get svc gateway-istio -n istio-ingress -o 'jsonpath={.spec.ports[?(@.name=="default")].nodePort}')如果你的集群可以正常使用 LoadBalancer,那么 Gateway 控制器在部署后会自动分配一个 IP 地址,该地址会显示在 Gateway.status 中。我们这里暂不支持,所以还是可以通过 NodePort 方式来进行访问。

curl 访问 httpbin 服务: 1[root@master1 Gateway]#curl -s -HHost:httpbin.example.com "http://$GATEWAY_URL/get"
2{
3 "args": {},
4 "headers": {
5 "Accept": "*/*",
6 "Host": "httpbin.example.com",
7 "User-Agent": "curl/7.29.0",
8 "X-B3-Parentspanid": "ae0fb00234efbb67",
9 "X-B3-Sampled": "1",
10 "X-B3-Spanid": "def5a89d6387f5fc",
11 "X-B3-Traceid": "5ecf2622a7a30d2dae0fb00234efbb67",
12 "X-Envoy-Attempt-Count": "1",
13 "X-Envoy-Internal": "true",
14 "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=694397dba4ec481e805af11e29e6be30f330f509364307c8e997d1be3f1119fb;Subject=\"\";URI=spiffe://cluster.local/ns/istio-ingress/sa/gateway-istio"
15 },
16 "origin": "10.244.2.1",
17 "url": "http://httpbin.example.com/get"
18}
19[root@master1 Gateway]#curl -I -s -HHost:httpbin.example.com "http://$GATEWAY_URL/get"
20HTTP/1.1 200 OK
21server: istio-envoy
22date: Fri, 05 Jan 2024 07:36:26 GMT
23content-type: application/json
24content-length: 663
25access-control-allow-origin: *
26access-control-allow-credentials: true
27x-envoy-upstream-service-time: 9请注意,使用 -H 标志可以将 Host HTTP 标头设置为 httpbin.example.com。这一步是必需的,因为 HTTPRoute 已配置为处理 httpbin.example.com 的请求,但是在测试环境中,该主机没有 DNS 绑定,只是将请求发送到入口 IP。
1[root@master1 Gateway]#curl -s -I -HHost:httpbin.example.com "http://$GATEWAY_URL/headers"
2HTTP/1.1 404 Not Found
3date: Fri, 05 Jan 2024 07:35:14 GMT
4server: istio-envoy
5transfer-encoding: chunkedgateway-istio 的日志,可以看到类似于下面的日志:1$ kubectl -n istio-ingress logs -f gateway-istio-7474cd4d9b-8dw2k
2# ......
32023-12-18T07:04:33.164968Z info cache returned workload trust anchor from cache ttl=23h59m59.835033638s
42023-12-18T07:04:33.621616Z info Readiness succeeded in 813.201909ms
52023-12-18T07:04:33.621946Z info Envoy proxy is ready
6[2023-12-18T07:29:11.177Z] "HEAD /get HTTP/1.1" 200 - via_upstream - "-" 0 0 2 2 "10.244.1.1" "curl/7.29.0" "68f51e89-8125-4d9e-be36-e0cdc6e6ead8" "httpbin.example.com" "10.244.1.131:80" outbound|8000||httpbin.default.svc.cluster.local 10.244.1.132:46066 10.244.1.132:80 10.244.1.1:55626 - default.httpbin.0
7[2023-12-18T07:31:52.051Z] "HEAD /headers HTTP/1.1" 404 NR route_not_found - "-" 0 0 0 - "10.244.1.1" "curl/7.29.0" "a9a1002f-d65c-40d8-861d-ec99d4a4a442" "httpbin.example.com" "-" - - 10.244.1.132:80 10.244.1.1:53583 - -证明我们的路由规则已经生效了。
🔰 进一步测试
/headers 路由,那么我们可以更新下 HTTPRoute 对象: 1# httpbin-route.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: HTTPRoute
4metadata:
5 name: httpbin
6 namespace: default
7spec:
8 parentRefs: # 引用定义的 Gateway 对象
9 - name: gateway
10 namespace: istio-ingress
11 hostnames: ["httpbin.example.com"] # 域名
12 rules: # 具体的路由规则
13 - matches:
14 - path:
15 type: PathPrefix
16 value: /get # 匹配 /get 的请求
17 - path:
18 type: PathPrefix
19 value: /headers # 匹配 /headers 的请求
20 filters:
21 - type: RequestHeaderModifier # 添加一个修改请求头的过滤器
22 requestHeaderModifier:
23 add: # 添加一个标头
24 - name: my-added-header
25 value: added-value
26 backendRefs: # 引用的后端服务
27 - name: httpbin
28 port: 8000我们除了在 rules 中添加了一个匹配 /headers 的规则外,还添加了一个 RequestHeaderModifier 过滤器,用于添加一个 Header 头信息。
/headers,注意到 My-Added-Header 标头已被添加到请求中了: 1[root@master1 Gateway]#kubectl apply -f httpbin-route.yaml
2httproute.gateway.networking.k8s.io/httpbin configured
3
4[root@master1 Gateway]# curl -s -HHost:httpbin.example.com "http://$GATEWAY_URL/headers"
5{
6 "headers": {
7 "Accept": "*/*",
8 "Host": "httpbin.example.com",
9 "My-Added-Header": "added-value",
10 "User-Agent": "curl/7.29.0",
11 "X-B3-Parentspanid": "05845cb74fa4dd1a",
12 "X-B3-Sampled": "1",
13 "X-B3-Spanid": "6c96baf13d681b45",
14 "X-B3-Traceid": "54df57c881116cfa05845cb74fa4dd1a",
15 "X-Envoy-Attempt-Count": "1",
16 "X-Envoy-Internal": "true",
17 "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=694397dba4ec481e805af11e29e6be30f330f509364307c8e997d1be3f1119fb;Subject=\"\";URI=spiffe://cluster.local/ns/istio-ingress/sa/gateway-istio"
18 }
19}
20[root@master1 Gateway]#在上面的示例中,在配置网关之前,我们并没有去安装 Ingress 网关的 Deployment,因为在默认配置中会根据 Gateway 配置自动分发网关 Deployment 和 Service。但是对于高级别的场景可能还是需要去手动部署。
测试结束。😘
1、自动部署
默认情况下,每个 Gateway 将自动提供相同名称的 Service 和 Deployment。如果 Gateway 发生变化(例如添加了一个新端口),这些配置将会自动更新。这些资源可以通过以下几种方式进行定义:
将 Gateway 上的注解和标签复制到 Service 和 Deployment。这就允许配置从上述字段中读取到的内容,如配置内部负载均衡器等。Istio 提供了一个额外的注解来配置生成的资源:
networking.istio.io/service-type:控制 Service.spec.type 字段。例如设置 ClusterIP 为不对外暴露服务,将会默认为 LoadBalancer。通过配置 addresses 字段可以显式设置 Service.spec.loadBalancerIP 字段:
1apiVersion: gateway.networking.k8s.io/v1
2kind: Gateway
3metadata:
4 name: gateway
5spec:
6 addresses:
7 - value: 192.0.2.0 # 仅能指定一个地址
8 type: IPAddress2、手动部署
如果您不希望使用自动部署,可以进行手动配置 Deployment 和 Service。完成此选项后,您将需要手动将 Gateway 链接到 Service,并保持它们的端口配置同步。
要将 Gateway 链接到 Service,需要将 addresses 字段配置为指向单个 Hostname。
1apiVersion: gateway.networking.k8s.io/v1beta1
2kind: Gateway
3metadata:
4 name: gateway
5spec:
6 addresses:
7 - value: ingress.istio-gateways.svc.cluster.local
8 type: Hostname当然我们这里只是一个最简单的示例,我们将在后面的课程中继续介绍 Gateway API 的更多功能。
接下来我们来了解下如果通过 Gateway API 将请求动态路由到微服务的多个版本。
同样我们这里以 Bookinfo 示例为例(首先要部署 Bookinfo 应用),我们首先将所有流量路由到微服务的 v1 (版本 1),然后将应用规则根据 HTTP 请求 header 的值路由流量。
🚩 实战:配置请求路由-2023.12.27(测试成功)
1k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
2istio 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 资源对象,如下所示:
1# bookinfo-gateway.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: Gateway
4metadata:
5 name: bookinfo-gateway
6spec:
7 gatewayClassName: istio
8 listeners:
9 - name: http
10 port: 80
11 protocol: HTTP
12 allowedRoutes:
13 namespaces:
14 from: Same上面的 Gateway 资源对象与之前的示例类似,只是这里我们将 allowedRoutes 设置为 Same,表示允许同一命名空间中的所有路由资源对象都可以连接到这个网关。
HTTPRoute 资源对象,如下所示: 1# productpage-route.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: HTTPRoute
4metadata:
5 name: bookinfo
6spec:
7 parentRefs:
8 - name: bookinfo-gateway # 引用上面定义的 Gateway 对象
9 rules:
10 - matches:
11 - path:
12 type: Exact
13 value: /productpage
14 - path:
15 type: PathPrefix
16 value: /static
17 - path:
18 type: Exact
19 value: /login
20 - path:
21 type: Exact
22 value: /logout
23 - path:
24 type: PathPrefix
25 value: /api/v1/products
26 backendRefs:
27 - name: productpage # 引用的后端服务
28 port: 9080和以前 VirtualService 的类似,我们为 Productpage 应用配置了几个路由规则,这样我们就可以在页面上正常访问应用了。
1kubectl apply -f bookinfo-gateway.yaml
2kubectl apply -f productpage-route.yamlGateway 对象后,会自动在 default 命名空间中部署一个 gateway-istio 的 Deployment 和 对应的 Service:1[root@master1 Gateway]#kubectl get pods -l istio.io/gateway-name=bookinfo-gateway
2NAME READY STATUS RESTARTS AGE
3bookinfo-gateway-istio-548556df95-rmkh2 1/1 Running 0 53s
4[root@master1 Gateway]#kubectl get svc bookinfo-gateway-istio
5NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
6bookinfo-gateway-istio LoadBalancer 10.99.231.169 <pending> 15021:30661/TCP,80:30715/TCP 66s
7[root@master1 Gateway]#30715 这个 NodePort 端口来访问 Productpage 应用了:
测试结束。😘
同样的页面上的评论区域会出现 3 种不同的状态,因为我们背后有 3 个不同的版本的评论服务。
🚩 实战:路由到指定版本-2023.12.27
1k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
2istio v1.19.3(--set profile=demo)实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)

HTTPRoute 资源对象,首先将流量路由到 v1 版本: 1# route-reviews-v1.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: HTTPRoute
4metadata:
5 name: reviews
6spec:
7 parentRefs: # 这里我们引用的是 reviews 这个 Service 对象
8 - group: ""
9 kind: Service
10 name: reviews
11 port: 9080
12 rules:
13 - backendRefs:
14 - name: reviews-v1
15 port: 9080注意上面的资源对象中我们是通过 parentRefs 字段引用的是 reviews 这个 Service 对象,而不是 Gateway 对象了,因为我们流量并不是从 Gateway 直接过来的,而是通过 Productpage 访问 reviews 服务,也就是 Service 对象。然后背后的我们会将流量全部路由到 v1 版本的 reviews 服务 reviews-v1。
1kubectl apply -f route-reviews-v1.yaml不过这里需要注意不同于 Istio API 使用 DestinationRule 子集来定义服务的版本, Kubernetes Gateway API 将为此使用后端 Service 服务来进行定义。
reviews 服务创建后端服务定义:1kubectl apply -f samples/bookinfo/platform/kube/bookinfo-versions.yamlreviews:v1,而此版本的服务不访问星级评分服务。
测试结束。😘
接下来我们来更改路由配置,将来自特定用户的所有流量路由到特定服务版本,比如将来自名为 Jason 的用户的所有流量被路由到服务 reviews:v2(包含星级评分功能的版本)。
🚩 实战:基于用户身份路由-2023.12.27(测试成功)
1k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
2istio v1.19.3(--set profile=demo)实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)

HTTPRoute 资源对象: 1# route-reviews-jason-v2.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: HTTPRoute
4metadata:
5 name: reviews
6spec:
7 parentRefs:
8 - group: ""
9 kind: Service
10 name: reviews
11 port: 9080
12 rules:
13 - matches:
14 - headers: # 匹配请求头 end-user: jason
15 - name: end-user
16 value: jason
17 backendRefs:
18 - name: reviews-v2
19 port: 9080
20 - backendRefs:
21 - name: reviews-v1
22 port: 9080在上面的 HTTPRoute 资源对象中,我们将访问 reviews 的流量分为两个规则,第一个规则匹配请求头 end-user: jason,然后将流量路由到 reviews-v2 服务,第二个则是如果不匹配将流量路由到 reviews-v1 服务。
1kubectl apply -f route-reviews-jason-v2.yamljason 身份进行登录,登录后无论如何刷新浏览器,我们将始终在页面上看到黑色的星级评分,也就是 reviews 的 v2 版本。
我们也可以切换成其他用户,或者不登录,刷新浏览器,那么就不会显示星级评分了。
测试成功。😘
接下来我们再来测试下基于权重的路由,常常我们有将流量从微服务的一个版本逐步迁移到另一个版本的需求,同样使用 Gateway API 来实现也非常简单。
下面我们将会把 50% 的流量发送到 reviews:v1,另外,50% 的流量发送到 reviews:v3。接着,再把 100% 的流量发送到 reviews:v3 来完成迁移。
🚩 实战:基于权重的路由-2023.12.27(测试成功)
1k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
2istio v1.19.3(--set profile=demo)实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)

1kubectl apply -f route-reviews-v1.yamlreviews:v1 转移到 reviews:v3: 1# route-reviews-50-v3.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: HTTPRoute
4metadata:
5 name: reviews
6spec:
7 parentRefs:
8 - group: ""
9 kind: Service
10 name: reviews
11 port: 9080
12 rules:
13 - backendRefs:
14 - name: reviews-v1
15 port: 9080
16 weight: 50
17 - name: reviews-v3
18 port: 9080
19 weight: 50上面的对象中在 backendRefs 中我们使用了一个 weight 字段,用于设置权重,这里我们将 reviews-v1 和 reviews-v3 的权重都设置为 50,也就是说将流量平均分配到这两个版本的服务上。
1kubectl apply -f route-reviews-50-v3.yaml等待几秒钟,等待新的规则传播到代理中生效,然后我们再次刷新浏览器中的 productpage 页面,大约有 50% 的几率会看到页面中带红色星级的评价内容。 这是因为 reviews 的 v3 版本可以访问带星级评价,但 v1 版本不能。
如果你认为 reviews:v3 微服务已经稳定,那么接下来我们就可以将 100% 的流量路由 reviews:v3:
1# route-reviews-v3.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: HTTPRoute
4metadata:
5 name: reviews
6spec:
7 parentRefs:
8 - group: ""
9 kind: Service
10 name: reviews
11 port: 9080
12 rules:
13 - backendRefs:
14 - name: reviews-v3
15 port: 90801kubectl apply -f route-reviews-v3.yaml
测试成功😘。
接下来我们来看下如何通过 TLS 来暴露服务,这里我们以 httpbin 示例进行说明。
🚩 实战:使用 TLS 暴露服务-2023.12.27
1k8s v1.27.6(containerd://1.6.20)(cni:flannel:v0.22.2)
2istio v1.19.3(--set profile=demo)实验软件:
链接:https://pan.baidu.com/s/1pMnJxgL63oTlGFlhrfnXsA?pwd=7yqb
提取码:7yqb
2023.11.5-实战:BookInfo 示例应用-2023.11.5(测试成功)

1kubectl apply -f samples/httpbin/httpbin.yaml然后接下来生成客户端和服务器证书和密钥,这里我们使用 openssl 工具来生成。
1$ mkdir example_certs1
2$ 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.crthttpbin.example.com 创建证书和私钥:1$ 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"
2$ 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.crt1kubectl create -n istio-system secret tls httpbin-credential \
2 --key=example_certs1/httpbin.example.com.key \
3 --cert=example_certs1/httpbin.example.com.crt 1# httpbin-gateway.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: Gateway
4metadata:
5 name: mygateway
6 namespace: istio-system
7spec:
8 gatewayClassName: istio
9 listeners:
10 - name: https
11 hostname: "httpbin.example.com"
12 port: 443
13 protocol: HTTPS
14 tls:
15 mode: Terminate
16 certificateRefs:
17 - name: httpbin-credential
18 allowedRoutes:
19 namespaces:
20 from: Selector
21 selector:
22 matchLabels:
23 kubernetes.io/metadata.name: default在上面的对象中我们配置了 HTTPS 协议,并在 tls 中配置使用 Terminate 模式,也就是说我们将在网关上终止 TLS 连接,然后在 certificateRefs 中引用了之前创建的 Secret 对象,用于配置网关的凭据。最后通过 allowedRoutes 字段配置了允许的路由,这里我们配置的是将流量路由到 default 命名空间中的所有路由资源对象。
HTTPRoute 配置网关的入口流量路由: 1# httpbin-route.yaml
2apiVersion: gateway.networking.k8s.io/v1
3kind: HTTPRoute
4metadata:
5 name: httpbin
6spec:
7 parentRefs:
8 - name: mygateway
9 namespace: istio-system
10 hostnames: ["httpbin.example.com"]
11 rules:
12 - matches:
13 - path:
14 type: PathPrefix
15 value: /status
16 - path:
17 type: PathPrefix
18 value: /delay
19 backendRefs:
20 - name: httpbin
21 port: 8000这里最重要的就是在 parentRefs 字段中引用了之前创建的 Gateway 对象。
1kubectl apply -f httpbin-gateway.yaml
2kubectl apply -f httpbin-route.yamlgateway-istio 的 Deployment 和对应的 Service:1$ kubectl get pods -n istio-system
2NAME READY STATUS RESTARTS AGE
3mygateway-istio-64676bfc88-q8nft 1/1 Running 0 32s
4$ kubectl get svc -n istio-system
5NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
6mygateway-istio LoadBalancer 10.111.175.36 <pending> 15021:31206/TCP,443:32597/TCP 74s32597 这个 NodePort 端口向 httpbin 服务发送 HTTPS 请求: 1$ 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"
2
3* Initializing NSS with certpath: sql:/etc/pki/nssdb
4* CAfile: example_certs1/example.com.crt
5 CApath: none
6* SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
7* Server certificate:
8* subject: O=httpbin organization,CN=httpbin.example.com
9* start date: Dec 22 07:13:47 2023 GMT
10* expire date: Dec 21 07:13:47 2024 GMT
11* common name: httpbin.example.com
12* issuer: CN=example.com,O=example Inc.
13# ......
14
15 -=[ teapot ]=-
16
17 _...._
18 .' _ _ `.
19 | ."` ^ `". _,
20 \_;`"---"`|//
21 | ;/
22 \_ _/
23 `"""`
24* Connection #0 to host httpbin.example.com left intact正常我们就可以看到输出一个茶壶,这样我们完成了通过 TLS 来暴露服务。
测试成功。😘
除了 HTTP 路由外,Gateway API 还支持 TCP 和 UDP 路由,配置 TCP 的路由规则,需要使用单独的资源对象 TCPRoute,如下所示:
1apiVersion: gateway.networking.k8s.io/v1
2kind: Gateway
3metadata:
4 name: tcp-echo-gateway
5spec:
6 gatewayClassName: istio
7 listeners:
8 - name: tcp-31400
9 protocol: TCP
10 port: 31400
11 allowedRoutes: # 只允许 TCPRoute 资源对象连接到这个网关
12 kinds:
13 - kind: TCPRoute
14---
15apiVersion: v1
16kind: Service
17metadata:
18 name: tcp-echo-v1
19spec:
20 ports:
21 - port: 9000
22 name: tcp
23 selector:
24 app: tcp-echo
25 version: v1
26---
27apiVersion: v1
28kind: Service
29metadata:
30 name: tcp-echo-v2
31spec:
32 ports:
33 - port: 9000
34 name: tcp
35 selector:
36 app: tcp-echo
37 version: v2
38---
39apiVersion: gateway.networking.k8s.io/v1alpha2
40kind: TCPRoute # TCPRoute 资源对象
41metadata:
42 name: tcp-echo
43spec:
44 parentRefs: # 引用定义的 Gateway 对象
45 - name: tcp-echo-gateway
46 sectionName: tcp-31400
47 rules:
48 - backendRefs:
49 - name: tcp-echo-v1
50 port: 9000
51 weight: 80
52 - name: tcp-echo-v2
53 port: 9000
54 weight: 20其他的流量管理比如故障注入、熔断这些,Gateway API 尚不支持。
但是支持请求超时,比如对 reviews 服务的调用增加一个半秒的请求超时,可以使用下面的资源对象:
1apiVersion: gateway.networking.k8s.io/v1
2kind: HTTPRoute
3metadata:
4 name: reviews
5spec:
6 parentRefs:
7 - group: ""
8 kind: Service
9 name: reviews
10 port: 9080
11 rules:
12 - backendRefs:
13 - name: reviews-v2
14 port: 9080
15 timeouts:
16 request: 500ms上面的对象中我们添加了一个 timeouts 字段,用于设置请求超时时间。
同样还支持流量镜像,如下的资源对象:
1apiVersion: gateway.networking.k8s.io/v1
2kind: HTTPRoute
3metadata:
4 name: httpbin
5spec:
6 parentRefs:
7 - group: ""
8 kind: Service
9 name: httpbin
10 port: 8000
11 rules:
12 - filters:
13 - type: RequestMirror
14 requestMirror:
15 backendRef:
16 name: httpbin-v2
17 port: 80
18 backendRefs:
19 - name: httpbin-v1
20 port: 80在上面的资源对象中我们添加了一个 RequestMirror 过滤器,该过滤器用于将流量镜像到另外的服务上去。
我的博客主旨:
🍀 微信二维码
x2675263825 (舍得), qq:2675263825。

🍀 微信公众号
《云原生架构师实战》

🍀 个人博客站点


🍀 语雀
https://www.yuque.com/xyy-onlyone

🍀 csdn
https://blog.csdn.net/weixin_39246554?spm=1010.2135.3001.5421

🍀 知乎
https://www.zhihu.com/people/foryouone

好了,关于本次就到这里了,感谢大家阅读,最后祝大家生活快乐,每天都过的有意义哦,我们下期见!

日历 · 精选 · 友链 · 更多
如果内容对你有帮助,欢迎请我喝杯咖啡 ☕



One的公众号
爱折腾博客的小白