1. 前言
Kubernetes設計了一種特別的網絡模型,其跟原生Docker網絡模型有些偏離。在這種設計中,Kubernetes定義了一個抽象概念:Pod, 每個Pod是一系列容器的集合,而且有一個共享IP,所有容器共享相同的網絡命名空間。Pod不僅可以與物理機器間通信,而且還可以使跨網絡間容器能通信。Kubernetes的這種IP-per-pod的設計思想有很多好處,比如:從端口分配、網絡、命名、服務發現、負載均衡、應用程序配置以及遷移方面來看,這種模型使得開發人員、運維人員可以把Pod當做一個虛擬機或者是物理機,有很好的後向兼容能力。當前Google在它的雲平臺GCE上實現了這種IP-per-pod模型,但是如果在本地使用Kubernetes,那就得自己實現這種模型,本文主要講述就如何使用Openvswitch GRE實現這種模型。
2. 實現方案
本文用2臺主機運行CentOS 7, 實現可如下圖描述:
2.1 安裝Docker
安裝步驟參照如下腳本:
#Docker默認配置文件 DOCKER_CONFIG=/etc/sysconfig/docker #下載最新Docker安裝文件 wget https://get.docker.com/builds/Linux/x86_64/docker-latest -O /usr/bin/docker chmod +x /usr/bin/docker #配置Docker unit文件 cat <<EOF >/usr/lib/systemd/system/docker.socket [Unit] Description=Docker Socket for the API [Socket] ListenStream=/var/run/docker.sock SocketMode=0660 SocketUser=root SocketGroup=docker [Install] WantedBy=sockets.target EOF source $DOCKER_CONFIG cat <<EOF >/usr/lib/systemd/system/docker.service [Unit] Description=Docker Application Container Engine Documentation=http://docs.docker.com After=network.target docker.socket Requires=docker.socket [Service] Type=notify EnvironmentFile=-$DOCKER_CONFIG ExecStart=/usr/bin/docker -d $OPTIONS LimitNOFILE=1048576 LimitNPROC=1048576 [Install] Also=docker.socket EOF systemctl daemon-reload systemctl enable docker systemctl start docker
2.2 安裝Openvswitch
下載Openvswitch並安裝:
wget http://cbs.centos.org/kojifiles/packages/openvswitch/2.3.1/2.el7/x86_64/openvswitch-2.3.1-2.el7.x86_64.rpm rpm -ivh openvswitch-2.3.1-2.el7.x86_64.rpm systemctl start openvswitch systemctl enable openvswitch
2.3 設置Docker默認網橋
在這裏,我們按下面的步驟新建一個Linux網橋localbr0並替換默認網橋docker0,
#停止Docker Daemon進程 systemctl stop docker.socket systemctl stop docker #設置默認網橋docker0爲down,並刪除 ip link set dev docker0 down brctl delbr docker0 #新建Linux網橋localbr0 brctl addbr localbr0 #在每臺主機上更改10.244.x.0/24,下面設置localbr0地址如: #10.224.106.127 ip addr add 10.244.1.1/24 dev localbr0 #10.224.106.128 ip addr add 10.244.2.1/24 dev localbr0 ip link set dev localbr0 up echo 'OPTIONS="--bridge localbr0 --iptables=false"'>>/etc/sysconfig/docker systemctl start docker
2.4 設置Openvswitch網橋及GRE
#新建Openvswitch網橋 ovs-vsctl add-br ovsbr #啓用SPT協議防止網橋環路 ovs-vsctl set bridge ovsbr stp_enable=true #添加ovsbr到本地localbr0,使得容器流量通過OVS流經tunnel brctl addif localbr0 ovsbr ip link set dev ovsbr up #創建GRE ovs-vsctl add-port ovsbr tep0 -- set interface tep0 type=internal #需在每個主機上修改tep0 IP地址 ip addr add 192.168.1.1/24 dev tep0 ip addr add 192.168.1.2/24 dev tep0 ip link set dev tep0 up #使用GRE隧道連接每個主機上的Openvswitch網橋 #10.224.106.127 ovs-vsctl add-port ovsbr gre0 -- set interface gre0 type=gre options:remote_ip=10.224.106.128 #10.224.106.128 ovs-vsctl add-port ovsbr gre0 -- set interface gre0 type=gre options:remote_ip=10.224.106.127 #配置路由使得跨主機間容器的通信 ip route add 10.244.0.0/16 dev tep0 #爲了使得容器訪問Internet,在兩臺主機上配置NAT iptables -t nat -A POSTROUTING -s 10.244.0.0/16 -o ens192 -j MASQUERADE
2.5 驗證
完成了以上的操作,這時以下應該能正常工作:
可以相互ping tep0的地址
[root@minion-1 ~]# ping 192.168.1.2 PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data. 64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.929 ms 64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.642 ms 64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=0.322 ms 64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=0.366 ms ^C --- 192.168.1.2 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3000ms rtt min/avg/max/mdev = 0.322/0.564/0.929/0.245 ms
可以相互ping localbr0的地址
[root@minion-1 ~]# ping 10.244.2.1 PING 10.244.2.1 (10.244.2.1) 56(84) bytes of data. 64 bytes from 10.244.2.1: icmp_seq=1 ttl=64 time=0.927 ms 64 bytes from 10.244.2.1: icmp_seq=2 ttl=64 time=0.337 ms 64 bytes from 10.244.2.1: icmp_seq=3 ttl=64 time=0.409 ms ^C --- 10.244.2.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2000ms rtt min/avg/max/mdev = 0.337/0.557/0.927/0.264 ms
兩臺主機上容器可以相互ping通
在主機10.224.106.127和10.224.106.128上執行如下命令運行一個新的容器:
docker run -ti ubuntu /bin/bash
然後10.224.106.127的容器ping 10.224.106.128的容器,
root@e38da4440eaf:/# ping 10.244.2.3 PING 10.244.2.3 (10.244.2.3) 56(84) bytes of data. 64 bytes from 10.244.2.3: icmp_seq=1 ttl=63 time=0.781 ms 64 bytes from 10.244.2.3: icmp_seq=2 ttl=63 time=0.404 ms ^C --- 10.244.2.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.404/0.592/0.781/0.190 ms
從10.224.106.128的容器ping 10.224.106.127的容器。
root@37b272af0d09:/# ping 10.244.1.3 PING 10.244.1.3 (10.244.1.3) 56(84) bytes of data. 64 bytes from 10.244.1.3: icmp_seq=1 ttl=63 time=1.70 ms 64 bytes from 10.244.1.3: icmp_seq=2 ttl=63 time=0.400 ms ^C --- 10.244.1.3 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 0.400/1.054/1.708/0.654 ms
3. 結論
本文通過Openvswitch GRE實現Kubernetes網絡模型,但是如果在大規模系統中,此方法顯得有點笨拙。例如,如果系統有n臺主機,且它們之間需要通信,則需建立n(n-1)/2條GRE隧道,雖然可以通過啓用SPT協議防止網橋環路,但維護n(n-1)/2條隧道仍然工作量很大。所以接下來考慮如何能自動化實現。
4. 參考資料
https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/design/networking.md
https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/ovs-networking.md
https://docs.docker.com/installation/centos/
https://goldmann.pl/blog/2014/01/21/connecting-docker-containers-on-multiple-hosts/
5. 作者簡介
楊章顯,現就職於Cisco,主要從事WebEx SaaS服務運維,系統性能分析等工作。特別關注雲計算,自動化運維,部署等技術,尤其是Go、OpenvSwitch、Docker及其生態圈技術,如Kubernetes、Flocker等Docker相關開源項目。Email: [email protected]