• 服务网格是下一代SDN吗?
  • 发布于 2个月前
  • 219 热度
    1 评论

在微服务架构当道的新时代下,无论你采用的是容器即服务(CaaS)架构还是函数即服务(FaaS)架构,亦或两者都采用,网络都已变得越来越重要,原因如下:

微服务应用程序组件通过网络相互脱离。它们通过网络重新整合,API作为远程过程调用(RPC),这些RPC已从CORBA和RMI之类的机制、SOAP和REST的昔日Web服务,发展成为像Apache Thrift和更新颖的 gRPC这些新方法,gRPC是谷歌捐赠的一个新的CNCF项目,以实现基于http2的安全又快速的RPC。RPC问世已有很久,但现在的网络实际上很快,足以作为应用程序组件之间一种基本的通信手段来处理RPC,因而让我们得以分解传统的整体式应用程序(monolith):在传统环境下,服务模块以前总是与更紧密的API通信机制捆绑或结合在一起,这些API通信机制基于包含的软件包和代码库,我们当中一些人可能还记得更复杂难懂的IPC。


每个微服务组件通过复制实例来进行扩展。因而,每个微服务的前端是负载均衡器(它本身就是一个网络组件),但除此之外,服务需要发现所依赖的服务,这一般通过DNS和服务发现来完成。


为了提升处理规模,并增强可靠性,每个微服务实例常常本身与应用程序状态及存储相脱离。状态通过网络来保存。比如说,使用API将状态保存在对象存储、数据库、键值存储系统、数据流队列或消息队列中。还有老式磁盘,但这种磁盘及配套的文件系统也可能是网络挂载的虚拟卷。这些用来存储状态的可通过API和RPC访问的系统本身也是微服务,这种存储方式事实上可能也是使用磁盘的最佳典例。它们还包含大量的分布式存储神奇功能,以兑现所作的各种承诺,这种神奇功能常常是通过网络来执行的。

但愿我们已在为什么网络是重要的微服务粘合剂这点上达成了共识。如果你对此很熟悉,那么也许对云原生SDN解决方案和服务网格也已经有所了解。


服务网格的概念和实现相当新颖。这个话题也备受关注,原因是服务网格可以解决上面提到的网络方面的主要挑战;如果是像CNCF Linkerd这样的新项目和最近发布的项目Istio,其功能远不止这些。


此前我写过关于容器SDN堆栈的文章,即OpenContrail for Kubernetes和OpenShift,在此不作深入探讨了,也不会深入介绍服务网格,只在比较时略提一二。

不妨介绍一下服务网格的一些用例和特性,并将它们与SDN解决方案(主要是OpenContrail)进行比较,那样我们就能回答标题中提出的问题:服务网格是“下一代”SDN吗?


自动化SDN和服务网格

首先,不妨看一下使用SDN和服务网格的各种环境中自动化的三大方面:可编程性、配置和安装。

1. 可编程性

说到自动化,可编程性必不可少。优秀的SDN不受网络硬件方面的限制,OpenContrail等许多SDN提供了逻辑上集中的控制平面,附带API。上面介绍的两种主要的服务网格也这么处理,它们遵循类似SDN的架构模式:集中式控制平面和分布式转发平面代理。虽然Istio有集中式控制平面API,但Linkerd更加分布式,不过通过其Namerd组件来提供API。大多数人可能会说,这两种服务网格的gRPC API比OpenContrail充分利用REST(RESTful)的 API更现代化、更有优势,但是另一方面,OpenContrail 的API与Istio仍很原始的API函数相比,得到了很充分的扩展和测试。

2. 配置

除API以外一个更大的区别是如何访问功能。服务网格引入YAML来声明可通过CLI来传达的配置意图。我猜大多数人会一致认为,这与并不提供这项功能的SDN相比是优势(至少OpenContrail现在不提供)。就基于Web的接口而言,服务网格与许多SDN一样,确实提供了这种接口。OpenContrail的Web接口在经历5年的开发后已变得相当高级,但仍感觉很现代、对企业友好。

