負載平衡是現代分佈式應用程序的主要要求。 1.12中引入的Docker Swarm模式具有本機內部和外部負載平衡功能,這些功能同時利用了iptables和ipvs,這是Linux內核內部的傳輸層負載平衡。
服務發現
Docker使用嵌入式DNS爲在單個Docker Engine上運行的容器和在Docker Swarm中運行的任務提供服務發現。 Docker Engine有一個內部DNS服務器,可爲用戶定義的網橋,覆蓋和MACVLAN網絡中主機上的所有容器提供名稱解析。每個Docker容器(或Swarm模式下的任務)都有一個DNS解析器,可將DNS查詢轉發到充當DNS服務器的Docker引擎。然後,Docker Engine檢查DNS查詢是否屬於請求容器所屬的網絡上的容器或服務。如果是,則Docker Engine在其鍵值存儲中查找與容器,任務或服務的名稱匹配的IP地址,並將該IP或服務虛擬IP(VIP)返回給請求者。
服務發現是網絡範圍的,這意味着只有同一網絡上的容器或任務才能使用嵌入式DNS功能。不在同一網絡上的容器無法解析彼此的地址。此外,僅在特定網絡上具有容器或任務的節點會存儲該網絡的DNS條目。這樣可以提高安全性和性能。
如果目標容器或服務與源容器不在同一個網絡上,則Docker Engine將DNS查詢轉發到配置的默認DNS服務器。
在此示例中,有兩個容器的服務稱爲myservice。 在同一網絡上存在第二個服務(client)。 client對docker.com和myservice執行兩個curl操作:
DNS查詢由客戶端針對docker.com和myservice發起。
- 容器的內置解析器攔截127.0.0.11:53上的DNS查詢,並將其發送到Docker Engine的DNS服務器。
- myservice解析爲該服務的虛擬IP(VIP),該IP在內部對各個任務IP地址進行負載均衡。 容器名稱也將被解析,直接解析爲其IP地址。
- docker.com作爲mynet網絡中的服務名稱不存在,因此該請求將轉發到配置的默認DNS服務器。
內部負載平衡
在Docker Swarm集羣中創建服務時,會自動爲它們分配一個虛擬IP(VIP),該IP是服務網絡的一部分。 解析服務名稱時,將返回VIP。 到該VIP的流量將自動通過覆蓋網絡發送到該服務的所有正常任務,避免了任何客戶端負載平衡,因爲只有單個IP返回給客戶端。 Docker負責路由,並在正常運行的服務任務之間平均分配流量。
下面演示一個如何查看虛擬ip
# Create an overlay network called mynet
$ docker network create -d overlay mynet
a59umzkdj2r0ua7x8jxd84dhr
# Create myservice with 2 replicas as part of that network
$ docker service create --network mynet --name myservice --replicas 2 busybox ping localhost
8t5r8cr0f0h6k2c3k7ih4l6f5
# See the VIP that was created for that service
$ docker service inspect myservice
...
"VirtualIPs": [
{
"NetworkID": "a59umzkdj2r0ua7x8jxd84dhr",
"Addr": "10.0.0.3/24"
},
DNS循環(DNS RR)負載平衡是服務的一種負載平衡選項(使用--endpoint-mode配置)。 Docker DNS服務器以循環方式將服務名稱解析爲單個容器IP。
外部負載平衡(Docker路由網格)
在創建或更新服務時,可以使用--publish標誌在外部公開服務。以Docker Swarm模式發佈端口意味着集羣中的每個節點都將監聽該端口。但是,如果服務的任務不在該端口上正在偵聽的節點上怎麼辦?
這是路由網格發揮作用的地方。路由網格是Docker 1.12中引入的一項功能,該功能結合了ipvs和iptables來創建功能強大的集羣範圍傳輸層(L4)負載均衡器。允許所有Swarm節點接受連接。當任何Swarm節點接收到發往正在運行的服務的已發佈TCP / UDP端口的流量時,它將使用稱爲入口(ingress)網絡將其轉發到服務的VIP。入口(ingress)網絡的行爲與其他覆蓋網絡相似,但其唯一目的是將流量從外部客戶端傳輸到羣集服務,基於VIP的內部負載平衡。
啓動服務後,將其映射到任何或所有Docker Swarm節點,無需擔心容器在何處運行,因爲集羣中的所有節點看起來都具有路由網格路由功能。
#Create a service with two replicas and export port 8000 on the cluster
$ docker service create --name app --replicas 2 --network appnet -p 8000:80 nginx
- 創建具有兩個副本的服務,並將其從外部映射到端口8000。
- 路由網格在羣集中的每個主機上公開端口8000。
- 前往該應用的流量可以訪問任何主機。 在這種情況下,外部LB將流量發送到沒有服務副本的主機。
- 內核的IPVS負載平衡器將入口(ingress)覆蓋網絡上的流量重定向到正常的服務副本。
ipvs
ipvs稱之爲IP 虛擬服務器 (IP Virtual Server,簡寫爲IPVS)。是運行在 LVS 下的提供負載平衡功能的一種技術。 LVS (Linux Virtual Server),虛擬服務器是一個高度可擴展性和高可用性的服務器,建立在一個集羣的服務器中。服務器集羣的架構對用戶是完全透明的,並且用戶使用起來感覺它只有一個高性能 虛擬服務器 。
IPVS基本上是一種高效的Layer-4交換機,它提供 負載平衡 的功能。當一個TCP連接的初始SYN報文到達時,IPVS就選擇一臺服務器,將報文轉發給它。此後通過查發報文的IP和TCP報文頭地址,保證此連接的後繼報文被轉發到相同的服務器。這樣,IPVS不用檢查到請求的內容再選擇服務器,這就要求後端的服務器組是提供相同的服務,不管請求被送到哪一臺服務器,返回結果都應該是一樣的
IPVS是LVS的關鍵,因爲LVS的IP負載平衡技術就是通過IPVS模塊來實現的,IPVS是LVS集羣系統的核心軟件,它的主要作用是:安裝在Director Server上,同時>在Director Server上虛擬出一個IP地址,用戶必須通過這個虛擬的IP地址訪問服務。這個虛擬IP一般稱爲LVS的VIP,即Virtual IP。訪問的請求首先經過VIP到達負載調度器,然>後由負載調度器從Real Server列表中選取一個服務節點響應用戶的請求。
ingress網絡
Docker Swarm 支持兩種服務發佈模式,兩種模式均保證服務從集羣外可訪問。
- Ingress模式(默認)。
- Host模式。
通過 Ingress 模式發佈的服務,可以保證從 Swarm 集羣內任一節點(即使沒有運行服務的副本)都能訪問該服務;以 Host 模式發佈的服務只能通過運行服務副本的節點來訪問。