取消
显示结果 
搜索替代 
您的意思是: 
cancel
429
查看次数
0
有帮助
0
评论
Cheng_Cao
Beginner
Beginner
意图网络(Intent Based Network)或者在国内也被翻译成为随愿网络,这词最早的由来应该是思科在发布软件定义接入(SDA)的市场宣传,而更早应该来自于思科在ACI的策略语言中所定义的EPG抽像。其实它是一个非常远大的愿景。当然国内也有另外的一种说法,叫意图驱动网络:
华为企业网络率先向业界发布了意图驱动的智简网络(Intent-Driven Network,简称IDN)解决方案,理解业务意图,以用户体验为中心,实现了网络的自动化、实时感知、预测性维护, 从而打通网络和商业之间的鸿沟。未来的网络一定是能够自治、自愈的网络,是具有生命力的网络,是能够自我学习和思考的网络,华为IDN网络正为此而生。
Based 还是Driven 还是self-driving,都是市场的话,但是发展了这么多年了,却连一个最根本的问题两家都没回答清楚,网络的意图是什么,意图应该如何被理解和定义?基于意图的策略系统应该如何实施?其实研究语言学也就是这个目的, 通过自然语言了解意图并通过自然语言交互理解意图并修改网络或者进行网络排错。此文就是对这些研究的一个分享,以及给大家一个正确的设计Intent Based/Driven Network的框架。

1. 人类意图的描述
其实人类意图的描述都需要来自沟通,而沟通的媒介自然就是语言, 迄今为止我们可以把所有沟通的语言分为三类,自然语言,数学语言 和 程序语言。其实世间万物的描述,无非是在这三种语言系统中选择,以下便是最近在看的一些书,懒得做链接了,我又不是带货的。

2 网络的意图的描述
网络的意图我们从一段自然语义说起,当你网络有故障的时候,通常的做法就是打电话给网管,或者填个工单:“我(Who)在什么时候(When),访问什么应用(Which)有问题了”,这就是一个最直观的意图,而无论是SDN还是什么控制器还是人肉运维,结果都是要反馈两点:故障源是什么(What),故障的影响有多大(How) ?然后再根据决策树这一系列的算法进行自愈修复,或者评估影响不大就不管了~

这就是从Assurance的视角看到的网络的意图,另一个方面是从部署来看,也就是如何在网络中制定规则,也就是我们常说的策略语言。思科最早的Class-map和Policy-map配合ACL,到后期Juniper和Cisco都有一些脚本一类的语言定义Routing policy,也都是类似的东西,其实从策略来看,本源是什么?“我(Who)在什么时候(When),访问什么应用(Which)需要怎么干(Action)

其实这就非常容易的抽象出来了一个网络的意图模型, 围绕着这个模型其实就很容易定义网络的意图和如何实施网络的自动驾驶或者自愈的功能了.

Classification:<Who,When,Which>

Assurance: <What,How>

Policy: <Action>

那么问题来了,这些东西该如何翻译呢?我们接下来就通过Classification,Policy,Assurance这几点来分类讨论。


2.1 如何对数据包分类
我们先来看第一个问题, 如何分类,通信嘛,最早只有IP地址,为了区分应用设计了Port和Protocol,同时为了区分服务加了DSCP字段。这个问题的核心其实就是一个函数:

<Who,Which> =f(proto, src_IP,src_Port,dst_IP,dst_Port,dscp...)

最简单的函数自然是线性函数咯,所以简单粗暴的线性分类大法:配置ACL,而本质上配置ACL这个问题,我们可以抽像为对一个空间的线性划分:

而后期诞生的DPI一类的工具,以及2014年McKeown发布的《P4:Programming Protocol-Independent Packet Processor》本质原因是什么?传统的ACL线性分类的方法出现了极高的复杂度,无法满足直观的运维需求和对人类意愿的描述, 所以才会有Protocol-Independent的需求,即根据应用和报文特征自己构建一种策略语言,从而使得Match-Action执行,其实直观来看,P4相对于ACL也就是在如上线性空间中构建了一些非线性的分类器
另一种做法则是对报文进行tagging,也就是Cisco SDA所使用的SDA和ACI使用的EPG,将IP地址映射到不同的组中,然后实现组策略,它们的做法都很简单,在报文的特殊字段中插入源组(Source Group)然后到目的端,根据不同的目的地址匹配目的组和组策略,本质上还是翻译成了ACL。
还有一种做法就是对IP地址进行编址,特别是在IPv6部署的时候, 很多人建议将地址根据应用来编址或者用户身份来编址,于是出现了一些MobileIPv6的草案,但这种编址方法最终带来的负担就是策略需要跟拓扑紧耦合,否则松耦合会给路由表造成巨大的麻烦。
所以,总结出来这么多年的分类实现如下图所述,从早期的ACL一刀流,到现在标记一个SRC GRP然后用ACL做Dst GRP Match, 最后src/dst GROUP pair做policy的两步法,到以后应该如何呢?

分类问题本质上就是一个间划分的问题,刚好有一段时间在看泛函分析又随手看了一点流型学习的东西, 本质上如果一个空间分类很困难,那么为啥不通过空间映射的方法来降低复杂度呢?换个坐标系就好了

其实这个思想也就是当年LISP和一些Overlay技术想做的, 在overlay的系统上构建灵活的地址分配,通过Overlay地址和underlay地址解耦的方式来获得策略和拓扑的解耦合。那么问题来了,服务器端Overlay上虚机的创建和冗余需求带来了极大的路由复杂性,而接入端设备移动漫游等业务导致移动端编址无法固定。所以才会看到Cisco会抽像出一个Group的概念,以及现在业界常见的微分段(Micro-Segment)策略。
将GroupID放置在数据包中同样会面临挑战, 不同的业务颗粒度不同,甚至有些业务需要用到per-user的policy(例如:让领导先走?嘻嘻~),单一的ID编码或许不符合需求,那么干脆通过某种方式对它进行编址,然后类似于IP地址那样做LPM match不就好了么,所以总结如下
Intent based classification就是一个对在网设备进行重编址的映射,并将编址映射放入报文头中,而组策略可以通过对ID进行LPM实现

这样有个显而易见的好处,也就是说策略和底层的IP地址拓扑完全解耦合了,终端设备无论使用5G或者WIFI或者有线都能获得一致性的策略体验,而且无论他在哪,策略都是一致的,但是问题也伴随着产生了,IPv6网络好解决因为IP Header随便定义或者直接借用SRv6的SRH就好,而IPv4比较难, 如果要做标准实现,只能想别的办法,vxlan GPE里面加?但是有不可避免的要引入Overlay,有没有更简单的办法呢?那就是给IPv4安装上SRH和SRv6一起玩,这也是我前段时间在另一项工作QUIC-SR中研究的,当时RFC草案就提出了将映射的ID放入SRH中。

所以在这个设计中,所有网络中传输的报文其实都包含了两个Label,一个是SR相关的路径选择Label,另一个是跟策略相关的label用来呈现<Who,Which>,而具体如何做呢,一方面在客户端可以为第一跳的接入设备打上这个标签,而在服务器端servicemesh的sidecar可以提供标签或者很多SmartNIC也可以打上这样的标签,如下图所示,这样网络中其它路径上的节点就可避免二次Classification,直接使用标签进行策略处理就好:



2.2 如何定义策略
策略是什么?配个ACL,限制带宽,改个下一跳?这些都是一些命令式的策略(Imperative Policy),它将带来一系列问题,对业务的影响无法描述和用户的意愿隔得太远需要大量的人工进行策略翻译,本质上看上去是API运维了,而策略翻译的人脑还是瓶颈,而且翻译质量还得看心情。例如一个最简单的业务需求,某个流量可能不安全需要弄个防火墙。接下来就存在一系列问题需要思考:防火墙放哪,分支机构还是总部,靠近用户还是靠近业务,负载均衡和冗余如何处理,对称路由如何实现?当看到这一系列问题时,是否直接想到了K8S+Service Mesh?采用申明式的策略(Declarative Policy),剩下的事情全交给业务编排器或者你们常说的SDN控制器去做就好了。但是即便是申明式策略,某司有个论文