然而展望“网络即代码”趋势,CLI和YAML在可编程和版本控制方面比OpenContrail 的API调用更容易操作。在OpenStack环境中,OpenContrail可以用基于YAML的 Heat模板来配置,但这对基于容器的K8s和OpenShift环境而言没有太大关系。在K8s环境下,OpenContrail SDN配置被注释为K8s对象。它有意很简单,以便只展示OpenContrail的一小部分功能。可以通过K8s TPR、ConfigMaps或通过某种OpenContrail解释器能完成什么样的工作,仍需拭目以待。

3. 安装

Linkerd背后有Buoyant这家公司,这意味着谁都能得到支持,不过一开始上手很简单。与Kubernetes一起部署在 DaemonSet模型中,很容易上手。

Istio是全新的,但它已有Helm图,与Kubernetes一起迅速部署。另一方面,使用Istio意味着将Envoy代理捆绑到每个Kubernetes pod中,作为sidecar。这是额外的步骤,但借助kube-inject命令,很容易实现。抛开Sidecar vs DaemonSet的考虑不说,这种结合会收到一定的奇效,这对于理解后面的调试很重要。

说到SDN,它们是完全不同的wrt部署。OpenContrail在开发一种用于简单部署的支持Juniper的Helm图,而与此同时,社区还提供Ansible playbook和其他同类的配置管理解决方案。

OpenContrail与Istio和Linkerd这两种服务网格有一个共同点,那就是它部署成了容器。一个区别是,每个节点上的OpenContrail转发代理既是用户空间组件,又是内核模块(基于DPDK或基于SmartNIC)。它们是容器化的,但内核模块只用于安装,以便引导insmod安装。内核模块可能让人觉得有点矛盾……内核模块明显会简化性能和与网络堆栈的集成,但是它所使用的资源不是基于容器的,因此没有资源方面的限制,所以资源管理与用户空间sidecar进程不一样。无论如何,这与使用kube-proxy或OpenContrail vRouter取代的任何基于IP表的网络一样。


SDN与服务网格:DevOps方面的考量因素

考虑微服务架构时,我们要牢记复杂性远不止此。还有DevOps工具来管理应用程序的开发、测试、试运行和和生产等环节,还要管理持续集成、持续交付和响应。不妨看看其中的一些考量因素:

1. 多租户/多环境

在共享集群中,代码不该专注于诸如操作员或应用程序开发/测试环境之类的运维环境。要做到这一点,我们需要隔离机制。虽然Kubernetes命名空间和基于角色的访问控制(RBAC)在这方面有所帮助,但仍然存在诸多不足。下面我会简要介绍OpenContrail和服务网格中的路由,以便更认真地剖析针对环境隔离的考量因素。

OpenContrail for K8s概述:覆盖网络(overlay network)是用来隔离的一种常见的SDN方法。它让我们得以在网络上创建彼此独立,带有不同封装标记的虚拟网络,在转发代理中也常常这样。OpenContrail确实就是这种情况,但OpenContrail也允许更高级的类似命名空间的名为域/租户和项目的包装器(wrapper)。

域和域彼此隔离,域内的项目彼此隔离,项目中的虚拟网络也彼此隔离。这种结构层次很好地隔离了租户和开发/测试/试运行/生产环境,然后我们可以使用一个虚拟网络来隔离每个微服务。为了连接网络(还可以跨域和项目连接),应制定一个策略,并运用于需要连接的网络上,该策略可以指定方向、网络名称、端口和要插入的服务链(比如说有状态的防火墙服务)。

