openstack neutron
转载:https://www.cnblogs.com/pmyewei/p/6280445.html
云数据中心底层网络架构
云数据中心流量类型
当前云数据中心的流量可以简单分为以下几个大类:
- 管理网络(API网络):用于云数据中心内部的管理流量,包括对内部虚拟化组件之间的、SDN控制组件之间、消息队列、以及各种HA的检测信号等。管理流量一般不对外,并且需要连接云数据中心中的每一个服务器节点,并只在数据中心内部传输。
- 租户网络:用于数据中心的各个租户之间流量,提供云计算服务,保证用户内部vm之间能够通信同时隔离不同用户之间的流量是最基本的要求。租户之间隔离的方式包括了vlan、vxlan、gre、stt、nvgre等等,后续我们再详细介绍。
- 外联网络(外部网络):外部网络的名称是站在租户角度进行描述的,即租户网络只能用户业务虚拟机之间的通信,与其余设备的通讯则都要通过外部网络的转发。除了路由以外,外部网路往往还兼具VPN、NAT、LB、FW等职能。此处往往需要将租户网络中为了隔离而修改过的数据包转封包成常见的二层帧,以及与外界网络的路由
- 存储网络:用于连接计算节点和存储节点,主要是为计算节点中的主机和虚拟机提供存储服务。存储网络也不对外,尽在数据中心内部传输。
Vmware NSX整体网络结构
我们先看一下NSX定义的整体网络结构:
在nsx的架构中,左侧区域对应的是计算节点集群,其上以运行租户的业务为主。包括用户部署的各类的虚拟机、虚拟网络、分布式网关、安全策略等等。是数据中心服务的核心。该区域的流量类型包括:租户网络、存储网络、管理网络。(也意味着服务器至少需要三块网卡)
中间区域对应是的基础架构集群,包括云计算数据中心的管理节点和IP SAN 共享存储。管理节点包括: vCenter Server、NSX Manager、NSX Controller、CMP 。IP SAN共享存储节点则主要是向计算节点集群中的主机或用户的虚拟机提供基于IP网络的iSCSI或者是NAS存储。流量类型包括:存储流量、管理流量。
右侧的边缘节点则用来为租户网络提供互联网访问服务。因此需要连接租户网络和外部网络,并为租户提供路由、NAT、防火墙、公网IP等服务。其中以NSX的EDGE虚拟网关为主。也可以有硬件路由器、防火墙等设备。流量类型以:外部网络、租户网络、管理网络为主。
管理网络(API网络)
管理网络需要连接云环境中的每一个节点,上面传输的数据包括虚拟化中心vcenter对host的管理流量、HA心跳、SDN控制器(nsx controller、nsmanager)、云管理平台API、云监控运营平台等多种云计算数据中心管理运营组件的管理流量,属于数据中心的神经网络。
在vmware的设计中,管理控制的节点部署在一个物理主机集群,集群开启HA、DRS等服务,保障数据中心整个控制平面的可靠和稳定。此外IP共享存储也被放置在该区域中。
vmware特意将vmotion的流量也单独列出来成为一类流量。除此之外共享存储也需要单独进行传输。管理节点上存储、vmotion、租户网络、管理网络、外部网络,一般通过物理交换机上的VLAN进行隔离的,并连接物理服务器上的不同物理网卡。管理网络对于带宽的要求并不高,千兆、万兆都可以。但是管理网络的IP共享存储对带宽的要求较高,至少需要部署万兆的网络。
总结:
管理网络连接数据中心所有的节点,主要用于对底层资源的控制,和API调用,对网络的要求不高。一般通过服务器的管理网卡 1 x 1 GbE 或者1 x 10 GbE 交换机网络互联,一般采用单独的接入交换机。
对于vmware的环境来说,vmotion的流量可以走单独的网卡和也可以和万兆管理网络互联
租户网络
租户网络对应的是云数据中心的租户之间的虚拟机用来通信的网络。一般连接所有提供计算服务的计算节点。租户网络的数据都被封装到指定的VLAN中,在外部看来就是VLAN内主机之间的通信,内部流量不可见。
租户网络涉及到NSX、openstack neutron 这类解决方案中一个核心的理念,那就是二层的overlay。
严格来说二层的overlay技术并不算sdn技术中的一部分。在数据中心的环境中,为了保障数据的安全,需要在网络层面上隔离各个租住的虚拟主机,根据业务的特点,一个租户可能使用到多个vlan,例如一个典型的三层架构的应用中,界面、中间件、数据库分属于不同vlan,并通过安全策略控制之间的访问。这种情况下一个租户就占用了3个vlan,而vlan的总数才4096个,还要扣除各个设备厂家的保留vlan和用作管理的vlan等。这样一个数据中心能够承载的用户数就被极大的限制住了。
云数据中心用户的虚拟网络通过不同的VNI号(Vxlan Network identifier)来区分,24bit的VNI包含2^24 = 16 777 216个网段,按照一个用户创建10个私有的网段来计算,一个机房可以满足上百万用户的使用需求。实际上即使是国内的阿里云的总的用户数加起来也才几十万。这还是由分布在全国和海外的多个机房共同承当。所以通过二层的overlay技术,租户网络仅需设计少量vlan即可满足海量用户的使用要求。甚至可以将所有租户的流量全部封装在一个vlan内,但是过多的广播包会影响网络的性能,vmware有针对广播、多播流量的解决方案。详细情况放到下一节。
因为单个主机上承载的虚拟机数量较多,为了保障虚拟设备之间有足够的带宽,租户网络至少应该采用万兆的网络,且因为二层数据层有额外的封装开销,所有需要将租户网络MTU设置成1600.
总结:
租户网络连接计算节点和云数据中心的出口区域,其上是通过overlay技术标记的租户的虚机之间的数据。租户网络一般会规划多个vlan来减轻广播流量的影响。物理机主机上虚拟机数量比较多,要保证比较良好的网络质量,则服务器的租户一般网卡通过1 x 10 GbE 或者1 x 40 GbE交换机网络互联。
外联网络
外联网络是相对用户来说,用户虚拟机之间的流量完全可以通过用户网络完成传输,但与外界(通常是是互联网,也包括数据中心内部网络)通信,则需要解除原本overlay的封装,并映射公网IP。除此之外还包括一起其他网络服务,如:NAT、VPN、防火墙、LB等。
所以外联网络内的流量包括:用户网络流量、管理流量、外网流量。
Vmware Edge 机架中主要运行的是NSX的edge设备。edge设备一边连接租户网络的分布式路由一边连接外网(WAN)。它代表是传统数据中心的南北向的流量,在网络的边缘提供NAT、VPN、LB、FW等服务。edge组件本身是一台虚拟设备,通过vmware nsx的管理页面来统一管理,但是控制层面和转发层面还是集中在设备上。它的实现方式更像NFV。
总结:
NSX采用软件路由器连接租户网络和外部网络。每个租户都能创建自己专属的软件路由器,并自定义出口的策略。外部网络一般通过1 x 10 GbE 或者1 x 40 GbE交换机网络互联。外部网络北向一般是数据中心的传统交换机和路由器。
存储网络
存储网络主要是用于连接存储节点和计算节点。在云计算数据中心中,存储以分布式的存储为主。
VMware推荐直接在计算节点使用VSAN来直接为租户业务提供持续化存储,也就是说计算节点也同时作为存储节点来使用。那就意味着存储网络是计算节点服务器之间互联的网络,VSAN的最佳实践,推荐主机采用相同或者类似的磁盘配置。并使用单独的网卡用作主机之间的存储流量。
VSAN支持通过千兆网络部署,前提是该网卡仅传输VSAN流量,但是实际使用中极度不推荐。且纯SSD架构中,不支持使用千兆网络。VSAN是以物理主机集群为单位组建的,每个集群有且仅有一个vsan存储集群。且所有需要使用到该存储的主机,必须都处于同一个集群内。即便该主机不提供vsan磁盘组。
所以存储网络至少应该使用使用万兆交换机,服务器通过单个万兆网卡互联(VSAN暂不支持网卡聚合),组建VSAN内部网络。同时VSAN需要通过组播来获取集群变化信息,所以组播也必须支持。
配置重点
存储网络以集群为单位,连接集群内的所有物理主机,存储网络至少需要1 x 10 GbE 或者1 x 40 GbE交换机网络,并且需要组播支持。
openstack整体网络结构
网络上流传的各种opnstack的架构图都是组件模块之间的架构图,基本上会让刚开始了解openstack的人看得一头雾水。Mastering openstack书中有一张物理拓扑,架构非常清晰,如下:
通过这个架构图很容易发现,其实两者openstack的物理网络架构和vmware NS的架构非常的类似。同样将流量分为管理网络、外部网络、存储网络、租户网络。(同中将租户网络和存储网络都用红色表示,但实际上是两张网的)。但是细细探究会发现两者还是有较大的差异。
管理网络:(上图中蓝线)
openstack的管理网络流量,同样需要连接所有的主机,其上传输的流量包括:horizon、nova、cinder、keystone、glance、neutron等组件的管理服务。并通过管理网络与计算节点、网络节点上的agent、client通信。
值得一提的是,与vmware不同的是,openstack没有将虚拟机迁移(vmotion)的流量单独出来,而是直接走的管理网络。所以此处会比vmware官方建议的少一类网络,计算节点上也会少一块网卡。
所以管理网络的带宽也会建议上到万兆。
外部网络:(上图中黑线)
同样是用来为租户的私有网络和我们常用的互联网。其上主要运行的是neutron的各种插件,包括L2 agent、L3 agent、DHCP agent、VPN agent、FW agent,以及配套各种软件(或者linux的network namespace网络命名空间,负责具体实现路由、防火墙、VPN等功能)。为租户提供各种诸如NAT、router之类的出口服务。
存储网络:(图中红线)
与VSAN计算和存储节点融合在一起有所不同,openstack架构中,普遍采用单独的存储服务器集群向计算节点服务器提供存储服务,且支持块存储、文件存储、对象存储多种类型。
在网络设计上也会有较大的差异,存储服务器集群内部需要通过高性能网络连接。同时存储服务器与计算节点服务器之间也要通过高带宽网络连接。
实际上,vmware vsan 同样允许计算节点和存储节点处于不同的物理服务器上,但是要求使用vsan存储的主机和提供vsan存储的主机处于同一个集群。但是vsan集群中对于主机数有限制(6.0版本中已经升级到64台),每个集群只能有一个VSAN,且集群中所有的主机都会消耗vsan的license数量。所以在这种特殊的收费方式下,vsan的实际部署都是采用融合方式也就是存储节点和计算节点结合在一起。
租户网络:(图中红线)
neutron的租户网络结构与vmware的类似,同样通过二层的overlay技术来对租户的流量进行标记,实现隔离。但是相比vmware必须采用自家的vDS或有限的几家合作伙伴(cisco、ibm、brocade)以外。Openstack neutron支持的二层设备包括一大票的开源虚拟交换机和商用虚拟交换机的插件,并且不同的二层设备支持的协议和功能的实现都有不同。
- Open vSwitch Plugin最开始nicira主导的开源标准openflow交换机
- Cisco UCS/Nexus Plugin
- Cisco Nexus1000v Plugin较早商用的虚拟交换机,支持包括openstack、vmware在内的多个平台
- Linux Bridge Plugin 老牌linux 网桥技术,很早就已经集成到linux内核
- Modular Layer 2 Plugin
- Nicira Network Virtualization Platform (NVP) Plugin 也就是NSX的插件
除此之外还有Big switch 、brocade、IBM、MidoNet等等非常多的二层插件。不用的插件在二层租户网络的实现上都有非常大的差异。而且也大量使用着各种私有协议。早期openstack版本中,因为不同的插件控制器不同,而控制器只能使用一种。导致网络使用的二层agent也必须为同一种。这一问题在后来版本中加入ML2层后得到了很好的解决。ML2屏蔽了不同插件的不同,而统一对外提供neutron网络功能的API,兼容不同的二层实现方式只需将不同厂家的插件加入到ML2中。ML2中间层能够很好地在一个网络中兼容多种二层的插件。
所以,neutron server成了SDN的控制器,通过openflow、OVS DB的协议兼容了多种二层软硬件设备。
后面的中心也会放在Open vSwitch和Linux Bridge上。
最后,这仅仅是openstack和nsx的标准范例,实际上不同的环境下,所采用的技术有非常大的差异,比如专用的高安全性的机房、物理的overlay实现等。不过总的来说,流量的类型还是逃不出这几大类。
二层技术和实现
二层的实现
SDN的解决方案中,用“二层”和“三层”来区分SDN的技术不太合适。所以说是二层的实现,实际上是如何用SDN的技术来实现传统网络二层的功能。
传统二层的主要功能无非就是:
- 实现主机之间的联通:包括二层的选路、MAC地址的学习、地址表的维护。主要是为了实现同一个二层网络内部主机的互联互通和不同二层网络之间的隔离。
- 对于广播、多播的处理:防止网络被过多广播包淹没而不知所措。
- 部分高级功能:包括接入控制、端口安全、802.1X认证等
实际上交换机发展到今天,已经包含了非常多的三层特性了,包括动态路由、MPLS、VPN等等,除去对异构网络的接入能力差于以前的路由器以外,交换机已经普遍被当作三层设备来使用。
在云数据中心中,主机被虚拟化后,虚拟机的接入交换机也普遍被软件交换机代替,Neutron用到的软件交换机有:Linux bridge、Open vswitch两种,虚拟机通过虚拟的端口连接上虚拟交换机。
本地联通与隔离
所以根据上面的定义,现行SDN技术首先要解决的就是同一网络内的互联互通和不同网络之间隔离的问题。
传统硬件交换机通过学习端口上连接主机的MAC地址,生成MAC地址表,来判断数据包该如何转发。在openstack 中,虚拟交换机依旧在模拟这一过程。而Linux bridge和 OVS 则分别代表了两种不同的数据层和控制层转发模式。
相同的是虚拟主机的网卡在创建后需要连接到 tap 接口上,并通过 tap 接口连接到计算节点内部的虚拟交换机上。虚拟机网卡将原本要通过物理网卡发送出去的数据改为读和写虚拟的 tap 接口,这样已经封包的数据重新进入网络协议栈,并转由虚拟交换机操作。
虚拟交换机本质上是物理主机上一个网络命名空间“network namespace”,厉害的是它拥有相对物理主机独立IP协议栈和路由表,所以它的转发规则可以不受物理主机的影响,在将主机上的物理网卡关联上这个网络命名空间,作为该netns对外的接口,则虚拟机之间即可以通过的物理网卡实现互通。
Linux bridge实现方式
Linux bridge 毕竟是老牌技术,很早就已经加入了linux的内核,其本身不支持 Openflow 协议,当Linux bridge 作为转发设备时,其转发实现依靠的是传统的地址学习机制。交换机识别出包头的内容后,即去查找交换机的 mac 地址列表,然后按照包头中目的mac对应的 port 转发出去,如果mac地址没有查到则在所有接口中洪泛数据包,直到收到包含未知mac 的数据包后,记录下mac地址和对应的接口,一个最基础的二层转发过程就完成了。
传统mac学习机制早已深入人心,不做过多的介绍。而SDN化后设备的配置、初始化等可以统一由Neutron server和主机上的 L2 agent来完成,但 Linux bridge本身的问题导致它跟传统网络交换机一样,转发行为不可控,添加功能麻烦。
Linux bridge的mac地址表
local
Local 模式为虚拟网络最基础的模式,该模式下的虚拟机连接到位于主机内部的虚拟交换机,同一台交换机上虚拟机之间能够通信,虚拟机无法与外界通信。
local模式下的本地联通
当采用Linux bridge作为二层转发设备时,每在主机上创建一个本地网络时,Linux bridge agent都会在物理主机上起一个新的虚拟交换机 bridge,交换机的名称的前缀为brq-xxxxxx ,Neutron的L2虚拟机主机连接到本地网络上时,就是通过tap类型的虚拟接口连接到了这个特定的bridge上。当有主机需要连接到交换机上时,
- 租户首先请求创建一个虚拟网络和一个端口,Neutron会分配对应的网络资源并分配vlan id,随后即创建端口和并关联到此网络。
- 租户请求创建虚拟主机,Nova组件将按照租户的需求调用虚拟网络驱动,创建一个tap类型的接口,随后nova创建虚拟机后即会将虚拟机与该接口关联。
- 随后租户请求将tap设备关联上之前创建的网络端口,Neutron将端口的关联信息记入数据库。
- 主机上的bridge agent不断扫描本地的接口变动情况,一旦发现新加的接口后,会上Neutron查询新接口的详细信息。
- 随后主机上的agent会根据Neutron server数据库中的配置在主机上创建bridge和vlan,并设置虚拟机接口的连接。最后更新Neutron server数据库中接口状态。
- vm正式关联上虚拟网络。
至此同一bridge上的虚拟主机已经可以相互通信。不同的 bridge 之间暂时还不行。这也就是Neutron、支持的最基础的网络类型:Local。
在实际环境中因为无法与外部通信,Local类型的网络在实际中使用得较少,仅仅在需要隔离进行测试系统或者业务时需要用到。
Flat
Flat模式为虚拟机与外部网络直连的模式,主机内虚拟机直接连接到租户网络。
而一旦当 Bridge 关联一个物理网卡后,每当物理网卡收到数据时,都会把数据转发到 Bridge 上进行处理。而linux Bridge 接收到此数据时,则开始进行mac地址学习、查找mac地址表、转发、丢弃等操作。这种情况下,物理网卡与虚拟设备直连,物理网卡上不配置任何IP地址,数据帧出物理主机也不带vlan的标签。虚拟机上的数据通过二层直接转发到外界的物理网络上。实现虚拟机与外界的直接通信。实现了Flat类型的网络。
在物理主机上查看Linux bridge虚拟交换机
除此之外,Linux bridge上还有另一个隐藏的三层接口,类似与传统交换机的SVI接口,用于bridge与linux 内核之间的通信。
flat模式下,云主机直接连接到物理网卡进行通信,这种情况下、物理网卡只能连接一个虚拟交换机,主机内部所有需要直连物理网络的虚拟机,都会接入到这台虚拟交换机上。
这种接入模式在实际环境中使用得较少,主要用于云主机需要与数据中心内部硬件服务器互联互通的应用场景,如:应用服务器安装在虚拟机上,而数据库服务器安装在硬件服务器上,以及虚拟机需要通过二层连接传统的 SAN 存储的情况下。在公有云上使用得不多,因为直接连接到物理网络上,意味着暴露给了其他租户,存在被扫描漏洞以及被攻击的风险。而且不同租户之间虚拟机需要通过通信的业务更少见。
VLAN
vlan 类型是比较经典的组网模型,同一 vlan 中的虚拟机可以通信,不同 vlan虚拟机之间的数据通过二层vlan标签进行隔离,该类型网络要求租户网络的接口与物理主机的借口通过trunk互联。
Linux bridge中,vlan类型的网络将在网卡eth1上创建1个子接口: eth1.xx ,当有流量从该接口流出到物理网卡上时,会加上一个xx的vlan标签。而带标签的流量流入时,则会去除标签并转发到对应虚拟交换机上。
VLAN 是一种非常普遍的网络类型。
公有云中云主机、路由器连接的“基础网络”、“经典网络”就是一个vlan类型的网络,租户的数据不再需要通过overlay的方式进行封装,而是去掉标签直接与互联网进行通信。
这个二层网络通常为数据中心内部的vlan,默认这个vlan内的主机之间都能通信,所以在连上基础网络后,通过端口扫描能够扫描出大量其他用户的主机。而且因为没有公网IP映射和回指路由,这个vlan内的ip是无法通往外部网络(Internet)的。
VXLAN
VXLAN扯开了讲,这篇博文就要明年才能更新了。简单说就是vlan最多只能隔离4096个网络。对于用户数庞大的云运营商来说,肯定是不够的。
虚拟交换机上创建一个 vxlan-1的虚拟接口,vxlan-1捆绑到配置了VETP地址的物理网卡上。
虚拟交换机上行数据包被vxlan-1接口封装到UDP包中,并通过VTEP接口转换到物理交换机上。
这几乎是每一个想公有云都会用到的技术了,更多的逻辑隔离,意味着容纳更多的用户、更多的流量。而且兼容传统网络设备,可以直接利旧。VXLAN本身也不完美,过长的包头导致带宽无用的损耗,其次协议的封装也会给设备带来更大的压力。
Open vswitch实现方式
与老牌的Linux bridge不同,OVS是由Openflow祖师爷的公司创建的,其通过流表(flow table)的方式实现数据层面的转发和操作。控制器直接将数据包转发的规则以流表的方式发送给交换机,流表包含了详细的匹配信息——什么样的数据包(包类型、源mac地址、目的mac地址、源IP地址、端口等等,1.5版本中已经支持最多45个匹配域),执行什么样的操作(转发、丢弃、修改其中某些字段,匹配其他流表),如果遇到流表无法匹配的数据包,默认也会转发给控制器,由控制器生成新的流表。以下是流表中一个条目包含的字段。
以下太长了懒得看系列:每条 Openflow 流条目包含了匹配条件和执行的操作。匹配到的数据包会按照操作进行转发或者丢弃等。
Openflow 条目
- 匹配字段:用来匹配需要处理的数据包,可根据数据包的入接口、包头字段、和上一流表定义的元数据字段等等来匹配。最新的1.5.1支持45个匹配域,包括了:入接口、源mac地址、目的mac地址、以太网帧类型、vlan id、vlan priority、ip DSCP、ip ECN、ip源地址、ip目的地址、源端口、目的端口、arp opcode、icmp code、MPLS 标签、流表之间传递的元数据等等。
- 优先级:流条目匹配的优先级。优先级高的条目先匹配。
- 计数器:匹配成功后计数器会+1。
- 说明:用来指定对于匹配成功的数据执行的操作。
- 超时:流的过期时间。
- cookie:自定义字段,用于实控制器的一些自定义操作,例如批量地删除或修改cookie值为XXXXX/16 的流条目(这些流条目可能是用于对某一类业务或者某一个租户的数据包进行处理的)。cookie不会对于数据包的转发和匹配造成影响。
- Flag:flag用于标识流条目的管理方式。比如当flag包含 OFPFF_SEND_FLOW_REM ,则当交换机因为流条目超时或者流条目空间不足而删除条目时,都会触发交换机发送流删除的消息给控制器。
(相信对于很多人来说都会发现流表其实与传统交换机上的ACL、route-map等策略路由的处理方式是有点类似的)
Openflow v1.5 数据包处理流程
以下太长了懒得看系列:Openflow 交换机对数据包的处理可以看成两条管道对数据流进行过滤,流表和流条目就是滤网,将筛选出来的数据转发出去或者丢弃。
Openflow 在1.5版本后有一个非常大的功能改动,那就是引入了出端处理流程(Egress processing)。过去版本中数据包进入交换机后直接只需经过一次处理,确定出口后即被转发出去。1.5版本后,数据包匹配完,确定出接口后,会再进入出端的匹配流程。例如:
- 数据包的进入Openflow的交换机后,首先进入入端处理流程(Ingress porcessing)逐条匹配入流表中的流条目;
- 数据包 match 到的优先级最高的条目,流条目对应动作集也将执行,并更新流条目相关的计数器。
- 根据动作,数据包有可能被传递(Goto-Table)到另一个流表,然后重新按顺序匹配。也有可能直接丢弃(drop),或者最终匹配到优先级最低的条目。
- 如果匹配正常,确定的了数据包的出接口,则开始出接口处理流程(egress processing),出流表与入流表在功能上时类似的,不同的是入流程和出流程之间不能通过(Goto-Table)传递数据包。出流程无法重新指定数据包的出接口。
- 每个流表都必须支持一个 Table-miss 条目,Table-miss 条目优先级最低,为 0。并且匹配域全部匹配。可以看成是一条全为 0 的ACL条目,用来处理那些还没有建立转发规则的数据流。对于这一类的流量,可以选择转发给其他表、或者转发给控制器用于生成新的流表、以及直接丢弃。从流表的设计优化的角度来说,table 0 内的table-miss条目会将数据包转发给控制器,而不是任由无法识别的流量向下持续匹配。
一次流表操作示例
所以基于此,我们完全可以制定出这样的流表:
Ingress processing:
table=0 , priority=1 , ARP类型的数据包(ETH TYPE=0x0806) , 交给 table(10)处理 resubmit(10) -通过匹配域识别出arp类型的流量,并交由指定的流表处理。
table=10 , priority=1 , ARP请求的目标ip为 192.168.1.0/24 (OXM_OF_ARP_TPA=192.168.1.0/24) , action 修改请求中的源mac地址为网关的mac(0xa0a0a0a)。修改请求中的源IP为用户请求的IP(192.168.1.x)。修改包的类型为arp 回复 ——(arp代理的实现)用网关的ip来回应原主机
将原请求中的 源mac 和 源ip 移动到 目的mac 和 目的ip ,返回给源端口(OXM_OF_IN_PORT)。 ——构建arp返回包
进入出处理流程
Egress processing:
table=233,priority=100,修改以太网帧的源mac地址,目的mac地址,转发出接口。——重新封装二层帧
(实际中不一定包含 egress processing ,相应的流条目可以放在入处理流程内,实际现有arp代理功能并没用到egress processing ,此例仅为演示效果。)
交换机收到目标IP为192.168.1.100的ARP请求,交换机用自身的mac地址来代替远程主机的mac,并修改数据包类型为ARP回应后,从源端口发送出去。
由此可以看出,SDN交换机可以在完全不懂arp协议是什么的情况下,仅仅通过匹配和操作即实现了传统交换机的 arp代理功能。同理如果需要增加新的功能,只要制定流表就可以,当然前提是交换机上Openflow协议支持对应的匹配域和动作。
处理前
原二层帧头 | 发送器MAC地址 | 发送器IP地址 | 目标MAC地址 | 目标IP地址 |
---|---|---|---|---|
OXM_OF_ARP_SHA | OXM_OF_ARP_SPA | 00-00-00-00-00-00 | 192.168.1.100 |
处理后
新二层帧头 | 发送器MAC地址 | 发送器IP地址 | 目标MAC地址 | 目标IP地址 |
---|---|---|---|---|
0a-0a-0a-0a-0a-0a | 192.168.1.100 | OXM_OF_ARP_SHA | OXM_OF_ARP_SPA |
1.5版本中,Egress processing 的引入大大缩减流表匹配的复杂度, 然而 Openflow 每次版本更新所带来的改变同样让sdn交换机厂家比较头疼,这意味着交换机和控制器的协议栈要重新编译,甚至不得不重新设计转发芯片。所以sdn交换机都会注明支持 1.0、1.3等版本的Openflow,如果交换机只支持旧版本的Openflow协议,则意味着交换机的功能也有限。而且新版本的协议发布后,设备厂家跟进也需要时间。其次Openflow这种协议无关的规则,也限制了其本身的应用。
从国内主流厂商官网的信息来看,大部分的交换机依旧只支持Openflow 1.3
local
OVS 会在主机上创建三类虚拟交换机
• Integration bridge (br-int) : 内部交换机,用于连接主机上所有的虚拟机和其他两类交换机。 还有一些特殊功能的插件也会连接的br-int上。如浮动ip、dhcp等。
• External bridge (br-ex) : 外部交换机,即 ovs Provider Bridge 用于连接外部网络。即租户网络的边界。
• Tunnel bridge (br-tun) : 隧道交换机,即 OVS Tunnel Bridge 用于连接各计算节点之间的租户网络,所有租户网络的流量在打上vxlan的标签后都会发送到此网络。
简单来讲,OVS 的三个虚拟交换机各有分工,br-int 内部交换机主要用于计算节点内部的网段之间的通信,而br-tun用于节点之间的网段通信。Br-ex 与虚拟主机与外部网络的通信。三个交换机都通过各自不同的流表来实现相关的功能。
ovs也支持local类型的网络,在openvswitch中有所不同,所有的实例都连接到 br-int 交换机上,每一个本地的网络相当于一个ovs 上的 local vlan,连接本地网络中的所有节点。Neutron不会为local vlan创建任何flow rule。意味着不同的local vlan之间是无法通信的。
Local vlan位于主机本地,不同于我们常理解的vlan,从名字就能看出,一个主机内的 local vlan 在其他主机上是没有意义的,当两个主机之间通信时,需要通过流表把各自把 local vlan 标签通过流表转换为外部统一的 vlan 标签。
ovs 和 Linux bridge 之间通过虚拟以太网 veth 类型的接口互联,veth 类型的接口可以理解为一条网线,数据包从一头进入,另一头出来。
ovs 的交换机之间(br-int、br-tun、br-ex)通过 patch 类型的接口互联,patch 接口与 veth 类似,不过为 ovs 做了优化。据说能提供更好的性能。
Flat
ovs上flat类型的网络亦是通过flow rules(流表)来控制的,flat类型的网络关联到本地的local vlan,Neutron创建对于local vlan网络的规则:从ovs 的flat网络中出去的流量,将取出local vlan的标签,并通过 br-ex 交换机转发出去;而未打标签的流量从 br-ex 中进来的时候则会加上local vlan标签。
VLAN
openvswitch,每个vlan类型的网络都会映射到OVS上的一个local vlan。当OVS上有Local vlan的流量出去网卡时,OVS会根据local vlan和真实vlan的映射关系进行标签的转换。然后从br-ex 交换机转发出去。
VXLAN
在此模式下 br-tun 虚拟交换机终于派上用场,OVS通过名为 br-tun 虚拟交换机来实现流量的封装和解封,tunnel bridge连接内部的integration bridge 和配置了VTEP的物理网卡。br-tun 通过流规则来实现数据包的封装,将从br-int交换机传输过来的数据包,根据目的地点的不同选择从VXLAN、或GRE的隧道转发出去,并对数据包进行重新封装,封装之后的数据包外层为节点物理网卡的二层和三层包头,数据包的载荷则是原来完整的数据包,就跟包饺子一样,馅被整个地包到了外皮里面。当使用VXLAN类型的网络时,br-int传来的数据包会被 br-tun 重新封装一遍,并在原数据包的前面加上一个UDP的包头,里面包含了该网段对应的VXLAN的网络ID,新数据包的包头为主机物理网卡的IP和mac地址,加上目标主机物理网卡的IP和mac地址。
VXLAN数据包的结构
GRE
GRE是一种历史悠久的隧道协议了,其优点是支持组播,甚至能够用来承载动态路由协议的数据包,被广泛运用在各种场景下,不仅仅只是云数据中心。GRE隧道模式下与ovs工作流程与VXLAN 非常类似,不过一个 VNI 号位于TCP的字段,一个位于UDP的字段内。
GRE包头
需要注意的是 Linux bridge不支持GRE协议。
对于广播、多播的处理
传统模式下,当虚拟交换机处于地址学习的模式下,当交换机收到到一个未知mac地址的数据帧,这时如果交换机不做任何的优化,则默认需要将该数据包重新封装后从二层广播出去,直到那个未知的主机返回数据帧后,才能准确知道目标虚拟主机对应的节点。这一问题也只有在overlay的环境才更突出。
在下面的例子中,租户233位于计算节点1和计算节点N上的 VM1需要与节点N上的 VM4 通信,VM1还不知道VM4的MAC地址,VM不得不发送ARP请求进行查询,而虚拟交换机上也没有对应的mac地址记录,因此数据在整个租户网络上洪泛。同一承载网络上的所有主机都收到这一请求,直到节点N 核对网络号和主机IP后,将数据转发给VM4,VM4再做出单播的回应。
Ovs 默认的处理流程也与此类型,不同的是ovs的虚拟交换机收到arp请求之后,并不懂得如何处理,而是转发给控制器,控制器会让交换机在所有端口上洪泛,直到收到虚拟主机的回应后,交换机再将回应的包转发给控制器,控制器依据此信息更新流表,随后才能正常转发两个主机之间的流量。
这种方式显然有问题,通常一个租户有多台云主机时,并不会将所有的云主机都放置在同一台云主机上(这个放置算法也很有料,有空可以聊一下)。这时,如果所有的未知地址的二层帧,或虚拟网络的广播、组播包全部都在物理网络上洪泛的话,物理网络将长期被各种广播包占据。特别是租户较多的网络中,这种方式无疑会导致物理网络无法正常工作。
对于这一问题,主要有以下几种解决办法:
1、在虚拟交换机上启用arp proxy,Neutron L2 driver 会在所有的虚拟交换机之间预加载远程VM的 IP 和 mac 的对应关系、以及VM的mac和物理节点网卡mac的对应关系,本地虚拟交换机响应主机的arp请求,从而杜绝 arp广播在传输网络中的广播。但这仅能处理arp的广播包。
2、仅将二层的广播包发送给包含了该租户网络(VNI)的节点,主要有两种实现方式。
2.1、在物理网络上启用多播,这样当节点上有虚拟机加入租户网络时,节点发送IGMP请求加入该虚拟网络对应的组播组,这样,广播流量被转化为组播流量,当该租户网络上有广播包时,节点的网卡会将虚拟机的广播包封装成组播包,发往物理交换机,物理交换机只会将组播包复制到加入到该组播组的主机,无需再在网络中进行洪泛。这要求物理网络支持组播,而且需要规划好组播组与租户网络的对应关系。因为组播地址数远少于租户网络(VNI)的数量,所以通常多个租户网络对应一个组播地址,这样依旧会有一些租户网络的数据包被发送到不相干的节点上。
组播复制
2.2、租户网络二层广播包被物理主机单播到一个服务节点,该服务节点本地保存所有vm ip、vm mac、主机mac信息,由该服务节点将原始数据包复制多份之后,分别发给包含该租户网络的节点。这不要求物理网络支持组播,也不会有多余的传输,但是对于服务节点的存在本身就是一个较大的问题。
单播复制
其他功能
安全组
Neutron 选择使用linux内核中的 iptables 来实现的虚拟安全组的功能,所有安全组的策略都关联在虚拟机所连接的tap接口上,流量进出虚拟机网卡时都要经过 iptables 的过滤,保证了虚拟机的安全。然而尴尬的是,这种方式下需要将数据包交由主机内核的协议栈来执行iptables的处理,而 ovs 基于流表的处理方式是独立于内核的。所以当使用ovs来实现安全组的功能时,不得不在每台VM和ovs之间添加一台 Linux bridge,虚拟机发出的数据包先到达 Linux bridge,经 iptables 过滤后再上行到ovs。如果是进入虚拟机的流量则将这一过程反过来,最终成了下面这种奇葩的连接方式。
详细的安全组的介绍还是放到后面吧….
OVS与Linux bridge之争
功能对比
总结以上来看Linux bridge为早期的虚拟交换机实现方式,理念也更接近以前思科的网络模型,更多的依赖物理网卡作为网关。而OVS的实现更加符合SDN的理念。由此可以看出,Linux bridge更加成熟稳定,但是如果要添加功能会比较麻烦。比如至今任不支持GRE、也不支持DVR(这才是最伤的,只能使用集中式路由意味着VPC之间的流量需要绕过网络节点的发卡弯,这个后面路由的时候再详细介绍)。
OVS更符合SDN的理念,通过flow-rule 来实现各种二层、三层的特性,这样优点是可以简单的通过流表添加新的功能的,也有可能兼容更多的SDN解决方案,除此之外OVS 也支持模拟传统交换机的行为,实现与传统交换机的共同组网。
但是同样,Rackspace 也列出了ovs当前存在的问题:
1、内核错误(版本 1.10),可能导致物理主机出错
2、分段错误(版本 1.11),ovs分段错误重启导致流表被清空
3、广播风暴,物理主机大批量开机,而同时主机上的ovs 插件没有起来,则可能导致广播风暴,可以通过修改ovs的启动脚本解决,不过会使ovs变得复杂。
4、数据损害(版本2.01),这里他们举了一个例子,mysql的“BEGIN”指令到了接收端变成了“BEGie”(真是个奇怪的问题,不知道有没有大神能阐述一下原因)
而他们看重的linux bridge的理由则很简单:
1、稳定
2、容易排错
3、同样被社区支持
追求稳定性的同时,也意味着失去更多的可定制化(包括对DVR的支持)
两者功能对比:
性能对比
OVS和Linux bridge两者在性能上的差异并不大,在使用vlan类型的网络时,OVS 和 Linux bridge都能获得不错的性能表现,约等于物理网卡的理论速率的90%,而运行在Vxlan模式时,则会有非常高的性能损耗。在使用SCP这一类单线程协议,传输大文件时,传输速率接近腰斩。
iperf打流的情况下,ovs 和 Linux bridge 都只能达到网卡理论速率的10%左右,性能衰减非常厉害。可能的原因有:在数据包数量较多,数据收发频繁时CPU容易成为性能的瓶颈,这一问题在使用DPDK技术后能得到一定的缓解。不过根据rackspace的实测结果,即便在多线程的情况下,对于交换机的性能也没有显著的改变,可见瓶颈在于CPU对于VXLAN数据的封装和解封装上。不过我没有实测过ipref在打流时CPU的利用率,有测过的同学可以一起讨论一下。
但是总的来看,吞吐性能与交换机采用的网络类型有着直接的联系,考虑到封装VXLAN后数据包多了一圈包头,数据的有效载荷减少,实际网络的吞吐要比测试的稍微好那么一点点,但是性能下降的程度可见一斑。
Rackspace的ovs和Linux bridge跑分测试结果
总结
Linux bridge 、ovs 这两者都被Neutron容纳进来,既有国外巨头因为ovs的不成熟而整体切换到 Linux bridge,也有国内厂家使用OVS 流表实现了各种 Neutron 都还不具备的高级功能。而除了 Linux bridge、OVS这两大代表解决方案外,还有与这两者完全不同的解决方案。
OVS | Linux bridge | |
---|---|---|
工作方式 | 基于流表 | 基于地址学习 |
功能 | 不成熟,不同的版本支持不同的功能,可扩展性强 | 较为成熟,可扩展性差 |
性能 | 一般 | 一般 |
优势 | 可定制能力强,通过流表可满足非常多特殊应用场景下的功能需求使用得最为普遍的SDN 交换机 | 成熟稳定,主流功能都由相应的插件满足要求。足以满足大部分用户的使用需求。 |
劣势 | Openflow的特性还未被完全利用,部分功能还无法实现。Openflow协议本身的不成熟,新版本与老版本之间差异较大,导致硬件厂家需要较长的适配周期。技术与市场脱节。 | 难以响应新型业务的需求,导致在一些教新的SDN领域应用得很少。 |
代表方向 | 数据层和控制层的完全标准化,特性的业务需求完全可自主实现,无需依赖硬件厂家 | 与传统网络兼容,在各种设备混杂的环境下,通过封装统一的北向接口实现网络的自动化。 |
花了老鼻子力气来讲 Linux bridge与 OVS 在原理上的不同,核心是试图摆明现在SDN实现中两种不同的方向。一个天生就不屑于与传统势力共舞,立意高远试图以更接近理想地方式颠覆传统的网络,并定义标准的协议的软交换产品,技术实力雄厚的大佬们已经凭借着技术的优势获得了不菲的成绩。可是大众的用户依旧面临着不够成熟的产品,和自身羸弱的开发能力,许多时候只能望洋兴叹。
- 代表组织:ONF
- 涉及势力:Facebook、Google、Big switch
而另一个在现有的基础上兼容着传统的网络设备和协议,不涉及到转发层面的操作,并不限定任何南向的技术标准,允许各个厂家百花齐放。只是定义一套统一的北向接口,试图的作为一个口袋方案,囊括底层所有的复杂性,尽量以统一的面目对外。大量地厂家投入到该项目,用户有大量的可选方案,然而厂家参与者们各自心怀鬼胎,用户依旧不得不面临各参与者人为制造出复杂性和隐藏的深坑。
- 代表组织:ODL
- 涉及势力:Cisco、Juniper、Brocade等
这两种情况在现实中都拥有着大量的用户群体。部分运营着大规模网络的用户,选择的是在现有设备的基础上,实现管理控制 的SDN化,以更好地满足业务的需求。一方面不得不耗费大量的人力和时间去适配网络中各种厂家、型号、软件版本的硬件设备。另一方面大量使用overlay+软交换机的模式,期望最大限度地降低这种复杂性和对底层的依赖,典型如:如运营商(电信、联通)、大型企业(阿里、百度、腾讯)等。中小企业如果耗费大量资金来招募团队来做SDN的实现就违背了做SDN的初衷,但是大量企业又希望能享受SDN带来的便利,而只能转投传统网络企业的阵营,采购现成的产品,如,思科、brocade、vmware、juniper、华为、H3C、锐捷。这些产品往往被打包融入厂家的基础架构中,用户依旧被绑架,而不得不购买整套的产品,同时这些厂家之间同样基本缺乏完备的互操作性,看似支持开源技术的产品,实则被各个厂家包装后,依旧和原来一样封闭。然而对于用户来说,是否开源并没有那么重要,
SDN的现状,正如朝霞的天空一样色彩斑斓,剧烈涌动,没人知道这种混乱要持续到什么时候。
附各厂家SDN控制器阵营划分
部分参考:
《Neutron L2 and L3 agent:how they work and how kilo improves them》 - opnestack summit
https://www.ibm.com/developerworks/cn/linux/1310_xiawc_networkdevice/
http://www.innervoice.in/blogs/2015/01/26/using-mac-table-linux-bridge-wilt/
Openflow® Switch Specification Ver 1.5.1
三层技术和实现
Neutron 三层技术简介
三层的实现主要对应传统路由器组网的功能。包括三层的路由、NAT转换、ARP代理、DHCP服务等。neutron在三层的实现上与二层的耦合性较低,即无论二层采用linux bridge还是ovs,L3都是采用的相同的实现方式。
但有意思的是,三层也分两种不同的实现架构:分别是集中式、分布式。这两者之间也恰好代表了传统和未来的两种实现方式。
- 集中式路由
- 分布式路由
集中式路由
openstack的 Juno 版本时期,用户只能创建单机的路由器,即不同的VPC之间要实现互联,VPC内的数据需要全部转发到该路由实例上进行转发。
路由实例在这种场景下,提供:
1、用户内网(VPC与VPC)之间的互联、
2、用户内网与外网(VPC与基础网络、Internet、DCI)之间的互联,通常还要兼任NAT网关的工作。
用户创建的虚拟网络之间是隔离的,无法互相访问。Neutron router 作为默认的网关能够实现租户网络之间的互访。
路由器同样是主机linux系统内的一个网络命名空间,单机部署时,一般部署在物理集群的网络节点上,一边连接租户网络,一边连接外部网络。下图是openstack官方文档中对neutron router的介绍:
图中br-int、br-ex、br-eth 是ovs的交换机,路由器和虚拟主机一样连接在br-int上,用户的每一个私有网段都会连接到路由器的一个接口上,同时路由器上行连接到外部交换机上,实现用户私有网络与外部的通信。并由主机上的 L3 Agent 来完成路由器的配置。图中的 dnsmasq 是linux上的一个小型服务器,neutron 用它来实现 DHCP server 的功能,租户的每一个私有网络都会创建一个对应的 dnsmasq 实例。
内网与外部网络之间的NAT地址转化则是在路由器上完成。NAT转换使用的是在安全组的介绍中提到过的iptables。由iptables对数据包源地址或目的地址进行重写,实现路由器的SNAT和DNAT。
在openstack的网络节点上创建用户路由器的整体流程如下:
1、在节点上安装L3 agent
安装neutron L3 agent需要在cotroller节点上运行以下命令,跟安装一般软件包没有区别。
apt-get install neutron-l3-agent
Neutron router同时支持linux bridge和ovs。
2、配置外部网络
/etc/ neutron/l3_agent.ini
[DEFAULT] …
external_network_bridge =
该配置项用于指定路由器的上行交换机。默认值为 br-ex ,即使用br-ex作为连接外部网络的交换机,一旦使用br-ex后,neutron会将路由器的上联口连接到br-ex上,并且路由器将不会处理vlan标签的插入和移除。这种情况下L3 agent只能关联一个外部网络,该主机上的所有的路由器都将使用这个外部网络作为上行的网络。
如果这值为空,L3 Agent将自行创建交换机、端口、和交换机的流规则。并且同时关联多个外部网络。所以该怎么做,已经一目了然了吧。
当有多个外部网络时,需要手动设置网络属性为 router:external。
除此之外如果要制定某个特定的外部的网络,则需要设置 gateway_external_network_id =
此外较早期版本的openstack中,路由器删除后,路由器所使用的网络命令空间不会自动删除,需要修改配置文件中
[DEFAULT] ...
router_delete_namespaces = true
3、通过CLI或者Horizon 来创建路由
然后就可以开始创建路由器了。
router-create [--tenant-id TENANT_ID] [--admin-state-down] NAME
4、连接租户网络和外部网络
连接指定的租户网络
router-interface-add ROUTER INTERFACE
连接外部网络
router-gateway-set [--disable-snat] ROUTER EXTERNAL-NETWORK
路由器默认会开启SNAT功能,为租户网络内的虚拟机提供NAT服务,保证虚拟机与外部网络通信。
需要注意的是,目前为止,一个路由器只能连接一个外部网络。所有内部网络的流量都将经由此接口流出。这既与neutron router的定位有关,又影响了openstack三层的组网结构。很明显neutron 的路由器不适合作为汇聚路由器、核心、或者出口路由。无法实现路由之间的互联、也不支持动态路由协议。所以当前opentsack是无法实现租户复杂组网环境的。不同子网的虚拟机需要连接到一个路由器,来实现互联互通。这直接导致大规模部署时,集中式路由器基本不可用。基本上是一环扣一环推出,未来铁定是分布式路由器的天下。只能说当前 openstack 在三层组网上稍有欠缺,而nicira在这一块则完整得多。
有意思的是,当前 opentack 的 project 中还没有看到路由器的规划,有点好奇未来openstack将用何种方式填补这一空缺,是直接像 nicira 一样引入 NFV, 还是用ovs来代替路由器,亦或是再给iproute2缝缝补补续上几年。
5、启动实例
启动虚拟机,并按照上一篇的内容连接租户网络。
6、配置路由器的NAT功能
这里就主要是使用浮动IP了。
neutron路由器支持一对一的静态NAT,和多对一的PNAT。默认情况下路由器执行PNAT操作,租户网络内的主机经路由器与外部通信时,源地址都会修改为路由器路由器外部接口的地址。这也被称作源地址转换SNAT。是内网主机上网最常用的一种方式。这种情况下所有的主机共用一个外网地址,外部网络的主机无法主动发起与内网的通信。这时就需要静态NAT功能,将内网主机映射为特定的外网地址。即给主机绑定一个fip。
Neutron route 为虚拟机提供NAT服务
通过路由的NAT功能,只要统一做好外部网络的地址规划后,即可实现租户内网IP子网的复用,不同的租户之间能够复用完全相同的子网网段,且不会冲突。这也是公有云上能够容纳大量租户的原因之一。
集中路由模式的问题显而易见,网络节点上的路由成为流量的瓶颈点和故障点。在这种模式所有租户的VPC之间的流量的都经由网络节点上的路由器转发,当云上的租户较多,所有的流量都汇集到网络节点的设备上,会直接导致网络拥塞。同时单个router出现故障,如被重启时,租户网络之间就无法通信了。
高可用路由
高可用路由模式是对集中路由模式的一种补充,其核心是采用VRPP协议实现双路由部署模式下的高可用。VRRP(虚拟路由冗余协议)脱胎于 cisco 的 HSRP,是一个老牌的网络协议了。在传统网络设备中就被大量的使用,曾经也有过VRRP+MSTP这种典型的组网模式,扯远了。
VRRP 部署模式下,网络节点上需要部署多个路由器,组成一个 VRRP 组,组内的路由器将通过一个虚拟IP与外界通信。也就是说外部回指路由指向这个虚拟的IP。
VRRP组内将选举出一个活动的路由器,其余的路由器则作为热备路由器。主路由器将响应发送给虚拟IP的数据包,备用路由器则不会响应。备用路由器将通过心跳信号检测主路由器的存活情况,当主路由发生故障时,剩下的备用路由器中将选举出一个新的活动路由器,备胎转正。
VRRP的大名路人皆知,这里就不赘述了。很容易看出,高可用路由模式解决了路由器单点故障的问题,单个路由器故障时,备用路由将接替故障路由器的工作,以保证租户网络流量的正常。
但是同时,高可用路由模式依旧同时只有一台路由在工作,流量发卡弯的问题依旧没有解决,路由器依旧是大规模部署时的网络性能瓶颈。这个时候最终就该DVR(分布式虚拟路由器)登场了。
分布式路由(DVR)
是的,就是上篇中提到的Linux bridge不支持的那个DVR。
分布式的使用场景下,内外网的流量不再汇集到网络节点上之后再转发。而是在计算节点本地就能处理,在该模式下,当租户在计算节点上创建了使用DVR的私有网络时,该节点随之会自动创建一个路由器实例。传统模式下跨子网的通信都需要将数据包转发到网络节点的路由器上,分布式路由器模式下跨子网的通信,都会由本地的路由器来执行路由。
dvr 流量模型
DVR有两种运行模式。一个是 dvr-snat 模式,该模式的下,主机上的 dvr_snat 不仅要负责不同子网之间东西向的流量,还要作为租户网络与外部网络通信的网关。内网与外部网络所有的南北向流量都需要经过该主机上的 dvr 进行传输,并启用路由器SNAT功能。另一种则是 dvr 模式,这一模式下,dvr 仅处理租户网络内部子网的东西向流量,即租户在物理主机与物理主机之间的内网流量。该配置由由L3agent的配置文件实现
agent_mode = dvr_snat/dvr
dvr创建
dvr 路由器的创建的命令则与普通路由器一样,不过最后要带上--distributed 参数。其他命令与传统路由器类似,采取同样命令进行管理。不过需要注意的是 dvr 二层只能使用 ovs,且需要在所有计算节点上启用 ovs,并修改 neutron ML2 的配置文件的参数:
/etc/neutron/plugins/ml2/ml2_conf.ini
……
enable_distributed_routing = True
l2_population = True
dvr创建好后,neutron L3 agent 会在所有连接了 dvr 的子网所在的主机上都会自动创建一个dvr的实例,用来对本地子网的流量进行路由。ovs则会连接路由器接口,并生成对应的流表。
在管理的时候,看到的是单个路由器
实际上在每一个计算节点上都有一个该路由器实例,如下图中的MyRouter-DVR 就在controller01和computer01、02上分别创建了路由器实例,这些路由器由DVR统一配置。
通过ip netns exec命令可以查看ar路由器的接口信息和命名空间,每个路由器实例都共享相同的接口名称、IP地址、MAC地址。
控制节点:
计算节点:
可以看到,控制节点和计算节点上的两个路由器都包含ip地址为192.168.1.1 的qr-29db7422的接口,这个接口都连接到同一个子网 VPC 。VPC内的虚拟机需要跨子网通信时,可以就近将数据包发往本地的网关。本地的路由实例收到数据包后进行路由。
不过这也带来一个显著的问题,如果两个路由器的接口使用相同的 IP 地址和 MAC 地址的话,那么交换机将从不同的接口上学到相同的MAC地址,在交换机收到虚拟机发来的目的MAC地址为网关的二层帧的时候,交换机将不知道要将数据包发送到哪个接口上,这将导致交换机转发表的震荡。
dvr东西向流量
为了解决相同的IP和MAC,导致虚拟交换机上 MAC 地址漂移的问题,neutron 引入了独立MAC地址,每个命名空间都有各自不同的MAC地址,但是当分布式路由器的数据包从计算节点内部离开时,ovs的流规则会对数据包的源MAC地址进行改写,改为各个节点的独立 MAC地址。这样而当数据从外部接入节点时,流规则会将源mac地址中的统一mac地址修改为本地路由实例的 mac 地址。实现 mac地址的转换。
不同子网的虚拟机跨主机之间通信的这一详细过程如下:
第一步:blue VM将数据包发往本地的网关,数据包的源mac地址为虚拟机网卡,目标mac地址为路由器在的接口。Br-int在收到数据包后将它发送给本地的router。
第二步,本地路由实例查找路由表后,发现Red VM 位于子网red,因此将数据包从路由器位于子网2的端口发送出去。此时处理还正常,源 MAC 地址为路由器在子网 Red 的 MAC 地址,目的地址为 Red 子网内 Red VM的地址。同时发往 br-int。
如果 br-in t如果不加任何修改,直接转发,br-tun势必从多台物理主机收到相同的 MAC,br-tun将无法正常回包。所以此 时br-int 会将路由器发来源 MAC 地址转换为主机的独立MAC,这样 br-tun 收到的数据包分别来自不同的主机。
第三步:接下来,br-tun 看到目的为Red VM ,正常将数据包转发给位于主机B。
第四步:主机B上的 br-tun 收到数据包之后,正常将数据包解封装,并根据流规则添加local vlan的标签,并转发给br-int。
第五步:主机B上的br-int 在收到数据包后,知道要发给 vlanxx 内的Red VM。同时主机B上的 br-int将包的源 MAC 地址从主机A的独立 MAC 转换为路由器在 Red 子网的接口的 MAC。
第六步:br-int 根据流规则去掉vlan标签随后转发到对应的red VM。
经过这一系列的转换,Red VM以为自己全程在与本地路由器在通信,而实际上数据包是从另一台主机上的路由器发来的。而在br-tun看来,只是三个不同 MAC地址的主机在通信而已。
全程缩略图如下:
dvr南北向流量
南北向的流量主要分为两种情况,一种是子网内所有主机共有一个出口:SNAT、一种是单个主机绑定浮动IP,这两种情况稍有不同。
NAT流量模型
Neutron 默认开启了SNAT,没有绑定FIP的虚拟机访问外部网络时,路由器会将数据包中虚拟机的内网地址改写为路由器外部接口的地址。集中式路由、HA路由、分布式路由都支持SNAT。当使用DVR时,只有工作于dvr_snat模式的路由器才负责与外部的网络的通信和SNAT。
传统模式下,所有与外部交互的流量都通过网络节点上的路由器上,并通过浮动地址与外部通信。SANT 命名空间专门用作 SNAT服务,浮动IP和路由上的SNAT都是由它实现。
Dvr-snat模式下,路由器会附加一个同名的nat命名空间。创建后,路由器不再与外部网络直接连,而是通过SNAT的 qg 端口与外部连接。同时,SNAT上还有一个端口连接到内网,这个内网端口的地址与路由器内网接口的地址在同一个子网。例如同为 192.168.1.0/24.
路由器的内网接口
snat的两种接口
计算节点上添加的默认路由
注意,此时计算节点上的默认路由指向了SNAT的内网接口地址。SNAT收到包后会修改包头的源IP地址为外网接口的地址,然后转发到外部网络。
浮动IP
如果说SNAT是一群主机的狂欢,那么浮动IP就是一台主机的孤单。公有云中最为常见的功能,通过将公网地址直接绑定到主机网卡上,实现主机与外部网络的直接通信。并可以随时解绑,关联到其他任意主机。
浮动IP本质上是1对1的静态NAT,将主机的内网地址翻译成公网地址,实现主机与外部的通信。当租户创建FIP关联时,neutron L3agent即在节点上创建一个network namespace,作为3层的插件来实现NAT地址转换。FIP一端连接外部网络、一端连接着路由器。
当浮动IP直接关联到虚拟机上时,计算节点上的L3 agent会创建一个新浮动ip命名空间(fip namespace),并创建新的 fg 端口与浮动ip所属的外部网路进行通信。fip命名空间依靠该端口与外部网络通信,该端口也需要配置一个外部网络的ip地址。
该计算节点上的路由器命名空间也连接到相同的外部网络,则会通过一个veth接口与fip的命令空间相连,并且会使用169.254.x.x地址段中一个反掩码为/31的ip地址作为接口地址。每个主机上只有一个fip命名空间,多个路由器连接到这一个命名空间。
在路由器这端,接口名称为rfp (router to FIP)
在fip 命名空间这端,接口名称为fpr(FIP to router)
同时qrouter的命名空间中会添加一条新的源路由规则:
32768: from 10.30.0.3 lookup 16
其中 对应的路由条目为:
也就是,当关联了浮动ip的vm与外界通信时,默认会通过rfp接口转发到FIP命名空间中进行处理。所有的计算节点上都可能有主机需要通过 FIP 来连接外部网络,这要求所有的物理主机都有网卡连接到外部网络。这会导致公网ip的浪费,现实中通过其他途径来解决这一问题。
ARP代理
之前的内容都是内网上行的流量,那么从外界进入内网的流量呢?这就涉及到南北向流量的最核心的问题——上下行流量的对称性。特别是云环境中,虚拟机会任意漂移,绑定了FIP的虚拟机可能出现在集群的任意一台主机上,这就给路由带来了很大的困扰。
arp**代理用于fip 回包
FIP的fg接口上设置了公网地址,同时FIP可能还关联了多个绑定了公网IP地址的云主机,当路由器需要知道这些云主机在哪时,例如访问一个绑定了公网IP的web服务云主机。这时FIP会启用ARP代理,即当外界的路由器发起ARP请求时,FIP会通过将自己的MAC地址提供给路由器,这样路由器能够正常回包,而又不用每个云主机都绑定一个不同的FIP。
这要求外界的路由器接口与这些FIP之间具备二层的互联能力,路由器的ARP的广播包能够直接传递到集群的主机。
云上的三层架构设计
Neutron router的三层功能发展至今已经基本能够满足云上租户的需求。租户可以基于以下的拓扑组建自己的云上三层网络。租户不同的VPC通过路由器连接在一起,实现VPC之间、VPC和外网之间的通信。
集中式路由逻辑拓扑
分布式路由DVR逻辑拓扑
但也仅此而已。流量从VPC出去之后呢?underlay网络的路由如何走?
出口选路和负载均衡由谁负责?公网地址池的容量不够了怎么办?核心网络的路由有调整该怎么办?
对于云服务提供者来说,neutron的功能还远不能满足他们的使用需求。云的运营者需要的是从租户创建虚拟网络、连接虚拟机、关联公网地址、创建到外部的访问策略等这一完整的服务链的协调、编排、控制。而且这一切要对上层透明,对底层交换机、路由器、防火墙、虚拟路由、虚拟防火墙等设备的操作。实现underlay网络和overlay网络一体化的自动化管理。
云网络自动化
显然,Neutron还不能形成一个完整的闭环,这也是大量SDN企业的发力点。那有较为完善的商业系统能够与openstack集成,实现全网络的自动化编排以满足我们的需求么?
VMware(nicira)
VMware 给出的解决方案是NFV,VMware在租户层面上与openstack类似,同样的分布式交换机、分布式路由器。但是VMware比openstack多出了一个组件:Edge。VMware推荐使用Edge作为租户分布式路由器的下一跳设备,Edge以NFV的方式承载了租户网络的FW、NAT、LB等功能,并且运行着动态路由协议,可以实现与外部网络之间的路由交换。
这样做的好处显而易见,Edge 可以通过 VMware 的NSX平台统一管理,租户网络的所有操作都可以自动化完成,无需底层unerlay网络的参与即可实现,物理设备仅需实现互联即可,无需做任何更改。从租户的创建到最后租户的离开,都可以实现自动化的编排。
其次,Edge是虚拟设备,云提供商可以按需增加和缩减设备,为不同的租户分配不同的虚拟设备,这样整个网络中不会存在明显的单点故障点,流量被分散开来。
但是这样做也存在以下的问题:1.使用NFV的方式实现,则底层硬件只能使用X86的设备,X86设备作为转发设备费效比太低,NAT、FW性能嬴弱,单个NFV设备能够承载的租户有限,如果数据中心内部流量过大,很可能导致需要部署大量的网络节点来解决这一问题。
相比openstack,VMware的NSX平台显然更为成熟,也更为完善。
juniper
Juniper 在SDN方面收购了open contrail 与其硬件路由器、虚拟防火墙一起组成了较为完整的云数据中心SDN解决方案。并可以与openstack平台集成,实现网络的自动化编排。
Open Contrail 架构
Contrail 的控制器包含三大组件,分别是配置、分析、控制。配置组件负责与其他系统的对接(如,Openstack Neutron),并将北向的应用层的需求翻译成对网元的操作,控制组件负责将配置信息同步到各个网元中,分析系统则实时从网元中获取数据并进行呈现。
转发层面则是由分布在各个计算节点上的vRouter完成,vRouter定位类似OVS,本身由vRouter Agent和位于hypervisor中的转发平面构成。vRouter Agent通过XMPP与控制器通信,获取路由等信息,并植入到转发平面中。转发平面上的转发表(FIB)记录了到达各个目标主机的路由信息,同时其包含的流表则提供了丰富的防火墙、负载均衡等功能。
相比Neutron更为优势的是,Open Contrail 的服务链支持更为智能的转发策略。并支持通过gateway节点实现租户网络与外部Internet或VPN的连接。得益于juniper在硬件领域的优势,gateway节点可以选用 Juniper Networks MX 系列 3D 通用 Edge Routers 和 QFX 系列 、EX 系列的交换机。
MX系列路由器
juniper的MX系列路由器有着不错的性能和丰富的特性,支持MPLS、BGP、VPN、VXLAN、和VRF等特性,基本可以满足云租户的各种出口场景的使用需求。并且也可以扩展DPI、防火墙、负载均衡等等线卡。
而且Contrail 控制模块与Gateway之间是通过BGP协议来交换路由信息的,这也是现如今大部分硬件路由器和软件路由广泛支持的协议,所以使用非juniper的路由器无需改动也一样能达到相同的效果,仅仅只是缺失部分juniper独有的特性。
OpenContrail的解决方案在转发层面虽有不同但与openstack是非常类似的,同时通过bgp协议对硬件设备的的统一编排,实现租户与外部、租户与租户之间L2-L7的服务链实现。整个方案的架构上没有明显的短板,难怪的获得了Mirantis 的认可,作为其openstack发行版默认的SDN组件,将来很有可能将完全替代 Neutron,成为其私有云甚至容器平台的SDN解决方案。但技术的先进不能决定产品的成功,未来还等 OpenContrail 给出答案。
cisco
Cisco的 DNA (Digital Network Architecture) 解决方案覆盖了从接入到WAN、数据中心和云多个领域,包含了网络的方方面面。
与此同时Cisco也推出一系列的网络设备作为数据转发设备,包括Cisco Catalyst系列、Nexus系列交换机、ISR、ASR、ASA路由、安全设备、以及无线设备等。以及一系列的管理、控制软件 SD-Access(终端接入)、DNA Center(云内网络)、SD-WAN、IWAN(智能广域网)。产品成熟度较高,且拥有能够覆盖大多数网络使用的场景。
基于这个统一的平台,Cisco希望能够在所有这些场景下上提供一套端到端的的控制策略,实现全网的的SDN化。与此同时Cisco甚至允许用户自行编写应用运行在设备上,以提供额外的功能和更适应客户的网络环境。
DNA解决方案
DNA 产品
Cisco的SDN解决方案秉承着有限的开放策略,允许用户在Cisco允许的范围内进行一定的开发,但是这种开放是极度受限的,所有其上运行的应用都是通过调用设备自身提供的接口来实现新的功能,这受限于设备硬件和NOS本身的能力,以及软件的License。真正涉及到操作系统、底层功能等核心的部分依旧是封闭的。在当前环境下这种有限的开放能满足大部分企业的需求,但是鉴于其架构与常用的开源方案架构差异较大,用户迁移壁垒较高,整个服务链中只要有一环不是Cisco的设备就无法实现完全的自动化和编排,而同时开源解决方案展现的强大生命力已经让昔日的大哥黯然失色。
最后,Cisco这套全家桶可不便宜…
midonet
midonet同样采用的是分布式架构,没有中心化的网络节点,所有节点的流量都由计算节点本地的midolm agent来路由,但是midonet 引入了一个 gateway 节点,网关节点上运行开源的BGP Daemon ( Quagga )路由软件,通过BGP实现外部网络与Internet之间的路由交换。新版的(5.0以后)midonet以及支持创建多个gateway实现出口的分流。
midonet的实现与vmware类似。通过 Provider router 来实现云内网络与云外网络的互联,provider router可以代替传统的出口路由器或者VPN设备,而云内部的流量则由计算节点上的网络agent来管理和维护。
big switch
Big Switch Fabic最大的特色是在转发层面上有两套方案:
一是,Switch light OS,一个轻量化网络操作系统,基于开放计算联盟(OCP)中的开放网络项目构建。Switch light OS可安装在支持Broadcom Trident系列或 Tomahawk 系列ASIC芯片的交换机内部。并可以兼容诸多开源的转发插件,如:Quagga(是的,就是Midonet gateway上使用的那个,支持非常丰富的路由特性)、BIRD以及Facebook FBOSS 。这样使得一台支持OCP标准的白牌交换机能够直接变为一台SDN交换机。
另外一个,Switch Light VX则是一套部署在KVM上的虚拟化版本,在OVS内核上增加了更多的功能并提升了性能。类似vmware的纯软件部署模式,同样能够实现网络的SDN化。
Big Network Controller 则是基于开源项目Floodlight 开发的SDN控制器,南向采用的是标准的openflow 标准协议对网元的转发行为进行控制,北向则向各种应用提供标准的API接口。
Big switch 这种“软硬结合”的方式,也可以算得上另辟蹊径了,不过Big Switch显然想做的是SDN界的微软,把控SDN设备的操作系统。不过显然的事实是,相比要用openflow统一南向的ONF来说,想把各设备厂家最核心的OS都给替换掉的Bigswitch简直是冒天下之大不韪,要了所有硬件厂家的命。几乎难以获得厂家的支持,除了与DELL合作了数款设备外少有大型设备厂商的支持。注定难以全面下沉到普通用户侧,其未来可能还要看由Facebook主导的开放计算联盟(Open Compute Project)的发展情况。
各路解决方案已经演化出自己的特色,给网络这一领域的技术发展带来了极大的活力,并开始在各个领域广泛应用,那么这些系统能够满足你的需求么?
LBaaS v2
Neutron 包含负载均衡服务,即LBaaS。负载均衡器可以将用户的访问流量通过算法均摊到多台主机实例上,实现以 Scale-out的方式扩容应用的性能。Neutron LBaaS 包含以下核心的概念:
- 服务器池 Pool:服务器池内包含了多个服务器成员,同一个池内的服务器至少包含一种统一的对外服务。
- 服务器成员 Member:服务器成员,包含服务器的IP和端口。
- 监听器 Listener:监听器将持续监听指定的端口上的连接请求。一个负载均衡器中允许存在多个监听器,同时通过共享服务器池,多个监听器也可以关联到同一个服务器池。
- 健康监控 Health monitor:检查服务器池中成员的状态,以及服务器的加入、离开。
之所以称之为 lbaas v2,是因为Neutron的负载均衡的模型有过一次如上图的进化,在v2的版本中,neutron 对负载均衡的架构有了一次非常大的调整,v2版本变得更符合行业标准,且驱动和功能扩展变得更为简单,除此之外新版本还允许一个负载均衡器下添加多组 Listener 监听服务,以及加入了TLS。Lbaas v2无法和lbaas v1同时运行,开启lbaas v2需要停止lbaas v1。
改进后的LBaaS v2经过了更为全面的测试,并且加入了更多的HTTP层代理的特性。并开始支持Active-Standby部署模式,后续版本中将进一部支持Active-Active。新版可以说是负载均衡架构和功能的一次飞跃。
负载均衡概念
服务器池 Pool
服务器池即后端一组提供服务的实例,每个成员都是一个IP地址+4层的端口。例如,常见的提供web服务的实例,在服务器池中表示为:192.168.1.1:80。提供的服务不同则端口号也不相同。池内的服务器都统一对外提供某一种服务。例如:
服务器 1:192.168.1.1:80
服务器 2:192.168.1.3:80
服务器 3:192.168.1.4:80
负载均衡器通过 VIP 统一对前端提供服务,用户向虚拟IP发起连接请求,监听器监听到对应端口的请求后,通过负载均衡算法将请求转发到后端服务池中的一个成员上。然后成员对用户请求的资源进行响应,这样整个过程对于用户来说是透明的。包括后端服务器的增加、减少以应对用户规模的增缩,都不会对已经建立的连接产生影响。
监听器 Listener
监听器即一个不断在端口上检查连接请求的进程,一旦发现客户端的连接请求,则会按照你设定的规则将连接请求转发给后端的服务器池。一个监听器关联一个端口,如:HTTP(80)、HTTPS(443),当使用HTTPS,则需要上传用于https 加密和解密的证书到监听器中。
L7 转发策略 l7 policy
l7策略转发流程
LBaaS v2 支持L7的转发策略,每个监听器上都可以配置多条转发策略(L7 Policy)。策略由由规则(rule)和操作组成,类似 if…then…的条件语句,当有流量匹配了 rule 的条件时,就按照策略中的操作转发。否则就继续向下匹配。规则可以匹配HTTP请求中的特殊字段或URL,这给业务带来了极大的灵活性。
rule 支持的匹配项包括:
- Hostname,L7 rule 支持匹配HTTP/1.1 请求中的host字段
- path,HTTP URI 中路径的部分
- file_type,请求的文件类型
- header,HTTP 头中其他字段
- cookie,cookie的值
需要注意的是,同一个policy下的rule是“与”的关系,即策略下的所有rule都匹配的情况下,才会按照策略的操作转发。其中任何一条不匹配都会跳过该策略向下匹配。
匹配的算法包括:
- regex,正则表达式,非的意思
- starts_with,字符串开头
- ends_with,字符串结尾
- contains,字符串中包含的值
- equal_to,等于
L7 policy 的操作支持:
- block,请求将直接被拒绝;
- redirect_to_url,重定向用户的url;
- redirect_to_pool,重定向到后端特定的主机池内。
例如:可以在监听器上添加两条rule,一条匹配HTTP请求中 file_type 包含:jgp、png、gif、zip、txt 的请求转发给 image pool。另一条一条匹配URI中 path 以“*/login”开头的请求转发给APP pool。
这样就简单的实现了网站上静态内容(图片)与动态内容(用户登录)的分流处理,这能在不改变应用架构的情况下,减轻web服务的负载。对于云原生应用来说,这样的功能非常重要。
L7策略配置示例如下:
- neutron --policy policy1 lbaas-create-l7policy --name "policy1" --description "My Description" --listener "listener1" --action redirect_to_pool --pool "pool1" --position 1 (创建L7策略,命名为“policy1”描述为“lb策略”,并关联 “listener 1”,策略的动作是将匹配的流量转发到“pool1”)
- neutron lbaas-create-l7rule rule1 --rule-type path --compare-type starts_with --value "/api" --policy policy (在“policy 1”下添加一条规则,匹配所有URL中以 “/api”开头的请求)
可见到 LBaaS v2可根据业务需求制定出非常灵活的7层转发策略。
负载均衡算法 Algorithms
本身Neutron支持的负载均衡算法包括:轮询、最少连接、源IP。
- 轮询 Round robin,是最普遍的算法,每当有一个新的请求来临,负载均衡器都会按顺序选择服务器池中的一台设备来响应。有点类似音乐播放软件的列表循环。这种模式下服务器池中的每一个服务器都能均匀地分配到相同的访问请求数,而不会管服务器繁忙程度、服务器配置的高低。比较适用于服务器池内的服务器配置相同、用户访问习惯相同的业务。加权轮询是改进的负载均衡算法,当后端服务器池中设备配置高低不一时,可根据服务器处理能力的高低分配服务器的权值,权值高的服务器会被分配更多的用户请求。
- 最少连接算法 Least connections,负载均衡器收到新的请求时,都会从当前服务器池中挑选一个当前并发连接数最少的服务器来负责。最少连接算法考虑的服务器的实时负载情况,尽量保证了任务分配的平均,防止单个服务器超出负载,但是当后端服务器池中存在高处理能力的服务器时,这个处理能力高的设备始终无法获得更多的工作负载,存在性能的浪费。最少连接算法有优化后的加权最小连接算法
- IP hash,负载均衡器在收到主机的连接请求后,会根据数据包的源IP地址字段的hash值,同时按照轮询的方式为客户端分配主机,当负载均衡器再次收到同一IP的请求时,则会按照之前的记录为客户端分配上次建立连接的主机。这样保证了当同一个IP的用户,多次独立的访问都能由同一台服务器来处理,适用于服务器需要临时记录或保存客户信息的应用中。
健康监测 Monitor
健康检测的机制是指是负载均衡器通过定期的心跳信号检测服务器池中的服务器运行状态,从而排除掉后端故障的主机,保证服务整体正常。
Neutron支持的健康检测方式包括 ICMP、TCP、HTTP几种。
- ICMP是最简单的,通过ping 和echo的方式,看根据服务器是否响应。只要服务器操作系统TCP/IP协议栈运行正常,网卡不出问题,服务器到负载均衡之间的网络正常,ICMP的方式都起到良好的作用,但以上情况都不能代表服务器上面运行的应用是正常的。
- TCP是4层的检测方式,相比ICMP、TCP会请求主机的特定端口,看特定的端口能否正常响应。
- HTTP的方式则更进一筹,会通过get特定的页面,根据HTTP的返回代码来判断应用是否正常。
健康监测的指标越精确,越能反映服务的实际响应情况,如果是web服务,最好是使用HTTP的方式,这样检测结果更可信。
会话保持 Session persistence
会话保持功能常用于有状态的服务中,比如服务器通过session来维护用户连接的状态,因为session保存在服务器本地,如果不断地通过网络来在服务器池中同步session的话,会消耗服务器的带宽和处理能力,所以这时会选择使用负载均衡器的会话保持功能。它能保证同一个用户的请求会被发送到同一台服务器。
Lbaas v2支持的会话保持的类型为:
- 源IP:源IP即IP hash 算法,根据IP地址来识别客户。负载均衡器在收到请求后会计算数据包头源IP地址的hash值,并按照轮询的方式给该客户端分配一个服务器,同时将两者的对应关系记录到表中,当再次收到同一源IP发来的请求时,则查找到之前的服务器进行转发。但是当客户端通过NAT、或代理的方式上网时,源IP的方式就可能导致多个客户端被分配到同一个主机。顺便一提,去年在公司用12306在高峰期抢车票时,刚打开网站就被提示“您的操作频率过快”,即很有可能12306后端也是判断同一个IP提交的访问请求过多,从而误把新接入用户当作了已访问过的用户。
- HTTP_cookie:该模式下会根据浏览器中缓存的cookie来识别用户,cookie里面一般都缓存了计算机信息和浏览器的信息以及用户认证的信息。Lbaas v2中负载均衡器会在服务器第一次返回给客户端的回应中插入“SRV”的cookie值,标识了回复的服务器。当再次收到客户端发起的HTTP请求时,lbaas v2会找出 cookie中的"SRV"字段,并剥离掉后转发给之前回复的服务器。HTTP_cookie 的问题在于,有可能一些用户会禁用掉浏览器上的cookies,这种情况下基于cookies的会话保持就将失效了。
- App_cookie:该模式下需要在负载均衡器中预先定义各个后端中设置的cookie,并将对应关系存储到表中,当收到客户端的请求时,检查请求中是否有预先定义的cookie,如果有,则转发到对应的服务器。
虽然当今互联网应用中通过token来实现用户的识别和鉴权已经比较常见了,但负载均衡的会话保持能够很好弥补通过 seesion 识别用户的应用的不足。但是基于cookie的会话保持无法支持服务器直接返回的部署模式,即服务器返回给用户的流量不经过负载均衡器,而是直接上行转发出去。所以在某些大流量的应用中,负载均衡器可能成为性能的瓶颈。
非对称流量中,服务器直接返回到客户端,上行流量不经过负载均衡器,LBaaS v2 暂时还不支持这种部署模式。
实现
Neutron中 LBaaS v2有两种实现方式,
一是:使用HAproxy作为负载均衡器,在网络节点上运行LBaaS agent,agent会完成节点上的Haproxy 的创建和配置工作。这也是目前较为成熟的使用方式。
二是:使用Octavia 作为负载均衡器,Octavia是在LBaaS v2中加入到openstack中的,官方对它的定位不是要代替HAproxy在neutron中的地位,而是作为一个可选开源的LB服务提供者,类似LVS+F5等。Octavia的架构是全新设计的,而且在一开始就立志成为运营级的负载均衡解决方案。只是目前Octavia还是远谈不上成熟,官方推荐只在Devstack中使用。
HAproxy + keepalived
比较常用的开源负载均衡器有LVS、Nginx、HAproxy,其中LVS只能做到四层的负载均衡,即只能依据IP+端口的方式进行转发,不支持L7的转发策略,Nginx不仅能做Web服务器,同时也能作为负载均衡器使用;HAproxy 和Nginx都能基于L7策略进行转发。LVS也经常和HAproxy、Nginx混用,在大流量的集群中,先由LVS将流量分摊到不同的Nginx/HAproxy集群,再由Nginx/HAproxy做L7转发。除此之外Neutron也支持Ctrix、F5、Radware等公司的插件,从而通过专用的负载均衡硬件来实现。
LBaaS v2的经典实现方式就是在网络节点上部署HAproxy+Keepalived 实现负载均衡服务。 其中HAproxy提供L7的负载均衡,Keepalived用于实现高可用方案。
HAproxy
HAproxy能够为服务器池提供7层的负载均衡功能,即能根据HTTP请求头中的内容来执行负载均衡算法。而且作为开源软件,被广泛使用。
1.启用lbaas v2首先需要修改neutron的配置文件,加入插件:
/etc/neutron/neutron.conf
service_plugins = [existing service plugins],neutron_lbaas.services.loadbalancer.plugin.LoadBalancerPluginv2
2.在lbaas的配置文件中添加lbaas v2:
/etc/neutron/neutron_lbaas.conf
service_provider = LOADBALANCERV2:Haproxy:neutron_lbaas.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
3.选择2层设备的驱动:
/etc/neutron/lbaas_agent.ini
[DEFAULT]
interface_driver = openvswitch
根据实际,选择 ovs 或者 linux bridge,需要与节点上的2层设备类型匹配。
4.开启数据库迁移
neutron-db-manage --subproject neutron-lbaas upgrade head
5.启动 lbaas v2 agent。
neutron-lbaasv2-agent \
--config-file /etc/neutron/neutron.conf \
--config-file /etc/neutron/lbaas_agent.ini
来自 <https://docs.openstack.org/ocata/networking-guide/config-lbaas.html#configuring-lbaas-v2-with-octavia>
随后即可以创建负载均衡器:
1.创建负载平衡器,指定负载平衡的名称和关联的子网名。需指定与虚拟机所在的子网。
neutron lbaas-loadbalancer-create --name my-lb private-subnet
2.为新负载平衡器创建侦听器。
neutron lbaas-listener-create \ //添加监听器
--loadbalancer my-lb \ //关联之前创建的负载均衡器
--protocol HTTP \ //选择监听器协议,TCP\HTTP\HTTPS
--protocol-port 80 \ //选择监听器对外监听的端口(即向用户开放的端口)
--name webservice-listener \ //设置监听器名称
3.创建 LBaaS 服务器池。
neutron lbaas-pool-create \
--lb-algorithm ROUND_ROBIN \ //选择负载均衡算法,支持上文中提到的轮询、最少连接、IP hash等
--listener LISTENER_1_NAME \ //关联监听器
--protocol HTTP \ //服务器池使用的协议
--name LB_POOL_1 //服务器名称
4.将服务器实例添加到创建的 LBaaS 池中。
neutron lbaas-member-create \
--subnet <subnet-id> --address <server 1 IP> \ //将后端服务器添加到地址池中
--protocol-port 80 <pool name> //后端服务器上服务所使用的端口,可以与前端的端口不一致
neutron lbaas-member-create \
--subnet <subnet-id> --address <server 2 IP> \
--protocol-port 80 <pool name>
5.设置Health monitor指标。
neutron lbaas-healthmonitor-create \
--delay DELAY_IN_SECONDS //设置心跳检测发送到服务器成员的周期,单位为秒。需避免过于频繁的心跳检测,以及检测不及时的情况出现,达到平衡。对可用性要求高可以设置为3~5秒,
--type [HTTP | TCP] //选择心跳检测的协议,如果TCP则只检测服务器上端口是否开启,HTTP则支持检测web服务的状态。当选择HTTP时,可以指定http的方法,默认是 get 一个特定的页面。同时还能指定服务器正常响应对应的HTTP状态码,如返回200时,代表web服务正常,200以外的值,如404、408等则代表异常。可通过 expected_codes 设置。url_path 则用来指定health monitor 请求的页面。
--max-retries NUMBER \ //设置在改变服务器可用状态之前,等待服务器的应答的次数。假设为n,如果是n次未响应,则切换为inactive,之后如果n次正常响应,则切换为active。推荐为 3
--timeout TIMEOUT_IN_SECONDS //设置超时的时长,当超过该时长服务器都没有回应,则认为服务器此次心跳监测为故障。
--pool LBAAS_POOL //将健康监测配置关联到服务器池。
一个服务器从出现故障,到负载均衡器发现并标记为不可用,不再为其分配流量,这其中需要的时间为:Time = delay *(max-retries -1) + timeout (*忽略从服务器发生故障到下一次健康监测中间的延时),在这个时间段内,负载均衡器都会为服务器分配流量。
6.分配浮动IP,为负载均衡器分配浮动IP与为云主机分配浮动IP是一样的,都是在fip的命名空间中为指定一个公网地址到内网地址的映射。这样外部的用户就可以通过公网地址直接访问到服务器池内的主机。如果作为内部使用的负载均衡器,则不需要分配浮动ip。
neutron floatingip-associate FLOATINGIP_ID LOAD_BALANCER_PORT_ID
最后不要忘记设置防火墙和安全组,允许外部流量访问负载均衡器的VIP和开启的listener端口。
Keepalived
HAproxy的 Active/Standby 部署模式就是通过keepalived 来实现的。keepalived的核心是vrrp,openstack的HA中大量使用了vrrp协议来提供高可用,包括之前L3中提到的路由器的高可用。负载均衡器的vip将会配置在vrrp的 vip上,对外提供服务。同时vrrp会通过心跳检测负载均衡主备设备运行的状态,并实现vip的切换。
Octavia中还有一个假主备模式,即负载均衡在实际中为单节点部署,不过Octavia Controller内的Health manager会频繁检测负载均衡节点的运行状态,一旦发现负载均衡器故障,则从备用的负载均衡器中选一个代替故障的设备,并套用原来的配置。
Octavia
Octavia项目是在 Liberty 版本中随着LBaaS v2一同发布,其amphorea模块是实现负载均衡功能的模块,支持部署在虚拟机、容器、裸机上,为云上的租户提供负载均衡服务。
上图是Octavia的架构,neutron原生集成了Octavia的驱动,可以直接通过Neutron的接口来完成Octavia的管理。同时Octavia也支持独立工作,其拥有独立的数据库,租户的配置信息不仅会保存在Neutron的数据库中,也会保存在Octavia的独立数据库中。(同时按照网上的部署经验,octavia和neutron的数据库同步是一个较大的问题)
Octavia 0.8版本中的amphorae 镜像是一台运行了HAproxy的ubuntu虚拟机,已经支持RH Linux、Centos、Fedora。未来还将支持以容器和裸金属的方式部署。
除此之外是Octavia的核心Controller,它包含4个组件:
- API Controller:运行Octavia 的API,并接受外部的调用申请,然后通过消息总线传送给worker。
- Controller Worker:负责执行API的各种操作,包括对nova、neutron接口的调用,以实现amphorae虚拟机的生命周期管理、创建端口、创建外部网络等资源,除此之外还有SSL证书、工作流等等功能管理。都由worker来一一实现。
- Health manager:用于监控amphorae的运行状态,并执行amphorae的故障切换。
- Housekeeping manager:用于删除无用的数据库记录,管理备用池和安全证书等。
用户在openstack环境中创建负载均衡服务时,创建amphorea虚拟机、端口、安全组等操作,这些都是由Octavia Controller自动完成,用户不可见,用户能见到的只有部署完成之后的Octavia的配置项和对应的网络端口。
service_provider = LOADBALANCERV2:Octavia:neutron_lbaas.drivers.octavia.driver.OctaviaDriver:default
Octavia的创建和配置命令与创建HAproxy的命令是完全一样的,配置好插件后 Octavia API Controller 将执行neutron指令,并完成amphorae的创建和配置等工作。
可见到Octavia项目目标是搭建一个完善的本地负载均衡管理平台,目前它是以虚拟机的方式提供服务,将来计划能够对云主机、容器、甚至裸机部署负载均衡服务,并支持Active、Active部署方式。
更多内容可以参考以下文章
https://docs.openstack.org/octavia/latest/reference/introduction.html
http://lingxiankong.github.io/blog/2016/03/30/octavia/
http://502245466.blog.51cto.com/7559397/1303506
Load Balancing as a Service : Liberty and Beyond
负载均衡本身的技术并不复杂,也发展得较为成熟,但如今负载均衡在各种云上扮演着非常重要的角色,各个云上与部署解决方案中都能看到它的身影。究其原因是其给租户的应用带来的弹性和可用性。云的租户可以在前端用户完全无感知的情况下,按负载增删后台服务器的数量,并实现服务的高可用,这非常符合云“按需使用”“分布式高可用服务”的理念。所以当服务的弹性伸缩和高可用性成为云计算的基本属性时,负载均衡器就开始在云上扮演不可替代的角色,可以说,不支持负载均衡的云不能称之为云。而传统的硬件负载均衡器无论是在可靠性、扩展性、可编程性、成本等方面都无法满足云供应商的需求。
Otavia的加入也可以说是openstack社区很清楚地看到了这一趋势,并立志将负载均衡单独拿出neutron作为一个重要项目来对待。从Octavia支持的部署模式就能看出这一项目的野心。或许它未来将成为一个跨虚拟机、容器、裸机的统一负载均衡服务。
安全
当业务从传统环境迁移到云上之后,安全问题变得更为复杂了。Neutron包含了2大安全组件:安全组(security group)、防火墙(firewall)。安全组解决的是虚拟机东西向的访问控制问题,而防火墙解决的则是南北向的访问控制问题。
两者都只解决了网络层和传输层的访问控制,更高层级的安全功能,则留待更为专业的安全厂商解决,如:Palo Alto、Checkpoint、F5 等等。在这一点上 Openstack 和 VMware 等各个云平台的做法可以说是非常的一致。各个传统的安全厂家也纷纷转型推出云上的安全解决方案。
iptable:起源
安全组、防火墙的功能都依赖于iptables实现。Iptables 很早就已经集成到了Linux 的内核中,它由转发表 和 规则链 组成,通过表和链的组合,能适应各种场景下的安全需求功能。
tables
iprable默认包含了表,每个表都有不同的用途,比如 Filter 表用来过滤数据包,发往主机内部的包,和发往主机外部的包都由 filter 表中相应规则链来处理。主机中默认的表有:
- Raw:数据包最先经过的表,一般用来配置需要绕过iptable处理的流量。在安全组和防火墙功能中都没有使用到该表。
- Filter :默认用于过滤数据包的表。neutron安全组和防火墙都是通过该表的不同链来实现的。
- NAT:看名字就知道,用于网络地址转换。
- Mangle: 可以修改数据包的特定字段,常用来标记流量(如用来实现策略路由功能),也没有被安全组或防火墙使用。
http://cn.linux.vbird.org/linux_server/0250simple_firewall.php
查看filter表内的转发规则
chains
链这个概念指的是一组规则,这些规则会在不同的场景下生效。默认有5种规则链,规则链内部的规则详细地定义了数据包的处理方式(转发或丢弃等等)。一旦开启iptables后,所有进出接口的数据包都需要经过至少一条规则链。规则允许数据包从一个规则链跳转到另一条规则链。如果跳转后没有匹配上任何规则,数据包将回到跳转之前的位置,并继续向下匹配规则。
- Prerouting:跟名字一样,在数据包执行路由的策略之前会进入该规则链。除了Filter以外,其他表都有用到该策略链。比如NAT,在数据包路由之前修改数据包的源地址或目的地址。
- Input:所有发往本地主机的数据包(即目的地址是本地的地址)都会经该规则链处理。Mangle 和 Filter 中都有用到。
- Forward:所有目的地址非本机的数据包都用到该规则链。Mangle 和 Filter都有用到。
- Output:由本地主机发往外部的数据包都使用该规则链。Raw、Filter、NAT、Mangle都有用到。
- Postrouting:所有完成了路由选择的数据包都将通过该规则链。安全组的功能没有使用到这个规则链,但浮动ip则有使用。Mangle和NAT表有使用。
Chain 的应用流程可以用上图来囊括,所有进入主机的数据包都要先经过prerouting链,raw、mangle、nat表中都有prerouting链,所以数据包要依次匹配 raw——>mangle——>nat 三个表中prerouting链的规则。随后主机将进行路由选择,如果是数据包的目的是主机自己,那么接下来则由input 链来处理,此时是数据包是经过 mangle——>filter表的,然后数据包被拆包并发往本地的进程。
而从本地发出的流量,经过路由选择后进入output链,分别经过raw—mangle—nat—filter表后交给postrouting。
如果数据不是发往本地的,则是经过prerouting,forward,postrouting3个规则链。
rules
可以看到表格内的规则被组织成不同的链,默认的规则链会在不同的场景下生效,一个规则链内通常包含多条规则,规则的语法与我们常用的ACL语法类似,同样是对数据包头的字段进行匹配,包括常用的数据包的5元组:
- 协议< -p protocol>:需要匹配的数据包的协议,例如ICMP、TCP、UDP等
- 源地址< -s source ip address>:数据包头的源地址
- 目的地址<-d destination ip address>:包头的目的地址
- 源端口< -sport source port>:包头的源端口
- 目的端口<-dport destination port>:包头的目的端口
- 入接口<-i interface>:数据包进入主机的接口(需要在input链中使用)
- 出接口<-o interface>:数据包出主机的接口(注意,当使用该项来匹配数据包时,只有在主机执行了路由选择之后的output链中才能生效,表 raw、mangle、output、filter中都有)
- (除此之外还可以通过各种插件来匹配更多的字段)
安全Rule匹配和动作示例
而一旦规则中的条件匹配到数据包后,数据包就会执行规则配置的动作。每个规则支持的动作包括:
- Accept :接受
- Drop:丢弃
- Reject:丢弃。与drop不同的是,reject会向数据包的源地址返回一个错误信息
- Log :记录数据包的细节信息
- DNAT:重写数据包的目的地址
- SNAT:重写数据包的源地址
- RETURN:将数据包返回给跳转前的规则
有经验的人一眼就能看出 accept、drop、reject、log这些不都是一般防火墙上常见的操作么,是的,防火墙主要用的Filter表中的规则主要就是记录的数据包的丢弃、转发等操作。
方向
Neutron正是应用了iptable不同的表和链实现了安全组和防火墙的功能。
这样配置规则时就很清晰了,当要对发往本地主机内部的流量进行控制时,则需要在filter表 的input 链内设置访问控制规则。
而当主机作为路由器,在不同的网段之间进行数据转发时,则需要在filter表的forward链内设置访问控制规则。
这样就清晰了,无论是经由主机转发(充当路由器)、或者是发往本主机、以及本主机发出去的流量,都有特定的表和规则链进行处理。而且iptable是支持状态的,即由内部向外部发起的会话而产生的回包,防火墙是能记录并放行的。也正是借用了iptable的功能Neutron才得以实现NAT、浮动IP、安全组、防火墙等等的功能,可以说iptables占据了Neutron的半壁江山。
更多iptables的介绍可以参考鸟哥的 http://cn.linux.vbird.org/linux_server/0250simple_firewall.php
Security group 安全组
安全组的核心就是上面提到iptables了。而且因为安全组是直接关联的虚拟机的端口,所有进出虚拟机网卡的流量都要经过iptables处理。这样vpc内部虚拟机与虚拟机之间东西向的流量也能通过安全组管理起来,所以安全组也已经成了所有云服务的标配了。
而一个安全组指的是采用同一套访问控制规则的一个或多个虚拟机。这些虚拟机都向外提供相同的服务,访问群体也相同,例如:一组向外提供web服务的虚拟机,同样开放80端口,允许其他网段的访问。用户配置的安全组策略,最终会通过neutron自动映射到虚拟机所在的计算节点内的 iptables 规则上。
因为安全组是直接关联的虚拟机接口,所以的当虚拟机在集群中迁移时,通过安全组配置的规则也会随之迁移到新的宿主机。
安全组策略的创建
在之前讲二层的博客中有提到,正因为通过 iptables 实现的安全组需要经过主机的ip协议栈,而ovs的流表转发模式不支持,而且ovs流表不支持记录连接状态,所以类似NAT、状态防火墙等功能均无法实现,导致ovs的二层环境下要在ovs和虚拟机之间额外添加一个Linuxbridge 来实现安全组的功能。
但是ovs还是有一个原生的防火墙驱动,通过流表而不是 iptable 的方式来实现安全组的功能。这要求宿主的 linux 系统内核版本为 4.3及更高,并支持conntrack。也就是使用conntrack来记录会话的状态信息,以实现状态防火墙功能。但是该实现方式在实现环境中使用得较少。
可通过修改ovs节点上 openvswitch_agent.ini 文件中的以下参数来开启。
[securitygroup]
firewall_driver = openvswitch
开启后对于用户来说没有明显的不同,neutron提供的是与 iptables 相同的API。但是实现方式已经从iptables/netfilter 换成了ovs流表。虚拟机发出的包依旧由 br-int进行处理,但是全部会由conntrack来记录会话的状态。
Firewall 防火墙
Neutron中的防火墙和安全组一样,是通过iptables系列工具来实现的。不同的是防火墙与虚拟路由器关联,所有流经路由器的流量都会经过防火墙的过滤。包括南北向流量和用户不同vpc之间的流量。
防火墙规则也同样支持网络的五元组。
firewall-rule-create [--tenant-id 租户] [--name 名称] [--description 描述] [--shared] [--source-ip-address 源地址] [--destination-ip-address 目的地址] [--source-port 源端口] [--destination-port 目的端口] [--enabled 是否启用该规则] --protocol {tcp,udp,icmp,any 协议} --action {allow,deny 动作}
跟负载均衡一样,防火墙在 openstack 的 Newton 版本中也迎来了 FWaaS v2。在v2 中防火墙的概念变成了防火墙组。防火墙组由入策略和出策略组成。并且不是再是在整个路由器级别生效,而是可以将防火墙关联到特定的路由器端口。这样可以对不同的接口(子网)设置不同的防火墙规则,使用起来更加方便。官方对比图如下:
相比 LBaaS v2带来的巨大变化,FWaaS v2只能算得上是一次功能的优化,使得防火墙能够为每个子网提供更细粒度的访问控制。后续二层的防火墙的更新也会给防火墙带来更强的生命力,整体算是一次不大不小的进步。
更高的安全
无处安放的安全
openstack和能为用户提供的安全特性非常有限,仅能实现基础的访问控制,这肯定不够,所以这到了传统安全企业的发挥空间。所以在讨论云上的安全时,更多的应该讨论安全企业们在云上的解决方案。水平有限不再展开,不过还是有几个有意思的变化值得梳理一下:
首先就是云供应商和安全企业的关系:
无论是原来的网络供应商还是服务器供应商、亦或是软件供应商,安全的供应商都很少跟他们有过交集,大家相安无事好多年,各自岁月静好。较为松散的业务结构,使得各种设备能够很好地塞到用户的数据中心,但是这种情况已经完全被打破,云已经吞噬掉用户的网络、服务器、存储、管理平台等占据了数据中心的核心位置,所有其他数据容灾、备份、网络管理、网络安全、业务安全厂商突然发现自己与用户之间多了一层隔膜。至于大的云供应商在努力向客户证明自己的一体化方案已经足够完善,同时也支持第三方的服务。当然这种支持从来就是有限度的,出于利益的角度,或者出于控制力的角度。而小的云供应商们则在抱团以提升竞争力,云供应山和安全供应商都在努力向用户证明自己平台的开放兼容性,处于相互利用的情况。而且大家都知道这种合作关系太不牢靠,一旦有任何一方开始涉足对方的领域,那么这层薄薄的关系就变得岌岌可危。这其中占主动的已经是云供应商。果然还是谁更靠近用户,谁就更有话语权。
目前私有云市场还处于混战的阶段,没有谁能号令四方,这种情况也许还要持续一段时间。私有云暂时还无法完全吞下用户的数据中心,安全厂家们终将走上一条共同的道路,实现在方案层面而非产品层面上实现与私有云们的共存,以至于不让私有云过于牵制自身发展,又不用过多地去适配各种云厂家。或许网络资源池/安全资源池是个出路。
然后就是用户与安全企业的关系
关键字是统一,当用户发现计算、存储、网络资源都可以在一个平台里随意管理、使用的时候,开始尝到了统一管理的甜头,这是以前网管、运维系统多少年想做都没做成的事情,所以说进步靠的不是厂家之间的合作,而是代替。
而现在,用户强调统一管理比以前多得多得多。但凡涉及到基础IT资源,都想实现在一个平台内的统一管理。基础架构即是云,云即是统一平台。用户对于各种厂家统一的期盼,就是能够和云平台进行适当的融合,减少管理复杂性。
公共安全
虽然AWS一直以来的口号都是由用户和AWS共担责任,但是类似AWS和阿里云这样的大型公有云已经在越来越多地染指高级的安全服务,对应的安全产品也越来越齐全,用户已经可以使用公有云服务商的安全产品搭建较为完善的安全防护体系。而与之对应的是,公有云上各种安全合作伙伴的产品购买量实在稀少。大量安全产品购买量维持在个位数。
这种情况非常常见,各安全企业在公有云上基本在赔本赚吆喝。
一来是因为公有云彻底改变了安全行业,最传统的4层防火墙、DDOS设备、堡垒机。他们要么弱化成云上的一个服务,要么已经不适用。特别在PaaS化后,甚至SaaS化后,云租户需要承担的安全建设责任越来越少。安全厂家的主战场已经完全转移到了私有云和混合云上。谁转型更快、谁的产品更好谁将重洗企业安全市场。
二,传统厂家的安全设备在公有云上的使用体验太差,因为网络结构、底层架构变化的原因,传统安全设备在云上的部署过程繁琐,而且许多传统网络中的功能不再适用。安全厂家们急匆匆搬上云的各种安全服务无论在UI亦或功能上都没能为云用户做出足够多的优化,导致用户体验极差。而各种云们天生集成的各种安全服务,在这种情况下优势明显。
所以我依旧认为公有云最终将成长为巨无霸型的IT服务商,巨大的用户量足以支撑公有云将各种常用的IT产品全部包含在其产品体系内,其产品体系将越来越庞大。公有云企业吞噬掉的的不仅仅是传统IT硬件的市场份额,还包括部分软件和服务的市场空间。
所以当我们说IT总市场在不断增长,但是这其中有相当大一部分将被公有云蚕食,公有云在IT建设中的比重将越来越高,中小IT企业的存活堪忧。也许用不到10年,到那时公有云或许已经不能叫公有“云”了。当未来云计算公司真的变成自来水公司后,IT将变成什么样子?眼镜、手表会不会纳入到云计算的平台?是否会有新的计算平台出现,又引领一波自建的浪潮?运维这一职业是否变成开发语言的package?也许唯一能够肯定的是,现在我们耳熟能详的业务都会“消失”,人们不再提起它,但是IT行业将变得更具活力。到那个时候 Nicholas G. Carr 应该再写一篇 “Cloud Doesn't Matter”。
扯得有点远,但是只有放开脑洞畅想一下未来,才能更好地看清现在。
neutron的vpn没啥可讲的,所以就看一看sd-wan吧。
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)