近兩年,容器已經隨着 Docker 技術的傳播火遍全球,如今已經有愈來愈多的企業用戶在開發、測試甚至生產環境中開始採用 Docker 等容器技術。linux
然而,目前主流的 Docker 管理平臺,好比 K8S,當企業想構建一套網絡方案,須要精通 Linux 提供的各類高級網絡功能,這個技術門檻過高了。特別是對專一於業務開發的 Docker 用戶而言,這類操做每每顯得過於複雜。後端
並且,因爲在虛機中部署容器,雲平臺和 Docker 平臺都有本身的虛擬化網絡實現方案,兩者功能重疊,使用時會相互嵌套,致使的其網絡性能損耗很是嚴重,甚至達到 80%。安全
因此,雖然容器技術正在逐步被你們承認與應用,但其網絡性能以及配置的複雜程度一直都在被你們所詬病。今天的內容,將會給你們介紹一種容器部署方案,幫助你們解決網絡這個難題。服務器
首先,咱們先看看 Docker 提供了哪些網絡功能,Docker 的網絡模型是這樣的:網絡
Docker 的網絡結構分爲 3 個層次:Network、Endpoint 和 Container。對比到物理設備能夠這麼理解:Network 是交換機,Endpoint 是網卡,Container 就是服務器。架構
決定 Network 這個交換機的工做方式的組件,就是 Network Driver。經常使用的 Driver 有兩個:負載均衡
Bridge Driver分佈式
Bridge Driver 是種比較直接的方式:Bridge 指的是 Linux Kernel 實現的虛機交換機。每一個網絡在宿主機上有一個 Bridge 實例,默認是 Docker0,有對應的 IP 地址和網段,每一個 Docker 實例從網段裏面分配一個地址。結構以下:性能
在同一個 Bridge 下的 Endpoint 是一個二層網絡,要實現跨宿主機的 Endpoint 之間通訊,只能走三層網絡,也就是經過路由轉發過去。要對外提供服務,還須要對宿主機的 IP 端口作轉換(Nat)。這種狀況下主要網絡性能損失發生在端口轉換(Nat)和路由上面。測試
同時這也和青雲 SDN 1.0 裏面的基礎網絡實現方式是徹底同樣,優勢是結構簡單可靠,缺點也很明顯: 不能把多個宿主機連成一個二層網絡。這個問題會致使 Docker 實例的 IP 地址,必須跟當前宿主機定義的網段一致。若是啓動到別的宿主機上,IP 就須要更換。
Overlay Driver
Overlay Driver 的做用是把位於多個宿主機的 Docker 實例鏈接在一個虛擬的二層網絡裏面。相比 Bridge,在功能上有必定進步,本質上是一個分佈式的虛擬交換機。
舉個送快遞的例子,方便你們理解:有的公司對員工提供內部郵件的服務,位於不一樣寫字樓的員工能夠用工位號互發郵件。公司的收發室拿到郵件後,會從新再打個包,上面寫着雙方寫字樓的地址,交給真正的快遞公司去投遞。收件方的收發室會拿到郵件後,會拆掉外面的信封,把裏面的郵件按工位號送給收件的員工。
這例子裏面,工位號就是 Underlay 的地址, 寫字樓的地址是 Overlay 的地址。Docker 的這個虛擬二層網絡,就是企業內部郵件,可是真正派件的仍是快遞公司。跟普通快遞相比,多了個環節:收發室對郵件從新包裝,不只打包費時間,多的包裝也佔了重量,也就帶來了額外的性能損失。
目前,Overlay 模式的虛擬網絡應用已經很廣泛,青雲給用戶提供的虛擬二層網絡也是相同的工做原理。
Docker 目前有兩種方式部署:
今天和你們分享的就是爲何要在雲平臺上部署 Docker。
雖然看起來在公有云的虛擬機部署 Docker 的作法比較奇葩,目前也沒有公有云能讓用戶直接部署 Docker 在物理機上,固然,Softlayer 這種物理機託管的雲除外。
由於 Docker 自己的安全性還不夠讓人放心。雖然 Docker 已經有各類安全保護,包括 Namespace 提供的隔離機制、Selinux、Apparmor 等安全機制,以及最近纔有的Unprivileged Container 功能來控制 Docker 實例在宿主機上的用戶權限,可是因爲容器的本質是跟宿主機共用同一個 Linux Kernel,一旦 Kernel 自己有安全漏洞,就有可能被 Docker 用戶利用,侵入到雲平臺的物理機。
好比幾個月前發現的 COW 漏洞,就有可能讓 Docker 實例得到物理機的 Root 權限,實現容器的「越獄」。這個漏洞存在了十幾年才被人發現,徹底有可能還有不少相似漏洞存在,只是沒有被公開而已。
因此,公有云直接讓用戶在多租戶的物理機上運行 Docker,是極不安全的作法。
所以,要在公有云使用 Docker,就只有在虛擬機裏面運行 Docker 這一個選擇。那麼在公有云上部署 Docker 業務,存在哪些問題呢?其實,主要仍是性能和功能兩方面。
網絡性能
網絡虛擬化的本質是用軟件實現物理網卡和交換機的功能,所以虛擬網絡中的全部流量都會消耗 CPU 資源。
Linux 在處理網絡流量時,有幾個方面會消耗 CPU:
其中 1 和 2 佔的 CPU 消耗較高,這是由於地址轉換和路由都會對數據包的包頭作修改,並從新計算 Checksum, 並且地址轉換還須要查詢 Conntrack 的鏈接表和 IPtables 的地址轉換規則,這些功能都是全靠宿主機的 CPU 完成。
雲平臺提供的 SDN 網絡,是第一層網絡虛擬化,已形成必定的性能損失。可是能夠經過利用物理網卡的硬卸載功能,好比 Vxlan Offload, 具體包括 Gso、Gro、Rx Checksum 等在這一層減小虛擬化帶來的部分性能損失。
雖然容器自己因爲跟宿主機共享 Kernel 的這個特性,相比 VM 網絡性能更好,沒有 第 5 條的損失,可是 Docker 搭建的虛擬網絡,仍然會帶來顯著的性能損失。
同時,因爲第二層虛擬化沒法利用硬卸載功能,因此性能損失一般會高於第一層。兩層網絡虛擬化帶來的性能損耗相疊加,將顯著影響網絡性能。
舉個例子:
在上海一區(SH1A),使用 IPerf -C 命令進行的基本性能測試 (關閉雲平臺的網絡限速)結果以下:
虛擬主機之間:帶寬 9Gbps;
虛擬主機內:使用 Docker Overlay 插件的 Docker 實例之間帶寬降低爲 2.3 Gbps。
因而可知,這種使用 Docker Overlay 的方案會帶來近 3/4 的性能損耗。而若是算上對外提供服務所須要的地址轉換帶來的性能損失,總體性能損失將更爲巨大。
配置複雜
首先,Docker 自身的網絡複雜。Bridge 和 Overlay 都須要配合地址轉換功能使用,而地址轉換的規則不只多,並且複雜。
我最近遇到個私有云客戶,其在雲平臺上面部署基於 K8S 的業務系統。他們遇到一個問題,同一個宿主機的 Docker 實例之間,用 K8S 提供的業務 IP 沒法訪問,而不一樣宿主機之間用相同的 IP 訪問正常。
這個開發團隊,通宵加班好幾天,也沒搞清楚怎麼回事,來找我幫忙解決。這個問題其實是由於 K8S 少下發了一條 IPtables 規則,沒有對同宿主機的這種狀況作源地址轉換。
這個問題對熟悉 Linux 網絡功能的人來講,不是什麼難題,可是對專一於業務開發的 Docker 用戶而言,可就很難解決了。
我說這個例子的目地就是要說明,配置 Docker 虛擬網絡是件難度很高的事情。
另外一方面,要在雲平臺上面,使用 Docker 對外提供服務,還須要跟雲平臺的網絡作整合。
一般是在雲平臺的 IP 和 Docker 的 IP 之間作地址轉換。自己 Docker 實現這些功能就比較複雜,而在此基礎上,再作一層地址轉換,會帶來額外的複雜度。
使用 Docker 管理平臺的初衷是簡化產品部署,而經過這樣的方式跟雲平臺整合,卻與這一方向背道而馳。
性能問題的根源在於雲平臺和 Docker 平臺都有本身的虛擬化網絡,兩者功能重疊,使用時相互嵌套。而配置複雜的難度一個是 Docker 自身網絡複雜,另外一個方面是跟雲平臺的網絡整合也複雜。
目前青雲的 SDN 直通方案經過讓 Docker 實例掛載雲平臺提供的虛擬網卡的方式,讓 Docker 實例直接使用雲平臺的 SDN 功能,代替 Docker 的虛擬網絡。
一方面減小了第二層虛擬網絡的性能損失;另外一方面,雲平臺的 SDN 是經過 API 和控制檯封裝好的服務,Docker 直接使用就能夠了,不須要本身再配置 Docker 的網絡,因此大幅下降了使用難度。
SDN 網絡直通方案包含兩個方面:
插件已經開源,地址是 https://Github.Com/Yunify/Docker-Plugin-Hostnic
這是青雲Qingcloud 自主開發的一款 Docker 網絡插件。在啓動 Docker 實例的時候,經過該插件,能夠將虛擬主機上的綁定的多個網卡一一掛載到 Docker 實例上, 並能夠配置 IP 地址和路由。
啓動以後,Docker 實例就加入了雲平臺 SDN 提供的網絡,可以使用雲平臺全部的網絡功能。雲平臺網卡管理,就是可以讓虛擬主機掛載多個網卡。網卡對應到 Docker 的網絡組件,就是Endpoint,這個設備受雲平臺管理,底層由 SDN 內部的控制器下發規則,可使用 DHCP 管理 IP 地址,並接入全部雲平臺的網絡模塊。
相比 Docker 的網絡功能,青雲的網卡能夠提供更多的功能:
VPC
前面說過,Docker 的 Overlay 網絡其實是虛擬的二層網,而 VPC 提供的是一個虛擬的三層網。能夠理解爲一個分佈式的核心交換機。青雲的 VPC 最多能夠建立 252 個虛擬網絡,容納超過 6 萬臺虛擬主機。
就技術上來看,虛擬二層網使用 Vxlan 實現,是如今較成熟的技術。而虛擬的三層網,是 SDN 技術的一個關鍵點,由於它背後須要有個分佈式網關才能作到虛擬機數量增長時,VPC 總體網絡性能不變。
目前 SDN 廠商和技術好的雲計算公司都有各自的實現,尚未看到靠譜的開源產品可以作到。
當 Docker 掛載上青雲的網卡時,就加入了對應的 VPC,跟其餘實例連在了一塊兒。用戶能夠根據網卡對應的網絡來定義實例間是二層仍是三層聯通。
公網 IP
每一個網卡能夠綁定本身獨享的公網 IP,也可使用 VPC 共享的公網 IP 對外提供服務。公網和私網地址的轉換,由雲平臺的分佈式網關來作,不須要 Docker 配置任何 IPtables 規則。
負載均衡器
網卡能夠做爲負載均衡器的後端,以集羣的方式,對外提供高可用和高性能的服務。相比 Docker 的負載均衡器,青雲的負載均衡器有許多優勢:
給虛擬主機掛載網卡以後,須要使用到 Hostnic 插件,有 3 步:
這樣就完成了對 Docker 實例網絡的全部功能配置。
前面說的公網 IP、負載均衡器和防火牆,均可以經過青雲控制檯、SDK、 CLI 或者 API 的方式去單獨配置。對這些功能使用上有疑問的話,能夠經過工單跟咱們的工程師溝通,沒必要在死磕 Docker 那些複雜的網絡配置。
除了青雲本身研發的 Hostnic,如今已經有另一款 Docker 插件支持青雲 SDN 直通。是希雲Csphere 開發的 Qingcloud-Docker-Network,一樣也已經開源: Https://Github.Com/Nicescale/Qingcloud-Docker-Network 。
跟 Hostnic 相比,這款插件整合了青雲 API,可以在啓動 Docker 實例時,自動建立,並綁定網卡,使用起來更方便一些。
對於公有云,目前只能選擇在虛擬主機裏面使用 Docker,可是對於私有云,能夠在青雲提供的容器主機裏面部署 Docker。
容器主機的工做原理跟 Docker 同樣,都是用到了 Linux Kernel 的容器技術,可是用起來更接近虛擬主機,有着幾乎相同的功能,好比:掛載 SSH 密鑰、Web Terminal、鏡像製做、備份等功能,跟虛擬主機鏡像全兼容,還能作到在線擴容 CPU、內存、系統硬盤。
也就是說,對於私有云用戶,可使用跟公有云虛擬主機徹底同樣的操做方式,在容器主機裏面部署 Docker,從而減小 KVM 虛擬化這一層在性能上的損失,能達到接近物理機的性能。
跟直接在物理機上部署 Docker 相比,使用容器主機能夠有云平臺便捷的功能,好比秒級建立或者消毀一個容器主機。雲平臺的副本能夠保證物理機宕機後,經過離線遷移,迅速恢復業務。再加上前面說的這些雲平臺的網絡功能,爲構建用戶業務集羣,節省大量時間。同時青雲的 SDN 網絡在 Linux Kernel 上有深度優化,相比直接在物理機上使用 Docker 的 Overlay 網絡性能還會好很多。