開發與維運

ECS彈性網卡+彈性公網IP配置最佳實踐之策略路由

作者:霄翎

概述

目前阿里雲ECS部分機型可以配置多張網卡(一張原生網卡+若干張彈性網卡),用來實現業務上對於系統內多網卡的需求,詳細可以參考 【新功能】彈性公網IP綁定彈性網卡新功能及最佳實踐
。在使用過程中,可能會遇到多個彈性公網IP綁定到一個ECS上的原生網卡、彈性網卡上後無法通信的問題,這個時候需要檢查系統內的路由配置和策略(policy rules)。

從route路由表說起

默認情況下,linux系統中都會有一張路由表,使用route或ip route就可以進行查看,如

 default via 172.16.127.253 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.16.112.0/20 dev eth0 proto kernel scope link src 172.16.115.242

以上起到關鍵作用的是第一行路由,它聲明瞭一條默認路由,從eth0網卡中出去,目標是網關172.16.127.253。在只有一張網卡的實例中,這樣的配置是沒有問題的,但如果有多張網卡的情況下,入流量會從不同的網卡中進入實例,但出流量都會從eth0網卡中出去(譬如從外部ping 綁定在彈性網卡上的彈性公網IP,ICMP request包會從實例的彈性網卡中進入實例,而實例回覆的ICMP reply包會從eth0中流出),導致出入路徑不一致,會造成一系列的問題,如單網卡流量瓶頸、負載不均衡等問題。

真實的路由表

在linux系統中,實際上是有255張路由表的,默認使用的是254這張路由表,使用route命令展示的即是這張表中的路由條目。除此之外的路由表我們可以對它進行適當的配置,以實現自定義或高級需求。

我們可以使用ip route list table [table index]來查看系統內的路由表條目,如

[root@xiaoling-hz-test ~]# ip route list table 254
default via 172.16.127.253 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.16.112.0/20 dev eth0 proto kernel scope link src 172.16.115.242

以上條目可以看到系統內默認的254號路由表內的條目,另外,還可以將index置為0來查看系統內所有的路由條目,這在需要循環遍歷系統內自定義路由表時非常有用。

PS. table==253這張路由表被系統默認為是default表,建議使用1-252號路由表來添加自定義的路由條目。被linux預先定義的路由表詳情可以查看系統內/etc/iproute2/rt_tables,以下是一個示例,可以看到253 - 255已經被系統定義:

# reserved values
#
255     local
254     main
253     default
0       unspec
#
# local
#
#1      inr.ruhep

策略路由

為什麼會需要多張路由表呢?這不得不提到策略路由,目前我們需要實現的功能是同進同出,保證從eth0口進來的包從eth0口出去,eth1進從eth1出,但彈性公網IP需要有一條默認路由來讓ECS可以正常訪問公網,但卻又不能直接在默認路由表裡添加兩個目標網段是0.0.0.0,分別從eth0、eth1中出去的路由,這個時候策略路由就派上用場了,我們需要根據源地址進行策略選擇。

簡單來說就是配置兩張路由表,路由表中分別有從eth0、eth1中出去的默認路由,在系統需要發包時,根據包的源IP進行選擇,eth0的源IP就從包含eth0的路由表出去,eth1的源IP就從eth1的路由表走,從而實現同進同出。

linux系統內關於策略的索引是一個無符號的32位整型數值,所以理論上策略索引的數值可以達到4294967295之多,當然通常我們只需要使用個位數的索引條目即可。

具體的一個配置

以上說的都是理論,可能會有一些虛,下面我們來實際進行一個配置。我們特意選取阿里雲官方尚未支持自動配置的鏡像Ubuntu 16.04 64位來進行配置,以下是這個場景中相關參數:

ECS實例網關地址:172.16.127.253

==原生網卡信息==
名稱:eth0
IP地址:172.16.116.38
綁定的彈性公網IP:47.99.42.x

==彈性網卡信息==
名稱:eth1
IP地址:172.16.116.39
綁定的彈性公網IP:116.62.163.x

如何獲得ECS實例完整的網卡信息

阿里雲ECS控制檯對於實例的網卡信息展示的不是很完全,建議通過API方法 DescribeNetworkInterfaces 來獲取,若沒有API調試環境,可以使用阿里雲的API Explorer來調試,非常方便,以下是一個示例 URL ,點擊後可以直接進入在線調試頁面。

檢查系統的默認配置

依次查看網卡、默認路由,可以看到系統內的配置殘缺不全:

