我们有一堆微服务,以 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 在容器内运行。
问题
- 有没有办法可以使用容器内的应用程序核心转储转发到主机
apport
? apport
为了正确传递核心转储集合,容器内部应该做什么?- 为了实现这一点,我们真的需要在 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=container
从apport-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 存储库