如何理解Istio在FreeWheel微服务中的实践

64次阅读
没有评论

共计 4876 个字符,预计需要花费 13 分钟才能阅读完成。

如何理解 Istio 在 FreeWheel 微服务中的实践,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

FreeWheel 的微服务之痛

FreeWheel 是一家数字视频解决方案公司,我们核心业务系统可以理解为一个 Web ERP。最初核心业务系统完全基于 Rails,是一个典型的三层架构,但这个大型单体应用在发展了近十年以后,维护成本越来越大,而且难以扩展。2016 年 FreeWheel 开始迁移到微服务架构,所有的业务功能都用 Golang 来重写,同时引入了 Kubernetes 作为服务的部署平台。

但在迁移到微服务之后,FreeWheel 面临很多通信方面的矛盾。一方面,平台层的运维开始和应用层的改动互相牵制。有时升级核心网络设备,整个系统都会被波及。另一方面,随着应用层越来越快的迭代,模块之间开始互相牵制,进而影响了客户,同时也降低了应用迭代的效率。归结起来是两方面的问题:一个是通信的控制,另外一个是通信的可见性,可以理解成监控。

最初我们尝试用一个中心化的服务网关 Gateway 来解决这种矛盾。但随着迁移微服务的模块越来越多,这种服务出现了两个矛盾:一个是服务和服务之间的流量互相影响,第二个是在微服务中服务网关的配置有很多个性化的地方,大锅饭带来了复杂的配置管理,渐渐难以为继。

在这样的背景下,FreeWheel 切换到了 Service Mesh 解决方案,选择了 Istio。

FreeWheel 选择 Istio 解决方案的主要原因,是因为 FreeWheel 的技术栈是 Golang 和 Kubernetes,Istio 是目前最合适的选择。

02

Istio 的架构和基本原理

首先来看一下 Istio 的架构和基本原理。Istio 有四个核心模块:

1. 反向代理模块: Istio Proxy 劫持 Pod 的所有流量,管理 Service Mesh 里面的通信。同时,管理 Mesh 内外边界交互的流量也是反向代理。

2. Pilot 模块: 管理所有 Service Mesh 的动态配置。

3. Citadel 模块: 主要是自动维护服务之间通信的证书。

4. Mixer 模块: 在 Kubernetes 部署了两组服务:一组服务提供授权和容量检查的能力,另外一组 Policy 提供数据采集的能力,通过该服务将数据汇总。

如果从整个系统设计上看,也可以分成四个板块:

1. 反向代理。

2. 网络安全,目前主要兼容 Spiffe 标准实现。

3. 为 C ++ 实现的 Proxy 接入 K8s 的动态配置管理。

4. 对于 Attribute 的有限状态机模型,授权、容量、管理监控等所有的基础。

03

Istio 管理下的微服务

Service Mesh 部署 pod 之后,发生了什么?

1. 创建 Pod 之前,首先由 Sidecar Injector 来将自定义的 initContainer, sidecar container、volume 添加到 Pod 中,这里的 volume 是 Istio 自带的通信安全相关的,Istio 为 Pod 维护了动态的认证密钥。

2. 接下来创建容器启动 Pod,其中 initContainer 先为当前 Pod 生成流量劫持的 iptables 规则。

3. 然后启动 Pod 中的 sidecar 和实际应用容器。

4. 接下来 sidecar 和 Pilot 建立连接接受动态配置和更新;和 Mixer(policy) 建立连接来检查授权、容量等;和 Mixer(telemetry) 建立连接来上报流量相关的监控元数据。

Pod 启动完成并且接入 Service Mesh 后,这里面还有两个组件:

Galley:实现对动态配置的校验。

Citadel:检查 Pod 中 mount 的 secret 的有效性,并自动为 Pod 分发合法的证书。

04

FreeWheel 如何充分利用 Istio?

FreeWheel 已经有一套复杂的自定义认证、授权机制,为了充分利用 Istio,我们通过扩展 Istio 来整合这些系统,涉及两方面:

