开发人员是否在为JVM、内存和Docker苦苦挣扎?今天我们就用Jelastic来一起解决。MattWilliams提出的Java及其在Docker中的内存限制的话题最近受到广泛关注,而这些容器使用中不可避免的条件也在Twitter上引发了一系列讨论。那么在今天的文章中,让我们一起来分析一下这个问题,并尝试找出解决的办法。问题Matt讲述了他在Docker容器内使用JVM堆时的发现之旅。他指出容器的内存限制没有正确显示,这导致任何Java或其他应用程序都可以分配宿主设备的所有内存资源,而JVM无法指示该资源有多少应该专用于父级它正在运行。容器。于是开始出现OutOfMemoryError。事实上,大多数Linux工具都提供了比cgroups更早创建的系统资源指标(例如free和top,均源自procps)。它通常从proc文件系统读取内存指标:/proc/meminfo、/proc/vmstat、/proc/PID/smaps或其他位置。不幸的是,/proc/meminfo、/proc/vmstat等位置无法容器化,即无法被cgroups识别。它只能显示宿主系统(物理机或虚拟机)的整体内存容量,无法被现代Linux容器技术所利用。容器中的进程不能依赖free、top等指标来确定自己可以使用的内存量;它必须遵循cgroups提供的约束,并且不能使用主机系统中的所有内存。事实上,了解实际内存限制对于应用程序优化和故障排除至关重要,例如内存泄漏、交换空间使用、性能下降等。此外,一些用例需要垂直扩展来优化容器内的资源使用,包括自动更改工作程序、进程或线程的数量。垂直缩放通常取决于特定容器可用的实际内存量,因此它必须在容器中的可见性有限的情况下工作。解决方案opencontainerinitiative配合runC使用文件系统用户空间覆盖/proc文件。LXC创建的lxcfs文件系统让容器拥有虚拟的cgroup文件系统和虚拟的/proc文件查看方式,所以上述问题的本质是如何维护容器。我们也遇到了类似的问题,但是在Jelastic的帮助下,我们成功地为我们的客户解决了这个障碍。让我们看看具体的方法。首先打开Jelastic向导,为测试账户选择服务提供商并创建一组具有预定义内存限制的JavaDocker容器——例如8个cloudlets,相当于1GB内存。接下来转到JelasticSSHgate(1),选择之前创建的测试环境(2),然后选择容器(3)。现在我们可以使用免费工具来检查可用内存(4)。正如我们所见,内存限制等于之前定义的1GB。让我们检查一下顶级工具。一切正常。为了进一步检查,我们重复了Matt之前提到的Java启发式行为问题。当前的MaxHeapSize=268435546(~256MiB),也就是说当前容器的内存容量是默认JVM堆的四分之一。秘诀是什么?当然,这是各种“成分”的完美结合。本例中,我们将OpenVZ与Docker技术相结合,提供更好的安全性和隔离控制效果,同时保证不会影响容器热迁移、容器休眠等必要功能。下面,你可以看到Docker容器在Jelastic中的高级应用思路。在OpenVZ中,每个容器都有一个/proc伪文件系统的虚拟化视图。应该强调的是,容器中的/proc/meminfo是一个“自定义”版本,它显示每个容器的信息,而不是直接从主机中提取信息。这样,top和free等工具在容器中运行时,可以在遵守约束的情况下显示特定容器中的内存和swap使用情况。值得注意的是,容器中的swap并不是真正的swap,只是一种虚拟的机制(所以它的整体技术叫做VSwap)。其核心思想是,一旦启用了VSwap的容器超过了配置的内存限制,其部分内存将被转换为所谓的交换缓存。没有真正的空间交换发生,这意味着没有I/O-除非整个环境存在全局(而不是每个容器)内存短缺。另外,使用VSwap的容器会通过降低运行速度来解决内存溢出问题,从容器的角度来看,这类似于进行真正的空间交换。该技术可以有效控制每个容器的内存和swap使用情况。当然,除了Jelastic之外,您始终可以为JVM指定堆大小,而不是根据Matt的提示依赖启发式机制。如果您有其他更好的想法,请在评论中与我们分享。原标题:JavaandMemoryLimitsinContainers:LXC,DockerandOpenVZ[.com独家翻译,合作站点转载请注明出处。】
