7

在我们的项目中,我们继承了包含一些服务堆栈的 Docker 环境。

我注意到 Docker 一旦面临内存限制就会重新启动堆栈。

不幸的是,根据我在 Docker 网站上的问题,我没有找到任何信息,所以我在这里问:

  1. 这种行为是可配置的吗?例如,我不希望 Docker 在任何情况下都重新启动我的堆栈。如果它是可配置的,那么如何配置?
  2. 是否有任何 docker 日志来保持任何堆栈在其条目时重新启动?
4

2 回答 2

14
  1. 这种行为是可配置的吗?例如,我不希望 Docker 在任何情况下都重新启动我的堆栈。如果它是可配置的,那么如何配置?

使用版本 3 堆栈,重新启动策略移至部署部分:

version: '3'
services:
  crash:
    image: busybox
    command: sleep 10
    deploy:
      restart_policy:
        condition: none
        # max_attempts: 2

有关这方面的文档,请访问:https ://docs.docker.com/compose/compose-file/#restart_policy

  1. 是否有任何 docker 日志来保持任何堆栈在其条目时重新启动?

根据任务历史限制(可配置docker swarm update),您可以查看服务之前运行的任务:

$ docker service ps restart_crash
ID                  NAME                  IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
30okge1sjfno        restart_crash.1       busybox:latest      bmitch-asusr556l    Shutdown            Complete 4 minutes ago
papxoq1vve1a         \_ restart_crash.1   busybox:latest      bmitch-asusr556l    Shutdown            Complete 4 minutes ago
1hji2oko51sk         \_ restart_crash.1   busybox:latest      bmitch-asusr556l    Shutdown            Complete 5 minutes ago

您可以检查任何一项任务的状态:

$ docker inspect 30okge1sjfno --format '{{json .Status}}' | jq .
{
  "Timestamp": "2018-11-06T19:55:02.208633174Z",
  "State": "complete",
  "Message": "finished",
  "ContainerStatus": {
    "ContainerID": "8e9310bde9acc757f94a56a32c37a08efeed8a040ce98d84c851d4eef0afc545",
    "PID": 0,
    "ExitCode": 0
  },
  "PortStatus": {}
}

Docker 引擎中还有一个事件历史记录,您可以查询:

$ docker events --filter label=com.docker.swarm.service.name=restart_crash --filter event=die --since 15m --until 0s
2018-11-06T14:54:09.417465313-05:00 container die f17d945b249a04e716155bcc6d7db490e58e5be00973b0470b05629ce2cca461 (com.docker.stack.namespace=restart, com.docker.swarm.node.id=q44zx0s2lvu1fdduk800e5ini, com.docker.swarm.service.id=uqirm6a8dix8c2n50thmpzj06, com.docker.swarm.service.name=restart_crash, com.docker.swarm.task=, com.docker.swarm.task.id=1hji2oko51skhv8fv1nw71gb8, com.docker.swarm.task.name=restart_crash.1.1hji2oko51skhv8fv1nw71gb8, exitCode=0, image=busybox:latest@sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812, name=restart_crash.1.1hji2oko51skhv8fv1nw71gb8)
2018-11-06T14:54:32.391165964-05:00 container die d6f98b8aaa171ca8a2ddaf31cce7a1e6f1436ba14696ea3842177b2e5e525f13 (com.docker.stack.namespace=restart, com.docker.swarm.node.id=q44zx0s2lvu1fdduk800e5ini, com.docker.swarm.service.id=uqirm6a8dix8c2n50thmpzj06, com.docker.swarm.service.name=restart_crash, com.docker.swarm.task=, com.docker.swarm.task.id=papxoq1vve1adriw6e9xqdaad, com.docker.swarm.task.name=restart_crash.1.papxoq1vve1adriw6e9xqdaad, exitCode=0, image=busybox:latest@sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812, name=restart_crash.1.papxoq1vve1adriw6e9xqdaad)
2018-11-06T14:55:00.126450155-05:00 container die 8e9310bde9acc757f94a56a32c37a08efeed8a040ce98d84c851d4eef0afc545 (com.docker.stack.namespace=restart, com.docker.swarm.node.id=q44zx0s2lvu1fdduk800e5ini, com.docker.swarm.service.id=uqirm6a8dix8c2n50thmpzj06, com.docker.swarm.service.name=restart_crash, com.docker.swarm.task=, com.docker.swarm.task.id=30okge1sjfnoicd0lo2g1y0o7, com.docker.swarm.task.name=restart_crash.1.30okge1sjfnoicd0lo2g1y0o7, exitCode=0, image=busybox:latest@sha256:2a03a6059f21e150ae84b0973863609494aad70f0a80eaeb64bddd8d92465812, name=restart_crash.1.30okge1sjfnoicd0lo2g1y0o7)

在以下位置查看有关 events 命令的更多详细信息:https ://docs.docker.com/engine/reference/commandline/events/

大型组织的最佳实践是将容器日志发送到中央位置(例如 Elastic)并在外部监控指标(例如 Prometheus/Grafana)。

于 2018-11-06T20:08:31.843 回答
1

由于您尚未在帖子中添加任何配置片段或运行时命令,因此我必须对您的实际问题做出假设。

我的假设:

  • 您正在使用 docker-compose 运行多个服务
  • 这些服务配置了内存限制(在 docker-compose.yml 文件中)
  • 您会看到它们在达到配置的内存限制后重新启动,并且您希望阻止它们重新启动

我假设您的 docker-compose.yml 如下所示:

version: '2.1'
services:
   service1:
     image: some/image
     restart: always
     mem_limit: 512m
   service2:
     image: another/image
     restart: always
     mem_limit: 512m

使用此配置,任何服务容器在尝试使用超过 512Mb 的内存时都会被内核 OOM-Killed。然后 Docker 会自动重启一个新的容器来替换被杀死的容器。

所以回答你的第一点:是的,只需将“restart”更改为“no”,或者只是删除此行(因为“no”是此参数的默认值)。至于您的第二点,只需在 docker 守护进程日志中查找服务重新启动。

但是,如果您需要保持服务正常运行,这对您没有帮助:您的服务仍会尝试使用超过其允许的内存限制,它仍然会被杀死,......并且不再自动重新启动.

最好查看服务的内存使用模式,并了解它们为什么尝试使用超过配置的限制。最终,解决方案是配置你的服务以使用更少的内存,或者mem_limit在你的 docker-compose.yml 中提高。

例如 :

  • 对于数据库服务,配置内存选项以强制引擎使用的 RAM 不超过 mem_limit(Oracle 下的 SGA 和 PGA,MySQL/MariaDB 的各种缓冲区和缓存大小,...)
  • 对于 java 应用程序,将 Xmx 配置为小于 mem_limit (记住对非堆内存的需求),或者最好使用最近的 JDK(最新的 8 或 9+)去-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap.

我希望这能帮到您; 更准确地说,我真的需要更多的上下文。

于 2018-11-06T18:57:12.237 回答