1. 程式人生 > 其它 >Docker 之Swarm介紹

Docker 之Swarm介紹

為什麼需要Docker Swarm

  1. 我們從Docker到Docker Compose都是在單機上完成,這樣會帶來一個很現實的問題就是高可用的問題,如果只部署到一臺機器是無法做到高可用的,這樣就不具備生產的條件;

  2. Docker Compose只是簡單做了單機服務的編排、擴容,對於多機器的管理、釋出、服務發現、負載均衡都沒有很好的解決;

  3. 目前我們所有的容器都是在單個宿主機上進行網路通訊,多機情況的網路通訊也沒有解決方案;

針對以上三點,Docker給出了Docker Swarm的解決方案,Docker swarm可以讓使用者輕鬆在多個機器上釋出和管理應用,並且我們不需要關注每個容器例項具體落在哪一個節點,Docker swarm把我們的應用以服務的形式暴露出去,並內建服務發現和負載均衡,讓執行在多個節點上的容器叢集感覺就像只有一個應用在跑一樣簡單,可以輕鬆實現擴容和自動容錯。Docker swarm叢集通常有幾個工作程式節點和至少一個管理程式節點,負責高效地處理工作程式節點的資源並確保叢集有效地執行,提高了應用可用性。

Docker Swarm概念介紹

img

Manager Node

Manger 節點是負責管理工作的,從名字就可以看出,注意負責以下事情:

  1. 維護叢集的狀態;

  2. 對 Services 進行排程;

  3. 為 Swarm 叢集提供外部可呼叫的 API 介面;

  4. 提供服務註冊發現、負責均衡等功能;

Manager 節點需要時刻維護和儲存當前 Swarm 叢集中各個節點的一致性狀態,在保證一致性上,Manager 節點採用 Raft 協議來保證分散式場景下的資料一致性;

Worker Node

Worker 節點是用來執行 Task 的;預設情況下 Manager 節點也同樣是 Worker 節點,同樣可以執行 Task;

image.png

Service

Services 是指一組任務的集合,服務定義了任務的屬性,比如任務的個數、服務策略、映象的版本號等等,服務有兩種模式:

  1. replicated services 按照一定規則在各個工作節點上執行指定個數的任務;
  2. global services 每個工作節點上執行一個任務;

Task

Task是 Swarm 叢集中的最小的排程單位,任務包含一個Docker容器和在容器內執行的命令,如果某一個任務奔潰,那麼協調器將建立一個新的副本任務,該任務將生成一個新的容器;

Task排程

img

Task排程主要分為兩部分: Manager節點的任務分配和Worker節點的任務執行;

Manager節點的任務分配主要有以下四步:

  1. 使用者通過 Docker Engine Client 使用命令 docker service create 提交 Service 定義;

  2. Manager節點根據定義建立相應的 Task,並分配IP地址;

  3. 將Task分發到對應的節點上;

  4. 節點進行相應的初始化使得它可以執行Task;

Worker節點的任務執行主要有兩步:

  1. 連線Manager節點的分配器檢查該Task相關定義的資訊;
  2. 驗證通過以後,開始在 Worker 節點上執行Task;

注意,上述 Task 的執行過程是一種單向機制,比如它會按順序的依次經歷 assigned, prepared 和 running 等執行狀態,不過在某些特殊情況下,在執行過程中,某個 Task 執行失敗了,Manager 的編排器會直接將該 Task 以及它的 Container 給刪除掉,然後在其它節點上另外建立並執行該 Task;

Docker Swarm網路

核心概念介紹

img

  1. Overlay Network:管理 Swarm 中 Docker 守護程序間的通訊。你可以將服務附加到一個或多個已存在的 overlay 網路上,使得服務與服務之間能夠通訊;

  2. Ingress Network:一個特殊的 overlay 網路,用於服務節點間的負載均衡。當任何 Swarm 節點在釋出的埠上接收到請求時,它將該請求交給一個名為 IPVS 的模組。IPVS 跟蹤參與該服務的所有IP地址,選擇其中的一個,並通過 ingress 網路將請求路由到它。初始化或加入 Swarm 叢集時會自動建立 ingress 網路,大多數情況下,使用者不需要自定義配置,但是 docker 17.05 和更高版本允許你自定義;

  3. Docker Gwbridge Network:一種橋接網路,將 overlay 網路連線到一個單獨的 Docker 守護程序的物理網路。預設情況下,服務正在執行的每個容器都連線到本地 Docker 守護程序主機的 docker_gwbridge 網路,一種橋接網路,將 overlay 網路(包括 ingress 網路)連線到一個單獨的 Docker 守護程序的物理網路。預設情況下,服務正在執行的每個容器都連線到本地 Docker 守護程序主機的 docker_gwbridge 網路;

image.png

流量分類

Docker Swarm 資料流量分為兩個層面:

  1. 控制管理流量(control and management plane traffic): 包括 Swarm 管理訊息,例如加入/退出 Swarm 的請求,這些流量總是被加密的;

image.png

  1. 應用資料流量(Application data plane traffic): 包括容器之間的資料交換,以及容器與外部網路的資料交換,關於這塊的原理探討放在實踐的地方;

叢集搭建

資源準備

