KVM部署LVS集群故障案例一則



一、故障現象

 

KVM部署LVS(Linux Virtual Server)集群后,能夠單獨以HTTP方式訪問RS(Real Server)的實際IP,但無法通過VIP(Virtual IP)訪問。

 

二、故障分析過程

 

1.簡化架構

 

在原部署環境中,采用的架構是LVS的DR(Direct Return)模式,如下圖所示:

 
                         

為了便於故障排查,我們簡化為

也就是在2台宿主機上,各保留一個虛擬機,角色分別是LVS的Director(調度器)和RS。

 

該架構中的服務器(及虛擬機)的IP和MAC地址如下:

角色

IP

MAC

網絡結構

宿主機1

x.y.z.70

a0:d3:c1:f4:66:ac

宿主機1的eth0和Director1的eth0(在宿主機1中對應為vnet0)橋接到br0

Director1

x.y.z.200

02:00:73:b6:53:c8

宿主機2

x.y.z.73

a0:d3:c1:f9:f3:fc

宿主機2的eth0和RS2的eth0(在宿主機2中對應為vnet0)橋接到br0

RS2

x.y.z.226

02:00:73:b6:53:e2

VIP

x.y.z.208

02:00:73:b6:53:c8

 

Client IP

192.243.119.145

   

 

2.確認Director1是否能夠正確識別到RS2提供的服務

 

在Director1上,使用如下的命令檢查

 

[root@Director1 ~]# ipvsadm -ln --sort

IP Virtual Server version 1.2.1 (size=4096)

Prot LocalAddress:Port Scheduler Flags

  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn

TCP  x.y.z.208:80 rr

  ❶-> x.y.z.226:80           Route   2      0         0        

 

由以上的輸出❶可以看出,Director1能夠正確識別到RS2提供的服務。

 

3.確認Director1是否能夠正確重寫MAC地址

 

在Director1上執行以下的命令:

 

[root@Director1 ~]# tcpdump -vvv -nnn -e -i eth0 host 192.243.119.145

❶11:39:19.372804 84:78:ac:27:6c:41 > 02:00:73:b6:53:c8,ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 48, id 47264, offset 0, flags[DF], proto TCP (6), length 60)

    192.243.119.145.51643 > x.y.z.208.80:Flags [S], cksum 0x000e (correct), seq 3639534333,win 14600, options [mss 1460,sackOK,TS val 780753501ecr 0,nop,wscale 7], length 0

❷11:39:19.372815 02:00:73:b6:53:c8 > 02:00:73:b6:53:e2,ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 48, id 47264, offset 0, flags[DF], proto TCP (6), length 60)

    192.243.119.145.51643 > x.y.z.208.80:Flags [S], cksum 0x000e (correct), seq 3639534333,win 14600, options [mss 1460,sackOK,TS val 780753501ecr 0,nop,wscale 7], length 0

❸11:39:20.372079 84:78:ac:27:6c:41 > 02:00:73:b6:53:c8,ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 48, id 47265, offset 0, flags[DF], proto TCP (6), length 60)

    192.243.119.145.51643 > x.y.z.208.80:Flags [S], cksum 0xfc25 (correct), seq 3639534333,win 14600, options [mss 1460,sackOK,TS val 780754501ecr 0,nop,wscale 7], length 0

❹11:39:20.372091 02:00:73:b6:53:c8> 02:00:73:b6:53:e2, ethertype IPv4 (0x0800), length 74: (tos 0x0,ttl 48, id 47265, offset 0, flags [DF], proto TCP (6), length 60)

    192.243.119.145.51643 > x.y.z.208.80:Flags [S], cksum 0xfc25 (correct), seq 3639534333,win 14600, options [mss 1460,sackOK,TS val 780754501ecr 0,nop,wscale 7], length 0

---以下略去客戶端第3、4、5次重傳數據

 

從❷所示的以太網幀中,我們能夠看到❶所示的以太網幀目的MAC地址被Director1重寫成了RS2的MAC地址,同時源MAC地址被Director1重寫成了Director1本身的MAC地址。

 

從❸和❹所示的以太網幀中,我們能夠看到Client(192.243.119.145)在1s后(❸中的TSval 780754501比❶中的TSval 780753501大1000ms,TCPSequence相同)(注:TS val表示發送方的時間戳,單位是ms)進行了SYN包重傳,說明Client和RS2沒有正常建立TCP連接。此時,Director1仍然正確重寫了MAC地址。

 

