注:本篇僅僅是對各個網絡方案的簡介和思考。須要深刻學習如何部署和使用的同窗請自行度娘~docker
docker的使用者十分普遍,不止有網易蜂巢,daocloud,時速雲這類的已經成熟化的公有云服務,許多中小型企業內部也在試圖將docker容器應用到內部的運維工做中。網絡
在成熟的容器服務架構中,每每會依賴IaaS層去實現更好的隔離效果,一個很明顯的例子就是網絡的連通性和隔離性。許多企業使用neutron做爲這方面的支持而且能得到不錯的效果。架構
而中小型企業內部,甚至一些我的用戶的docker環境就不多考慮租戶隔離了,連通性和性能是這類用戶的至高需求。
好比下面這段對話:
「咱們部門這套業務是基於dubbo的架構來開發的,如今其中的服務A要放大家容器環境裏面跑。」
「能夠啊,來來來,我幫你打鏡像,我幫你跑,要幾個實例?OK沒問題。」
「大家容器集羣裏的服務,咱們的dubbo註冊中心都訪問不到啊!搞什麼鬼?」
「很差意思很差意思,咱們的容器IP是虛擬的IP,你無法主動訪問咱們的。不過咱們用了k8s,能夠把整個服務以一個IP:port的形式提供給註冊中心,你看咱們還幫大家作了負載均衡。」
「咱們不須要大家幫咱們作負載均衡,咱們就想把容器當虛擬機同樣用嘛~」
「這...」負載均衡
實際上,對於每個初步接觸docker的人來講,網絡是絕對的痛點,要搭建一套能讓容器跨機器的集羣,是玩轉容器,建設CaaS的第一步。這裏簡單介紹一下幾種使用較爲廣泛的容器網絡方案,並詳細講述筆者在「遠古時期」的網絡方案解決思路。運維
容器直接使用宿主機的網絡配置,包括網卡,路由等,這種方案下,從網絡層面來看,容器就不是容器了,只是一個宿主機上的進程(端口)而已。
使用這種模式的性能損耗最少(直接用宿主機的網卡,能有什麼損耗)。可是除非在容器中咱們作好端口的自動化配置,不然端口被佔用了,容器就啓動不了。分佈式
flannel已經日趨成熟,從本來的udp,vxlan支持,到後來的aws,host-gw,gce網絡。這裏主要說udp,vxlan,host-gw。
udp和vxlan在flannel中其實只是封裝協議的不一樣而已。筆者瞭解很少,不敢多作解釋,不過這兩種方式的性能實際上是差很少的(不少人會以爲vxlan性能更好)。flannel實現的是一個三層網絡。可是udp,vxlan協議是經過隧道方式進行跨機互聯,簡單地說就是:
容器a的數據包pkg->宿主機A的docker0->路由到宿主機A的flannel0網卡->被封裝->宿主機A的物理網卡->宿主機B的物理網卡->路由到宿主機B的flannel0網卡->被解封->經過暴露出來的目的容器IP找到docker0->docker0轉給容器的虛擬網卡微服務
封裝解封的過程致使flannel會有20-30%的損耗。工具
host-gw是一個比較新鮮的方式,在slaver節點屬於同一個二層網絡,且能夠自由配置slaver節點網絡的前提下,咱們使用host-gw,會使得slaver節點上建立出一系列路由規則,經過這套路由規則,將容器發出的數據包轉發給相應的機器。這種模式性能會更好。
flannel的主要缺點在於,既沒有租戶隔離(即:一套環境裏,每個容器均可以訪問到其餘任何容器),也沒有對外開放(集羣外沒有搭建flannel的機器ping不通容器)。性能
calico是一種容器級路由和防火牆工具,它可以在容器級別上爲每一個容器實例或k8s的Pod實例指定訪問規則,達到服務間可控的訪問。
Calico的原理是經過修改每一個主機節點上的iptables和路由表規則,實現容器間數據路由和訪問控制,並經過Etcd協調節點配置信息的。所以Calico服務自己和許多分佈式服務同樣,須要運行在集羣的每個節點上。
calico已經併入了k8s的CNI插件。在每個slaver節點上啓動一個calico容器,去劫持docker的建立命令,接管容器網絡的配置。
calico吸引人的地方在於:他有一套本身的管理體系,給不一樣的子網絡增長了標籤,能夠經過這種方式實現容器網絡的隔離;同時業內認爲他的性能也是很好的,基本接近裸機的網絡性能,然而筆者在本身的環境中測試了幾回,效果並不盡如人意,。學習
接下來講下橋接+IPAM模式。這個方案針對的是一種比較特殊的使用場景:
docker有許多用法,微服務是其中一種,經過docker技術圈內愛好者的交流,咱們瞭解到確實有一些企業試圖,或者已經將容器當作虛擬機在用。上文中的對話就是這個使用場景之一,這種場景下的網絡問題總結爲:同一個網絡環境中的機器裏,非docker機器主動鏈接docker機器上的容器是連不通的。
解決方法:
1.給這個網絡環境中非docker的機器也部署虛擬網絡,將flannel,calico這類組件在全網絡範圍內作分佈式的部署。(考慮到機器數量,可能存在的VM,VM會有起停操做,這個方案基本不可行)
2.給容器一個和宿主機器同一層網絡的IP,即二層網絡IP,路由到宿主機的物理網卡,進行轉發。
咱們知道docker1.9之後增長了network特性,docker daemon能夠本身建立一個network,經過選擇network給容器配置網絡。
在二層網絡的基礎上,咱們在宿主機創建一個網橋,橋接了物理網卡和docker network(固然了type必須是bridge)。設置好路由規則和gateway,docker容器建立時橋接到相應的network上,就能夠正常地訪問二層網絡內的任何機器/容器。
一樣的,由於這種方式下容器建立後IP是一個二層網絡內的IP,因此外部機器能夠很方便地訪問容器。這是一種全暴露的網絡模式。作到了徹底的連通,但沒辦法作到網絡的隔離。
那IPAM又是什麼鬼?
假設這種狀況:橋接模式下,容器和宿主機是同一個網段,好比172.16.1.0/24,假設該網段中的.1~.10都是宿主機,咱們在.1的宿主機上建立的容器,其IP一定是172.16.1.2,172.16.1.3,...會發現容器的IP和宿主機重複了。這就麻煩了,要麼咱們就連不上容器,要麼咱們就連不上IP爲172.16.1.2的宿主機。(簡單地說下緣由:每一個宿主機彼此並不知悉對方的IP和MAC信息,咱們建立的那個網橋也沒有這方面的記錄,容器啓動時,網橋上已經記錄了本機的IP:172.16.1.1,但沒有記錄172.16.1.2,因此就會給容器分配172.16.1.2這個IP)
那就開發一個服務用於管理IP吧,docker原生支持network plugin,其中一個插件就是IPAM,即ip分配管理服務。docker network建立/銷燬容器時會使用IPAM去申請/釋放一個合法的IP。若是沒有指定IPAM插件,docker daemon會自動配置的網段中選一個IP,其邏輯是按數字從小到大進行分配。
咱們開發一個IPAM,經過IPAM來進行IP的申請和釋放,並在整個集羣中創建一個IP的管理中心,維護整個容器集羣的IP資源。保證一個IP只能同時被最多一個容器使用。
這種方案的性能看起來應該是和flannel host-gw,calico差很少的,由於其本質仍是路由轉發,不一樣之處是給容器分配了二層網絡IP,全部容器都暴露了,所以這種模式下網絡就難以作租戶隔離(容器更像一個瘦VM了~),而這種狀況下,dubbo的服務能夠直接在容器上部署,k8s的service特性,kube-proxy組件基本能夠酌情棄用。
綜上所述:
展望:calico可能會是最適合容器雲的網絡方案,由於租戶的網絡隔離是生產化過程當中絕對不可缺乏的。若是僅在內部小規模使用,追求簡單配置,可使用flannel,若是將容器vm化,能夠考慮使用橋接+ipam。