什么是docker swarm
Swarm是Docker公司推出的用來管理docker集群的平台,幾乎全部用GO語言來完成的開發的
源碼地址: https://github.com/docker/swarm
Swarm使用標准的Docker API接口作為其前端的訪問入口
換言之,各種形式的Docker Client(compose,docker-py等)均可以直接與Swarm通信
甚至Docker本身都可以很容易的與Swarm集成
這大大方便了用戶將原本基於單節點的系統移植到Swarm上
同時Swarm內置了對Docker網絡插件的支持
用戶也很容易的部署跨主機的容器集群服務
Docker Swarm 和 Docker Compose 一樣,都是 Docker 官方容器編排項目
但不同的是,Docker Compose 是一個在單個服務器或主機上創建多個容器的工具
而 Docker Swarm 則可以在多個服務器或主機上創建容器集群服務
對於微服務的部署,顯然 Docker Swarm 會更加適合
從 Docker 1.12.0 版本開始,Docker Swarm 已經包含在 Docker 引擎中(docker swarm)
並且已經內置了服務發現工具,我們就不需要像之前一樣,再配置 Etcd 或者 Consul 來進行服務發現配置了
Swarm deamon只是一個調度器(Scheduler)加路由器(router)
Swarm自己不運行容器
它只是接受Docker客戶端發來的請求,調度適合的節點來運行容器
這就意味着,即使Swarm由於某些原因掛掉了,集群中的節點也會照常運行
當Swarm重新恢復運行之后,他會收集重建集群信息
部署swarm集群
1 環境准備,購買服務器
建議到雲平台購買4台服務器,服務器的配置為1C2G
操作系統為centos7.9
網絡和安全組
自定義密碼
2 給4台服務器安裝docker環境
docker環境安裝完成
3 部署swarm集群(兩管理節點,容易出現問題)
1 在docker001服務器上(manager管理節點)
# 查看swarm命令幫助
[root@docker001 ~]# docker swarm init --help
Usage: docker swarm init [OPTIONS]
Initialize a swarm
Options:
--advertise-addr string Advertised address (format: <ip|interface>[:port])
# 查看docker001服務器的ip地址
[root@docker001 ~]# ip addr
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
inet 172.18.213.61/20 brd 172.18.223.255
# 創建swarm集群的管理節點
[root@docker001 ~]# docker swarm init --advertise-addr 172.18.213.61
# 提示已經是管理節點
Swarm initialized: current node (qbia02mk2as1k1j27qevxe623) is now a manager.
# 如果以worker節點加入到這個集群,運行以下命令
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0dakw28f2r0amjeb5wr32i69i2fdfpv4eers78lwkyhibxc547-9bdz0yt7jiaqdxx9exmve7ky8 172.18.213.61:2377
# 如果以管理節點加入到該集群,運行命令生成token令牌
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
# 以管理節點加入到該集群,運行如下命令
[root@docker001 ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0dakw28f2r0amjeb5wr32i69i2fdfpv4eers78lwkyhibxc547-b9ghpo4knegpp3b5hp77q8y2k 172.18.213.61:2377
2 在docker002服務器上(manager管理節點)
[root@docker002 ~]# docker swarm join --token SWMTKN-1-0dakw28f2r0amjeb5wr32i69i2fdfpv4eers78lwkyhibxc547-b9ghpo4knegpp3b5hp77q8y2k 172.18.213.61:2377
3 在docker003服務器上(worker工作節點)
[root@docker003 ~]# docker swarm join --token SWMTKN-1-0dakw28f2r0amjeb5wr32i69i2fdfpv4eers78lwkyhibxc547-9bdz0yt7jiaqdxx9exmve7ky8 172.18.213.61:2377
4 在docker004服務器上(worker工作節點)
[root@docker004 ~]# docker swarm join --token SWMTKN-1-0dakw28f2r0amjeb5wr32i69i2fdfpv4eers78lwkyhibxc547-9bdz0yt7jiaqdxx9exmve7ky8 172.18.213.61:2377
5 測試查看
# 在manager節點,不然命令會報錯
# 雙主雙從模式 該模式存在問題,不推薦使用
[root@docker001 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
qbia02mk2as1k1j27qevxe623 * docker001 Ready Active Leader 20.10.8
x25eceyb65w590c25yguqsy7o docker002 Ready Active Reachable 20.10.8
fpctrtqs0zlodpfl5ze2yr65r docker003 Ready Active 20.10.8
09ih2yeax5pwwkmv5kwke981y docker004 Ready Active 20.10.8
6 命令總結
# 創建swarm集群,並把該主機設置為manager管理節點
docker swarm init --advertise-addr IP地址
# 在manager管理節點上才能執行如下命令
# 查看加入manager管理節點的命令
[root@docker001 ~]# docker swarm join-token manager
To add a manager to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0dakw28f2r0amjeb5wr32i69i2fdfpv4eers78lwkyhibxc547-b9ghpo4knegpp3b5hp77q8y2k 172.18.213.61:2377
# 查看加入worker工作節點的命令
[root@docker001 ~]# docker swarm join-token worker
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0dakw28f2r0amjeb5wr32i69i2fdfpv4eers78lwkyhibxc547-9bdz0yt7jiaqdxx9exmve7ky8 172.18.213.61:2377
Raft協議
Raft協議:保證大多數節點存活才可以使用,至少節點存活>1,集群節點至少>3
所以,上面的雙主雙從的架構,假設一個節點掛了,那么其他節點也不可用
實驗:兩台manager管理節點
1 將docker001服務器的docker服務停止,模擬manager節點出現故障,可以看到另外一個manager節點也不能使用
# 停止docker服務
# 注意這里要執行2條命令,不然不能完全停止docker服務
[root@docker001 ~]# systemctl stop docker.service
[root@docker001 ~]# systemctl stop docker.socket
# 查看節點信息失敗
[root@docker001 ~]# docker node ls
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
2 在docker002上查看節點信息,也失敗
[root@docker002 ~]# docker node ls
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online. Make sure more than half of the managers are online.
結論:manager管理節點建議至少3台服務器,2台服務器沒啥意義,因為掛掉一台,另外一台也不可用
實驗:三台manager管理節點
1 在dokcer001服務器上啟動docker服務
# 啟動docker服務
[root@docker001 ~]# systemctl start docker
[root@docker001 ~]# systemctl start docker.socket
# 查看節點信息
# 可以看到該節點已經變成了Reachable,不再是Leader,但仍然是管理節點
[root@docker001 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
qbia02mk2as1k1j27qevxe623 * docker001 Ready Active Reachable 20.10.8
x25eceyb65w590c25yguqsy7o docker002 Ready Active Leader 20.10.8
fpctrtqs0zlodpfl5ze2yr65r docker003 Ready Active 20.10.8
09ih2yeax5pwwkmv5kwke981y docker004 Ready Active 20.10.8
2 在docker003服務器上離開該集群
[root@docker003 ~]# docker swarm leave
Node left the swarm.
3 在docker001服務器上查看
# 可以看到 docker003 的狀態為 down 說明已經離開了該集群
[root@docker001 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
qbia02mk2as1k1j27qevxe623 * docker001 Ready Active Reachable 20.10.8
x25eceyb65w590c25yguqsy7o docker002 Ready Active Leader 20.10.8
fpctrtqs0zlodpfl5ze2yr65r docker003 Down Active 20.10.8
09ih2yeax5pwwkmv5kwke981y docker004 Ready Active 20.10.8
4 在docker003服務器上以manager管理者加入集群
[root@docker003 ~]# docker swarm join --token SWMTKN-1-0dakw28f2r0amjeb5wr32i69i2fdfpv4eers78lwkyhibxc547-b9ghpo4knegpp3b5hp77q8y2k 172.18.213.61:2377
# 三個管理節點了
[root@docker003 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
qbia02mk2as1k1j27qevxe623 docker001 Ready Active Reachable 20.10.8
x25eceyb65w590c25yguqsy7o docker002 Ready Active Leader 20.10.8
fpctrtqs0zlodpfl5ze2yr65r docker003 Down Active 20.10.8
ssatmcxgxh0rv16mb7lvadc56 * docker003 Ready Active Reachable 20.10.8
09ih2yeax5pwwkmv5kwke981y docker004 Ready Active 20.10.8
5 將docker001服務器的docker服務停止,模擬manager節點出現故障
[root@docker001 ~]# systemctl stop docker
[root@docker001 ~]# systemctl stop docker.socket
# docker001管理節點不可用
[root@docker001 ~]# docker node ls
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
6 可以看到其他manager節點還可以繼續使用
[root@docker002 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
qbia02mk2as1k1j27qevxe623 docker001 Down Active Unreachable 20.10.8
x25eceyb65w590c25yguqsy7o * docker002 Ready Active Leader 20.10.8
fpctrtqs0zlodpfl5ze2yr65r docker003 Down Active 20.10.8
ssatmcxgxh0rv16mb7lvadc56 docker003 Ready Active Reachable 20.10.8
09ih2yeax5pwwkmv5kwke981y docker004 Ready Active 20.10.8
[root@docker003 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
qbia02mk2as1k1j27qevxe623 docker001 Down Active Unreachable 20.10.8
x25eceyb65w590c25yguqsy7o docker002 Ready Active Leader 20.10.8
fpctrtqs0zlodpfl5ze2yr65r docker003 Down Active 20.10.8
ssatmcxgxh0rv16mb7lvadc56 * docker003 Ready Active Reachable 20.10.8
09ih2yeax5pwwkmv5kwke981y docker004 Ready Active 20.10.8
7 如果再停掉一個manger管理節點,則剩下的另外一台manager管理節點也不可用
結論:集群要想高可用,建議3個主節點以上,>1台管理節點存活才可以使用,雙管理節點沒啥意義
使用swarm集群發布服務
swarm集群的好處
可以彈性擴縮容
docker run: 啟動單個docker容器
docker-compose up: 啟動單個項目(多個容器)
docker service(swarm): 啟動一個服務集群
1 創建服務
# docker run 容器啟動 不能擴縮容器功能
# docker service 服務 具有擴縮容器功能
# 目前環境 3個管理節點 1個工作節點
[root@docker001 ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
qbia02mk2as1k1j27qevxe623 * docker001 Ready Active Reachable 20.10.8
x25eceyb65w590c25yguqsy7o docker002 Ready Active Reachable 20.10.8
fpctrtqs0zlodpfl5ze2yr65r docker003 Down Active 20.10.8
ssatmcxgxh0rv16mb7lvadc56 docker003 Ready Active Leader 20.10.8
09ih2yeax5pwwkmv5kwke981y docker004 Ready Active 20.10.8
# 查看創建服務的命令幫助
[root@docker001 ~]# docker service --help
Usage: docker service COMMAND
Manage services
Commands:
create Create a new service
inspect Display detailed information on one or more services
logs Fetch the logs of a service or task
ls List services
ps List the tasks of one or more services
rm Remove one or more services
rollback Revert changes to a service's configuration
scale Scale one or multiple replicated services
update Update a service
Run 'docker service COMMAND --help' for more information on a command.
# 創建一個nginx服務
[root@docker001 ~]# docker service create -p 8888:80 --name my-nginx nginx
# 查看服務
[root@docker001 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
5582lwjnor9g my-nginx replicated 1/1 nginx:latest *:8888->80/tcp
[root@docker001 ~]# docker service ps my-nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
l1gb7cpk9ya5 my-nginx.1 nginx:latest docker001 Running Running 2 hours ago
測試訪問
docker001服務器
# 可以看到容器是隨機創建的
[root@docker001 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9879932a5b64 nginx:latest "/docker-entrypoint.…" 2 hours ago Up 2 hours 80/tcp my-nginx.1.l1gb7cpk9ya5llop42kradb93
[root@docker001 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
5582lwjnor9g my-nginx replicated 1/1 nginx:latest *:8888->80/tcp
docker002服務器
[root@docker002 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@docker002 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
5582lwjnor9g my-nginx replicated 1/1 nginx:latest *:8888->80/tcp
結論:發現docker容器即使只跑在docker001的服務器上,然而nginx服務卻可以通過這個集群中的任何一台服務器的外網IP進行訪問
2 動態擴縮容
# 動態擴容
# 第一種方法
# 加上之前創建的,總共3個副本
[root@docker001 ~]# docker service update --replicas 3 my-nginx
my-nginx
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
[root@docker001 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
5582lwjnor9g my-nginx replicated 3/3 nginx:latest *:8888->80/tcp
[root@docker001 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9879932a5b64 nginx:latest "/docker-entrypoint.…" 2 hours ago Up 2 hours 80/tcp my-nginx.1.l1gb7cpk9ya5llop42kradb93
# 動態擴容
# 第二種方法
[root@docker001 ~]# docker service scale my-nginx=5
my-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
[root@docker001 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
5582lwjnor9g my-nginx replicated 5/5 nginx:latest *:8888->80/tcp
# 動態縮容
# 方法1
[root@docker001 ~]# docker service update --replicas 2 my-nginx
my-nginx
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged
[root@docker001 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
5582lwjnor9g my-nginx replicated 2/2 nginx:latest *:8888->80/tcp
# 方法2
[root@docker001 ~]# docker service scale my-nginx=1
my-nginx scaled to 1
overall progress: 1 out of 1 tasks
1/1: running [==================================================>]
verify: Service converged
[root@docker001 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
5582lwjnor9g my-nginx replicated 1/1 nginx:latest *:8888->80/tcp
[root@docker001 ~]#
Docker swarm 只要掌握搭建集群、啟動服務、動態管理容器即可
概念總結
Swarm
集群的管理和編號,docker可以初始化一個swarm集群,其他結點可以加入(管理者,工作者)
Node
就是一個docker服務器的結點,多個結點就組成了一個網絡集群(管理者、工作者)
Service
任務,可以在管理結點或者工作結點來運行,是核心,提供用戶訪問
Task
容器內的命令、細節任務!
命令 -> 管理 -> api -> 調度 -> 工作結點(創建Task容器,維護容器)
服務副本和全局服務
調整service以什么方式運行
# 移除my-nginx服務
[root@docker001 ~]# docker service rm my-nginx
my-nginx
[root@docker001 ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
# 查看命令幫助
[root@docker001 ~]# docker service create --help
--mode string Service mode (replicated, global, replicated-job, or global-job) (default "replicated")
# 1 隨機創建一個服務,可能在管理節點也可能在工作節點
[root@docker001 ~]# docker service create --mode replicated --name test-nginx -p 8888:80
[root@docker001 ~]# docker service scale test-nginx=5
# 2 全局創建,這個會在所有的節點都創建服務,包括管理節點和工作節點
# 這里創建了4個服務
[root@docker001 ~]# docker service create --mode global --name g-nginx nginx
q8llksq08rglze7lmwd43djkv
overall progress: 4 out of 4 tasks
qbia02mk2as1: running [==================================================>]
09ih2yeax5pw: running [==================================================>]
x25eceyb65w5: running [==================================================>]
ssatmcxgxh0r: running [==================================================>]
verify: Service converged
# 3 只在工作節點運行
[root@docker001 ~]# docker service create --mode replicated-job --name job-nginx nginx
網絡模式
# 查看所有網絡
[root@docker001 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
6ea4eb855f69 bridge bridge local
ac9c1f580cc5 docker_gwbridge bridge local
6bd28b52cb44 host host local
tsxu9o5jas6w ingress overlay swarm
3f4a7bbd59f3 none null local
# 查看 ingress 網絡
[root@docker001 ~]# docker network inspect ingress
[
{
"Name": "ingress",
## 這里分別是集群中每台服務器的內網地址
"Peers": [
{
"Name": "9878bafdb90b",
"IP": "172.18.213.62"
},
{
"Name": "6d36e762e052",
"IP": "172.18.213.59"
},
{
"Name": "338c241250eb",
"IP": "172.18.213.60"
},
{
"Name": "dbf2be54f556",
"IP": "172.18.213.61"
}
]
}
]
# 網絡模式 "PublishMode":"ingress"
# Swarm:
# Overlay:
# ingress: 特殊的Overlay網絡!負載均衡的功能!ipvs vip!
其他命令
docker statck
# docker-compose 單機部署項目
# docker stack 集群部署
# 單機
docker-compose up -d wordpress.yaml
# 集群
docker stack deploy 服務名稱 --compose-file=docker-compose.yml
[root@docker001 wordpress]# pwd
/root/wordpress
[root@docker001 wordpress]# cat docker-compose.yml
version: "3.9"
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- wordpress_data:/var/www/html
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
deploy:
replicas: 2 # 這里創建了2個副本
volumes:
db_data: {}
wordpress_data: {}
# 創建並且啟動服務
[root@docker001 wordpress]# docker stack deploy my_wordpress --compose-file=docker-compose.yml
# 可以看到db服務只有一個副本,而WordPress服務有2個副本
[root@docker001 wordpress]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
stsyruc88v6n my_wordpress_db replicated 1/1 mysql:5.7
rihqk9g304m8 my_wordpress_wordpress replicated 2/2 wordpress:latest *:8000->80/tcp
可以通過在該集群服務器所在的任何外網IP訪問
docker secret
# 安全相關
# 配置密碼
# 證書
[root@docker001 wordpress]# docker secret --help
Usage: docker secret COMMAND
Manage Docker secrets
Commands:
create Create a secret from a file or STDIN as content
inspect Display detailed information on one or more secrets
ls List secrets
rm Remove one or more secrets
Run 'docker secret COMMAND --help' for more information on a command.
docker config
# 配置
[root@docker001 wordpress]# docker config --help
Usage: docker config COMMAND
Manage Docker configs
Commands:
create Create a config from a file or STDIN
inspect Display detailed information on one or more configs
ls List configs
rm Remove one or more configs
Run 'docker config COMMAND --help' for more information on a command.