用openvswitch配置跨節點的docker網絡環境


在一篇隨筆中,我們已經嘗試了在不依賴工具的情況下設置docker的ip,連我都想吐槽,MD單機都這么麻煩,在多機的環境中豈不是要了我的小命!

本文就是為了多機環境中各個節點的容器通信而做的,網絡拓朴如下,這里用到了openvswitch工具。

 

openvswitch為我們建立一個擴展到三層網絡的網橋,我們知道vlan是不能跨子網的,openvswitch利用了隧道技術,將二層的報文用三層的協議(udp/sdn)重新封裝,從而實現二層網絡在三層中進行擴展:如下圖:

 

openvswitch是一個比較直觀的解決方案,它暴露了足夠多的細節給我們,生產環境中定位問題也是比較方便的。

openvswitch的安裝

首先在centos7上安裝openvswitch(很可惜yum源中並沒有編譯好的rpm,但debian是有的),我們編譯的時候生成rpm而不是利用make install的方式,因為openvswitch的啟動是比較麻煩的(可以讀一下INSTALL.md),生成rpm然后安裝rpm的方式在系統中添加了啟動和停止服務,使用起來很方便。

下面是安裝過程,基本是INSTALL.md的翻譯,但INSTALL.md寫得有點冗長,有細節問題會對我們的編譯過程造成一些干擾。

1、下載openvswitch的源碼,下載release版本的openvswitch源碼可以減少很多麻煩。

wget http://openvswitch.org/releases/openvswitch-2.5.0.tar.gz

2、建立rpmbuild結構(這里其實只需要建立$HOME/rpmbuild/SOURCES目錄即可,其它的目錄可以在rpmbuild執行過程生成的)

cp openvswitch-2.5.0.tar.gz $HOME/rpmbuild/SOURCES

3、安裝編譯所需要的依賴包:

   yum install gcc make python-devel openssl-devel kernel-devel graphviz \
       kernel-debug-devel autoconf automake rpm-build redhat-rpm-config \
       libtool

4、檢查內核開發kernel-devel源碼的位置是否正確:

ls /lib/modules/$(uname -r) -ln

從上圖可以看出,build是一個無效的稱號鏈接,刪除這個鏈接,重新鏈接到正確目錄:

rm /lib/modules/$(uname -r)/build
ln -s /usr/src/kernels/3.10.0-327.13.1.el7.x86_64 /lib/modules/$(uname -r)/build

5、在任意目錄下解壓開源碼,進入源碼目錄:

tar -zxvf openvswitch-2.5.0.tar.gz
cd openvswitch-2.3.2

6、執行rpmbuild生成rpm安裝包:

rpmbuild -bb --without check rhel/openvswitch.spec

--without check表明不運行測試。

另外我們可以不需要編譯內核模塊,這樣子,報文會發到用戶空間由程序去處理,這樣子效率會有所下降,但對內核動手畢竟是一件比較危險又麻煩的事。SO。。。

7、最后安裝我生成的rpm包:

yum localinstall $HOME/rpmbuild/RPMS/openvswitch-2.5.0-1.x86_64.rpm

 

建立vxlan拓朴

下面利用openvswitch建立我們所需要的vxlan網絡拓朴:

1、在192.168.1.102執行:

# 有錯誤則停止執行
set -e
# 創建一個openvswitch bridge
ovs-vsctl add-br ovs-br0
# 添加一個到192.168.1.108的接口
ovs-vsctl add-port ovs-br0 vxlan-port-to-192.168.1.108 -- set  interface vxlan-port-to-192.168.1.108 type=vxlan option:remote_ip="192.168.1.108"

# 創建一對虛擬網卡veth
ip link add vethx type veth peer name vethContainer

# sleep 3 seconds to wait for the completion of previous work.
sleep 3

# 將vethx接入到ovs-br0中
ovs-vsctl add-port ovs-br0 vethx
ifconfig vethx up

# 啟動docker容器,使用--net=none策略
export containerID=$(docker run -tid --net=none ubuntu:latest /bin/bash)
export pid=$(docker inspect -f "{{.State.Pid}}" ${containerID})

echo containerID=${containerID}
echo pid=${pid}

# 如果net namespace目錄沒有創建則新建一個
if [ ! -d "/var/run/netns" ]; then
  mkdir -p /var/run/netns
fi

# 將docker容器使用的net namespace 打回原形
ln -s /proc/${pid}/ns/net /var/run/netns/${pid}
ip netns list

# 將vethContainer加入到容器的net namespace中
ip link set vethContainer netns ${pid}

# 配置vethContainer接口
ip netns exec ${pid} ifconfig vethContainer 192.168.100.100/24 up
ip netns exec ${pid} ifconfig -a

2、同樣在192.168.1.108上執行:

# 有錯誤則停止執行
set -e
# 創建一個openvswitch bridge
ovs-vsctl add-br ovs-br0
# 添加一個到192.168.1.102的接口
ovs-vsctl add-port ovs-br0 vxlan-port-to-192.168.1.102 -- set  interface vxlan-port-to-192.168.1.102 type=vxlan option:remote_ip="192.168.1.102"

# 創建一對虛擬網卡veth
ip link add vethx type veth peer name vethContainer

# sleep 3 seconds to wait for the completion of previous work.
sleep 3

# 將vethx接入到ovs-br0中
ovs-vsctl add-port ovs-br0 vethx
ifconfig vethx up

# 啟動docker容器,使用--net=none策略
export containerID=$(docker run -tid --net=none ubuntu:latest /bin/bash)
export pid=$(docker inspect -f "{{.State.Pid}}" ${containerID})

echo containerID=${containerID}
echo pid=${pid}

# 如果net namespace目錄沒有創建則新建一個
if [ ! -d "/var/run/netns" ]; then
  mkdir -p /var/run/netns
fi

# 將docker容器使用的net namespace 打回原形
ln -s /proc/${pid}/ns/net /var/run/netns/${pid}
ip netns list

# 將vethContainer加入到容器的net namespace中
ip link set vethContainer netns ${pid}

# 配置vethContainer接口
ip netns exec ${pid} ifconfig vethContainer 192.168.100.101/24 up
ip netns exec ${pid} ifconfig -a

測試:

192.168.1.102上的容器:

192.168.1.108上的容器:


免責聲明!

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



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