如何使用 apport 获取 Docker 容器内崩溃的进程的核心转储?

如何使用 apport 获取 Docker 容器内崩溃的进程的核心转储?

我们有一堆微服务,以 docker 镜像的形式发布,并在本地运行它们以进行本地测试和在 AKS k8s 集群中运行。我们使用 ubuntu 16.04,因为 AKS 目前使用它。

我们希望在微服务在 docker 容器内崩溃时自动收集 coredump。我们已成功使用以下代码实现此目的:指示在本地环境中,但我们想使用ubuntu 批准拦截器来收集 CoreDump。

但由于以下错误,我们无法收集转储:

错误:apport(pid 26994)2020 年 4 月 9 日星期四 16:17:34:主机 pid 26979 在没有 apport 支持的容器中崩溃

docker run -d --privileged -v /var/crash:/var/crash ubuntu:16.04 /bin/sleep 50000
docker kill <CreatedContainerId>

看看 apport 在做什么看来我们必须在容器内安装 apport。没问题,创建一个包含 apport 安装的 Dockerfile:

FROM ubuntu:16.04

RUN apt-get update && apt-get install -y --no-install-recommends systemd apport && rm -rf /var/lib/apt/lists/*
RUN sed -i "s/enabled=0/enabled=1/g" /etc/default/apport
RUN sed -i "s/'problem_types'/#'problem_types'/g" /etc/apport/crashdb.conf
COPY ./super.sh /opt/super.sh
RUN ["chmod", "+x", "/opt/super.sh"]
WORKDIR /opt
ENTRYPOINT [ "/opt/super.sh" ]

其中 super.sh 是:

#!/bin/bash
service apport start
sleep 50000

但这些也会导致相同的结果。apport.socket主机/proc/<host_pid>/root/run/目录下必须有一个条目,它可能告诉 apport 它的另一个实例已在容器内启动并运行。apport.socket是激活套接字,它将要求 systemd 在容器内运行。

这不是很好

问题

  1. 有没有办法可以使用容器内的应用程序核心转储转发到主机apport
  2. apport为了正确传递核心转储集合,容器内部应该做什么?
  3. 为了实现这一点,我们真的需要在 docker 内部安装 systemd 吗?

附言

当我们注释掉 /usr/share/apport/apport 中的一些代码块时,我们实现了我们想要的行为,由

869366238 data/apport (Brian Murray 2017-11-20 08:46:52 -0800)

但这不是我们愿意接受的解决方案。

答案1

对于那些真正感兴趣的人,以下是我们的发现。

为了能够apport.socket被收听,你必须安装systemd首先。为了systemd正常运行,它必须是容器中的第一个进程,因此您必须将ENTRYPOINT命令更改为/sbin/init。为了使 apport 在容器内正常工作,您必须安装python3-systemd启用的模块systemd激活和参数传播。为了运行你的进程,你必须编写简单的单元文件,描述如何使用启动你的应用程序systemd。对于 ubuntu 18.04,您还必须安装init包才能/sbin/init运行。

如果你使用其他类型的虚拟化,比如我的情况中的 vmware(运行主机 ubuntu,docker 容器在其上运行),你也必须ConditionVirtualization=containerapport-forward.socket文件中删除,否则systemd将不会监听前面提到的激活套接字。

总而言之,这里您可以采取以下措施以使容器内的 apport 正常工作。

Dockerfile

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-bionic
COPY dotnet.service /lib/systemd/system/
RUN apt-get update && apt-get install -y --no-install-recommends \
    systemd \
    init \
    apport \
    python3-systemd && rm -rf /var/lib/apt/lists/*
RUN sed -i "s/enabled=0/enabled=1/g" /etc/default/apport && \
    sed -i "s/'problem_types'/#'problem_types'/g" /etc/apport/crashdb.conf && \
    sed -i "s/ConditionVirtualization=container//g" /lib/systemd/system/apport-forward.socket
RUN systemctl enable apport-forward.socket && \
    systemctl enable dotnet.service

# our app
COPY . /opt/app
WORKDIR /opt/app
EXPOSE 5000
ENTRYPOINT [ "/sbin/init" ]

点网服务

[Unit]
Description=My service

[Service]
Type=oneshot
ExecStart=/opt/app/MyServiceElf

[Install]
WantedBy=multi-user.target

所有这些都增加了约 65MB 的数据,这看起来很疯狂,所以我们将此问题转发至 apport 存储库

相关内容