4.確認宿主機1是否能夠正確轉發虛擬機Director1重寫后的幀

 

在宿主機上執行以下命令:

 

[root@HOST1 ~]# tcpdump -vvv -nnn -e -i br0 host 192.243.119.145

❶11:39:19.430993 84:78:ac:27:6c:41 > 02:00:73:b6:53:c8,ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 48, id 47264, offset 0, flags[DF], proto TCP (6), length 60)

    192.243.119.145.51643 > x.y.z.208.80:Flags [S], cksum 0x000e (correct), seq 3639534333,win 14600, options [mss 1460,sackOK,TS val 780753501ecr 0,nop,wscale 7], length 0

❷11:39:20.430238 84:78:ac:27:6c:41 > 02:00:73:b6:53:c8,ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 48, id 47265, offset 0, flags[DF], proto TCP (6), length 60)

    192.243.119.145.51643 > x.y.z.208.80:Flags [S], cksum 0xfc25 (correct), seq 3639534333,win 14600, options [mss 1460,sackOK,TS val 780754501ecr 0,nop,wscale 7], length 0

---以下略去客戶端第3、4、5次重傳數據

 

從❶和❷所示的以太網幀中,我們能夠看到宿主機1未轉發虛擬機Director1重寫后的以太網幀(其中❷是❶的Client重傳,我們沒有觀察到❶和❷的MAC地址被重寫的情況)。

 

很明顯,問題出在宿主機1上,它沒有轉發Director1重寫后的以太網幀。

我們來看看為什么會發生這個問題。

 

5.檢查宿主機1上虛擬機Director1的網絡配置

 

在宿主機1上執行以下命令:

 

[root@HOST1 ~]# virsh dumpxml r2-10105

    <interfacetype='bridge'>

      <mac address='02:00:73:b6:53:c8'/>

      <source bridge='br0'/>

      <target dev='vnet0'/>

      <modeltype='virtio'/>

      ❶<filterref filter='clean-traffic'>

        ❷<parameter name='IP' value='x.y.z.200'/>

      </filterref>

      <aliasname='net0'/>

      <address type='pci'domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>

    </interface>

 

從❶和❷中,我們看到Director1被引用了一個名為'clean-traffic'的過濾策略,同時給變量IP賦值為Director1的IP地址x.y.z.200。

 

在宿主機1上執行以下命令:

 

[root@HOST1 ~]# virsh nwfilter-dumpxml clean-traffic

<filter name='clean-traffic' chain='root'>

 <uuid>8c2059f9-d00f-4d1d-b96e-69e7d2b41c0f</uuid>

  <filterreffilter='no-mac-spoofing'/>

  ❸<filterreffilter='no-ip-spoofing'/>

  <rule action='accept'direction='out' priority='-650'>

    <macprotocolid='ipv4'/>

  </rule>

  <filterreffilter='allow-incoming-ipv4'/>

  <filterreffilter='no-arp-spoofing'/>

  <rule action='accept'direction='inout' priority='-500'>

    <macprotocolid='arp'/>

  </rule>

  <filterreffilter='no-other-l2-traffic'/>

  <filterreffilter='qemu-announce-self'/>

</filter>

[root@HOST1 ~]# virsh nwfilter-dumpxml no-ip-spoofing

<filter name='no-ip-spoofing' chain='ipv4-ip' priority='-710'>

 <uuid>bf7be725-1486-410f-8a8b-42c82b952261</uuid>

  <rule action='return'direction='out' priority='100'>

    <ip srcipaddr='0.0.0.0'protocol='udp'/>

  </rule>

  <rule action='return'direction='out' priority='500'>

    ❹<ipsrcipaddr='$IP'/>

  </rule>

  ❺<rule action='drop' direction='out' priority='1000'/>

</filter>

 

從❸、❹、❺中,我們看到在宿主機1中把Director1的發出的數據包的源地址限定為x.y.z.200,任何從Director1發出的數據包,如果源IP為其他,則被過濾掉(drop)。

 

注意:

 在LVS的DR模式部署中,Director會重寫來自客戶端的以太網幀的源MAC地址和目的MAC地址,但會保留源IP地址和目的IP地址,因此Director發出的數據包得源IP地址並不是在這個虛擬機上配置的IP地址,也就是進行了IP的偽裝(spoofing)。恰好被宿主機1上對它限制給過濾了。

 

三、故障解決方法

 

根據以上的分析,我們知道,為了能夠在KVM集群中配置DR模式的LVS集群,我們必須禁用’no-ip-spoofing’的過濾策略。

