[root@k8s-master ~]# docker swarm init --advertise-addr 192.168.192.133
Swarm initialized: current node (vy95txqo3pglh478e4qew1h28) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-2kte699k2ldtsyklop1mvcg1ioekinv2nzoop9g83fu8vsrnms-87073ncbef748kvt6raj1mliy 192.168.192.133:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
[root@k8s-master ~]#
管理节点和工作节点的防火墙都要关闭
$ systemctl stpo firewalld
上一步我们初始化了一个 Swarm
集群,拥有了一个管理节点,下面我们继续在两个 Docker 主机中分别执行如下命令,创建工作节点并加入到集群中
[root@localhost ~]# docker swarm join --token SWMTKN-1-2kte699k2ldtsyklop1mvcg1ioekinv2nzoop9g83fu8vsrnms-87073ncbef748kvt6raj1mliy 192.168.192.133:2377
This node joined a swarm as a worker.
经过上边的两步,我们已经拥有了一个最小的 Swarm
集群,包含一个管理节点和一个工作节点。
在管理节点使用 docker node ls
查看集群
[root@k8s-master ~]# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
o1j5nc40q4nqdoc4pvu86jgtu * k8s-master Ready Active Leader 18.06.1-ce
nnt0btawjgep1vn6kfftnp17m localhost.localdomain Ready Active 18.06.1-ce
我们使用 docker service
命令来管理 Swarm
集群中的服务,该命令只能在管理节点运行
在创建的 Swarm
集群中运行一个名为 nginx
服务。
[root@k8s-master ~]# docker service create --replicas 3 -p 80:80 --name nginx nginx:1.13.7-alpine
hpdegwsvi05bscs97wjrmv2dw
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
使用 docker service ls
来查看当前 Swarm
集群运行的服务。
[root@k8s-master ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
hpdegwsvi05b nginx replicated 3/3 nginx:1.13.7-alpine *:80->80/tcp
使用 docker service ps
来查看某个服务的详情。
[root@k8s-master ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
hpdegwsvi05b nginx replicated 3/3 nginx:1.13.7-alpine *:80->80/tcp
[root@k8s-master ~]# docker service ps nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
hhwngdta2dje nginx.1 nginx:1.13.7-alpine k8s-master Running Running about a minute ago
kk3viynpynr2 nginx.2 nginx:1.13.7-alpine k8s-master Running Running about a minute ago
u6ddmugvrbpx \_ nginx.2 nginx:1.13.7-alpine localhost.localdomain Shutdown Rejected about a minute ago "error creating external conne…"
ju8twz34e4pk \_ nginx.2 nginx:1.13.7-alpine localhost.localdomain Shutdown Rejected about a minute ago "error creating external conne…"
qcnqsj1oh0ap \_ nginx.2 nginx:1.13.7-alpine localhost.localdomain Shutdown Rejected 2 minutes ago "error creating external conne…"
7csr1tjsiefl \_ nginx.2 nginx:1.13.7-alpine localhost.localdomain Shutdown Failed 2 minutes ago "error creating external conne…"
w6py7p1i8vfp nginx.3 nginx:1.13.7-alpine k8s-master Running Running about a minute ago
u9o91wc94z64 \_ nginx.3 nginx:1.13.7-alpine localhost.localdomain Shutdown Rejected 3 minutes ago "error creating external conne…"
使用 docker service logs
来查看某个服务的日志
[root@k8s-master ~]# docker service logs nginx
nginx.1.hhwngdta2dje@k8s-master | 10.255.0.2 - - [14/Aug/2023:06:01:37 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36" "-"
nginx.1.hhwngdta2dje@k8s-master | 2023/08/14 06:01:37 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 10.255.0.2, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.192.133", referrer: "http://192.168.192.133/"
nginx.1.hhwngdta2dje@k8s-master | 10.255.0.2 - - [14/Aug/2023:06:01:37 +0000] "GET /favicon.ico HTTP/1.1" 404 571 "http://192.168.192.133/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36" "-"
[root@k8s-master ~]#
我们可以使用 docker service scale
对一个服务运行的容器数量进行伸缩。
当业务处于高峰期时,我们需要扩展服务运行的容器数量。
$ docker service scale nginx=5
当业务平稳时,我们需要减少服务运行的容器数量。
$ docker service scale nginx=2
使用 docker service rm
来从 Swarm
集群移除某个服务。
$ docker service rm nginx
正如之前使用 docker-compose.yml
来一次配置、启动多个容器,在 Swarm
集群中也可以使用 compose
文件 (docker-compose.yml
) 来配置、启动多个服务。
在 Swarm
集群中部署 WordPress
为例进行说明。
version: "3"
services:
wordpress:
image: wordpress
ports:
- 80:80
networks:
- overlay
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
deploy:
mode: replicated
replicas: 3
db:
image: mysql
networks:
- overlay
volumes:
- db-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
deploy:
placement:
constraints: [node.role == manager]
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:
db-data:
networks:
overlay:
在 Swarm
集群管理节点新建该文件,其中的 visualizer
服务提供一个可视化页面,我们可以从浏览器中很直观的查看集群中各个服务的运行节点。
部署服务使用 docker stack deploy
,其中 -c
参数指定 compose 文件名。
[root@k8s-master ~]# docker stack deploy -c docker-compose.yml wordpress
Creating network wordpress_overlay
Creating network wordpress_default
Creating service wordpress_wordpress
Creating service wordpress_db
Creating service wordpress_visualizer
[root@k8s-master ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
i3pmffagn5kj wordpress_db replicated 0/1 mysql:latest
arf56or4vgye wordpress_visualizer replicated 0/1 dockersamples/visualizer:stable *:8080->8080/tcp
ybl36pyvr14n wordpress_wordpress replicated 0/3 wordpress:latest *:80->80/tcp
[root@k8s-master ~]# docker stack rm stop wordpress
Nothing found in stack: stop
Removing service wordpress_mysql
Removing service wordpress_web
Removing network wordpress_my-network
在动态的、大规模的分布式集群上,管理和分发 密码
、证书
等敏感信息是极其重要的工作。传统的密钥分发方式(如密钥放入镜像中,设置环境变量,volume 动态挂载等)都存在着潜在的巨大的安全风险。
Docker 目前已经提供了 secrets
管理功能,用户可以在 Swarm 集群中安全地管理密码、密钥证书等敏感数据,并允许在多个 Docker 容器实例之间共享访问指定的敏感数据。
注意:
secret
也可以在Docker Compose
中使用。
我们可以用 docker secret
命令来管理敏感信息。接下来我们在上面章节中创建好的 Swarm 集群中介绍该命令的使用。
这里我们以在 Swarm 集群中部署 mysql
和 wordpress
服务为例。
我们使用 docker secret create
命令以管道符的形式创建 secret
[root@k8s-master ~]# openssl rand -base64 20 | docker secret create mysql_password -
pq1yxd5ztpcpu5ygucnintlsw
[root@k8s-master ~]# openssl rand -base64 20 | docker secret create mysql_root_password -
o1cazb12n97hpeyv5yfeg40hr
使用 docker secret ls
命令来查看 secret
[root@k8s-master ~]# docker secret ls
ID NAME DRIVER CREATED UPDATED
pq1yxd5ztpcpu5ygucnintlsw mysql_password 35 seconds ago 35 seconds ago
o1cazb12n97hpeyv5yfeg40hr mysql_root_password 28 seconds ago 28 seconds ago
$ docker network create -d overlay mysql_private
$ docker service create \
--name mysql \
--replicas 1 \
--network mysql_private \
--mount type=volume,source=mydata,destination=/var/lib/mysql \
--secret source=mysql_root_password,target=mysql_root_password \
--secret source=mysql_password,target=mysql_password \
-e MYSQL_ROOT_PASSWORD_FILE="/run/secrets/mysql_root_password" \
-e MYSQL_PASSWORD_FILE="/run/secrets/mysql_password" \
-e MYSQL_USER="wordpress" \
-e MYSQL_DATABASE="wordpress" \
mysql:latest
如果你没有在 target
中显式的指定路径时,secret
默认通过 tmpfs
文件系统挂载到容器的 /run/secrets
目录中。
$ docker service create \
--name wordpress \
--replicas 1 \
--network mysql_private \
--publish target=30000,port=80 \
--mount type=volume,source=wpdata,destination=/var/www/html \
--secret source=mysql_password,target=wp_db_password,mode=0444 \
-e WORDPRESS_DB_USER="wordpress" \
-e WORDPRESS_DB_PASSWORD_FILE="/run/secrets/wp_db_password" \
-e WORDPRESS_DB_HOST="mysql:3306" \
-e WORDPRESS_DB_NAME="wordpress" \
wordpress:latest
在动态的、大规模的分布式集群上,管理和分发配置文件也是很重要的工作。传统的配置文件分发方式(如配置文件放入镜像中,设置环境变量,volume 动态挂载等)都降低了镜像的通用性。
在 Docker 17.06 以上版本中,Docker 新增了 docker config
子命令来管理集群中的配置信息,以后你无需将配置文件放入镜像或挂载到容器中就可实现对服务的配置。
注意:
config
仅能在 Swarm 集群中使用。
这里我们以在 Swarm 集群中部署 redis
服务为例。
新建 redis.conf
文件
port 6380
此项配置 Redis 监听 6380
端口
我们使用 docker config create
命令创建 config
[root@k8s-master ~]# docker config create redis.conf redis.conf
wjchg6thkm76p7rknrskkd751
使用 docker config ls
命令来查看 config
[root@k8s-master ~]# docker config ls
ID NAME CREATED UPDATED
wjchg6thkm76p7rknrskkd751 redis.conf 27 seconds ago 27 seconds ago
$ docker service create \
--name redis \
# --config source=redis.conf,target=/etc/redis.conf \
--config redis.conf \
-p 6379:6380 \
redis:latest \
redis-server /redis.conf
如果你没有在 target
中显式的指定路径时,默认的 redis.conf
以 tmpfs
文件系统挂载到容器的 /config.conf
。
经过测试,redis 可以正常使用。
以前我们通过监听主机目录来配置 Redis,就需要在集群的每个节点放置该文件,如果采用 docker config
来管理服务的配置信息,我们只需在集群中的管理节点创建 config
,当部署服务时,集群会自动的将配置文件分发到运行服务的各个节点中,大大降低了配置信息的管理和分发难度。
现在我们想要将 NGINX
版本升级到 1.13.12
,那么在 Swarm mode 中如何升级服务呢?
你可能会想到,先停止原来的服务,再使用新镜像部署一个服务,不就完成服务的 “升级” 了吗。
这样做的弊端很明显,如果新部署的服务出现问题,原来的服务删除之后,很难恢复,那么在 Swarm mode 中到底该如何对服务进行滚动升级呢?
答案就是使用 docker service update
命令
[root@k8s-master ~]# docker service update --image nginx:1.13.12-alpine nginx
[root@k8s-master ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
068en74dtckx mysql replicated 0/1 mysql:5.7
w352biyrmaw6 nginx replicated 3/3 nginx:1.13.12-alpine *:80->80/tcp
v2d11uspjz68 redis replicated 1/1 redis:latest *:6379->6380/tcp
现在假设我们发现 nginx
服务的镜像升级到 nginx:1.13.12-alpine
出现了一些问题,我们可以使用命令一键回退
[root@k8s-master ~]# docker service rollback nginx
nginx
[root@k8s-master ~]# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
068en74dtckx mysql replicated 0/1 mysql:5.7
w352biyrmaw6 nginx replicated 2/3 nginx:1.13.7-alpine *:80->80/tcp
v2d11uspjz68 redis replicated 1/1 redis:latest *:6379->6380/tcp