暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

由一起生产问题谈获取docker内部性能信息的正确姿势

开系植物园 2018-04-05
1120

        Docker是一种容器技术,它可以将应用和环境等进行打包,形成一个独立的,类似于iOSAPP形式的“应用”,这个应用可以直接被分发到任意一个支持Docker的环境中,通过简单的命令即可启动运行。

使用Docker可以让每个应用彼此相互隔离,在同一台机器上同时运行多个应用,不过他们彼此之间共享同一个操作系统。Docker的优势在于,它可以在更细的粒度上进行资源的管理,也比虚拟化技术更加节约资源。


Docker的出现极大地加快了PAAS的发展,是PAAS平台的核心,通过Docker的封装(运行环境和应用程序打包),实现了PAAS平台面向应用开发人员的运行环境快速交付和弹性扩缩能力。

Docker的使用对于传统的生产运维方式也带来了较大的改变,由于Docker的资源隔离特性(如PID Namespace隔离进程,Network Namespace隔离网络等)。在Docker容器运行所在的宿主机上无法通过传统OSnetstat等命令来获取容器进程的性能信息,需要在容器内部进行获取,而要进入容器典型的是docker提供的docker exec命令,该命令是Docker1.3版本之后提供的一个的工具,可以直接在容器内运行命令。该命令简洁有效,在生产环境上为了能够定时获取容器内进程的运行情况,我们也基于该命令集成了脚本定时运行。

然而,在某一段时间,我们的监控系统陆续发现部分服务器的SWAP交换空间使用率高。进一步查看历史使用趋势看,SWAP交换空间存在泄露的情况。登录服务器检查发现Docker守护进程内存开销较大,达到G级别,对比正常的服务器只有十几M


于是我们将服务器内存泄露的问题重点排查放在docker守护进程上,查看docker守护进程的日志,发现日志生成量非常大,达到好几个G。而正常的服务器上该日志只有几十M。查看日志发现,里面有大量的docker exec执行信息,而docker exec执行的命令便是我们用来获取容器内TCP连接数信息。我们渐渐地把问题的怀疑方向指向了服务器上部署的定时脚本上。

    为了排查脚本问题,同时避免服务器内存持续增长而对生产稳定运行造成隐患,首先我们在生产环境取消了该脚本内docker exec命令的调用,取消后观察一段时间,发现没有再出现内存使用持续增长的情况。该情况在测试环境也得到了验证。于是明确了引起内存泄露的元凶就是docker exec,下一步就是要找到原因了。

于是我们网上查了一下相关案例,均未有收获,一次偶然的机会,在通过docker inpect 命令查看容器的详细信息时会返回大量的的信息,而且由于返回的信息量过大,导致在屏幕上输出时也出现了卡顿。这时脑海中突然意识到,可能这就是问题的根本原因。再进一步查看返回的信息,发现有大量的ExecIDs的信息,查阅了相关文档后,原来该ExecIDs也与docker exec命令相关,ExecIDs相当于是执行记录,在服务器上对于容器每执行一次docker exec,就会在容器的详细信息ExecIDs内追加一条执行记录,随着定时任务脚本内的docker exec不断被调起,ExecIDs的信息会随着时间变得越来越庞大,导致docker守护进程的内存消耗越来越大,与服务器出现的内存泄露现象完全符合。


经过一番排查分析,引发问题的元凶和原因均已找到,下一步就是找到解决方案了,由于docker execdocker提供的原生命令,要解决的话,可能要升级docker版本,或者对docker重新编译了,显然难度会比较大,且存在一定的风险。最便捷的方案就是能够找到一个能够替代docker exec来进入容器的方法,经过了一番查阅后,一个nsenter命令进入了我们的视野。

nsenterlinux系统提供的一个工具,它可以用来访问进程的名字空间,而这正是我们需要的,要知道Docker容器的资源隔离就是通过名字空间,只要连上Docker容器内进程的名字空间,就能够获取到容器内的性能信息了。由于nsenterlinux的工具,并不是调用docker的接口,显然也不会出现因为记录ExecIDs信息导致大量内存占用的问题。吃一堑,长一智,在测试环境上进行了验证,没有出现服务器内存泄露的问题,最终在生产服务器上进行了部署解决了该问题。

nsenter工具的使用方法:先获取容器进程的PID号:pid=`docker inspect --format"{{.State.Pid}}" $id`,然后通过nsenter命令nsenter --target $pid --mount --uts--ipc --net --pid 命令连到容器进程上获取相关信息。

    总结,docker exec虽然是一个很不错的工具,但是在频繁执行,或者作为定时任务执行的场景下容易引发服务器内存开销增长等性能问题,对于这类场景慎用,建议可以使用linux系统的nsenter工具。


文章转载自开系植物园,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论