root@iZbp14bxrlofsqs3d5dw43Z:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:0c:72:5d brd ff:ff:ff:ff:ff:ff
    inet 172.16.116.38/20 brd 172.16.127.255 scope global eth0
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 00:16:3e:10:aa:7e brd ff:ff:ff:ff:ff:ff
root@iZbp14bxrlofsqs3d5dw43Z:~# ip route list table 254
default via 172.16.127.253 dev eth0
172.16.112.0/20 dev eth0  proto kernel  scope link  src 172.16.116.38

首先編輯/etc/network/interfaces文件,在最後加上關於eth1的定義,新添加的兩行分別告訴系統在啟動時自動拉起eth1、eth1的參數配置使用DHCP協議,詳細的配置說明可以參考man interfaces:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

auto eth1
iface eth1 inet dhcp

保存後執行systemctl restart networking重啟網絡服務,可以看到eth1網卡已經配置上IP地址了:

root@iZbp14bxrlofsqs3d5dw43Z:~# ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:0c:72:5d brd ff:ff:ff:ff:ff:ff
    inet 172.16.116.38/20 brd 172.16.127.255 scope global eth0
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:16:3e:10:aa:7e brd ff:ff:ff:ff:ff:ff
    inet 172.16.116.39/20 brd 172.16.127.255 scope global eth1
       valid_lft forever preferred_lft forever

接下去就需要配置策略路由了,針對這個場景,我們定義了以下信息:

==原生網卡==
使用路由表100,策略路由優先級索引為200
添加路由的命令(網關地址根據實際情況而定):ip route add default via 172.16.127.253 dev eth0 tab 100
添加策略的命令(源IP根據實際情況而定):ip rule add from 172.16.116.38 tab 100 priority 200

==彈性網卡==
使用路由表101,策略路由優先級索引為300
添加路由的命令(網關地址根據實際情況而定):ip route add default via 172.16.127.253 dev eth1 tab 101
添加策略的命令(源IP根據實際情況而定):ip rule add from 172.16.116.39 tab 101 priority 300

執行以上命令後,系統內策略路由就已經配好了,通過相關命令查看的結果如下(已經略去無關信息):

  root@iZbp14bxrlofsqs3d5dw43Z:~# ip route list table 0
default via 172.16.127.253 dev eth0  table 100
default via 172.16.127.253 dev eth1  table 101
default via 172.16.127.253 dev eth0
172.16.112.0/20 dev eth0  proto kernel  scope link  src 172.16.116.38
172.16.112.0/20 dev eth1  proto kernel  scope link  src 172.16.116.39
root@iZbp14bxrlofsqs3d5dw43Z:~# ip rule list
0:      from all lookup local
200:    from 172.16.116.38 lookup 100
300:    from 172.16.116.39 lookup 101
32766:  from all lookup main
32767:  from all lookup default

可以看到系統中增加了table==100、101的兩張路由表,增加了200、300兩個優先級的策略,分別指定eth0、eth1出入的規則,這樣就可以做到一張網卡同進同出了。

持久化配置

以上的配置,除了網卡的IP信息可以持久化,其他的配置如路由、策略都會在重啟後失效,可以把以上命令寫到系統的配置文件中。理論上更優雅的方法是在/etc/sysconfig/network-scripts/ (CentOS) 、 /etc/network/ (Ubuntu)目錄下將命令寫到特定的文件中來解決這個問題,但無奈無法測試所有的場景,我採取了比較“暴力”的方法來統一的解決:將命令寫到/etc/rc.local文件中,可以無視發行版。

比如本文中的場景,就可以將四條ip route/ip rule命令添加到rc.local中:

root@iZabcdeZ:~# vim /etc/rc.local

ip route add default via 172.16.127.253 dev eth0 tab 100
ip rule add from 172.16.116.38 tab 100 priority 200
ip route add default via 172.16.127.253 dev eth1 tab 101
ip rule add from 172.16.116.39 tab 101 priority 300

阿里雲原生的做法

查看阿里雲官方關於配置 ECS 實例的彈性網卡的說明,以下幾種鏡像是可以直接支持不需要手工配置:

CentOS 7.3 64 位
CentOS 6.8 64 位
Windows Server 2016 數據中心版 64 位
Windows Server 2012 R2 數據中心版 64 位

實際上CentOS系統內部也是採用了類似的策略來實現的,使用ip route和ip rule命令可以查看到響應的策略,只是路由表索引和策略路由的優先級序號有些許不同,各位可以實際驗證一下。

參考文獻

https://www.linuxjournal.com/article/7291

Leave a Reply

Your email address will not be published. Required fields are marked *