扩展 Sidecar:加入认证支持,提供了对业务系统的认证支持,将用户相关信息以 header 的形式传入 Mesh,后续的授权、监控、限流都可以用 Istio 原生的机制来完成。

扩展 Mixer:选择一部分流量来应用对应的授权逻辑。

扩展 Sidecar 接入认证

FreeWheel 原本就有一个简单的服务网关实现,将认证逻辑抽取到这个模块中,认证完成之后在反向代理中为下游的服务插入一些 header,比如认证后得到的用户信息等。

Istio 没有开发这种对请求完全定制的接口,所以要想修改请求和响应的内容,就必须要定义反向代理。我们没有替换 Envoy,改为在它下面接一个反向代理来实现,这个反向代理同时还接入了配置管理服务,可以利用原生的 k8s 配置管理接口来实现动态配置管理。不过需要注意的是,Sidecar 里面的容器的流量默认是不被 Iptables 劫持的,如果需要纳入流量劫持,需要显式指定 Aannotation 来包含端口或者 CIDR。

接入 Sidecar 其实就是修改 Istio-system/istio-sidecar-injector 的 ConfigMap,并加入自定义的反向代理。

这个反向代理很简单,写死了 token 和用户信息的映射关系,如果上游传入了 token,就将用户信息塞到 header 中传给下游,然后流量被转发给应用服务,在反向代理和应用服务之间还有一个检查授权、容量的过程,这是通过定制 Mixer 来实现的。

通过在 Sidecar 中增加 FreeWheel 自定义认证支持,下游可以充分利用 Istio 提供的授权、限流、监控接口。不过在 Sidecar Injector 用了一段时间以后,发现里面有两个问题:

Sidecar 没有 K8s 自动注入的 secret,也无法通过容器内环境变量自动建立 Master 连接,需要管理额外的 Kubernetes。

Sidecar 内的服务流量默认是不被劫持的,如果需要劫持需要添加额外的 Annotation。

扩展 Mixer 接入授权

我们为实现高度定制的请求和响应内容时,用 Sidecar 实现扩展,但服务在授权、自定义限流的时候,很多类似的功能并不需要修改请求响应,只是在请求到达下游服务之前算一下,结果拒绝,或者通过。这时候就可以通过 Mixer 来扩展。

Mixer 是一个高度可定制的状态机模型,Envoy 提供两个接口:Report 和 Check。这两个接口会在连接和请求的不同生命后期被多次调用,我们经常用到的 Quota,Metrics,Tracing 之类的功能都是通过它来实现的。

下图为 Mixer 的基本原理,Template 是对 Proxy 上报的 Attribute 的特定处理机制的框架,支持四类:

Preprocess: 汇总流量相关元数据和环境(k8s)相关的元数据。

Report: 上报数据。

Check: 决策是否允许当前访问。

Quota: 决策容量是否足够。

Mixer 的基本原理

FreeWheel 是如何扩展 Mixer 的呢?

首先,增加了一个 adapter 来实现授权的模板。其实,FreeWheel 已有一个默认的 RBAC 模板。但新增一个授权能力的时候,我们希望做到绝对可控。比如,通过一个动态配置,在只有某一部分 user 或访问某一类 URL 的时候打开这个授权,其他的时候则把它关掉。

Mixer 提供了一种非常灵活的模型,让 Handler 可以在流量中动态地选择一部分来引入额外的机制(如权限控制、限流等),在应用运维中这是很重要的能力,只要是不修改请求、响应的功能都可以采用扩展 Mixer 来实现。

这里,mymock 会完全拒绝所有被匹配到的流量:

mymock Handler 的基本原理

在扩展 Mixer 的过程中有三个关键要素:

1. Handler 的配置。这是一个默认行为,让 checknothing 匹配到 user1 的时候返回到 400,然后全部拒绝。

2. 系统进程 instance。这是每个模块固定的东西,定义了这种输入以后,里面可以有一个黑盒,是面向对象的概念。

