Openvswitch GRE實現Kubernetes網絡模型

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, 實現可如下圖描述:w7djVFg.png

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 驗證

完成了以上的操作,這時以下應該能正常工作:

  1. 可以相互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
  2. 可以相互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
  3. 兩臺主機上容器可以相互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. 參考資料

  1. https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/design/networking.md

  2. https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/ovs-networking.md

  3. https://docs.docker.com/installation/centos/

  4. 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]


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章