7.2docker官網入門-Docker Swarm 叢集(下)---最重要
Docker Swarm 叢集
(1)容器與應用: 講述 centos docker的安裝,倉庫、映象、容器、服務的概念, dockerfile,compose 檔案,容器管理圖形介面,以單機操作為主線。
(2)Docker Swarm 叢集:講述叢集(cluster)manager,worker,node 的概念與應用在叢集部署。重點講述容器網路、儲存管理、叢集管理、服務發現等知識。
1、Docker Swarm 體驗
docker swarm 是 Docker 公司的一個開源專案。自 v1.12.3 以來, docker swarm 成為 docker 引擎內建的服務。它和谷歌的 K8s 產生了直接競爭。很難說哪個好,對於熟悉 docker 容器的人來說,docker swarm 應該友好一些。
本部分內容主要來自 docker 官網 Get Started, Part 4~5
1.1 瞭解叢集(Swarm clusters)
群集是一組執行 Docker 的計算機組成,其中部分機器是叢集管理機(Swarm Manager) ,其他的是工作機(Worker)。在叢集中,在 Manager 機器上使用 Docker 命令,會在群集上執行。群集中的機器可以是物理機或虛擬機器。加入群集後,它們被統稱節點(Node)。
Swarm管理機可以使用幾種策略來執行容器,例如“最空閒節點”- 容器會填充最少使用的機器。或“全域性策略”,它確保每個機器能只能獲得指定容器的一個例項。您可以將這些策略寫在 docker-compose.yml 這樣的服務組合定義檔案中,Swarm管理機會按策略部署。
Swarm Manager是群集中唯一可以執行 docker 命令的機器,或授權其他機器作為工人機(worker)加入群集。worker 只是提供能力,沒有權力指揮其他機器工作。
如果您已經熟悉單主機中使用Docker。現在,可切換到 Docker 叢集模式。啟用群組模式(swarm mode)使當前的機器成為群組管理機。這時,這臺 Docker 將執行管理這個群集的指令,而不再是在當前的機器上執行。
主要概念:
- Swarm Manager 叢集的管理者
- worker 叢集中的執行者
- Node 叢集中任意的 docker 機器
- Swarm mode 叢集模式, docker 機器的狀態
1.2 配置叢集
(1) 準備機器
1) 清理 docker-master 機器
- 清理所有的容器
docker rm -f $(docker ps -q)
- 退出可能的叢集狀態
docker swarm leave --force
- 刪除從倉庫下載的實驗用映象
docker rmi registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:friendlyhello
2) 複製 docker-master 生成 workers
關閉 docker-master ,以它為模板,用 VBox 連結複製 workers,配置如下:
- docker-worker1:配置 192.168.56.111/24;主機名=“docker-worker1”
- docker-worker2:配置 192.168.56.112/24;主機名=“docker-worker2”
配置完成後,一般用無介面模式啟動,用 ssh登陸
(2)建立 docker 叢集
1) 建立第一個 Manager
ssh 連線 docker-master 機器上,啟動 docker swarm mode :
docker swarm init --advertise-addr 192.168.56.110
# docker swarm init --advertise-addr 192.168.56.110
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-0o8kwg6rwcsyllo8yr4x24t304wtjvh01h1mq3jhcxi1qy5qrl-00hvxabe2qpuwyh4odii07omo \
192.168.56.110:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
這時,manager 將在埠 192.168.56.110:2377
偵聽叢集節點請求。
docker swarm join-token worker
顯示作為 worker 加入該叢集的指令docker swarm join-token manager
顯示作為 manager 加入該叢集的指令
2) 將兩個 worker 分別加入叢集
分別用 ssh 連線兩個 worker 。貼入 manager 上 docker swarm join-token worker
顯示的指令, 格式如下:
docker swarm join \
--token <token> \
<ip>:<port>
This node joined a swarm as a worker.
這時,我們的第一個叢集就建完了。
提示, 如果因為防火牆,無法加入叢集,可使用以下命令關閉防火牆:
setenforce 0
systemctl disable iptables-services firewalld
systemctl stop iptables-services firewalld
3) 在 manager 上檢查結果,這時使用 docker node
指令組
# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
srm9pnuj0zum7z79xb8ptnmdi * docker-master Ready Active Leader
vhrpxjbbu3ijt84t6c9cm2t64 docker-worker2 Ready Active
yzzt6k9rfcrti19ergdpde77u docker-worker1 Ready Active
在 manager 啟動 Portainer 容器
在瀏覽器中, Swarm 選單看到類似的結果。
1.3 在叢集中部署服務和使用服務
(1) 部署服務
我們在 docker-master 機器上執行同樣的部署命令
docker stack deploy -c docker-compose.yml myservice
檢查結果:
# docker stack ps myservice
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
w04szt4o9u9b myservice_web.1 registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:friendlyhello docker-worker2 Running Running 5 minutes ago
t6bhw4yoybcr myservice_web.2 registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:friendlyhello docker-worker1 Running Running 5 minutes ago
wzdvrjgfeyiy myservice_web.3 registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:friendlyhello docker-worker2 Running Running 5 minutes ago
mr3zw4q6y99n myservice_web.4 registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:friendlyhello docker-master Running Running 5 minutes ago
kdu43k6ayfnz myservice_web.5 registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:friendlyhello docker-worker1 Running Running 5 minutes ago
果然,服務(容器)被平均分配到三臺機器上了。
(2) 訪問服務
使用叢集中任意一臺機器的 IP, 我們都能看到迴圈訪問不同容器服務的結果,體現了負載均衡。
每個IP地址都工作的原因是群集中的節點參與入口路由網格(route mesh)。這樣可以確保在群集中某個埠部署的服務始終將該埠保留給其自身,無論實際執行的是哪個節點。以下是在三節點群集my-web埠8080上釋出的服務的路由網格的示例:
注意:如果您遇到連線故障,請注意,為了在叢集中使用入口網路,需要在啟用群組模式之時,在群集節點之間使用以下埠:
埠7946用於容器網路發現的TCP / UDP。
埠4789 UDP用於容器入口網路。
1.4 部署一個簡單應用
(1)叢集容器視覺化工具
官方文件 Part 5 介紹了官方的簡單容器狀態視覺化工具,並將它dockersamples/visualizer
新增到專案中。
(2)新增資料服務
現在我們為 web 服務新增 Redis 資料服務。
1) 新建一個 compose 檔案
cd && mkdir myapp && cd myapp
cp ../service_test/docker-compose.yml docker-compose.yml
mkdir data
注: data 目錄用來存放 redis 的資料
2) 修改服務棧配置 vi docker-compose.yml
version: "3"
services:
web:
image: registry.cn-shenzhen.aliyuncs.com/pmlpml/repo:friendlyhello
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "80:80"
networks:
- webnet
redis:
image: redis
ports:
- "6379:6379"
volumes:
- ./data:/data
deploy:
placement:
constraints: [node.role == manager]
networks:
- webnet
networks:
webnet:
上述配置中,添加了 redis 這個服務,redis 服務被指定到 [node.role == manager] 機器,因為它與這臺機器要共享資料卷 ./data 對映到容器 /data 資料卷
啟動這個棧:
docker stack deploy -c docker-compose.yml myservice
網站會計數了,它們共享一個 Redis 資料服務。
最後, docker stack rm myservice
(3) 什麼是“棧(stack)”
一切似乎都很完美,其實服務之間依賴、在叢集中資料遷移都是重要研究的話題。問題:
- Redis 就必須繫結某個主機?
- 服務啟動順序對應用有影響嗎?
- 管理機只能一臺?
- … …
當然,最大的麻煩還是:上午在官網讀某文件,下午網站內容變了。
2、容器與叢集技術基礎
倉庫、映象、容器、服務、服務棧、dockerfile、compose.yaml 讓我們看到容器簡單易用的一面。事實上,任何和雲相關的技術,需要你對網路、資料儲存、作業系統、應用開發等等技術的修養,俗稱“全棧”。
2.1 容器網路
(1)準備環境
前面我們建立了3臺機器的叢集。現在我們把 worker1 撤出叢集,完成以下實驗。ssh 登陸 worker1:
# docker swarm leave
Node left the swarm.
成功退出 manager 組織的叢集。
(2)容器執行的預設網路
Docker 通過使用網路驅動程式來支援容器的網路。Docker 目前提供bridge
和 overlay
兩個網路驅動程式。你可以利用網路驅動外掛,建立自己的網路驅動。Docker Engine 安裝都會自動包含三個預設網路。使用 docker network
命令管理這些網路,例如:
# docker network ls
NETWORK ID NAME DRIVER SCOPE
4ff847509bb3 bridge bridge local
68f3b3d86d97 host host local
690f242840f5 none null local
bridge
是一個特殊的網路。除非您特別說明,否則Docker會在此網路中啟動容器。例如:
docker run -itd --name=networktest centos
我們在後臺啟動了一個叫 networktest
的容器,運行了 contos 容器。可以用一下命令,檢查容器網路:
# docker network inspect bridge
...
"Containers": {
"56d7e244d4ddcf442ddd0211c0433d11871a6bd88be3704f61ca2ece734f2a06": {
"Name": "networktest",
"EndpointID": "7720f7cd31f8124c5177f002628988418e6bda92d7810511f66e033a297247db",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
...
或者
# docker inspect networktest
...
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "79e0f4bbc9211925bc5fd08c3401a581520ccd61dac014ae75dcbf1d1c3a3fa6",
"EndpointID": "7720f7cd31f8124c5177f002628988418e6bda92d7810511f66e033a297247db",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
}
}
...
這時,容器網路如圖:
使用命令 docker network disconnect bridge networktest
可以將容器與網路斷開,也可以使用 docker network connect bridge networktest
連線。
(3)建立使用者的 bridge 網路
現在我們需要定製如圖網路,怎麼做呢?
1) 建立虛擬橋接網路 my_bridge
# docker network create -d bridge my_bridge
2)在虛擬橋接網路 my_bridge
建立名字叫 db
的容器
docker run -itd --name=db --net=my_bridge centos
檢查結果:
# docker network ls
# docker network inspect my_bridge
記錄 db 在 my_bridge 上的 ip 地址。
3) 在 bridge 上建立 web 的容器
docker run -itd --name=web centos
達到以下效果:
再將web容器綁到 my_bridge,即可達到目的
docker network connect my_bridge web
檢查結果, web ip 172.17.0.4;172.19.0.3
及 db ip 172.19.0.2
。 進入容器 web
docker exec -it web /bin/bash
你可以在容器中 ping db
在容器 db 中 ping web
4) 清理
docker rm $(docker ps -q) -f
docker network rm my_bridge
小結:
- 使用 docker network 命令可以建立、立表、刪除 使用者定義網路
- 使用 –net 可以在特定網路上建立容器,也可以用 connect/disconnect 掛接或斷開網路
- 在自定義網路上,自帶 dns 服務,可以用 容器名 訪問服務
官網在不醒目的地方提及:
- * bridge 網路上沒有 dns 的支援,是為了相容*,
- 服務與容器的區別只有在機器重新啟動後你才知道,服務是自動啟動的,docker run 的容器則不會。
2.2 容器儲存管理
2.2.1 聯合檔案系統(Union FS)簡介
容器檔案系統:是容器映象檔案系統(只讀)與可讀寫層(Thin)的檔案系統聯合而成的。如圖:
一個容器檔案,是多層疊加起來的,在下載容器時就可以直觀觀察到。Thin R/W 層,是當前容器檔案讀寫層,如果你修改映象層的檔案,就會在 Thin 產生一個覆蓋。多個容器例項執行時,層次共享情形如下:
為了高效管理容器檔案,適應叢集中跨機資料遷移、多機共享等應用場景,產生了許多解決方案,它依然是容器技術熱點研究技術之一。
2.2.2 資料卷
資料卷是一個越過 Union FS 的特殊目錄。用它可以實現資料持久化、和資料共享。簡單描述,讀寫資料卷只會發生在該資料卷中,而不會訪問 Union FS 系統,而提升容器資料訪問效率。
(1)新增資料卷
例如:
docker run -itd --name web -v /webapp centos
這時,你在容器檔案系統 /webapp
的位置建立了一個卷。進入該容器 docker exec -it web /bin/bash
,使用 ls
就會看到該目錄,進入/webapp下:cd /webapp,
你可以用 vi aaa.txt
在其中建立檔案。退出該容器
docker inspect web
...
"Mounts": [
{
"Type": "volume",
"Name": "8b6f417df2f99d59924276f9476a0759d73afb0d27db5d57d7d24d5b7ff3c56b",
"Source": "/var/lib/docker/volumes/8b6f417df2f99d59924276f9476a0759d73afb0d27db5d57d7d24d5b7ff3c56b/_data",
"Destination": "/webapp",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
...
這時,使用命令 ls <source>
就看到你剛建立的檔案了。
(2)將本機目錄作為資料卷
docker rm web -f
docker run -itd --name web -v /root/web:/webapp centos
本命令就是將本機當前目錄下的 /root/web
目錄掛載到容器的 /webapp
目錄下。
注意:
- docker run -v 主機目錄卷僅支援全路徑。如果
-v web:/webapp
則表示命名為 web 的資料卷,通常位置:/var/lib/docker/volumes/web
。 - 資料卷旨在持久保留資料,而與容器的生命週期無關。因此,Docker 在刪除容器時不會自動刪除卷,也不會自動刪除容器不再引用的卷。
(3)與主機共享檔案/將主機檔案作為卷
例如:
docker run -itd --name web -v ~/.bash_history:/root/.bash_history centos
2.2.3 建立共享資料卷
為了在容器間共享資料,需要建立共享資料卷。共享資料卷應用場景大致分為幾類:
- 一臺主機上的多個容器共享資料卷
- 通過 back-end 共享儲存,如 iSCSI, NFS 等,建立多主機共享資料卷
- 在叢集中建立可在節點間遷移的資料卷
(1)建立共享資料卷
Docker 17.04 通過 local
資料卷驅動(overlay)提供卷服務,其他版本,請使用 docker info
檢視。
建立共享資料卷,非常簡單。使用 docker volume
命令建立一個命名卷。例如:
docker volume create webdata
通過命令 ls /var/lib/docker/volumes/
就可以看到這個資料卷,使用也非常簡單,例如:
docker run -itd --name web -v webdata:/webapp centos
(2)建立共享儲存資料卷
官網資料提供了在 iSCSI 或 NFS 提供共享卷服務的案例,使用的驅動是 rancher/convoy 。
這是需要專題研究的內容,因為在不同網路和儲存環境下,需要使用不同的驅動,參見:Use Docker Engine plugins 。涉及多租戶(multi-tenant)、多主機(multi-host)、高可靠等多種裝置解決方案。
2.2.4 資料卷管理
- 資料卷列表:
docker volume ls
- 資料卷的刪除:例如,刪除所有卷,
docker volume rm $(docker volume ls -q)
備份資料卷
由於一個容器可以載入多個數據卷,通常將 backup 目錄載入到容器介面,典型的命令如下:
docker run -itd --name backup --volumes-from dbcontainer -v $(pwd):/backup centos
這樣就把 dbcontainer 資料卷載入到容器 backup 中,然後,你可以隨時進入 backup 容器, tar 到備份目錄中。
相當於在backup這個容器中,會有/backup目錄,對應掛載$PWD, 還會有dbcontainer容器所對應掛載目錄的目錄,進入不同的目錄,建立內容,會再對應的掛在目錄下出現內容。其實就相當於這個backup容器掛載了兩個目錄。
使用共享卷的重要提示
多個容器也可以共享一個或多個數據卷。但是,寫入單個共享卷的多個容器可能會導致資料損壞。確保您的應用程式旨在寫入共享資料儲存。
資料卷可以從Docker主機直接訪問。這意味著您可以使用普通的Linux工具讀寫它們。在大多數情況下,您不應該這樣做,因為如果容器和應用程式不知道您的直接訪問,它可能會導致資料損壞。
2.3 Docker 物件標籤
標籤(Label)用於分類、描述物件語義,方便指令碼過濾、選擇容器進行操作。 可標籤的物件包括:
- 映象
- 容器
- 本地守護程序
- 資料卷
- 網路
- 叢集節點
- 叢集服務
標籤是一個鍵值對,通常在物件建立時用 –label 引數建立。
3、Docker Swarm 管理
Docker Swarm 特點:
- 與引擎整合
- 去中心化的設計
- 宣告式的服務模型
- 動態可伸縮服務
- 自動狀態協調
- 多主機(Multi-host)網路
- 負載均衡
- 滾動更新
- 預設安全模式
3.1 管理叢集、節點與服務
docker swarm
docker service
docker node
三個命令組。如果你瞭解前面的概念,按文件操作是比較容易的。
3.2 叢集工作原理
一個 docker swarm 叢集的組成結構,如圖:
它分為兩類節點,manager 和 worker。
manager 節點處理叢集管理任務:
- 維護叢集狀態(配置)
- 排程服務
管理節點共同維護一個強一致狀態資料(你可以認為每個管理節點擁有一個同步的叢集狀態/配置資料庫),任何一個經理退出都不會導致叢集失效。
高可靠模式 是指容器叢集擁有 3 個以上 manager。一個 manager 是基數(如 3、5、7),一半以下 manager 失效都不會導致叢集狀態失效。Docker為群組建議最多七個管理器節點。
多於 7 個 manager 不會提高可靠性,反而會提高開銷
強一致狀態資料庫常見實現包括: etcd 、consul 、zookeeper 等等。
worker 節點的唯一目的就是執行容器(服務)。預設情況下,manager 同時承擔 worker 的職能,所以一個 manager 可以單節點執行,所有容器執行在一個節點中。
對於大型的容器叢集,需要設定管理器節點的可用性設定為 Drain
以阻止服務的任務執行。
docker node update
是一個很有用的命令,可以改變節點的 role,label 等
3.3 服務、任務和容器
在叢集模式下,服務(Service)部署時, manager 管理並維持服務的狀態。如果服務定義了 N 個負載均衡任務,它按策略在叢集中啟動 N 個任務(Task),每個任務執行在叢集的一個容器(Container)中。
任務排程策略
docker 目前提供 複製 和 全域性 兩種策略。複製策略可指定任務的數量,它可以按資源定義,選擇合適的 host 執行任務。 全域性策略指每個主機(host)啟動一個服務,用於監控主機相關資訊。
安全策略
Docker Engine內建的群集模式公鑰基礎設施(PKI)系統使安全部署容器編排系統變得簡單。群集中的節點使用相互傳輸層安全(TLS)來認證,授權和加密他們與群集中其他節點之間的通訊。
3.4 Overlay 網路與服務發現
docker 叢集預設使用 Overlay 網路驅動,Overlay 驅動實現了跨主機叢集內部虛擬網路。它的作用:
- 將執行的多個容器(不同主機),附加(attach to)到一個網路
- 預設情況下,服務發現為群集中的每個服務分配虛擬IP地址(VIP)和 動態 DNS,使其可以通過服務名稱將其提供給同一網路上的容器。即在一個 Overlay 虛擬網路內,使用服務名稱訪問,將實現任務級別的負載均衡
- 在群集中使用覆蓋網路,需要在群集節點之間開啟以下埠:
- 埠7946 TCP / UDP用於容器網路發現。
- 埠4789 UDP用於容器覆蓋網路。
(1) 建立 Overlay 網路
建立 Overlay 網路與建立 local 網路一樣,僅需指定 --driver overlay
,例如:
docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--opt encrypted \
my-network
預設情況下,群集中的節點會加密自身與其他節點之間的流量。可選–opt encrypted標誌在覆蓋驅動程式中為不同節點上的容器之間的vxlan流量啟用附加的加密層。
(2)服務發現
預設情況下,建立一個連線到網路的服務時,群集將為該服務分配VIP。VIP根據服務名稱對映到DNS別名。網路上的容器使用共享服務的DNS對映,因此網路上的任何容器都可以通過其服務名稱訪問該服務。
注意:只有使用者自定義網路,才有 dns 服務和服務自動發現
最後
將 Portainer 和 Registry 作為服務部署, 為什麼?
4 、 小結
本文給出了在 centos 環境下,完成 docker 官方叢集教程(Part4-5)的要點。並給出了容器網路、儲存、叢集、服務發現管理的基礎,以及叢集的工作原理。
本文圍繞叢集、Manger、Worker、Service、Task 核心知識以及相關的操作,讀者應可以在叢集上釋出與部署簡單的 web 應用。