为Kubernetes创建这些域、项目和网络的方式基于注释。OpenContrail将命名空间映射到其自己的OpenContrail项目或自己的虚拟网络,那样一个庞大网络上的微服务彼此都能够联系(类似默认的集群行为)。但这里存在安全问题,OpenContrail也可以强制执行ACL规则,并自动创建规则,作为隔离微服务以确保安全的一种方法,可以基于K8s对象注释,也可以将Kuberneteds NetworkPolicy对象作为OpenContrail安全组和规则来实现。K8s部署、任务或服务等对象上另一种新的注释将指定整个OpenContrail域、项目和所选择的虚拟网络。

就个人而言,我认为最好的方法是设计一个层次结构,以匹配DevOps团队和环境结构,这种环境结构充分利用OpenContrail模式按域、项目和网络来分割的特点。遗憾的是,与之相比,一种更简单、但更常使用的全局默认拒绝规则和越来越庞大的白名单确保将你的集群变成瑞士干酪。

SDN的覆盖在第2层、第3层和第4层,这意味着节点上收到数据包时,vRouter(以OpenContrail为例)将接收发送给它的数据包,查看里面的报头(VXLAN ID或MPLS LSP编号),确定域/租户、项目和网络。大致上来说,这个编号指明了哪个路由表将用作内部目标地址的查询上下文,然后(等待ACL之际)数据包按CNI标准被转交给相应的容器/pod接口。

服务网格背景:Istio的Envoy和Linkerd的模式之所以被使用,是由于微服务的前端有第7层路由器和代理。所有流量都在该代理处被截获,并在节点之间传输。可以说,它也是更高层的覆盖。

从概念上来讲,第7层的覆盖与SDN覆盖一样,只不过网络上的覆盖协议一般是HTTP、HTTP2或者TLS加上HTTP或HTTP2。在Linkerd的DaemonSet部署模式中,主机有一个IP地址,Linkerd将代理所有流量。它在概念上类似vRouter,只不过实际上它只处理某些端口上的HTTP流量,而不是处理所有流量。流量路由和目标解析由从Finagle继承的委托表(dtabs)格式来完成。在Linkerd或Istio Envoy(始终是sidecar)的sidecar部署模式中,代理实际上与每个微服务在同一个容器网络环境中,因为它在同一个pod中。它们可以采用一些IP表技巧,隔开应用程序和网络。在Istio Pilot(控制平面)和Envoy(数据平面)中,流量路由和目标解析主要基于Kubernetes的服务名称。

介绍完了上述背景,再来说说给多租户带来的几个影响。

要注意的是,在SDN架构中,租户、环境和应用程序(网络)的分类在内核vRouter中进行。在服务网格代理中,我们仍需要CNI解决方案,以便最初让数据包进入到pod中。在Linkerd中,我们需要包括租户、环境和服务的dtabs路由规则。dtabs似乎提供了一种很好的分解方法,以便易于管理。在Envoy较为常用的sidecar模式下,流量最后进入的那个pod很可能已有与之关联的K8s命名空间,因此我们可以在Istio规则之外映射租户或环境,针对Envoy而言,只要专注于将服务名称解析成容器和端口。

OpenContrail在这里似乎有好办法可以匹配不同团队的层次结构,并分开那些RBAC和路由环境。Linkerd dtab可能更灵活,用户想要多少层路由解释,它就能创建多少层,但需要更强大的RBAC,允许在团队租户之间拆分dtabs,以确保安全性和协调性。Istio在隔离租户和环境方面没有太大的作用。也许这超出了它的能力范围,这可以理解,因为Envoy始终是sidecar容器,你应该有底层的多租户网络让流量进入到sidecar的pod。

另一点是,服务发现已内置到服务网格解决方案中,但它在SDN界仍很重要,包含DNS的系统(OpenContrail)有助于以多租户方式来管理命名解析,并且跨你创建的环境来提供IP地址管理(比如引入你自己的IP地址)。这超出了服务网格的范围,但对于多团队以及开发/测试/试运行/生产环境而言, IP地址管理池和子网最好相同。


2. 部署和负载均衡

说到部署和持续交付(CD),SDN具有可编程性有所帮助,但服务网格在这里有明显的优势,因为它们在设计当初就心系CD。

