【问题标题】:Server becomes unresponsive periodically, OOM Killer inactive?服务器定期无响应,OOM Killer 不活动?
【发布时间】:2018-10-11 16:35:09
【问题描述】:

我在 AWS 上的 docker 容器中托管一个 Ruby 应用程序。不幸的是,众所周知,这个 Ruby 应用程序会泄漏内存,因此最终它会消耗所有可用内存。

我也许天真地期待 OOM 杀手被调用并杀死 Ruby 进程,但没有任何反应。最终机器变得无响应(Web 服务器没有响应,ssh 被禁用)。我们从 AWS 控制台强制重启机器,并在日志消息中得到以下信息,因此在重启时它确实是活动的:

Apr 30 23:07:14 ip-10-0-10-24 init: serial (ttyS0) main process (2947) killed by TERM signal

我不认为这是 AWS 中的资源耗尽(即信用不足)。如果我定期重新启动应用程序,服务器永远不会关闭。

  • 我没有禁用 OOM Killer 或更改任何 default docker memory config
  • 我正在运行库存 Amazon Linux AMI 版本 2017.03 内核。
  • 此行为发生在 AWS 中的多个虚拟实例中

我在这里很茫然;为什么内存压力会导致机器锁定?

【问题讨论】:

  • 您是否在运行容器时指定了限制?我还假设这是一个带有 Docker 而不是 ECS 的 EC2 实例?

标签: ruby linux amazon-web-services docker out-of-memory


【解决方案1】:

显然我提供的解决方案似乎对提出问题的人没有帮助,但它可能会帮助其他偶然发现这里的人。以下是我建议的可能导致问题的 2 件事。

建议 1

我猜你正在使用官方的 ruby​​ docker 镜像,当你运行容器时,ruby 在容器内以PID 1 运行。

如果 ruby​​ 以PID 1 运行,那么 OOM 杀手将无法杀死它,从而导致您看到的所有问题。

要解决此问题,您必须确保正确的init 进程以PID 1 运行。

Docker 1.25 及更高版本具有用于docker run 命令的--init 选项。此选项将确保正确的init 处理PID 1 的任务,它还将所有信号传递给您的 ruby​​ 应用程序。

https://docs.docker.com/engine/reference/commandline/run/

--init API 1.25+ 在容器内运行一个 init 来转发信号和获取进程

以下是 docker 使用的 init https://github.com/krallin/tini

建议 2

Amazon Linux AMI 存在一个已知问题,可在以下链接 https://github.com/aws/amazon-ecs-agent/issues/794 中找到详细信息。在撰写本文时,我不确定 AMI 的问题是否已解决。

因此,请按照该线程中的建议尝试不同的 AMI,比如 Ubuntu AMI。

【讨论】:

  • 我使用的是passenger-full,这是一个由 Phusion 创建的基础镜像。它们有一个底层的初始化系统,所以 ruby​​ 进程不是 PID 1。
  • @EightyEight 哦,好的。在这种情况下,您是否看到以下问题github.com/aws/amazon-ecs-agent/issues/794。关于amazon linux ami中的一个bug,如果是这样的话,你可以试试Ubuntu
【解决方案2】:

我认为您假设 OOM 将始终针对您的 Ruby 应用程序,但我认为情况并非如此。您的日志行显示它杀死了您的 tty 连接。我打赌它会在你的 Ruby 进程之前杀死其他进程,这就是你的机器看起来没有响应的原因。您可以阅读 OOM 的工作原理,这可能会有所帮助。我会专门查看你的 oom_scores,看看你在那里找到了什么。

http://www.oracle.com/technetwork/articles/servers-storage-dev/oom-killer-1911807.html

祝你好运

【讨论】:

  • 感谢您的评论达雷尔。据我所知,您提到的事件是由系统重启触发的,而不是 OOM。
  • 没错,我错了。您是否确定 ruby​​ 容器在主机变暗之前消耗了所有内存?这可能是其他一些资源耗尽问题。你能得到一些下一个时间间隔的过程监控数据吗?
  • 达雷尔,什么样的信息会有帮助?应用程序服务器生成一组 ruby​​ 工作进程来处理 Web 请求。各个进程不断消耗更多内存。我有一个看门狗(monit),当它们达到阈值(通常约为 800 兆)时,它会杀死单个 ruby​​ 进程。对我来说,这暗示内存消耗是罪魁祸首。我没有看到任何不寻常的地方。
  • 为了快速和肮脏,我会抓取 cpu 和内存数据并将它们转储到一个文件中,理想情况下,您可以远程观看。我将使用单独的 EFS 共享并创建一个运行此 uptime && free && (ps aux --sort -rss | head) && echo threads=$(ps -eLf | wc -l) 的 cron'd 或循环,这应该让您知道它是内存、线程还是只是一般负载。祝你好运
猜你喜欢
  • 2021-12-02
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
  • 2017-06-15
  • 2016-10-18
  • 1970-01-01
  • 2011-02-28
  • 2016-06-17
相关资源
最近更新 更多