Rancher網絡全解讀

本文中,咱們首先將Rancher部署到EC2實例上,而且添加新的主機,以後用Rancher的Catalog啓動了RocketChat應用,緊接着對運行中的容器的網絡接口和其餘屬性的進行了分析。git

同時,咱們簡要介紹了Rancher的Overlay網絡和運行在Network Agent中的輔助服務進程,並經過上面實踐中收集的信息構建了Rancher集羣中網絡通訊的概覽圖。github

與此同時,還特別介紹了使用IPSec實現主機間的安全通訊。docker

Rancher 是一個容器管理的完整解決方案,而且即將成爲一個完整的容器管理平臺。咱們對在本身平臺上如何處理容器間的網絡進行了審慎的思考,並打算用一個簡單的例子和你們分享一下Rancher中的網絡。Rancher既能夠被部署在單機,也能被擴展到數千個節點,在這篇文章中咱們只用少許的主機和容器進行討論。ubuntu

配置並啓動一個容器化的應用

首先咱們要配置咱們的基礎設施,本文使用的是AWS。咱們先在EC2上用下面的命令安裝Docker而且啓動Rancher部署Master節點:安全

curl -sSL https://get.docker.com | sh - && sudo docker run -d --restart=always -p 8080:8080 rancher/server

Rancher的server在52.40.47.157:8080上被建立好了(須要注意的是:文中涉及的IP地址指向的AWS實例已經在發文的時候被銷燬了,文中所列IP僅做示例使用)。經過EC2的console,咱們再新增兩個主機——H1和H2,用來跑咱們的應用程序容器。下圖展現了咱們主機的邏輯拓撲關係:一個節點用來跑Rancher的Server,另外兩個跑Rancher agent:bash

圖片描述