想用SDN进行蓝绿部署,拥有浮动IP功能很有用。大致上来说,我们可以切换到绿版本(将虚拟IP提供给新版本的微服务),万一遇到问题,我们又可以安全地返回到蓝版本。你在持续交付或把试运行推入到非活动部署时,仍可以使用不同的浮动IP地址来联系。OpenContrail处理叠加的浮动IP,让你可以在必要时处理这个问题。

服务网格路由规则能实现同样的功能,但是基于HTTP层面的路由切换,比如指向更新的后端版本。服务网格进一步允许流量滚存(rollover),就像这个例子表明一开始只有很小比例的流量,最后是全部流量,实际上为你提供了面向流量负载的金丝雀部署,而不是Kubernetes滚动升级或Kubernetes部署金丝雀策略,后者为你提供了基于实例数量的金丝雀版本,依赖实例间的负载均衡来划分流量。

这就引出了负载均衡。默认情况下,微服务实例之间的负载均衡借助K8s kube-proxy控制器通过IP表的编程来实现。如果使用OpenContrail的vRouter,这里有一点性能和规模上的优势;vRouter使用自己的ECMP负载均衡和NAT,而不是使用内核的IP表。

服务网格也处理这种负载均衡,但支持更广泛的功能,比如EWMA等负载均衡方案、速度过慢时从负载均衡池中剔除某个实例。

当然,服务网格还可以为入站HTTP前端处理负载均衡。Linkerd和Istio整合了K8s Ingress作为入站控制器。虽然大多数SDN似乎不提供这项功能,但OpenContrail在这方面确实有一个基于开源TCP代理项目haproxy的解决方案。一个区别在于,OpenContrail还没有支持SSL/TLS,但也有nginx之类的K8s可插入替代方案,实现纯粹的软件定义负载均衡。


3. 可靠性工程

是的,我把SRE和持续响应归为DevOps这一类。在这个领域,由于服务网格更感知应用程序,它们在查明可靠性的根源方面更大有作为也就不足为奇。

说到可靠地优化和确保性能,有一点要注意:EWMA和这类先进的负载均衡策略有助于避免或剔除速度慢的实例,因而改善尾延迟(tail latency)。Buoyant公司的一篇关于性能的文章直接从延迟方面来解决性能。Envoy和Linkerd毕竟是TCP代理,在网络环境下解压和重新打包TCP数据流极慢(我个人可以证明这一点)。不管怎样,处理器取得了长足发展,Envoy和Linkerd可能是目前速度最快的TCP代理。话虽如此,总是有敏感的人不愿引入这种延迟。我认为这点给人启发:在上面提到的那篇文章中进行的试验中,研究人员增添了更多的延迟和步骤,但由于也增加了宝贵的信息,因而整体延迟反而缩短了!


达成的共识似乎是,服务网格解决的问题多于带来的问题,比如延迟。服务网格适合你的特定情况吗?正如一些人所说,“这要看情况”。基于DPI的防火墙也是如此,这种流量处理应用系统在特定的功能特性或负载下有出色的延迟和吞吐量,但是如果开启某些功能或面临沉重负载,性能大不一样。这不是公平的比较,而是说SDN转发代理所做的轻量级无状态处理总是会比这类代理快得多,智能网卡供应商用硬件实现vRouter更是如此,比如OpenContrail就是这样。

可靠性方面更需要关注的另一个话题是安全。我一想到TCP代理,马上会想到防范DoS攻击,因为为了跟踪每个会话创建了大量状态。通过使用TLS,服务网格很好地解决了这个问题。虽然Linkerd支持这一点,但Istio的方法更容易,因为它有用于密钥管理的Istio Auth控制器。这是很重要的步骤,不仅可以为网络上的流量确保安全,还可以为每个微服务建立强大的基于身份的AAA机制。值得一提的是,这些代理可以根据可配置的任何对象来改动网络协议。因此,可以将HTTP请求作为TLS里面的HTTP2请求在网络上发送。

