Knative通过header访问指定版本

2023-03-06 11:19:17 浏览数 (1)

背景

knative 0.14.0 实际修改可能与贴出来的代码不符,贴出来的代码只是为了方便快速实现功能

最近在搭建公司级的serverless平台,需要用到域名来访问内部服务,采取的是通过PATH来区分不同的服务,域名采用同一个。上一篇已经解决了通过Path访问不同服务的问题,但是在灰度过程中可能会想测试下新版本时候正常,如何将流量打到指定版本上呢?原生的knative是通过url的不同实现的,可以配置一个根据版本生成url的模板,设置后不同版本的服务url不同。但是我们的场景是所有服务url相同,于是我们约定通过在设置特殊的header的来实现此功能

方案

原生通过url来区分不同版本,实现方式是通过在生成vs时,设置其Match的条件Authroty为对应的url prefix即可。显然无法满足我们当前统一使用一个url的场景。但是我们可以参考其实现方式,换一个维度,靠header实现即可,但是又不能影响正常访问,即不添加header的时候,流量按照设置的比例打到不同的revision上,添加了header后,需要将流量打到指定版本,所以不能简单的在Match中添加Header,需要分别设置正常访问的情况和访问指定版本的情况,且访问指定版本的配置应该顺序靠前

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

// MakeIngressSpec creates a new IngressSpec func MakeIngressSpec( ctx context.Context, r *servingv1.Route, tls []v1alpha1.IngressTLS, targets map[string]traffic.RevisionTargets, visibility map[string]netv1alpha1.IngressVisibility, acmeChallenges ...v1alpha1.HTTP01Challenge, ) (v1alpha1.IngressSpec, error) { ... // add custom external domains customHostStr := r.Annotations["serverless.kakuchuxing.com/domains"] // 倒序,否则不生效,因为访问指定版本时name不为空,不区分版本时name默认为空 sort.Sort(sort.Reverse(sort.StringSlice(names))) if len(customHostStr) > 0 { customHosts := strings.Split(customHostStr, ";") for _, name := range names { if name != "default" { visibility := netv1alpha1.IngressVisibilityExternalIP rule := *makeIngressRule(customHosts, r.Namespace, visibility, name, targets[name]) // If this is a public rule, we need to configure ACME challenge paths. rule.HTTP.Paths = append( makeACMEIngressPaths(challengeHosts, customHosts), rule.HTTP.Paths...) rules = append(rules, rule) } } } ... } func makeIngressRule(domains []string, ns string, visibility netv1alpha1.IngressVisibility, name string, targets traffic.RevisionTargets) *v1alpha1.IngressRule { ... return &v1alpha1.IngressRule{ Hosts: domains, Visibility: visibility, HTTP: &v1alpha1.HTTPIngressRuleValue{ Paths: []v1alpha1.HTTPIngressPath{ { Splits: splits, // TODO(lichuqiang): #2201, plumbing to config timeout and retries. // 把tag name保存下来,传递给vs,用来区分是否需要设置header AppendHeaders: map[string]string{ "RevisionName": name, }, }, }, }, } } func makeVirtualServiceRoute(hosts sets.String, usn string, http *v1alpha1.HTTPIngressPath, gateways map[v1alpha1.IngressVisibility]sets.String, visibility v1alpha1.IngressVisibility) *istiov1alpha3.HTTPRoute { ... // add revision tag header to custom domain // 获取传递过来的tag,设置match header if tag := http.AppendHeaders["RevisionName"]; tag != "" { for i := 0; i < len(matches); i { if matches[i].Headers == nil { matches[i].Headers = make(map[string]*istiov1alpha3.StringMatch) } matches[i].Headers["RevisionName"] = &istiov1alpha3.StringMatch{ MatchType: &istiov1alpha3.StringMatch_Exact{ Exact: http.Splits[0].ServiceName, }, } } } ... }

总结

至此,已经实现了通过统一域名访问集群内服务,且根据Path转发请求,并且可以通过在访问时添加指定的header来把流量打到指定版本上,这在灰度或者测试时是一个非常实用的功能。

0 人点赞