F5 V9 LC Outbound 配置总结由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“软件配置管理总结报告”。
F5 V9 LC Outbound 配置总结
本文只涉及到链路负载均衡的outbound部分,针对用户外出访问internet的多种情况一一进行描述,其目的是为大家建立一个通用的标准LC outbound配置模板,方便今后大家讨论。也许其中的很多功能,我们可以用别的方法解决或者F5别的功能实现,但我们希望通过建立一个规范的处理流程来帮助大家更好的理解F5 v9的设计理念,以及一个标准的分析流程。
在具体讲述outbound的设置的之前,大家现看一下一个标准的ourbount case中的rule 内容:
(本case 共有七条链路的outbound的负载均衡,现将原有的irule简化)
rule out_rule { # outbound rule 通过判定用户的源IP和目标IP来确定用户外出的gateway地址(即ISP地址),所有外出的数据均会命中且只会命中下面的一个条件,所以F5的工程师的任务就是把用户描述转变成如下的条件判定流程!
when CLIENT_ACCEPTED { if { [IP::addr [IP::local_addr] equals 10.200.3.0/255.255.255.0 ] } { forward } elseif { [ matchcla [IP::local_addr] equals $::tel4www.daodoc.comc_only_pool&cnc_first_pool,前者代表只能走CNC的应用,后者代表优先走CNC(如果CNC故障,可以考虑其它备份,采用priority 将pool中的CNC设置最高优先级,其它ISP低优先级,active member要求1)。
个例分析规则
在本文中我们先给出了一个完整的解决方案,或者说是标准的解决方案,我们希望分析的所有个例都能够基于该方案得到解答。我们分析的方案可能不是最优的,我们分解的案例可能也不完全,但是希望大家在这个平台上去丰富,把各种各样的案例拿处理,群策群力,最终都能得到解答!同时,本文最后也探讨了一下优化性能的问题,只是抛砖引玉,希望更多编程高手能够加入!在不破坏这个平台的基础上,希望得到更多的优化方案。
第 3 页 / 共 18 页
二、分类描述
对于链路负载均衡中的outbound应用,我们总结下来,按照用户外出的snat方式,我们大致分为4大类: 第一类: automap 这是绝大多数内网用户上网时采用的算法,其特点是用户外出没有固定IP要求,只要保证选用哪个ISP就用哪个ISP的地址作为源地址就可。
第二类: 1:1 NAT/SNAT应用(多个服务器对应一个VS)这类地址一般是用户的MAIL 服务器、VPN 服务器、终端服务器。其特点是:用户服务器原先就直接采用某一ISP的公网地址直接对外发布服务,现在只是将该服务器移动到内部的DMZ区,并不需要其对外提供多个ISP的接入服务。比较典型的是mail服务器,由于对端mail服务器会通过反向域名查询IP,故mail服务器如果多ISP发布很可能被对端mail服务器拒绝,故只采用单一IP对应域名方式。
该类应用的outbound难点在于,用户进来访问是通过VS(返回包会自动命中L4交换记录的会话信息,不用考虑),而服务器外出必须首先采用SNAT将其源地址变为VS的地址以保证应用的统一,而更重要的是由于其外出地址VS是固定的,其外出的gateway也必须选择该VS所在的ISP,而这就必须由rules来保证。
在处理1:1 NAT时,F5相对于我们的竞争对手而言,可以说完全没有优势,我们必须采用VS+SNAT+irule才可以实现一个简单的NAT功能(特指在ISP LB项目中),所以我们应该鼓励客户将应用发布在多个ISP中,这样就能够体现我们的优势!或者,要求用户提供多台服务器同时对外提供服务(对我们而言,单一ISP发布和多ISP发布配置几乎一样)如果不行,大家就应该仔细分析用户需求,其实很多服务器外出并不一定要使用VS地址,可以使用任何地址!这样就不用考虑outbound的SNAT+irule而直接规类到第一类automap应用了。如果,用户一定要1:1 NAT而且要和竞争对手比较,你还可以大胆的提问客户,如果VS所在ISP故障,如何让服务器仍然可以外出internet? 竞争对手很难实现,我们则只要把外出irule中的CNC_ONLY_POOL 改为 CNC_FIRST_POOL就好了!
第三类: iSNAT 应用(多个VS对应1/N个服务器)
这类应用是F5的最大特色,也是真正意义上的ISP负载均衡。其特点是,服务器在多个ISP上对外发布,其外出时选用哪个ISP就用该ISP上的VS地址作为SNAT地址。在这里,技术难点就是如何绑定snat地址,如何在snatpool依据选择的gateway挑选snat地址。
第四类: 内网有公网地址
此类应用,是最麻烦的,其inbound采用network VS 转发,而outbound原则上必须采用该公网地址段的ISP作为gateway(外出的返回包一定是走该ISP返回!)。我们要考虑的是,如果该ISP故障是否要让其走其它ISP,并采用SNAT automap作为源地址。
第 4 页 / 共 18 页
一、1 snat automap 对于内网用户访问internet,可能直接Automap 到 default_gate_pool 里做roundrobin。一般在iRules中,我们都是命中最后的else语句。
最简单的就是如下的组合(黑体字部分):
when CLIENT_ACCEPTED { if { [XXXXXXXXXXXXXXXXXXXXXXXXXXXXX } { pool XXX_only_gw } else { pool default_gateway_pool snat automap } } when LB_SELECTED { if {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.83]} { snat 218.104.34.221 }。。
else{ snat automap } }
只是,这样的规则并不能够优化外出outbound的访问速度,尤其是不能分解出去电信和网通的数据流,所以需要编写irule 脚本来做更进一步的设置。
举例:如果outbound 有电信和网通两条链路,我们需要建立3个gateway策略pool telecom_only_pool —— telecom gateway 地址 cnc_only_pool —— cnc gateway 地址
default_gateway_pool —— 包含所有的gateway地址
然后在DATA GROUP中建立2个cla(telecom 和cnc),将电信和网通的地址段加入,在default_gateway_vs中(0.0.0.0:0)使用以下rule就可以解决的电信和网通的外出优化问题了。when CLIENT_ACCEPTED { if { [matchcla [IP::local_addr] equals $::telcom_cla]} { pool telcom_only_pool } elseif { [matchcla [IP::local_addr] equals $::cnc_cla]} { pool cnc_only_pool } else { pool default_gateway_pool
第 5 页 / 共 18 页
} }
很多工程师再这样做了之后,测试功能的时候就会发现一个问题了,如果去掉电信的链路访问电信地址不通,去掉网通链路访问网通地址不通。这是因为在irule中的先匹配到电信得链路,然后就转发到指定得ISP_gateway, 所以就访问不通.解决这个问题可以使用priority的功能,建立冗余措施:
telecom_first_pool —— telecom gateway addr priority 10 cnc gateway addr priority 1 cnc_first_pool —— cnc gateway addr priority 10 telecom gateway addr priority 1
default_gateway_pool —— cnc gateway addr priority 1 telecom gateway addr priority 1
这样就可以使用first_pool来实现外出gateway的选择,telecom和cnc 两个cla也是现成的。至于外出的snat由于是automap所以没有什么特殊之处。
对于上网用户,如果用户数很多,我们常常考虑增加snat automap地址来实现提升snat的性能,通常方式是在BIG-IP接口添加多个floating IP来实现多个automap地址,但是不论v4.5和v9系统都是按照连接数轮询得采用这多个floatingIP,导致用户msn或者IE访问产生问题。如何解决?用图形界面简单的snat是无法解决的,还是要用iRules。
首先,我们如何模拟多floating IP的snat automap,其实很简单,我们已经对每个gateway决心了判定,在其最后,我们不用snat automap,而用snat pool替代。
when LB_SELECTED { „
#最后判定用户采用电信网关218.104.34.193 if {[IP::addr [LB::server addr] equals 218.104.34.193] } { snat pool snat_tel_pool }。。
else{ snat automap } } 其次,如何实现一个源地址只采用一个snatIP外出? 我想到的是hash算法,即将用户的源地址按照snatpool内地址个数取余数,然后按照余数分配snat地址,大致的语法是
if {[IP::addr [LB::server addr] equals 218.104.34.193] } { switch “用户源地址取余数”
第 6 页 / 共 18 页
“0”
snat snat_tel_pool地址1 “1”
snat snat_tel_pool地址2 “2”
snat snat_tel_pool地址3。。}。。
else{ snat automap }
由于时间关系,这里还没有尝试具体的算法,有待大家帮忙完整!
第 7 页 / 共 18 页
二、2 NAT应用
在前面的基础上我们的客户一定会又提出了一些具体的需求,某些应用需要以VS的地址 SNAT出去,这时需要将该VS对应的服务器组POOL中的所有服务器做1对1或N对1的SNAT;例如:VS(222.92.15.12) POOL(172.22.253.12 + 172.22.253.13)对于这种NAT应用,我们判定其数据流有如下几步:
1> 当源地址等于特定服务器地址时,将优先选用该特定服务器对应的VS所处的gateway;
2> 如果选定了VS所对应的gateway,则将该服务器的源地址SNAT成其VS的地址; 3> 如果对应的gateway故障,且用户运行切换使用别的gateway,此时该服务器的源地址应该SNAT automap成对应选定gateway的地址。
步骤一,对应于irules中的以下内容:
when CLIENT_ACCEPTED {。。
if { [ matchcla [IP::client_addr] equals $::cnc_client ] } { pool cnc_only_gw }。。
我们没有1对1的采用if语句判定特定服务器地址,而是将服务器的源地址如:172.22.253.12 和172.22.253.13 按照其VS 222.92.15.12处于cnc而加入cnc_client这个cla。同样的,所有VS在cnc的pool服务器组成员均加入到cnc_client.当然,如果有特点客户必须走cnc链路的也可以加入cnc_client。
对于步骤3,我们需要用cnc_first_gw代替cnc_only_gw实现当cnc故障时系统能够选用别的gateway作为外出路径。
对于步骤2,我们将按照client_accepted事件中选定的gateway(LB:server addr 函数对应选定的gateway)并结合服务器源地址判定snat地址。切记必须两者绑定而非仅仅判定源地址!因为如果选定的不是指定vs对应的gateway,我们将使用snat automap外出。
when LB_SELECTED {...if {[IP::addr [LB::server addr] equals 222.92.15.12] and [IP::addr [IP::client_addr] equals 172.22.253.12]} { snat 222.92.15.12 } else{ snat automap } „ }
有很多人会这样问: 在web界面中有一对一的SANT设置,而且他的优先级比 Automap的要高(automap和 1:1的snat都是全局属性),为什么还要这样做呢?
答:在单独线路的Server LB的时候,我们在web 界面中设置1:1或1:N的SNAT,我第 8 页 / 共 18 页
们说是没有问题的,但是我们在两条或以上的时候,需要考虑到线路断线后的冗余问题。我们可以分析这两种实现方式的区别。
a.Web 界面的 1:1 SNAT 方式的判断逻辑:
Client IP——〉SNAT IP ——〉 Gateway_IPS_adder
在这样的方式中,如果IPS线路断线,那么SNAT的地址出去就不能访问;
b.irule 的方式 1:1 SNAT 方式的判断逻辑:
Gateway_IPS_adder——〉Client IP——〉SNAT IP 在这样的方式中,由于使用了priority的方式,就算IPS线路断线,在irule中匹配gateway pool 之后,最终还是能够有备份线路来选择gateway,然后再根据client IP来判断,所以这样的方式是不会出现无法访问的现象。
第 9 页 / 共 18 页
二、3 iSNAT应用
iSNAT应用指得是内网的服务器组(1台或N台),已经按照链路负载均衡在多个ISP上构筑了VS。当服务器主动向外发起请求时,其外出的源地址按照其选定ISP而采用该ISP上的VS地址。我们来整理一下其数据流:
1. 服务器发起对外的请求,达到F5后选择一个ISP的网关转发外出包;
2. 当决定了转发的ISP网关后,将服务器的源地址改为该ISP上的对应VS地址; 3. 如果含有VS的ISP都故障,是否让服务器采用别的ISP外出? 4. 如果采用别的ISP外出是否采用SNAT automap解决源地址问题?
通常需要iSNAT的应用如IPSEC VPN,mail Server等。在4.5版本中我们需要在CLI中使用SNAT pool的命令来实现iSNAT功能,可以很方便的将snat地址和isp绑定。而在V9的方式web界面中能够建立SNAT pool,但是我们将SNAT pool确无法自动选取ISP上的一个snat地址,即无法实现iSNAT,必须采用iRules 手工设定。
首先,让我们看看如何处理步骤1 ?我们首先要建立一个cla将VS对应的所有服务器组pool成员添加进去,当然如果服务器只有一台就无需建立。举个例子我们的mail服务器172.22.252.81,对外发布两个VS(在cnc 为218.104.34.201 网关为218.104.34.193;在telecom为222.92.15.27 网关为221.224.233.89)。我们的路由选择rules应该如此写:
when CLIENT_ACCEPTED {。。
if { [ matchcla [IP::client_addr] equals $::mail_srv ] } { pool mail_gw }。。} 其中,mail_srv cla含有172.22.252.81这一个服务器地址,mail_gw 含有218.104.34.193:0 和221.224.233.89:0 两个网关。这样,我们就实现了172.22.252.81外出时可以走两条isp。
步骤2, 如何确定外出地址? 我们在iRules中的LB_SELECTED事件中建立gateway+clientIP绑定的判定以确定是我们所要处理的这台mail服务器,再分别选取要的snat地址。
when LB_SELECTED { „
if {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.81]} { snat 218.104.34.201 } elseif {[IP::addr [LB::server addr] equals 221.224.233.89] and [IP::addr [IP::client_addr] equals 172.22.252.81]} { snat 222.92.15.27 } „ } 如上所示,只有当选中218.104.34.193这个gateway并且服务器地址是mail
第 10 页 / 共 18 页的地址172.22.252.81,我们才会将其转换成mail的VS地址218.103.34.201.其三,如何实现步骤三的冗余? 其实就是在mail_gw pool中将cnc和telecom的优先级设置为10,active member设置为1,然后将unicom等ISP加入pool中并将优先级定为1,这样当cnc和telecom故障时,仍然可以选用其它ISP链路。
其四,当你选用了其它ISP后,自然不能命中LB_SELECTED中的任何指定策略,只会命中else中的automap而外出。
第 11 页 / 共 18 页
二、4 公网地址应用
如果F5里面的某些服务器使用了公网地址,不做任何设置的时候是命中Automap,即使打开了0.0.0.0:0 forwarding vs 同样如此,如果希望以自己的地址路由出去,就必须不做SNAT出去。我们再来整理一下其数据流:
1> 当客户的源地址是公网地址,外出访问internet时,我们需要把它转发到该公网地址所属的ISP;
2> 由于其是公网地址,我们在外出snat中应该明确标注其snat none; 3> 如果该公网地址所属ISP故障,是否切换到其它ISP;
4> 当切换到其它ISP时,外出时必须选用其它ISP地址作为snat地址才能外出;
对于步骤1,我们只需要在client_accepted事件中描述出该公网网段,并将其指定到所属的isp gateway,如下文所示,当公网网段222.224.15.0/24外出时,我们将只把它转发到telecom(注意telecom_only_gw这个pool)
when CLIENT_ACCEPTED { „
if { [IP::addr [IP::local_addr] equals 222.224.15.0/255.255.255.0 ] } { pool telecom_only_gw } „ } 对于步骤2,更简单,我们只要在LB_SELECTED事件中将该网段标识出来,并选取snat none。切记!为了可以实施下两个步骤,我们还是用gateway+sourceIP的绑定而非纯sourceIP的判定,来选取这些服务器。
when LB_SELECTED { „
if {[IP::addr [LB::server addr] equals 221.224.233.89] and [ IP::addr [IP::client_addr] equals 222.224.15.0/255.255.255.0 ] } { snat none }。。
} 对于步骤3,如果考虑到电信故障,需要切换,同样的我们可以将telecom_only_gw改为telecom_first_gw,就可以在电信故障是切换到其它isp了。
由于切换到其它ISP,如果我们仍然用telecom的公网地址外出,则必定无法访问,所以我们这时候必须让其命中automap(当然也可以是其它你知道并明确的snat规则)。这就是为何我们在步骤2中必须绑定选定的gateway,否则只判定源地址,那么当我们切换到其它ISP时,仍然命中该规则,而导致仍然用电信的公网地址外出。
以上简单的描述了4种SNAT的方式的实现方法,也许大家会觉得这样的做法比较笨,比较麻烦,所以还是请具体问题具体分析咯。
第 12 页 / 共 18 页
三、系统优化
以下所述的优化,必须是完全理解前面的配置后,才方便实施!而且以下的配置主要是优化系统性能,并不增强功能。
三、1 LB_SELECTED事件中if的优化
按照前面所述,我们在LB_SELECTED事件中采用gateway+sourceIP绑定的方式书写if判定。这种方式在少量snat设置中十分简单易懂,但当snat数量达到十多个时,对性能影响甚大。为什么?因为如果你有30个判定,则snat automap必将作30个if判定后才到达最后的automap,性能影响甚大。最简单的方式就是按照gateway先规类判定一次后,再接下去判定sourceIP,如此可以减少大量if判定。如下:
when LB_SELECTED { „
if {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.81]} { snat 218.104.34.221 } elseif {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.82]} { snat 218.104.34.23 } elseif {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.83]} { snat 218.104.34.24 } elseif {[IP::addr [LB::server addr] equals 218.104.34.193] and [IP::addr [IP::client_addr] equals 172.22.252.84]} { snat 218.104.34.25 } „ } 我们可以先判定网关是CNC的218.104.34.193,再分析源地址。这样如果客户选定的是telecom gateway就可以避免后续的if判定。如下: when LB_SELECTED { „
if {[IP::addr [LB::server addr] equals 218.104.34.193] } { if { IP::addr [IP::client_addr] equals 172.22.252.81] } {
snat 218.104.34.21 } elseif { [IP::addr [IP::client_addr] equals 172.22.252.82]} { snat 218.104.34.23 } elseif { [IP::addr [IP::client_addr] equals 172.22.252.83]} { snat 218.104.34.24 } elseif { [IP::addr [IP::client_addr] equals 172.22.252.84]} {
第 13 页 / 共 18 页
snat 218.104.34.25 } else {
snat automap } } „ }
事实上,我们在现网中就应该用这样的嵌套if规则定义LB_SELECTED事件,本文主要是为了让大家容易理解SNAT运作才使用了上一章的gateway+sourceIP绑定if。但大家必须注意,随着语法改动带来的冗余切换尤其是automap的命中!
第 14 页 / 共 18 页
三、2 对于大量1:1 SNAT的优化
在上面众多的1:1 SNAT中后来在Devcentrol中看到一个case,深受启发。但是由于时间关系,没有测试,如果那位兄弟有条件的测试一下看能够实现,造福于他人.首先,将所有在CNC 上的1:1 / n:1 SNAT 地址配置到一个cnc_snat_addr cla中,其格式如下:
“client_ip SNAT_IP” “10.0.0.1 200.0.0.1” “10.0.0.2 200.0.0.2”。。
然后在LB_SELECETED规则中,就可以只判端是否为CNC gateway,而不需要采用gateway+sourceIP的判定,直接从cnc_snat_addr中选取该源地址对应的snat地址,如果没有就选取automap。
when LB_SELECTED { if {[IP::addr [LB::server addr] equals 218.104.34.193] { set my_snat [ findcla [IP::client_addr] $::cnc_snat_addr “ ” ] if { $my_snat ne “” } { snat $my_snat } else { snat automap} } 这样做的目的,是可以大大减少irule的if语句判定数量,并且极大的方便用户维护。举例,如果你在CNC有30个1:1的NAT,那你在LB_SELECTED 中就得有30判定if,而现在我只要判定一次gateway就搞定了,效率相差甚大。其次,如果你要添加第31个1:1NAT,不用这种方式,你必须在众多的if语句中添加一个if,而现在,你只要在cnc_snat_addr中添加一行,然后在client _accepted事件对应的cnc_client中也添加一个源地址就可以了,完全不需要改变irules!
第 15 页 / 共 18 页
三、3 troubleshoot中如何获取负载分担信息
由于目前在V9 平台上我们建立了0.0.0.0:0的 VS的时候,如果现在standard —〉all protocal 的时候就会直接改变为performance laryer 4的type,这样我们在tcpdump的时候就不能抓到内部向外的数据包,因为performance layer 4 的 vs是 直接走PVA 芯片,不会经过CPU的处理,所以对我们的troubleshooting带来很大的麻烦。
但是可能有人会建议建立两个VS,0.0.0.0:0 standard ——〉 tcp protocal 和0.0.0.0 standard ——〉ucp protocal;但是对于一个应用同时都要用到udp 和tcp的时候,那数据包会满天飞。
所以我们在测试的时候在可以在irule中打开log功能。
下面例子中就是先建立一个debug_cla,然后如果发现有客户端outbound有问题,我们就可以将client IP放在debug_cla中,然后再/var/log/中 使用命令tail –f pktfilter, 就可以通过log看到客户端向外访问情况了。
when LB_SELECTED { if { [ matchcla [IP::local_addr] equals $::debug_cla ] } { log local5.warning “select gateway [IP::client_addr]--> [IP:local_addr]->[LB::server addr]!!” } „ } 这条if语句可以放在最前面或最后,为何要作debug_cla?因为在正式环境中如果直接添加log “select gateway [IP::client_addr]--->[LB::server addr]!!”,这样会有很多的log很快就会写满硬盘的,当然在测试的时候是没有问题啦。而采用debug_cla 就可以轻松的决定要跟踪哪个IP,而不需要改变irules。
其他的log 方式还是需要根据毛主席他老人家的思想去做啦: 具体问题具体分析啦。
当然,如果我们想连snat成哪个IP都跟踪,则必须在LB_SELECTED语句中修改snat方式,举例,(时间关系,没有验证下面的语法是否准确!只是描述用意)when LB_SELECTED { set my_snat_addr “automap”
if {[IP::addr [LB::server addr] equals 218.104.34.193] } { if { IP::addr [IP::client_addr] equals 172.22.252.81] } {
$my_snat_addr = 218.104.34.22 } elseif { [IP::addr [IP::client_addr] equals 172.22.252.82]} { $my_snat_addr = 218.104.34.23 } elseif { [IP::addr [IP::client_addr] equals 172.22.252.83]} { $my_snat_addr = 218.104.34.24 } „
第 16 页 / 共 18 页
} snat $my_snat_addr log local5.warning “ snat addr is $my_snat_addr ” }
第 17 页 / 共 18 页
附一
我们在v9 的outbound的测试经常会碰这样的问题,向外一直ping 一个电信的地址,拔掉电信得链路的时候会发现ping 包会丢包会很长时间恢复,但是向外的ftp,http smtp都不受影响,迅速的切换回来。这是因为v9中吧ping作为一个长连接,所以timeout时间过来才会切换到另一条联路。如果要解决这个问题就是,在default_gateway_pool中actione service down中选择reselect 的option.这样就能够实现ping 包的快速切换。
第 18 页 / 共 18 页