最后说说断路(circuit breaking)机制。如果不对大量的分析和应用程序跟踪信息进行解读,并将该信息反馈到SDN的API中,我不知道SDN解决方案有什么方法可以很好地做到这点。即使这从理论上讲是有可能,但如今服务网格已经能做到这点,这项内置功能可以从容处理故障,而不是任由故障越来越严重。


4. 测试和调试

这是个重要的话题,但其实没有横向比较功能的文章,所以我只挑这个话题重要的几点来讲。

服务网格提供了面向RPC的应用程序视图,以便用户了解微服务网格中的内部通信。如果跟踪应用程序中的通信路径,这些信息对于监控、运维可视性和调试过程都非常有用。Linkerd整合了用于跟踪的Zipkin和提供度量指标的其他工具,与一些针对特定语言的跟踪库不同,它适用于用任何语言编写的应用程序。

服务网格还提供了这一功能:基于HTTP报头等对象进行请求级(per-request)路由,可以操纵HTTP报送之类的对象以便测试。此外,Istio还提供了故障注入以模拟应用程序中的错误。

SDN方面的解决方案不一样。与CNI提供商的其他选择相比,OpenContrail在这方面相当成熟。OpenContrail可以根据需要运行Wireshark之类的数据包捕获和嗅探器,综合的分析引擎和可视化工具可以显示流量记录及其他流量数据。除了在更高网络层上的调试外,还有一些出色的安全应用软件可用来审计ACL拒绝日志。最后,只要在物理网络上(不是在云上)运行,OpenContrail可以告知流量的端到端路径。这一切可能有助于调试,但应用程序方面的这类信息要间接得多,可能更适合网络运维(NetOps)。


遗留互连及其他互连

服务网格从许多方面来看不错,但要注意的一点是,它们如何允许或阻止你的微服务连接到遗留服务或前端没有代理的其他服务。

如果将状态存储在S3中或调用云服务,这是外部调用。如果回连至像Oracle数据库这样的遗留应用程序,也一样。如果调用RPC或不在服务网格上的另一个微服务(比如它在虚拟机中而不在容器中),也一样。如果微服务本该处理非TCP流量,该流量也不会通过服务网格来处理(比如DNS是UDP流量,ping是ICMP流量)。

以Istio为例,可以用服务别名来设置出站连接,但是这可能需要更改应用程序,因此直接连通可能是更简单的选择。还有很多种TCP流量不是HTTP,也不直接得到支持。常见的例子有ssh和邮件协议。


当然,你的应用中肯定有一些不太适合这种服务网格的通信。这种情况下,你不仅需要规划如何允许这种通信,还要规划如何安全地进行,这时可能需要使用像OpenContrail这样的底层SDN解决方案,这种解决方案涵盖了OpenStack、VMware、裸机和Kubernetes。
你怎么看?


回到文章标题:服务网格是下一代SDN吗?

一方面:是的!因为服务网格具有一些SDN通过在微服务之间实现微分段和RPC安全所带来的大部分价值。服务网格可以改进基于TLS的安全和为每个微服务分配身份,从而做到这一点。此外,服务网格添加了可感知应用的高级负载均衡和故障处理,如果不进行应用程序分析和代码重构,就很难获得这种功能。

另一方面:不是!因为服务网格在CNI和容器连接的上面。它们在SDN的上面,所以仍然需要坚实的基础。此外,大多数团队获得SDN解决方案的微分段和多租户机制时想要多重安全隔离,性能又没有任何降低。SDN解决方案还能跨集群、堆栈和容器之外的运行时环境进行连接,满足关注延迟的群体的要求。

不管怎样,服务网格是一种新颖酷炫的网络工具。它们的价值远不止体现在网络和安全方面,我们很快会看到服务网格出现在几乎每一种微服务架构和堆栈中

用户评论