3. RUL。当用户身份是 user1 的时候,instance 会被 handler 来处理。如果要扩展,第一步需要定义 handler 的数据结构;第二步,实现 time 的接口,这里有两个接口;第三把定义的 handler 的文件里面相关 go 的接口通过代码生成。最后,注册到 mixer 里面,重新编译打包 mixer 以后就可以直接用了。

需要注意的是,mixer 接入的是授权的 policy 模块,可能会影响服务网格(Service Mesh)不工作。因此,重新部署这些模块的时候,如果不能忍受短时间的宕机,则可能需要做一些灰度发布的机制。

对于 Istio 配置管理,我们也发现一些性能瓶颈和局限性。

Kubernetes 和对 etcd 配置管理存在性能瓶颈。单个 Resource 控制在 K 级别,能够比较正常的工作,一旦到达万级别可能会出现不工作,比如好几万的单个 Resource。

Istio 配置本身的局限性。首先是防抖动处理,集群里面部署变化再快,都不会阻塞 Istio。其次 Istio 其他的配置没有防抖动处理,一旦用程序插入的时候一定要做限流。最后 Istio 用了 CRD 无法做到的兼容性设计,所以升级 CRD 也没有办法做到平滑的升级。

FreeWheel 未来将怎么做?

首先是 Service Contract,封装 Istio 以及平台层其他配置的复杂度,抽象出一个安全,高效的应用运维体系,为未来技术上的改进留出空间。

然后是 Chaos Testing,解决复杂的微服务系统的持续运营和风险控制问题。这个也是目前比较火的一个主题。

现场问答

1. 对于 Service Mesh 外部流量进入,在 Kubernetes 有 Ingress,在微服务 Service Mesh 的应用里面也有一个 Gateway 的情况下,它里面是把 Gateway 转到 Service Mesh,这三个怎么联动让外部的流量能够顺畅地进去?

答:很简单。Service Mesh 可以理解成是一个封闭的盒子,你所有的外部的 Ingress 以前该怎么运作还怎么运作,我们现在就讨论在 Service Mesh 里面是怎么运作的。如果把它看作一个黑盒,现在你有一个 Ingress,可以把它转到 Istio 里面的 Ingress Gateway,过去流量会直接转发到各个 Pod,是直接打到 Pod,由 Pod 上 Sidecar,再转给应用。

2. 您刚才说的 Sidecar 里的应该是直接把 Pod 里面的流量屏蔽掉,只能通过 Service Mesh 里面的 Gateway 流量才能够进到 Pod 里面?

答:不会。你说的这个流量转发其实并没有任何的限制,Service Mesh 里面每一个反向代理都可以承担 Ingress Gateway 的功能,仅仅是路由配置的问题。如果把这个弄好了,在任何一个 Service Mesh 上都可以配置这个功能。这个反向代理是一模一样的。

3. 我用 Istio 的 Gateway,Kubernetes 里面的 Ingress 关掉,能够跟外部之间联系。

答:这个才是 Istio 比较推荐的模式,你管理这个集群外部进来流量的时候直接走 Ingress Gateway,可以做到很好的限制。

4. 你们在落地的过程中有没有遇到一些坑?

答:有。我们一开始试图把业务的权限数据直接转成原生的数据结构,因为我们想用它来做权限控制。但是后来发现它掌控不了那么大的数据量。第二个坑是 Istio 对它的一些 Resource 是没有防抖动处理的,可能会导致这个 Service Mesh 行为很不稳定,在客户端一定要做限流。

另外从长远看,Istio 的这些模块目前都还是单点,可能导致 Service Mesh 不可用。我们以前也有遇到过跑了三个月莫名其妙出问题了,维护这种监控系统要频繁地做演习。我们公司现在一个月做一次演习,会定时在一个主生产环境里把问题拿出来,然后检查各个环节有没有正常工作,这也是我们未来会发展的一个事情。

关于如何理解 Istio 在 FreeWheel 微服务中的实践问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注丸趣 TV 行业资讯频道了解更多相关知识。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-25发表,共计4876字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)