Knative Serving中的所有路由都是通过Route CRD完成的,Route CRD为用户的服务或应用程序提供网络端点,每个端点对应了不同的配置修订。Route提供了一个长期稳定的,并且HTTP可寻址的命名端点,该端点由一个或多个Revisions支持。默认配置是Route自动将流量定向到创建的最新版本上。
Knative使用Istio实现其网络路由能力,所有路由都可以通过共享的Istio网关接收外部流量。为了避免与用户的网关设置冲突,Knative可以使用与默认网关istio-ingressgateway不同的新网关,如knative-shared-gateway。在未来,应该会为用户提供一种方式来选择他们使用的网关。
一个有效的Route对象在Knative Route控制器的协调下,将生成以下对象:
·VirtualService,用于实现从Gateway knative-shared-gateway到Route指向的流量目标的路由。
·与Route同名的Kubernetes服务,以便我们可以使用<route-name>.<route-namespace>.svc.cluster.local来定位。此服务没有pod,仅使用它来包含要在VirtualService中使用的域名。
例如,如果我们有两个Knative修订hello-world-01和hello-world-02,以及一个路由hello-world将流量引导到这两个修订上,那么资源创建将如图11-6所示。

图11-6 路由流程一
事实上,在Knative 0.2之前,如果存在非活动版本的情况下,路由将通过服务activator-service接收请求流量,并在标头中包含足够的信息,以便服务activator-service可以在将流量转发给一个修订版本之前激活它。其中,服务activator-service主要做两件事情:一个是负责把pod启动起来,另外一个是把启动中的请求转发给pod。当业务的pod缩容到0的时候,Knative会更新Istio VirtualService,把流量按权重分配给activator-service。在业务pod正常启动之后,流量权重又重新直接指向业务pod,所有revision都就绪(ready)的情况下,activator不会分配到流量。
Activator是单一的多租户组件,可捕获所有Reserve状态下的Revision的流量。它负责激活修订,然后将捕获的请求代理到相应的pod。最好在Istio中使用钩子来做到这一点,这样就可以摆脱Activator)。当Activator收到Reserve Revision的请求时,它会调用Knative Serving控制平面将Revision修改为活动(Active)状态。所有资源都需要几秒钟的时间来配置,因此在此期间可能会有更多请求到达Activator。Activator为属于目标版本的pod建立监视。第一个pod启动后,所有排队的请求都会被代理到该pod。同时,Knative Serving控制平面将更新Istio路径规则以使Activator退出服务路径。
但在Knative 0.2之后,activator-service不再激活非活动的修订。它的职责变为:
·接收和缓冲非活动修订的请求。
·向自动缩放器autoscaler报告指标。
·在自动缩放器autoscaler根据上报的指标对修订进行扩展后,重试对该修订的请求。
在Activator的代码中,可以看到如下关于连接自动缩放器autoscaler上报指标数据的逻辑:
// Open a websocket connection to the autoscaler
autoscalerEndpoint := fmt.Sprintf("ws://%s.%s.svc.cluster.local:%s", "autoscaler", system.Namespace, "8080")
logger.Infof("Connecting to autoscaler at %s", autoscalerEndpoint)
statSink = websocket.NewDurableSendingConnection(autoscalerEndpoint)
go statReporter(stopCh)
从上一个示例方案中,如果修订hello-world-01因缺少流量而变为非活动状态,则资源将如图11-7所示。

图11-7 路由流程二
之后,修订hello-world-02由于缺乏流量请求,也会变为非活动状态,资源看起来将如图11-8所示。

图11-8 路由流程三
如果发生任何激活,则修订将再次变为活动状态,并且将调整流量,直接路由到修订,而无需通过服务activator-service。