前言
這篇文章介紹Docker生態中的常被提到的Engine、Machine和Swarm,大家以了解為主,工作需要再深入。
Engine
Docker Engine其實就是我們常說的「Docker」,它是一個C/S模型(Client/Server)的應用,包含如下組件:
Daemon。守護進程,屬于C/S中的Server(?
dockerd
)REST API。Daemon向外暴露的REST 接口
CLI。向外暴露的命令行接口(Command Line API:?
docker
)
客戶端訪問服務端的方式有三種:
使用命令行工具,如?
docker run
、?docker ps
等等直接通過調用REST API,如發送一個?
curl
請求通過腳本直接和Daemon交互
用戶通過Docker CLI向Docker Daemon發送REST API請求。Daemon創建和管理Docker objects(對象),如:
images。鏡像
containers。容器
networks。網絡
volumes。數據卷
Machine
在沒有Machine之前,Docker的安裝流程非常復雜,首先需要登錄到相應的主機上,根據官方的安裝和配置指南來安裝Docker,而且不同的操作系統的安裝步驟也不同。
Machine是一個簡化Docker Engine安裝和管理的命令行工具,這樣通過一個簡單的命令即可在相應的平臺上安裝Docker,如本地(macOS、Linux和Windows)、虛擬化平臺(VirtualBox、macOS xhyve等),公有云(AWS、Azure、Digital Ocean等)等。使用Machine可以啟動、審查、停止和重新啟動托管的宿主機、升級 Docker 客戶端和守護程序、并配置 Docker 客戶端與宿主機通信。
通過圖示可以看出來,Machine是管理本地/遠程帶有Docker Engine的主機的工具, docker-machine create
創建的「machine」包含了Daemon和REST API這2部分,Machine自己包含CLI。
我大概演示一下使用Machine的方法:
創建machine。?
docker-machine create--driver virtualboxdefault
,這就會可以創建一個叫做?default
的「機器」,它是Virtualbox類型的,所以可以在Virtualbox管理器里面看到這個虛擬機。連接到machine。?
eval"$(docker-machine env default)"
,其實就是做了對應的環境變量設置使用Docker CLI。之后就可以使用?
docker ps
等命令查看和管理這個主機里面的鏡像/容器等內容了
Swarm Mode
Docker Swarm是Docker 官方的集群管理和編排工具,可以將多個Docker主機封裝為單個大型的虛擬Docker主機,成為一個容器平臺。從 Docker1.12.0+
開始 SwarmMode
已經內嵌入 Docker Engine,成為子命令 docker swarm
可以直接使用。
SwarmMode
主要特性如下:
具有容錯能力的去中心化設計
服務發現。可以做到Docker集群中節點的動態加入和退出的感知,支持主流的etcd、consul和zookeeper。
負載均衡。讓資源分配負載,以達到最優化資源使用、最大化吞吐率、最小化響應時間、同時避免過載。
動態伸縮。服務在判斷監測指標超出所設定的上下限時,會按照你的設置觸發擴容或縮容。
滾動更新(Rolling updates)。可以實現「零停機時間部署」,下節我們還會再說。
安全傳輸。集群中的每個節點都執行TLS的相互認證和加密,以確保自己與所有其他節點之間的通信安全。
確保期望狀態。Swarm會在后臺進行輪訓檢查,確保實際狀態能夠滿足期望狀態的要求。
Swarm 是使用SwarmKit構建的 Docker 引擎內置(原生)的集群管理和編排工具。它包含如下三個重要概念: 節點、服務和任務,我們挨個看。
節點(Node)
運行 Docker 的主機可以主動初始化一個 Swarm 集群或者加入一個已存在的 Swarm 集群,這樣這個運行 Docker 的主機就成為一個 Swarm 集群的節點。節點分為管理 (manager) 節點和工作 (worker) 節點。
管理節點用于 Swarm 集群的管理,管理節點分發工作單元(稱為Task「任務」)到工作節點。docker swarm
命令基本只能在管理節點執行(節點退出集群命令 docker swarm leave
可以在工作節點執行)。一個 Swarm 集群可以有多個管理節點,但只有一個管理節點可以成為領導(leader, 通過Raft協議實現)。管理節點還要通過leader執行維護集群所需狀態所需的編排和集群管理任務。
工作節點接收并執行從管理節點分派的任務。默認情況下,管理器節點也作為工作節點運行服務(Service),但是你可以將它們配置為專門運行管理器任務,并且只運行管理器節點。代理在每個工作節點上運行,并報告分配給它的任務。工作節點通知管理節點其分配任務的當前狀態,以便管理器可以維護每個工作的所需狀態。
任務(Task)
任務是Swarm中的最小的調度單位,任務攜帶Docker容器和在容器中運行的命令。管理節點根據服務中設置的副本(Replicas)數量將任務分配給工作節點。一旦任務被分配給一個節點,它就不能移動到另一個節點。它只能在指定的節點上運行或失敗
任務是這么調度的:
服務(Service)
服務是指一組任務的集合,它定義了任務的屬性,是Swarm系統的中心結構:
服務有兩種模式:
Replicated services。按照一定規則在各個工作節點上運行指定個數的任務
Global services。每個可用節點上運行一個任務
PS: 兩種模式通過 docker service create
的 --mode
參數指定。
基本用法
我們創建一個最小的 Swarm 集群,包含一個管理節點和兩個工作節點。創建Docker 主機使用Docker Machine:
# 管理節點
? docker-machine create -d virtualbox manager # 創建管理節點,名字為manager
? docker-machine ssh manager # 登錄到管理節點
docker@manager:~$ /sbin/ifconfig eth1 | grep 'inet addr' | cut -d: -f2 | awk '{print $1}'
192.168.99.104 # 獲得IP
docker@manager:~$ docker swarm init --advertise-addr 192.168.99.104 # 在管理節點初始化一個Swarm集群,另外Docker主機有多個網卡,所以有多個IP,必須使用 --advertise-addr 指定IP
Swarm initialized: current node (k8cdrnrylrkxpsk4qoyybwpca) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-2gfzia6yrk172e8352jxpolevjr9gx1a9xu95hg0ibkhqat52p-d6j79273adew38s5mzmewgwoo 192.168.99.104:2377 # 記住這句命令
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
? docker-machine create -d virtualbox worker1 # 創建工作節點,名字worker1
? docker-machine ssh worker1
docker@worker1:~$ docker swarm join --token SWMTKN-1-2gfzia6yrk172e8352jxpolevjr9gx1a9xu95hg0ibkhqat52p-d6j79273adew38s5mzmewgwoo 192.168.99.104:2377 # 從上面直接粘貼來
This node joined a swarm as a worker.
? docker-machine create -d virtualbox worker2 # 創建工作節點,名字worker2
? docker-machine ssh worker2
docker@worker2:~$ docker swarm join --token SWMTKN-1-2gfzia6yrk172e8352jxpolevjr9gx1a9xu95hg0ibkhqat52p-d6j79273adew38s5mzmewgwoo 192.168.99.104:2377
This node joined a swarm as a worker.
這樣集群就做好了,在管理節點看一下狀態:
? docker-machine ssh manager
docker@manager:~$ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
k8cdrnrylrkxpsk4qoyybwpca * manager Ready Active Leader 18.09.9
puzrum9ixbt6holgfk5d8aokl worker1 Ready Active 18.09.9
sqwpb00zh5fp9z2o6r7vnebbt worker2 Ready Active 18.09.9
然后部署Nginx(只能在管理節點運行):
docker@manager:~$ docker service create --replicas 3 -p 80:80 --name nginx nginx:1.17.4-alpine # 創建服務,三個副本,服務監聽在80端口
pydkv5ffwfqiv1aua1ylmwhum
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
docker@manager:~$ docker service ls # 查看當前Swarm集群運行的服務
ID NAME MODE REPLICAS IMAGE PORTS
pydkv5ffwfqi nginx replicated 3/3 nginx:1.17.4-alpine *:80->80/tcp
# 現在我們使用瀏覽器,輸入任意節點IP(如管理節點的192.168.99.104),都能看到nginx默認頁面
docker@manager:~$ docker service logs nginx # 查看Nginx服務的日志
... # 省略輸出
docker@manager:~$ docker service scale nginx=5 # 業務高峰期時,擴展服務運行的容器數量
nginx scaled to 5
overall progress: 5 out of 5 tasks
1/5: running [==================================================>]
2/5: running [==================================================>]
3/5: running [==================================================>]
4/5: running [==================================================>]
5/5: running [==================================================>]
verify: Service converged
docker@manager:~$ docker service ps nginx # 查看服務詳情
i6xkgnneqbbq nginx.1 nginx:1.17.4-alpine worker2 Running Running 4 minutes ago
f517ogp705ne nginx.2 nginx:1.17.4-alpine manager Running Running 5 minutes ago
... # 省略輸出
docker@manager:~$ docker service scale nginx=2 # 業務平穩期時,減少服務運行的容器數量
在Swarm集群中使用Compose文件
在第一篇中我使用 docker-compose.yml
一次配置、啟動多個容器,在Swarm集群中也可以使用compose文件來配置、啟動多個服務。在上一小節中,使用 docker service create
一次只能部署一個服務(Nginx),使用 docker-compose.yml
可以一次啟動多個關聯的服務。還是拿lyanna項目的docker-compose.yml體驗一下,不過需要修改配置項,添加deploy(如mode和副本數等項),也要去掉一些stack不支持的項(如build、restart等):
version: '3'
services:
db:
image: mysql
environment:
MYSQL_DATABASE: 'test'
MYSQL_USER: 'root'
MYSQL_PASSWORD: ''
MYSQL_ROOT_PASSWORD: ''
MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
volumes:
- my-datavolume:/var/lib/mysql
deploy:
placement:
constraints: [node.role == manager]
redis:
image: redis:alpine
deploy:
mode: replicated
replicas: 3
memcached:
image: memcached:1.5-alpine
deploy:
mode: replicated
replicas: 3
web:
image: 127.0.0.1:5000/lyanna-app
build: .
ports:
- '8000:8000'
volumes:
- .:/app
- ./local_settings.py.tmpl:/app/local_settings.py
depends_on:
- db
- redis
- memcached
environment:
PYTHONPATH: $PYTHONPATH:/usr/local/src/aiomcache:/usr/local/src/tortoise:/usr/local/src/arq:/usr/local/src
command: sh -c './setup.sh && python app.py'
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
volumes:
my-datavolume:
其中有3個需要著重說明的點:
visualizer服務提供一個可視化頁面,可以從瀏覽器中很直觀的查看集群中各個服務的運行節點,一會會感受到
db/redis/memcached/visualizer這幾項都添加了deploy項,?
mode
指服務模式,?replicas
指副本數,?placement
可以限定滿足條件的Node,而避免在不合適的Node進行部署,這里限制db/visualizer都要在管理節點上web加了image項,是一個注冊服務的API地址,下面會看到如何注冊和推送鏡像上去
接著部署:
? eval "$(docker-machine env manager)" # 本機切換到管理主機
? git clone https://github.com/dongweiming/lyanna # 下載lyanna項目源碼,如果原來已經clone了不用再做
? cd lyanna
? docker service create --name registry --publish published=5000,target=5000 registry:2 # 創建注冊服務(名字叫registry),啟動在5000端口上
? docker-compose -f docker-compose.swarm.yml build # 用Compose的方式啟動,這個過程會構建lyanna-app鏡像
? docker-compose -f docker-compose.swarm.yml push # 把lyanna-app推送給本地的注冊服務
? docker stack deploy -c docker-compose.swarm.yml lyanna # 部署服務
Ignoring unsupported options: build
Creating network lyanna_default
Creating service lyanna_web
Creating service lyanna_visualizer
Creating service lyanna_db
Creating service lyanna_redis
Creating service lyanna_memcached
現在在瀏覽器輸入 任一節點IP:8080
即可看到各節點運行狀態,類似如下效果:
可以看到:
db、visualizer限定在管理節點manager
redis/memcached由于副本數和節點數一致,所以每個節點都有一個
web和registry由于負載平衡的作用分配到了2個工作節點上,讓服務整體看起來比較均衡
在瀏覽器新的標簽頁輸入 任一節點IP:8000
即可看到lyanna博客效果!
延伸閱讀
https://docs.docker.com/engine/docker-overview/
https://www.docker.com/products/container-runtime
https://docs.docker.com/machine/
https://docs.docker.com/engine/swarm/key-concepts/
https://docs.docker.com/engine/swarm/how-swarm-mode-works/services/
https://docs.docker.com/engine/swarm/stack-deploy/