節點全部使用CentOS8.2版, 這邊準備了兩個node節點和一個master節點:

  1. IP:172.16.0.191 主機名:demo-master-1 擔任角色:Swarm Manager
  2. IP:172.16.0.45 主機名:demo-slave-1 擔任角色:Swarm Node
  3. IP:192.168.0.231 主機名:demo-slave-2:Swarm Node

保證每個主機之間都能相互ping通並且2377埠可以telnet保持暢通, 每個節點都安裝了Docker。

叢集安裝

  1. 初始化Master節點,命令執行後,該機器自動加入到swarm叢集。這個會建立一個叢集token,獲取全球唯一的 token,作為叢集唯一標識。後續將其他節點加入叢集都會用到這個token值;
dockerswarminit--advertise-addr172.16.0.191

image.png

  1. 將Node節點加入叢集;
dockerswarmjoin--tokenSWMTKN-1-3cap7omkvmyuf0q1ybm868880eo5reoil8pcbovmejfzw6pil8-73hc367s4gitudqivrdirvu63172.16.0.191:2377
  1. 檢視Master節點資訊;
dockernodels

image.png

  1. 相關命令;
#建立服務
dockerservicecreate\
--imagenginx\
--replicas2\
nginx

#更新服務
dockerserviceupdate\
--imagenginx:alpine\
nginx

#刪除服務
dockerservicermnginx

#減少服務例項
dockerservicescalenginx=0

#增加服務例項
dockerservicescalenginx=5

#檢視所有服務
dockerservicels

#檢視服務的容器狀態
dockerservicepsnginx

#檢視服務的詳細資訊。
dockerserviceinspectnginx

實戰

  1. 在Manager節點部署Nginx服務,服務數量為2個,對外暴露的埠是8080對映容器內部的80埠,使用Nginx映象;
dockerservicecreate--replicas2--namenginx--publish8080:80nginx

image.png

  1. 檢視容器分佈狀況;
dockerservicepsswarm-nginx

image.png

  1. 訪問服務;
curl172.16.0.45:8080
curl192.168.0.231:8080

image.png

Internal

Internal容器與容器之間通過overlay網路進行訪問,通過service name進行通訊,但是service name所對應的ip不是真實ip而是VIP,我們可以下面這個案例進行驗證:

img

  1. 開始實驗前移除建立的服務,建立一個overlay的Network;
dockernetworkcreate--driveroverlayswarm-overlay
#檢視網路狀況
dockernetworkls

image.png

  1. 建立一個nginx的service ,使用swarm-overlay網路;
dockerservicecreate--namenginx-p8080:80--networkswarm-overlay-dnginx
  1. 再建立一個busybox服務;
dockerservicecreate--namebusybox-d--networkswarm-overlaybusybox:1.28.3sh-c'whiletrue;dosleep7200;done'
  1. 檢視服務列表;
dockerservicels

image.png

  1. 進入busybox服務內部,使用ping命令訪問nginx服務,我們會發現可以訪問;
dockerexec-it2f55d73adfb4sh
pingnginx

image.png

Ingress

當在任何一個Swarm節點去訪問埠服務的時候會通過本節點的IPVS ( ip virtual service )到真正的Swarm節點上。提供以下三種功能:

  1. 外部訪問的均衡負載;

  2. 服務埠暴露到各個Swarm節點;

  3. 內部通過IPVS進行均衡負載;

image.png

接著Internal案例繼續進行探索,Swarm節點內部是如何進行轉發的;

  1. 檢視工作節點的轉發規則,我們可以看到把請求轉發到172.18.0.2:8000這個地址上去了;
iptables-nL-tnat

image.png

  1. 接下來我們檢視下本機的網路情況,我們找到了docker_gwbridge,可以看到兩個ip處於同一網段,那麼172.18.0.2應該也連線上docker_gwbridge;

image.png

  1. 檢視docker_gwbridge的interface 資訊,我們會發現有多個interface;
brctlshow
  1. 接下來我們檢視下docker_gwbridge網路資訊,我們可以發現ingress-sbox就是我們要找的名稱空間,gateway_ingress-sbox就是所屬的容器;
dockernetworkinspectdocker_gwbridge
  1. 進入ingress_sbox內部,檢視iptables規則,可以看到傳送到該ip地址下的8000埠的請求被負載掉了;
#查詢ingress_sbox位置
ls/var/run/docker/netns
#進入ingress_sbox
nsenter--net=/var/run/docker/netns/ingress_sbox
#檢視ingress_sboxiptables
iptables-nL-tmangle
  1. 檢視負載的詳細資訊;
#在host安裝ipvsadm
yuminstall-yipvsadm
#再次進入ingress_sbox
nsenter--net=/var/run/docker/netns/ingress_sbox
#檢視詳細的規則
ipvsadm-l
  1. 接下來隨便在一臺主機找到nginx容器,檢視器IP情況,我們會發現與ipvsadm的相對應;
#進入容器
dockerexec-it56c475bb5b2f/bin/bash
#安裝一些命令
apt-getupdate
apt-getinstallnet-tools
#檢視網路情況
ifconfig

通過探究我們可以得出Docker Swarm網路情況如下:

當我們訪問任一節點的8080埠時,只要我們這個節點處於Swarm叢集中,不管服務是否部署到這個節點都能訪問,只要埠相同即可。我們本地的請求會被轉發到Ingress_sbox這個Network Namespace中,在這個名稱空間中再通過lvs轉發到具體服務容器的ip和8080埠中去。