方法是:

1)執行:

 

virsh edit r2-10105

 

2)刪除以下內容:

 

<filterref filter='clean-traffic'>

<parameter name='IP'value='x.y.z.200'/>

</filterref>

 

3)重啟虛擬機。

 

4)我們采用以下的步驟抓包驗證。

 

 [root@HOST1 ~]#  tcpdump -i br0 -s 0 host 192.243.119.145 -vvv-nnn -s 0 -e

tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size65535 bytes

❶16:39:37.842828 84:78:ac:27:6c:41 > 02:00:73:b6:53:c8,ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 48, id 59437, offset 0, flags[DF], proto TCP (6), length 60)

    192.243.119.145.48377 > x.y.z.208.80:Flags [S], cksum 0x8721 (correct), seq 2886813932, win 14600, options [mss1460,sackOK,TS val 885170369 ecr 0,nop,wscale 7], length 0

❷16:39:37.842990 02:00:73:b6:53:c8 > 02:00:73:b6:53:e2,ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 48, id 59437, offset 0, flags[DF], proto TCP (6), length 60)

    192.243.119.145.48377 > x.y.z.208.80:Flags [S], cksum 0x8721 (correct), seq 2886813932, win 14600, options [mss1460,sackOK,TS val 885170369 ecr 0,nop,wscale 7], length 0

   ---以下略去其他正常數據通信

 

從❶和❷所示的以太網幀中,我們能夠看到宿主機1轉發了虛擬機Director1重寫后的以太網幀。因此,這個問題得以完美解決。

 

四、再探原理

 

通過這個故障案例,我們對KVM的網絡過濾策略有了更深的理解。那么,這些過濾策略到底是如何在系統里面生效的呢?

 

通過在宿主機上配置iptables、ebtables,宿主機能夠對虛擬機進行網絡限制。其中,iptables實現對四層TCP、UDP端口的網絡流量過濾;ebtables對二層MAC地址、三層IP地址進行過濾。如下是在宿主機1上對虛擬機進行MAC地址限定、源IP限定的規則:

 

[root@HOST1 ~]# ebtables -t nat --list

Bridge table: nat

 

Bridge chain: PREROUTING, entries: 1, policy: ACCEPT

-i vnet0 -j libvirt-I-vnet0 #宿主機vnet0入流量走libvirt-I-vnet0策略

 

Bridge chain: OUTPUT, entries: 0, policy: ACCEPT

 

Bridge chain: POSTROUTING, entries: 1, policy: ACCEPT

-o vnet0 -j libvirt-O-vnet0 #宿主機vnet0出流量走libvirt-O-vnet0策略

 

Bridge chain: libvirt-I-vnet0, entries: 9, policy: ACCEPT

-j I-vnet0-mac

-p IPv4 -j I-vnet0-ipv4-ip

-p IPv4 -j ACCEPT

-p ARP -j I-vnet0-arp-mac

-p ARP -j I-vnet0-arp-ip

-p ARP -j ACCEPT

-p 0x8035 -j I-vnet0-rarp

-p 0x835 -j ACCEPT

-j DROP

 

Bridge chain: libvirt-O-vnet0, entries: 4, policy: ACCEPT

-p IPv4 -j O-vnet0-ipv4

-p ARP -j ACCEPT

-p 0x8035 -j O-vnet0-rarp

-j DROP

 

Bridge chain: I-vnet0-mac, entries: 1, policy: ACCEPT

-s 2:0:73:b6:53:c8 -j RETURN #限定源MAC地址

-j DROP

 

Bridge chain: I-vnet0-ipv4-ip, entries: 3, policy: ACCEPT

-p IPv4 --ip-src 0.0.0.0 --ip-proto udp -j RETURN

-p IPv4 --ip-src x.y.z.200 -j RETURN #限定源IP地址

-j DROP

 

Bridge chain: O-vnet0-ipv4, entries: 1, policy: ACCEPT

-j ACCEPT

 

五、總結

 

在KVM環境中部署LVS集群時,要特別注意宿主機上iptables、ebtables對虛擬機的影響。因為此時,虛擬機並不是使用用戶態的的應用程序進行代理,而是使用了網絡地址轉換(NAT模式)、MAC地址重寫(DR模式)等“非常規”方法。

 

通過這個案例,我們同時可以知道,在遇到未知可能涉及到網絡方便的問題時,使用網絡分析技術可以提供有效的信息來幫助我們定位和排除問題。

 

閱讀原文


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM