【问题标题】:How to spawn an interactive container in an existing docker swarm?如何在现有的 docker swarm 中生成交互式容器?
【发布时间】:2021-10-10 03:09:20
【问题描述】:

注意:我已经尝试以任何我能想到的方式搜索现有答案,但我不相信那里有任何关于如何实现我所追求的信息的信息

上下文

我有一个现有的 swarm 跨多个主机运行一堆网络服务。部署通过docker-compose build && docker stack deploy 完成。一些服务包含此堆栈所针对的主要服务的功能所必需的重要状态,包括通过 CLI 与其交互时。

目标

我如何在我的 swarm 上运行的现有堆栈中创建一个临时容器,以对我的主要服务进行交互式诊断和故障排除?该服务有一个 CLI 接口,但它需要访问其他组件才能使该 CLI 运行,因此它需要完全像在 docker-compose.yml 中声明的服务一样运行。要求:

  • 我需要以临时方式运行它。这是供操作员进行故障排除的,所以我不知道我什么时候需要它
  • 它需要是交互式的,因为它需要人工进行故障排除
  • 它需要能够运行任意映像(通常是为主服务及其 CLI 构建的映像,但有时可能需要通过其他容器进行其他诊断,我不会提前知道)
  • 它需要完全访问为堆栈设置的网络和其他资源,就好像它是其中的常规预定义服务一样

到目前为止,我能做的最好的事情是:

  1. 查找运行我的服务映像的现有容器
  2. 通过 SSH 连接到运行它的 swarm 主机
  3. docker exec -ti 进入它以调用 CLI

然而,这有许多缺点:

  • 我不想弄乱已经运行的容器,它有一项重要的工作我不想意外中断,而且它的状态可能与我需要做的事情无关,我不想破坏它
  • 它依赖于安装了 CLI 的服务映像。如果我想将两者分开,我就不走运了
  • 它依赖于 一些 已经在运行的容器。如果我的服务完全关闭并处于重启循环中,我将完全被淹没,因为我无处可执行和运行我的 CLI
  • 我只能在我已经声明和运行的上下文中执行。如果我需要事先没有想到要添加的东西,很遗憾我不走运
  • 找到运行容器的特定主机并手动去那里真的很烦人

我真正想要的是docker run 的一个版本,我可以指向堆栈并说“在那里运行”,或者docker stack run,但我找不到任何类似的东西。这样做的正确方法是什么?

【问题讨论】:

    标签: docker docker-compose docker-swarm docker-stack


    【解决方案1】:

    选项 1

    将诊断服务部署为堆栈的一部分 - 一个包含有用工具的容器,入口点为 tail -f /dev/null - 使用放置约束将其部署到已知节点。

    services:
      diagnostics:
        image: nicolaka/netshoot
        command: tail -f /dev/null
      deploy:
        placement:
          constraints:
            - node.hostname == host1
    

    注意。您不必使用普通堆栈部署此服务。它可以在单独的 stack.yml 文件中。以后你可以简单地stack deploy这个文件到你的栈中,只要--prune不被使用,服务是累积的。

    选项 2

    要允许常规容器访问您的服务 - 使您的网络可连接。如果您没有明确指定网络,您可以明确声明默认网络。

    networks:
      default:
        driver: overlay
        attachable: true
    

    现在您可以使用 docker run 并通过诊断容器连接到网络:-

    docker -c manager run --rm --network <stack>_default -it nicolaka/netshoot
    

    选项 3

    第三个选项没有解决直接访问运行服务的节点的需要,也没有解决运行服务实例的需要,但它允许您在不影响服务状态和状态的情况下调查服务无需容器中的工具。

    首先执行常用命令来发现感兴趣的服务任务的节点和容器名称和 id:

    docker service ps ${service} --no-trunc --format '{{.Node}} {{.Name}}.{{.ID}}' --filter desired-state=running 
    

    然后,假设您有 docker 上下文来匹配您的节点名称: - 从 {{.Node}}、{{.Name}} 的列表中选择一个 ${node}、${container}。{{.ID }} 并运行 ubuntu 或 netshoot 等容器,将其附加到目标容器的网络命名空间。

    docker -c ${node} run --rm -it --network container:${container} nicolaka/netshoot
    

    此容器可用于在运行服务任务的上下文中执行诊断,然后关闭而不影响它。

    【讨论】:

    • 谢谢。对于选项 2,如果我有一个所有服务都使用的显式声明的非默认(即命名)网络,但它没有声明为可附加的,该怎么办?
    • 显式网络更好——只需将“default”替换为您的网络名称即可。问题是,为了允许来自非服务的连接,它需要被创建为可附加的(我认为这不是可以即时对网络进行的操作)。如果您没有可连接的网络,那么您将被困在欺骗性的情况下,以在同一节点上查找和运行侧载容器作为感兴趣的服务。
    • 我明白了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多