爲了方便描述容器間的網絡,咱們須要先啓動一個容器化的應用服務。用Rancher的Catalog建立應用很是方便,這裏咱們選擇Rocket Chat。Rocket Chat的應用模板有三個容器鏡像組成,分別是:mongo、rocketchat和hubot。啓動以後Rocket Chat被分配到:52.11.188.233:3000(關於更詳細的關於Rancher Catalog的攻略能夠閱讀這裏:http://docs.rancher.com/ranch...)。微信

探索基礎設施

Rocket Chat跑起來後,咱們用Rancher UI來對H1和H2的狀況一探究竟。點擊Infrastructure標籤頁看看有哪些容器跑在宿主機上:網絡

圖片描述

圖中能夠看出,rocketchat容器被調度到H1上了,剩下的兩個容器:mongo和hubot被調度到H2上。截圖中咱們還能看到每一個節點都運行着一個network agent(注意:只有當有容器被調度到當前宿主機後,network agent纔會被建立)。各個容器的IP地址如截圖中所示——這些IP對於咱們後面討論很重要。app

咱們能夠下載machine config文件以得到主機更詳細的信息:ssh

圖片描述

解壓下載下來的machine configs以後,咱們能夠找到主機的私鑰和公鑰以及一些其餘相關的配置文件。用私鑰咱們ssh到主機。在每臺主機上咱們執行ifconfig列出主機IP和網絡接口。下面是在H1上的結果(精簡後的),能夠看到docker0網橋的IP(172.17.0.1)和eth0接口地址(172.31.38.255):

`ubuntu@leo-alpha-h1:~$ ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:64:4e:c0:c6
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:64ff:fe4e:c0c6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1114933 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1437072 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:198587596 (198.5 MB)  TX bytes:1813282482 (1.8 GB)
eth0      Link encap:Ethernet  HWaddr 02:b8:4d:31:40:f3
          inet addr:172.31.39.255  Bcast:172.31.47.255  Mask:255.255.240.0
          inet6 addr: fe80::b8:4dff:fe31:40f3/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:2187296 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1382626 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
         RX bytes:2627031496 (2.6 GB)  TX bytes:277190533 (277.1 MB)`

在H2上重複上面的過程,得到類似的結果:docker0的IP是172.17.0.1,物理網卡eth0的地址是172.31.38.133。

接下來,咱們深挖每臺主機上運行的容器的狀態並查看每一個網絡接口上的IP地址。在H1上咱們用sudo docker ps 和 sudo docker exec:

ubuntu@leo-alpha-h1:~$ sudo docker ps | awk '{print $1"\t"$2}'
CONTAINER    ID
b6a27f5fd2fe rocketchat/rocket.chat:latest
f0cd5839d719 rancher/agent-instance:v0.8.1
132d6ad0c6b9 rancher/agent:v1.0.1

ubuntu@leo-alpha-h1:~$ sudo docker exec -it b6a27f5fd2fe /bin/bash
rocketchat@b6a27f5fd2fe:/app/bundle$ ip addr
17: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:14:82:66:7d:fd brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.5/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet 10.42.64.98/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::14:82ff:fe66:7dfd/64 scope link
       valid_lft forever preferred_lft forever
ubuntu@leo-alpha-h1:~$ sudo docker exec -it f0cd5839d719 /bin/bash
root@f0cd5839d719:/# ip addr
11: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:14:82:82:b0:68 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet 10.42.162.246/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet 169.254.169.250/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::14:82ff:fe82:b068/64 scope link
       valid_lft forever preferred_lft forever

在H2上重複上述過程,咱們獲得了在H1和H2上運行着的容器的信息:

HOST Container Name MAC Address IP addresses
H1 rocket.chat 02:14:82:66:7d:fd 172.17.0.5/16
10.42.64.98/16
H1 agent-instance 02:14:82:82:b0:68 172.17.0.2/16
10.42.162.246/16
169.254.169.250/32
H2 hubot 02:14:82:36:a4:6c 172.17.0.5/16
10.42.42.48/16
H2 mongo 02:14:82:2d:a0:55 172.17.0.4/16
10.42.148.239/16
H2 agent-instance 02:14:82:ab:9d:5d 172.17.0.2/16
10.42.69.59/16
169.254.169.250/32

從上表中咱們發現每一個容器都有一個網絡接口eth0。除此以外,Rancher的network agent容器(上表中的agent-instance)用三個IP地址:一個屬於Docker的子網(172.17.X.X),一個屬於Rancher的子網(10.42.X.X),以及第三個屬於鏈路本地地址子網(169.254.X.X)。其它的應用服務容器(hubot、mongo、rocketchat)每一個容器有兩個IP地址,一個屬於Docker子網,另外一個屬於Rancher的子網。

Hops and Traceroutes

讓咱們繼續瞭解下Rancher中容器間的數據通訊。從mongo 容器 ping hubot 容器(這倆是在同一臺宿主機上):

root@ad4e749d2658:/# ping -c4 hubot
PING hubot.rocket-chat.rancher.internal (10.42.42.48): 48 data bytes
56 bytes from 10.42.42.48: icmp_seq=0 ttl=64 time=0.041 ms
56 bytes from 10.42.42.48: icmp_seq=1 ttl=64 time=0.046 ms
56 bytes from 10.42.42.48: icmp_seq=2 ttl=64 time=0.075 ms
56 bytes from 10.42.42.48: icmp_seq=3 ttl=64 time=0.060 ms
--- hubot.rocket-chat.rancher.internal ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.041/0.055/0.075/0.000 ms
root@ad4e749d2658:/#

網絡從mongo容器可達hubot容器,從traceroute的結果也能夠確認二者直接只有一跳:

root@ad4e749d2658:/# traceroute hubot
traceroute to hubot (10.42.42.48), 30 hops max, 60 byte packets
 1  ip-10-42-42-48.us-west-2.compute.internal (10.42.42.48)  0.029 ms  0.012 ms  0.015 ms
root@ad4e749d2658:/#

咱們再看下從mongo容器到rocketchat容器的traceroute結果(二者在不一樣的主機上):

root@ad4e749d2658:/# traceroute rocketchat
traceroute to rocketchat (10.42.64.98), 30 hops max, 60 byte packets
 1  * * *
 2  ip-10-42-162-246.us-west-2.compute.internal (10.42.162.246)  1.391 ms  1.229 ms  1.168 ms
 3  ip-10-42-64-98.us-west-2.compute.internal (10.42.64.98)  1.137 ms  1.108 ms  1.086 ms
root@ad4e749d2658:/#

上面的結果中能夠看出從mongo到rocketchat容器有三跳,而且中間通過了IP地址爲10.42.162.246的網絡,這個正是在H1上運行着的network agent的地址。

Mongo容器中的ARP Table和IPSec

咱們從mongo容器中看下此時的ARP table:

root@ad4e749d2658:/# cat /proc/net/arp
IP address HW type Flags HW address Mask Device
169.254.169.250 0x1 0x2 02:14:82:ab:9d:5d * eth0
10.42.64.98 0x1 0x2 02:14:82:ab:9d:5d * eth0
10.42.69.59 0x1 0x2 02:14:82:ab:9d:5d * eth0
10.42.42.48 0x1 0x2 02:14:82:36:a4:6c * eth0
172.17.0.1 0x1 0x2 02:42:6c:a6:5e:b8 * eth0
root@ad4e749d2658:/#

在ARP table中rocketchar容器的IP地址10.42.64.98的MAC地址是02:14:82:ab:9d:5d,這和在H2上運行着的network agent eth0的MAC地址是同樣的。

讓咱們看下IPSec的信息:

root@9cdde771152c:/# swanctl --list-conns
conn-52.11.188.233:
  local:  %any
  remote: 52.11.188.233
  local pre-shared key authentication:
  remote pre-shared key authentication:
  child-52.11.188.233: TUNNEL
    local:  0.0.0.0/0
    remote: 0.0.0.0/0
root@9cdde771152c:/#

從結果中咱們能夠看出H2和H1之間有一條加密的通訊通道52.11.188.233。上述結果的邏輯關係可由下圖所示:
圖片描述

Rancher中的Overlay網絡

咱們經過查看H1和H2上容器的IP地址能夠看出,Docker分配的IP地址在不一樣的主機上並非惟一的。例如,相同的IP地址172.17.0.5在H1上分配給了rocketchat容器,而在H2上則被分配給了hubot容器,因此單獨使用Docker分配的IP不能得到惟一的地址。爲了解決這個問題,Rancher給集羣中運行着的每一容器分配了一個惟一的IP地址,本文例子中的地址是從從ranher的默認子網10.42.0.0/16分配而來。

IPSec

在Rancher看來,安全性是頭等重要的事情!根據Rancher的設計,Rancher的集羣的環境既能夠公有云也能夠是私有云,因此就不能對主機間的通信信道作任何假設。咱們但願從主機流出的數據是安全的,所以咱們選擇用IPSec去構建主機間的完整網絡拓撲。雖然這會帶來一些性能上的影響,可是能夠確保Rancher的網絡默認是安全的。將來的版本里咱們可能會提供選項關閉IPsec。

Rancher用strongSwan來配置IPSec。其中strongSwan的組件Charon daemon用來實現IKEv2協議。若是想要看完整的拓撲細節,咱們能夠用命令swanctl:

root@f0cd5839d719:/# swanctl --list-sas
conn-52.11.198.155: #71, ESTABLISHED, IKEv2, 2146471635b90a25:1dc18102c0c48357
  local  '172.17.0.2' @ 172.17.0.2
  remote '172.17.0.2' @ 52.11.198.155
  AES_CBC-128/AES_XCBC_96/PRF_AES128_XCBC/MODP_2048
  established 524s ago, rekeying in 12694s
  child-52.11.198.155: #1, reqid 1234, INSTALLED, TUNNEL-in-UDP, ESP:AES_CBC-128/HMAC_SHA1_96
    installed 459878s ago
    in  cb2952a7,      0 bytes,     0 packets
    out c0992075,      0 bytes,     0 packets
    local  0.0.0.0/0
    remote 0.0.0.0/0
conn-52.11.198.155: #70, ESTABLISHED, IKEv2, ff2a5d9495f14efe:dda2d2a6df6a1cf3
  local  '172.17.0.2' @ 172.17.0.2
  remote '172.17.0.2' @ 52.11.198.155
  AES_CBC-128/AES_XCBC_96/PRF_AES128_XCBC/MODP_2048
  established 8076s ago, rekeying in 5913s
  child-52.11.198.155: #2, reqid 1234, INSTALLED, TUNNEL-in-UDP, ESP:AES_CBC-128/HMAC_SHA1_96
    installed 459859s ago
    in  cf604805, 13790077094 bytes, 11532487 packets
    out cb46151e, 776570467 bytes, 9019180 packets
    local  0.0.0.0/0
    remote 0.0.0.0/0

Network Agent 服務

若是在Network Agent容器中列舉全部在跑的進程,咱們能夠看到幾個關鍵的服務在運行:rancher-dns,rancher=net等。rancher-net進程是Rancher網絡服務的核心,它的做用是用strongSwan 和 charon建立IPSec網絡。rancher-net的源代碼能夠在https://github.com/rancher/ra...查看。相似的,rancher-dns服務的職責是解析容器的名字和IP地址,其代碼能夠在https://github.com/rancher/ra...查看。

經過應用容器內的/etc/resolv.conf文件咱們能夠看到容器的nameserver指向NetworkAgent的地址169.254.169.250。

rocketchat@b6a27f5fd2fe:/app/bundle$ cat /etc/resolv.conf
search us-west-2.compute.internal rocket-chat.rancher.internal rocketchat.rocket-chat.rancher.internal rancher.internal
nameserver 169.254.169.250

總結

本文中,咱們首先將Rancher部署到EC2實例上,而且添加新的主機,以後用Rancher的Catalog啓動了RocketChat應用,緊接着對運行中的容器的網絡接口和其餘屬性的進行了分析。

同時,咱們簡要介紹了Rancher的Overlay網絡和運行在Network Agent中的輔助服務進程,咱們經過上面實踐中收集的信息構建了Rancher集羣中網絡通訊的概覽圖。

與此同時,還特別介紹了使用IPSec實現主機間的安全通訊。

接下來......

Rancher中即將到來的幾點對於網絡的改進:

採用CNI/libnetwork 接口

目前網路中因爲給每一個容器引入了第二個IP地址,對於一些只能使用網卡第一個IP地址的應用帶來了一些問題。咱們打算改用CNI/libnetwork的方案,這樣能夠保證容器只有的默認網絡接口只有一個IP地址。於此同時,用戶也能夠方便的使用社區中不少其餘的網絡技術。

VXLAN支持

對於Rancher原生網絡,咱們打算除了IPSec外添加對VXLAN的支持。

多網絡

在接下來的發行版中,咱們打算爲每個Rancher支持的環境提供多個相互之間隔離的網絡。

期待您的反饋!

但願這篇文章能夠對您深刻了解Rancher的網絡提供有價值的信息。一如既往,您的任何問題和困惑均可以經過論壇 https://forums.rancher.com 或者微信公衆號(@RancherLabs )聯繫咱們,咱們的社區有裏一羣優秀和充滿激情的小夥伴期待與您的溝通!

相關文章
相關標籤/搜索