NEMO:一种声明式网络编程与业务定制语言CREATE Node headquarter Type l2-group Property ipprefix:192.0.2.0/24 location: Beijing;CREATE Node site Type l2-group Property ip-prefix:198.51.100.0/24 location: Shenzhen;CREATE Connection c1 Type p2p Endnodes headquarter, site;IMPORT Node fw1 Type fw;IMPORT Node lb1 Type lb;CREATE Node chain1 Type chain-group Contain fw1,lb1;
当然思科也有这样的研究发布在2015年的SIGCOMM上《A Declarative and Expressive Approach to Control Forwarding Paths in Carrier-Grade Networks》,但是很遗憾策略只是跟拓扑计算和路径控制相关




val goal = new Goal(topology){ for(d<-Demands) add(d.deviations <= 2for(l<-topology.links) add(l.load <= 0.9 l.capacity) minimize(MaxLoad)}
实际上这些策略的最大问题在哪?和底层太近和意图太远。在下面这本书里有一段很详细的描述,当然这本书中文翻译比较差。
广告

计算机网络问题与解决方案:一种构建弹性现代网络的创新方法

作者:[美]鲁斯·怀特(Russ White) 伊桑·班克斯(Ethan Banks)

当当

Policy comes primarily out of business decisions, and business decisions should be close to the business, not the topologyHence, policy, or least some element of policy, is often best done when centralized


Topology and reachability, however, are grounded in what should be the only source of truth about the state of the network, the network itself. Therefore, it makes sense that decisions related to the topology and reachability, from detection to reaction, should be kept close to the network itself; hence, topology and reachability decisions should trend toward being decentralized

非常经典的描述,也就是说,其实本质上policy需要做的一件事情是和拓扑解耦,解耦的结果其实就变得非常简单和显而易见了,也就是我们常说的SecOps和NetOps,一个管能不能访问,另一个管如何保证访问质量。SecOps更多是全局上的考虑通常采用Centralized Policy,而网络相关的则是Distributed Policy这样就很容易的在高层自然语义下实现了用户意图的描述:









SecOps {    require content inspection    require encryption    require lossless    }NetOps {    require priority  1    require large-bw }
那么如何在通信报文中描述, 底层的网络和可达性相关的Policy现在的Segment routing已经非常接近自然语义实现了, SR policy和SRTE可以很好的在传输满足NetOps的需求。而SecOps就相对麻烦一点了,需要分布式系统中引流,需要考虑流的负载均衡,HA等。而且通常SecOps策略都和防火墙等设备紧耦合,那么如何在网络中构建分布式防火墙系统并使得它们和底层拓扑/可达性解耦,同时最关键的是完成策略的动态触发呢?

2.3 Service-Mesh策略执行
实际上互联网公司在大规模业务部署的时候给了我们很好的借鉴,Service-Mesh通过Sidecar把网络拓扑的复杂性掩盖了,同时提供了Service Discovery和Circuit Breaker等一系列机制来解决HA和负载均衡等问题,使得服务本身的Scale扩展容易。

同样的思想也可以用于网络服务本身,网络界大概已经有了一些雏形, 例如基于vxlan NSH的service-chain或者SR的Service-chain机制,然后也有一些业务平台有了FastPath和SlowPath的设计, 实际上一个带流表和SR aware的FastPath便可以很容易的改造成一个Sidecar,然后服务可以直接注册上去。


那么问题来了,可能还有一些策略如何加载到这些Service Plane里面去呢?尽量让这些跑service的容器干净少配置才是整个设计的关键。例如我们有一个声明式的策略如下:












Match {    UserGroup  mobile-phone which belongs to HR group    ServerGroup Payment application group    AppGroup   Salary Payment}Action {    SecOps {        require content inspection        require encryption    }}

那么很显然,接入网络的第一跳设备会为每个数据包打上了一个<HR_Mobile_Phone, Payment,Salary>的标签(也成为uSeg标签),具体怎么打那就是各厂的identity识别系统怎么做了,可以用K8S集群自己的etcd里抽取或者radius/AD服务器上拿, 自己随意。

那么接下来这个策略居然要一个防火墙来做内容过滤,那就动态创一个虚拟防火墙实例,同时还启动了一个相应的SideCar,并且为它分配一个Node-SID用于后续的SR做Service-chain,至于怎么创建和资源调度,可以类似于K8S那样做一些亲和性的标签。创建完了以后具体的安全策略则可以使用包触发从控制器下载或者predownload的方式看各位的喜好,最后Sidecar向集群注册这个服务,并且给集群汇报用量以便以后扩容。扩容也非常简单,一个sidecar接管多个service-container, 负载均衡则直接采用对SRH的hash,因为<HR_Mobile_Phone, Payment,Salary>的标签明确区分的业务和用户身份。最终接入网络的第一跳设备就会为报文自动打上一个SRH,Segment中有sidecar的Node-ID,OptionTLV中有策略相关的uSeg标签。

至于整网的信令交互过程和分布式KV数据库如何设计,以及如何同步策略,这些东西都是看各家的喜好,偏互联网的云提供商用etcd,redis集群可以,而传统的网络设备上用BGP LISP同步也行。大家看,这样一来是不是不用考虑很多东西,借助于SR和一个新的uSeg label就很容易扩展了。


2.4 如何实现Assurance
Assurance的关键在全网可视化和全网的数据关联, 这个问题Google Dapper的论文很早就给出了答案,也就是说需要TraceID,SpanID,SpanParentID。Segment List很好的呈现了SpanID和SpanParentID,而我们前文分类所述的uSeg Label则可以很好的用作TraceID,这样全网的监控不就变得容易了么,某家在前年就实现了一个在路由器上扩展容器做全网监控的软件,具体不多说,说一些公开的,阿里云也有类似的东西会在今年的SIGCOMM中呈现,那就是<VTrace: Automatic Diagnostic System for Persistent Packet Loss in Cloud-Scale Overlay Network>:


文中有这样一段,事实上它也道出了报文染色的窘境,字段太少只能填很少的信息, 但是NAT转换日志本身输出会有Race condition导致潜在的关联问题:
由于数据包中用于VTrace染色的字段长度受限,难以将任务ID放入染色字段中,那么必须通过六元组(srcIp+dstIp+srcPort+dstPort+proto+vni)来识别任务信息,VTrace应用来保证任一用户发起的任务中六元组的唯一性(六元组也是用来染色的流规则),那么在VFD的采集中,数据包的六元组也是必须要采集出来的关键要素,然而由于转发中可能存在NAT转换,如果不能识别NAT,将无法识别同个任务的数据,所以要求在匹配采集中将NAT转换的前后数据分别采集下来,用以同任务判断。
另一方面论文借助了成熟的JSTORM框架,我只是有些好奇买这个业务的客户平均摊薄的成本是多少,如果全网极端情况下出现问题大量的客户开启业务后会不会产生日志风暴等问题,另外JSTORM的算法也有一些问题,不知道阿里云买了Flink的母公司为啥不用呢?关于STORM和FLINK其实可以看如下这本书:
广告

流式系统(影印版)

作者:Tyler Akidau,Slava Chernyak,Reuven Lax

京东
当年我在某家也是根据这本书写了一套流计算系统,重新造轮子的原因是在一些嵌入式平台上内存和CPU都比较紧张,没必要多运行一个Java的东西,而且有些基于窗格的计算任务会导致CPU周期性的抖动,所以使用了Welford's Online algorithm计算mean/std/skew等来降低对CPU的影响。

回到正题,Goog在设计QUIC的时候也考虑到了这一点,很巧妙的利用传输层(L4)解决了L3无法存放较长字段的缺陷,利用SCID和DCID无论IP地址端口怎么变,上层连接一致性是有保证的,为了节约字段长度,uSeg也可以直接encode到ConnectionID里面,这样有几个好处,第一给予了每个终端多路径的选择权,可以同时使用5G和WIFI链路,另一方面,给与整个Fabric一个全局唯一的Hash key用于负载均衡和日志关联。
而Assurance本身需要对应用质量进行评估和故障节点分析, 故障节点分析很多时候采用一些决策树算法就好,同时需要考虑Domain Specific的问题,例如AP的日志就要考虑到特殊的模型去处理RF噪音干扰和空口利用率以及终端SNR等信息,而路由器交换机更多的需要处理自身的buffer,还有就是根据QUIC报文的一些Sequence确定链路丢包,以及一些带内的延迟测量方法, 这些都是百家争鸣自己怎么干都行,而最终切记一点:
控制器其实并不需要很多DomainSpecific的东西,只需要一个简单的结果<What,How>,即评估性能损失的影响及应用健康度(How),如何导致的性能下降,最重要的影响原因是什么(What),而这些东西本质上都应该设备侧提供以分布式方式提供,最终多个设备的混合结果交由控制器分析。


3 关于语言的题外话

其实我们对意图网络的理解不透使得最近一段时间逼迫CLI网工开始写代码,然后很多网工又是通信专业出生本来就不是CS的没有接受过很好的编程训练,所以在意图转换的过程中也出现了很多问题。仔细思考了一下,主要是编程语言通常都是来自于英语语系的国家,而所谓的中文编程虽然出现了很多野鸡语言,但最终不成功的原因是什么?很大程度上还是汇编或者指令集设计思想背后为英语语系的缘故。
例如普通的非函数式语言编程,赋值语句等同于:

a = 1
那么问题就来了,其实这样的赋值变相的给这个值增加了一个时间轴上的意义,也就是英文的所谓的“时态”, 可能到了另一个CPU上,如果没有Cache 一致性的支持,那么就会变成过去时,但是现在是啥不知道...
另一方面,很多面对对象的语言就如同定语从句那样,给语言带来了很多累赘,例如OO类语言常说的一个笑话:“当我需要一个香蕉的时候, 我不得不从一个拿着香蕉的猴子那里派生出来”,这也是英语相对来说比较啰嗦的原因, 可怜的人类被迫跟着英语语系的人去继承着那些完全不必的定语从句结构,也是够可怜了。
所以这些年函数式编程的兴起也便是一个趋势, 无论是一些函数式编程语言,或者是一些流计算系统,本质上其实就是为了解决英语语系的程序语言上时态的问题。从长远来看,编程语言该如何发展,我一直认为针对不同的任务应该使用不同的语言,但是很多人总是在One Programming language fit all的路上走极端,真是有趣,前端工程师想用Node.JS占领后端, 而后端有些工程师又想通过Web Assembly 抢前端的饭碗...还有所谓的PHP是世界上最好的语言,或者Python一刀流,Java统治世界的..  真是有趣,而看看自己,最早在90年代初期以Logo语言入门,然后basic,后来用pascal搞竞赛,PHP写网页,然后在数学系用matlab和C高计算,后来工作了早期用Perl写脚本做一些基础的自动化控制,到现在用python做量化和AI算法,C++写CTP和股票的程序化交易,go写后端(用过一段时间node.js KOA的框架,但却是烦了,用Go系统依赖小,嵌入式也能跑),真要加速一些东西用CGO去Call一些已有的C代码就好,但还有一些性能要求较高的用C,最近还在慢慢学习用verilog写FPGA做SmartNIC的一些Prototype.  然后前端js/ts搞来搞去,搞多了,你就会发现,不同的语言真的有不同的用途,多看看,享受它们各自的快乐就好~



入门指南

使用上面的搜索栏输入关键字、短语或问题,搜索问题的答案。

我们希望您在这里的旅程尽可能顺利,因此这里有一些链接可以帮助您快速熟悉思科社区:







认可您的同行