一、什么是 Docker Stack

Docker Stack 是 Docker Swarm 环境中用于管理一组相关服务的工具。它使得在 Swarm 集群中部署、管理和扩展一组相互关联的服务变得简单。主要用于定义和编排容器化应用的多个服务。以下是 Docker Stack 的一些关键特点:

  1. 服务集合:Docker Stack 允许你在一个配置文件中定义应用的多个服务。这个配置文件通常是一个 docker-compose.yml 文件,定义了应用的服务、网络和卷。
  2. 简化部署:通过使用 docker stack deploy 命令,你可以一次性部署整个应用的所有服务。
  3. 配置管理:Docker Stack 允许你使用单个配置文件来管理多个服务的配置,这使得部署和更新变得更加一致和方便。
  4. 服务编排:它提供了高级的服务编排功能,如服务间的网络配置和卷挂载。
  5. 适用于生产环境:Docker Stack 被设计用于在生产环境中的 Docker Swarm 集群,提供了额外的可靠性和扩展性。
  6. 集群范围内的资源分配:Docker Stack 可以在集群的所有节点上分配和管理服务。

总而言之,Docker Stack 是 Docker Swarm 中的一个高级特性,用于在集群环境中管理复杂的多服务应用。它基于 Docker Compose 文件格式,但扩展了这种格式的功能,以适应集群和大规模部署的需求。

二、Docker Stack 使用示例

1、Docker Stack 结合 Docker Compose 部署单节点服务

以下是一个简单的 Docker Stack 使用示例,展示了如何在 Docker Swarm 环境中部署一个多服务的应用程序。在这个例子中,我们将部署一个包含两个服务的应用:一个 Web 服务(使用 Nginx)和一个数据库服务(使用 Redis)。

步骤 1: 创建 Docker Compose 文件

首先,创建一个名为 docker-compose.yml 的文件,其中定义了你的服务。这个文件应该看起来像这样:

version: '3'
services:
  web:
    image: nginx
    ports:
      - "80:80"
    deploy:
      replicas: 2
      update_config:
        parallelism: 2
        delay: 10s
      restart_policy:
        condition: on-failure
  redis:
    image: redis
    ports:
      - "6379:6379"
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure

这个配置文件定义了两个服务:webredisweb 服务使用了 Nginx 镜像,而 redis 服务使用了 Redis 镜像。每个服务都配置了端口映射、副本数量和重启策略。

步骤 2: 初始化 Docker Swarm

确保 Docker Swarm 模式被激活。如果尚未初始化 Swarm,可以在 Docker 主机上运行以下命令:

docker swarm init --advertise-addr <MANAGER-IP>

这里 <MANAGER-IP> 是管理节点的 IP 地址。这个命令会生成一个加入集群的令牌。

步骤 3: 部署 Stack

使用以下命令部署 Stack:

docker stack deploy -c docker-compose.yml mystack

这里 mystack 是你的 Stack 的名字。

注意:部署过程需要一点时间,稍微等一会儿,docker swarm会自动在各个节点启动服务
如果你需要更新服务,只需修改docker-compose.yml文件,然后再次运行docker stack deploy命令。

步骤 4: 验证部署

部署完成后,你可以使用以下命令来查看 Stack 的状态:

docker stack services mystack

使用docker service ls也可以查看

这将显示 Stack 中每个服务的状态,包括它们的副本数量和当前状态。

服务显示如下:

ID             NAME            MODE         REPLICAS   IMAGE          PORTS
mf47e9xz5cuq   mystack_redis   replicated   1/1        redis:latest   *:6379->6379/tcp
rhtrr5fw44k3   mystack_web     replicated   2/2        nginx:latest   *:80->80/tcp

步骤 5: 更新和移除 Stack

  • 如果你需要更新服务,只需更改 docker-compose.yml 文件并重新运行 docker stack deploy 命令。
  • 要移除 Stack,可以使用以下命令:
docker stack rm mystack

注意事项

  • 确保 docker-compose.yml 文件的格式正确。
  • 在生产环境中使用之前,建议进行充分的测试。

这个例子提供了一个基本的 Docker Stack 使用场景。实际使用中,你可能需要根据具体需求调整配置。更多详细信息和高级用法,可以参考 Docker 官方文档。

2、Docker Stack 部署多节点示例

在 Docker Swarm 集群中需要有多个节点才能展示其集群管理和服务调度的功能。
在多节点环境中,需要先设置一个 Docker Swarm 集群。

以下是在多节点 Docker Swarm 集群中部署服务的步骤:

设置 Docker Swarm 集群

  1. 选择一个管理节点(Manager Node):在你选择的管理节点上运行以下命令来初始化 Swarm 集群:
docker swarm init

这个命令会生成一个加入集群的令牌。

  1. 将其他节点加入到集群:在其他 Docker 节点上,使用初始化时生成的令牌来加入 Swarm 集群。在每个要加入的节点上运行以下命令:
docker swarm join --token [TOKEN] [MANAGER_IP]:2377

这里 [TOKEN] 是初始化时生成的令牌,[MANAGER_IP] 是管理节点的 IP 地址。

部署服务到 Swarm 集群

一旦集群设置完成,你就可以按照之前的步骤(创建 docker-compose.yml 文件和使用 docker stack deploy 命令)来部署你的服务。

确保 Swarm 集群正确配置并且所有节点都是活跃的是服务部署成功的关键。如果只有单个节点,Docker Stack 仍然可以工作,但是它的集群功能就不会体现出来。

这种方式可以更好地展示 Docker Stack 在多节点环境中的能力,尤其是在进行负载均衡和容错等高级功能时。更多关于 Docker Swarm 和 Docker Stack 的细节,可以参考 Docker 的官方文档。

三、服务发现机制

Docker Swarm 的服务发现机制是一种自动识别和定位集群中服务的方法。服务发现对于任何分布式系统,尤其是大型的、基于容器的环境非常重要。在Docker Swarm中,服务发现使得容器可以相互寻找并进行通信,即使它们可能在集群的不同节点上运行。

1、如何工作

在Docker Swarm中,服务发现通常通过以下几种方式实现:

  1. 内部DNS服务
  • Swarm集群有一个内部的DNS服务,当你在Swarm中创建服务时,Swarm会为这个服务的每个实例(即容器)创建一个DNS条目。
  • 这意味着服务之间可以通过服务名进行通信,而不必关心实际容器的IP地址。
  1. 服务发现的关键组件
  • 服务名称:在Swarm集群中创建服务时,你会为其指定一个名称,这个名称用于内部DNS解析。
  • 负载均衡:Swarm使用内置的负载均衡器来分发请求到不同的容器实例。

举例说明

假设你有一个由多个微服务组成的应用,其中有一个名为web的前端服务和一个名为db的数据库服务。

  1. 创建服务
  • 你在Swarm中部署这两个服务,分别命名为webdb
  1. 服务间通信
  • web服务的容器需要访问db服务。在web服务的容器中,你可以简单地使用db这个名称来引用数据库服务,而不需要知道它的具体IP。
  • web服务尝试连接到db时,Swarm的内部DNS服务会解析db到正确的IP地址。
  1. 动态扩展
  • 如果db服务需要扩展,你可以在Swarm中简单地增加更多的db容器实例。
  • web服务无需任何改变,因为它只是通过服务名db与数据库服务通信,Swarm会自动处理负载均衡和服务发现。

这种机制简化了服务配置和扩展,因为服务可以动态发现并与集群中的其他服务通信,而无需手动配置每个容器的网络设置。

2、示例:Docker Swarm 服务发现

让我们通过一个具体的例子来深入理解 Docker Swarm 的服务发现机制。假设我们有一个简单的应用程序,它包括两个服务:一个 Web 应用(前端)和一个数据库(后端)。我们将使用 Docker Swarm 来部署这些服务,并展示如何利用服务发现来实现它们之间的通信。

1)环境准备

  1. 安装 Docker:首先确保在所有节点上安装了 Docker。
  2. 初始化 Swarm:在主节点上运行 docker swarm init 来初始化 Swarm 集群。
  3. 添加工作节点:在其他节点上使用 docker swarm join 命令来加入 Swarm 集群。

2)步骤

步骤 1: 创建网络

在 Swarm 集群中创建一个叠加网络(overlay network)以便不同节点上的容器可以相互通信。

docker network create --driver=overlay my_overlay_network
步骤 2: 部署数据库服务

创建一个名为 db 的数据库服务。这里我们假设使用 PostgreSQL。

docker service create --name db --network my_overlay_network postgres:latest
步骤 3: 部署 Web 应用服务

创建一个名为 web 的 Web 应用服务,并确保它连接到同一个网络。

docker service create --name web --network my_overlay_network my_web_app_image

在这个例子中,my_web_app_image 是你的 Web 应用的 Docker 镜像。

步骤 4: 服务发现

现在,web 服务需要连接到 db 服务。在 Web 应用的配置中,你可以直接使用服务名 db 作为数据库的主机名。例如,如果你的 Web 应用使用环境变量来配置数据库连接,可以这样设置:

DATABASE_HOST=db
步骤 5: Swarm 的内部 DNS

web 服务中的容器尝试连接到 db 时,Swarm 的内部 DNS 服务会自动解析 db 为数据库服务的当前 IP 地址。即使 db 服务的容器迁移到了集群中的另一个节点,web 服务仍然可以通过名为 db 的 DNS 记录找到它。

步骤 6: 扩展和负载均衡

如果你需要扩展数据库服务以处理更多的负载,可以简单地增加 db 服务的副本数:

docker service scale db=3

Swarm 会自动在集群中分配并启动额外的 db 容器。由于内置的负载均衡,web 服务会在所有 db 容器实例之间分配请求,而无需任何额外配置。

3)总结

通过这个例子,我们看到了 Docker Swarm 的服务发现机制如何使得服务之间的通信变得简单和自动化。服务只需使用服务名来相互引用,Swarm 会处理所有的网络细节,包括 DNS 解析和负载均衡。这大大简化了分布式应用的管理和扩展。

3、示例:Docker Stack 服务发现

使用 docker stack 配合 docker-compose.yml 文件可以更加方便地管理和部署多服务应用。以下是一个示例,展示了如何使用 Docker Stack 和 Docker Compose 来部署一个包含 Web 应用和数据库服务的简单应用,同时展示服务发现的工作方式。

1)环境准备

  1. 安装 Docker:确保所有节点上安装了 Docker。
  2. 初始化 Swarm:在主节点上运行 docker swarm init 来初始化 Swarm 集群。
  3. 添加工作节点:在其他节点上使用 docker swarm join 命令来加入 Swarm 集群。

2)创建 docker-compose.yml 文件

创建一个 docker-compose.yml 文件,其中定义了 Web 应用和数据库服务。这个文件也定义了所需的网络。

version: '3.7'

services:
  web:
    image: my_web_app_image
    ports:
      - "80:80"
    networks:
      - my_overlay_network
    deploy:
      replicas: 2
      restart_policy:
        condition: on-failure
    environment:
      - DATABASE_HOST=db

  db:
    image: postgres:latest
    networks:
      - my_overlay_network
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
    environment:
      - POSTGRES_DB=mydatabase
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password

networks:
  my_overlay_network:
    driver: overlay

在这个文件中:

  • Web 服务 (web):使用自定义的 Web 应用镜像,映射端口 80,并设置环境变量 DATABASE_HOST 指向数据库服务。
  • 数据库服务 (db):使用 PostgreSQL 镜像,并定义了一些基本的环境变量。
  • 网络 (my_overlay_network):定义了一个叠加网络,允许服务间的通信。

3)部署服务

在 Swarm 集群的管理节点上,运行以下命令来部署这些服务:

docker stack deploy -c docker-compose.yml myapp

这个命令会根据 docker-compose.yml 文件的定义,在 Swarm 集群中部署 Web 和数据库服务。

4)服务发现

在这个配置中,Web 服务可以通过简单地使用 db 作为主机名来连接数据库。Swarm 集群内的内部 DNS 解析将自动将 db 解析为正确的数据库服务地址。这意味着即使数据库服务移动到集群中的不同节点,Web 应用也能够无缝地找到并连接到数据库服务。

5)扩展服务

如果需要扩展 Web 服务以处理更多的流量,你可以简单地更新 docker-compose.yml 文件中的 replicas 设置,然后再次运行 docker stack deploy 命令。Swarm 会自动更新服务配置并实现扩展。

6)总结

通过结合 Docker Stack 和 Docker Compose,我们可以轻松管理复杂的多服务应用,并利用 Docker Swarm 的服务发现功能,使得服务间的通信变得简单和高效。这种方式特别适合于生产环境中的应用部署和管理。

4、用于服务发现的网络类型 Overlay

在 Docker Swarm 环境中,使用 overlay 网络是至关重要的,尤其是在跨多个主机部署容器时。这是因为 overlay 网络提供了几个关键功能,使得在分布式和多主机环境中的容器通信成为可能。

1. 跨主机通信

  • 连接多个主机:Overlay 网络允许不同主机上的容器彼此通信,就好像它们在同一个主机上一样。在没有 overlay 网络的情况下,容器只能与同一主机上的其他容器通信。

2. 隔离和安全

  • 隔离网络流量:Overlay 网络为每个服务提供了独立的网络环境,这意味着服务之间的通信是隔离的,从而增加了安全性。
  • 加密通信:在某些配置中,overlay 网络还可以对跨主机的容器通信进行加密,提供额外的安全层。

3. 负载均衡和服务发现

  • 内置服务发现:Overlay 网络支持 Docker Swarm 的内置服务发现功能,使得服务可以通过服务名称相互发现和通信,而不需要知道对方的具体 IP 地址。
  • 支持负载均衡:Overlay 网络也支持 Docker Swarm 的负载均衡功能,可以自动在同一服务的不同容器实例之间分配流量。

4. 可伸缩性和灵活性

  • 动态伸缩:Overlay 网络支持在不同的主机上动态启动和停止容器,而无需手动重新配置网络。
  • 适合大规模部署:由于其跨主机通信和负载均衡能力,overlay 网络非常适合于大规模、分布式的容器部署。

5. 网络抽象

  • 简化网络配置:Overlay 网络提供了一个抽象层,隐藏了底层的网络复杂性,使得用户可以简单地通过服务名称来进行通信,而不必担心底层的网络细节。

总结

在 Docker Swarm 环境中,overlay 网络是实现跨主机容器通信、服务发现、负载均衡以及网络隔离和安全的关键组件。它为在分布式环境中运行的容器提供了必要的网络特性和功能,是构建和管理大规模容器化应用的重要基础。

虽然其他网络类型在特定场景下有其应用价值,但在 Docker Swarm 环境中,当涉及到跨主机的容器通信和集群管理时,overlay 网络因其支持服务发现、负载均衡、跨主机通信以及网络隔离等特性,通常是最佳选择。Bridge、host、none 和 macvlan 网络各有其特点和适用场景,但它们不支持 Swarm 集群中跨主机容器间的直接通信,这限制了它们在分布式应用和服务中的应用。

四、docker-compose.yml 中 deploy 配置

docker-compose.yml 文件中,deploy 部分包含了与 Docker Swarm 模式相关的一系列配置选项。这些配置专门用于调整和控制在 Swarm 集群上部署服务时的行为。

以下是一些主要的配置项及其详细说明:

1. replicas

  • 说明:定义服务的副本数量。
  • 用途:用于指定 Swarm 集群应该运行多少个该服务的实例。
  • 默认:1

2. update_config

  • 说明:控制服务更新时的行为。
  • 子选项
  • parallelism:一次更新的容器数量。
  • delay:更新批次之间的延迟时间。
  • failure_action:更新失败时的操作(如暂停、回滚)。默认 pause
  • monitor:在认定更新失败之前等待的时间。
  • max_failure_ratio:允许更新失败的容器比例。
  • order:更新顺序(例如,先停止再启动或先启动再停止)。默认stop-first

3. rollback_config

  • 说明:定义服务回滚到之前版本时的行为(与 update_config 类似)。
  • 子选项:与 update_config 相似,包括 parallelismdelay 等。

4. restart_policy

  • 说明:定义服务容器的重启策略。
  • 子选项
  • condition:重启的条件(例如,任何时候、失败时或不重启)。
  • delay:重启之间的延迟时间。
  • max_attempts:在放弃之前尝试重启的最大次数。
  • window:考虑重启尝试的时间窗口。

5. resources

  • 说明:设置服务容器的资源限制和保留。
  • 子选项
  • limits:资源使用的上限(如 CPU、内存)。
  • reservations:保留给服务的最低资源。

6. placement

  • 说明:定义服务容器的放置策略。
  • 子选项
  • constraints:约束条件,用于指定哪些节点可以运行服务的容器(例如,基于节点的角色或标签)。

7. labels

  • 说明:为服务定义元数据标签。
  • 用途:用于添加描述性信息,可以用于服务的分类和管理。

8. mode

  • 说明:指定服务的部署模式。
  • 选项
  • replicated:运行指定数量的副本(默认)。
  • global:在每个集群节点上运行一个服务实例。

9. endpoint_mode

  • 说明:定义服务暴露方式。
  • 选项
  • vip(Virtual IP):服务通过一个虚拟IP进行访问,Swarm 会自动进行负载均衡。
  • dnsrr(DNS Round Robin):通过 DNS 轮询方式访问服务。

表格整理如下

配置项

说明

默认值

使用示例

replicas

设置服务副本的数量

1

replicas: 3

update_config

控制服务更新时的行为

-

update_config: { parallelism: 2, delay: 10s }

- - parallelism

一次更新的容器数量

-

parallelism: 2

- - delay

更新批次之间的延迟时间

-

delay: 10s

- - failure_action

更新失败时的操作

pause

failure_action: rollback

- - monitor

在认定更新失败前等待的时间

-

monitor: 30s

- - max_failure_ratio

允许更新失败的容器比例

-

max_failure_ratio: 0.3

- - order

更新顺序

stop-first

order: start-first

rollback_config

定义服务回滚到之前版本时的行为

-

rollback_config: { parallelism: 1 }

restart_policy

定义服务容器的重启策略

-

restart_policy: { condition: on-failure }

- - condition

重启的条件

any

condition: on-failure

- - max_attempts

在放弃前尝试重启的最大次数

-

max_attempts: 5

- - window

考虑重启尝试的时间窗口

-

window: 120s

resources

设置服务容器的资源限制和保留

-

resources: { limits: { cpus: '0.50', memory: 50M } }

- - limits

资源使用的上限

-

limits: { cpus: '0.50', memory: 50M }

- - reservations

保留给服务的最低资源

-

reservations: { cpus: '0.25', memory: 20M }

placement

定义服务容器的放置策略

-

placement: { constraints: [node.role == manager] }

- - constraints

节点放置约束

-

constraints: [node.role == manager]

labels

为服务定义元数据标签

-

labels: [key=value]

mode

指定服务的部署模式

replicated

mode: global

endpoint_mode

定义服务暴露方式

vip

endpoint_mode: dnsrr

总结

deploy 部分的配置项专为 Docker Swarm 模式设计,提供了一系列强大的工具来管理服务的部署和运行。通过这些配置项,可以精细地控制服务的扩展、更新、资源分配和位置放置,使得在 Swarm 集群中运行的服务更加灵活和高效。

五、使用 Docker Stack 注意事项

当使用 Docker Stack 结合 Docker Compose 来部署和管理服务时,有几个重要事项需要考虑。这些事项确保你的部署流程顺畅,同时也确保你充分利用了 Docker Stack 和 Compose 的特性。

1. Docker Compose 文件版本

  • 使用与 Docker Swarm 兼容的 Docker Compose 文件版本。截至目前(2023年),推荐使用版本 3.7 或更高版本,Docker Swarm 模式支持的最低 Docker Compose 文件版本是 3.0

2. 服务定义

  • 服务配置:确保正确定义服务,包括镜像、端口映射、环境变量等。
  • 副本数量:通过 deploy.replicas 设置服务的副本数量,以实现负载均衡和高可用性。
  • 资源限制:可以设置资源限制(如 CPU 和内存限制)来确保服务不会消耗过多资源。

3. 网络配置

  • 使用 Overlay 网络:确保定义 overlay 网络以实现跨主机容器通信。
  • 服务间通信:服务应该连接到同一个 overlay 网络,以便它们可以相互通信。

4. 部署策略

  • 更新策略:通过 deploy.update_config 定义服务更新时的行为(例如,滚动更新)。
  • 重启策略:配置 deploy.restart_policy 来控制服务容器在失败时的重启行为。

5. 数据卷和持久化

  • 数据持久化:如果服务需要持久化数据,应该正确配置数据卷。
  • 数据卷位置:确保数据卷对所有主机都可访问,或使用集群内的存储解决方案。

6. 环境差异

  • 适应不同环境:可能需要为不同环境(如开发、测试和生产)准备不同的 Compose 文件或配置。

7. 安全性和隔离

  • 配置安全选项:考虑安全性,比如是否需要加密 overlay 网络,以及如何管理敏感数据(例如,通过 Docker Secrets)。

8. 日志和监控

  • 日志配置:配置适当的日志驱动,以便能够集中收集和分析日志。
  • 监控和健康检查:配置健康检查和监控系统,以确保服务的健康和性能。

9. 兼容性检查

  • Docker Engine 版本:确保所有 Swarm 节点上的 Docker Engine 版本兼容你的 Docker Compose 文件。
  • 测试部署:在正式部署之前,在测试环境中测试你的 Compose 文件。

10. 清理和维护

  • 服务更新和清理:了解如何更新和清理旧服务及其资源,以避免配置混乱或资源浪费。