Docker高级——Docker Swarm集群和部署应用

创建 Swarm 集群

初始化管理节点

[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

使用 compose 文件

正如之前使用 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 集群中部署 mysqlwordpress 服务为例。

创建 secret

我们使用 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

查看 secret

使用 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

创建 MySQL 服务

$ 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 服务为例。

创建 config

新建 redis.conf 文件

port 6380

此项配置 Redis 监听 6380 端口

我们使用 docker config create 命令创建 config

[root@k8s-master ~]# docker config create redis.conf redis.conf
wjchg6thkm76p7rknrskkd751

查看 config

使用 docker config ls 命令来查看 config

[root@k8s-master ~]# docker config ls
ID                          NAME                CREATED             UPDATED
wjchg6thkm76p7rknrskkd751   redis.conf          27 seconds ago      27 seconds ago

创建 redis 服务

$ 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.conftmpfs 文件系统挂载到容器的 /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

猜你喜欢

转载自blog.csdn.net/qq_51495235/article/details/132276489