简介
本文将介绍如何将vanilla ingress对象转换为Istio虚拟服务HTTP路由。它不会深入研究为什么这可能是必要的,也不会深入研究Istio的任何特殊功能。
问题描述
将仅仅使用前缀的对象从ingress转换到Istio是非常直接的。当被转换的对象中使用了Nginx重写目标时,事情就变得有点棘手了。Istio的虚拟服务文档非常好,涵盖了流量如何通过网关被转发。
提示、技巧和需要知道的事情
根据Istio的文档,HTTP路由是 "HTTP流量的有序路由列表。匹配传入请求的第一条规则被使用"。Istio将应用一个虚拟服务,其前缀永远不会被击中,但也会非常有帮助地提供一个消息,说明这个事实。
下面这个虚拟服务的例子将被用来触发一个错误。
关于这个虚拟服务需要注意的是,"/"被定义为"/api "之前的前缀,这意味着第一个HTTP路由将捕获每一个请求,甚至那些绑定在"/api "的请求。
而且,正如预期的那样,会产生一个警告。
[root@server:~]
所以Istio会很高兴地让你创建一个虚拟服务,其路由将永远不会被击中,并像...
重写目标
棘手的部分来自于重写目标,它被用来将URL从入口控制器看到的内容改为Pod期望看到的其他内容。
Nginx
Nginx重写目标的方式是通过对入口对象的注释。
Nginx入口对象
这个Ingress对象是旧的,但它是这篇文章的灵感来源,所以我们要用它来滚动。需要注意的是,从K8s 1.18开始,pathType是一个必要参数。
这个规则的作用是捕获所有进入入口控制器的流量,匹配以"/gateway/"开头的任何内容,删除"/gateway/",然后将请求传递给pod。如果URI在"/gateway/"之后还有其他部分,那么在请求被传递到pod时,它仍然是URI的一部分。希望一个例子能使事情变得更清楚。
重写目标实例
这种行为是由gist第6行的唯一注释完成的,"/$2 "是一个捕获组,是正则表达式中的一个结构(进一步阅读这里)。在这个正则表达式的位子上放一个针,它就会重新出现了。
Istio
现在考虑如何在Istio中实现这一目标,注意力转向Istio虚拟服务,因为它是控制流量如何被路由的对象,特别是在虚拟服务定义的 "http "部分。进一步研究虚拟服务文档,"http "部分的每个流量路由条目必须有 "匹配 "定义,告诉Istio哪些流量将作为规则的一部分被路由。匹配 "部分可以选择包括一个 "URI "部分,这是定义要被路由的URL路径的地方。URI匹配的选项是精确/前缀/重合,如果你停止阅读这里的文档,你可能会倾向于走重合的道路来转换这篇文章中提到的初始入口对象。试图用谷歌搜索如何转换这样的对象,很可能会引向一条有自定义envoy过滤器被创建的道路。有人甚至在Istio repo中开了一个问题,要求将该功能内置。
在阅读文档时,不完全清楚的是,已经支持像ingress对象那样对流量进行路由的能力,而不需要做任何花哨的事情,下面是Istio的配置来实现这一功能。
但是,等等......只是一个前缀URI类型,URI的其余部分是如何捕获的?同样,文档对此并不完全清楚。它有点暗示,URI的其余部分在重写后被保留,但没有明确说明。
来自Istio文档的摘录
匹配的类型是令人困惑的部分。原始入口对象的匹配逻辑中使用了正则表达式,这可能会让人相信 "regex "是这里要使用的正确的URI匹配类型。这有可能导致人们去研究如何复制原始入口对象中注释的"/$2 "部分。同样,上面的Istio虚拟服务定义使用 "prefix "的URI匹配,无需任何正则表达式就能完成工作。
总结
这里最大的收获是,Istio虚拟服务通过使用 "前缀 "URI类型支持Nginx入口对象的regex风格捕获组。为了在Istio中获得相同的功能,并不要求Regex URI类型。
和Jordan McClintock一起调试这个问题很有意思。