1

到目前为止,我认为容器技术(例如:docker)提供了所需的隔离和操作系统级别的虚拟化。并且在容器中运行的应用程序受到命名空间、cgroups、apparmour/selinux、功能的限制,它们无法确定它们所在的主机环境。但似乎这种理解并不是 100% 正确的。

正如 wiki -操作系统级虚拟化

操作系统级虚拟化是一种操作系统范式,其中内核允许存在多个隔离的用户空间实例。此类实例,称为容器(LXC、Solaris 容器、Docker)、区域(Solaris 容器)、虚拟专用服务器 (OpenVZ)、分区、虚拟环境 (VE)、虚拟内核 (DragonFly BSD) 或监狱(FreeBSD 监狱或 chroot 监狱),从运行在其中的程序的角度来看, 1可能看起来像真正的计算机。在普通操作系统上运行的计算机程序可以看到该计算机的所有资源(连接的设备、文件和文件夹、网络共享、CPU 能力、可量化的硬件能力)。但是,在容器内运行的程序只能看到容器的内容和分配给容器的设备。

从上面的引用来看,它似乎只增加了隔离和抽象,而没有像虚拟化那样。

由于 Java 团队必须向 JVM 添加容器支持,因此它不会直接查看主机环境,而是将 ITSELF 限制为 docker 提供的隔离/抽象。
参考:

  1. 在 docker 容器中运行的 Java(JDK8 更新 131 之前)应用程序 CPU/内存问题? 很好的答案解释了 JVM 对 linux 容器的支持。

Linux 容器支持最早出现在 JDK 10,然后移植到 8u191,

  1. 如何防止 Java 超出容器内存限制?

这是否意味着在容器环境中运行的 C 程序可以绕过限制并访问/读取主机环境详细信息。当然,当它尝试(即使用此信息)做任何超出容器允许做的事情时,容器引擎可能会终止容器本身的进程。

因此,如果我正在开发一个 C/C++ 应用程序来请求/查询主机资源(如 CPU/MEM/Devices 等),那么我是否有责任通过添加容器支持使应用程序在容器环境中按预期运行。

4

2 回答 2

1

尽管我怀疑这会是一个流行的答案,但我的观点是,可能曾经在容器环境中运行的应用程序必须提供明确指定资源限制的方法。依赖从系统查询的信息是错误的。

容器不是全虚拟化环境,一般不会完全隐藏底层平台。虽然容器可能并且通常在网络、文件系统和用户级别与其主机隔离,但这并不意味着它们是真正独立的。我遇到的一个典型问题是容器无法获得它自己对系统负载平均值的贡献——只有主机的负载平均值。

没有完全虚拟化的事实并不意味着主机不能强制执行限制——它通常可以并且确实如此。但这意味着容器不能轻易地找到它们是什么——不是以一种健壮的、平台中立的方式。

容器可以使用各种启发式方法。例如,它可能能够解析/proc/self/cgroup. 这可能会或可能不会提供有用的信息,具体取决于实现。这种方法只有在主机使用控制组时才会提供有用的信息——大多数当前的实现都是这样做的,但这并不意味着它是强制性的。

当前使用了许多不同的容器框架,而且这个数字可能会增加。很难预测将来必须使用哪些方法来使应用程序具有容器证明。我认为,最好为用户提供一种控制限制的方法,而不是对您开发的每一个软件进行持续的维护任务。

于 2020-10-12T07:27:52.893 回答
1

在容器环境中,构建可以运行多个副本的小型互连容器通常会更好地工作。然后,您可以根据工作负载调整环境大小,而不是根据环境调整工作负载大小。

一个更容易考虑的例子是处理异步任务的工作进程。在非容器环境中,典型的设置是询问主机它有多少内核,然后启动那么多线程。正是由于您引用的各种问题,这不能很好地转化为容器。相反,通常最好让您的工作进程是单线程的,然后根据您的工作需要启动尽可能多的副本。

特别是如果您在云环境中运行 Kubernetes,这样做有一些真正的优势。在 Kubernetes 部署中,您可以指定replicas:容器的数量,并动态更改它,因此您完全不受硬件配置的束缚。您可以使用一个称为水平 pod autoscaler 的 Kubernetes 部件来根据队列长度自动设置部署计数。当工作负载对于当前集群来说太大时,您可以使用另一个称为集群自动缩放器的 Kubernetes 组件来自动请求更多的云计算节点。这是一个基本假设,即单个容器(Kubernetes Pod)很小、无状态,并且在任何硬件设置上的行为都相同。

您引用的 JVM 内存限制问题面临着类似的问题。默认的JVM 行为是为堆使用 25% 的系统内存,但现在问题变成了,面对每个容器的资源限制,您如何决定使用多少内存?不过,大多数应用程序运行时都没有这样的系统相关硬内存限制;您谈论 C 程序,并且malloc()在达到内核强制(物理或 cgroup)内存限制之前可以正常工作。

所以,如果我正在开发一个 C/C++ 应用程序,它请求/查询主机资源,如 CPU/MEM/Devices ...

...在像 Docker 这样的隔离系统中运行它是不合适的。直接在主机上运行。

于 2020-10-12T13:21:46.463 回答