当前位置: 首页 > 知识库问答 >
问题:

应用程序(如用C开发的应用程序)是否应该添加容器(例如docker)支持?

隆睿
2023-03-14

到目前为止,我一直认为容器技术(例如:docker)提供了所需的隔离和操作系统级虚拟化。在容器中运行的应用程序受到名称空间、cgroup、设备/selinux、功能的限制,他们无法弄清楚自己所处的主机环境。但是这种理解似乎不是100%正确的。

与wiki-OS级虚拟化一样

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

从上面的引用来看,它似乎只是增加了隔离和抽象,一点也不像虚拟化。

因为Java团队必须为JVM添加容器支持,所以它不会直接查看主机env,而是将自己限制在docker提供的隔离/抽象中。< br >参考资料:

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

Linux容器支持首先出现在JDK 10中,然后移植到8u191,

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

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

共有2个答案

壤驷敏学
2023-03-14

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

一个更简单的例子是处理异步任务的工作进程。在非容器环境中,典型的设置是询问主机它有多少个内核,然后启动那么多线程。这并不能很好地转化为容器,正是因为你提到的那种问题。相反,通常更好的做法是让您的工作进程是单线程的,但随后根据您的工作需要启动尽可能多的副本。

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

您提到的JVM内存限制问题也面临类似的问题。JVM的默认行为是将25%的系统内存用于堆,但现在的问题是,如何确定每个容器的资源约束中有多少内存?不过,大多数应用程序运行时都没有这样的依赖于系统的硬内存限制;谈到C程序,malloc()将正常工作,直到达到内核强制的(物理或cgroup)内存限制。

因此,如果我正在开发一个请求/查询CPU/MEM/设备等主机资源的C/C应用程序...

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

楚嘉
2023-03-14

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

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

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

容器可以使用各种试探法。例如,它可能能够解析< code>/proc/self/cgroup。这可能给出有用的信息,也可能不给出有用的信息,这取决于实现。只有当主机使用控制组时,这种方法才会提供有用的信息——大多数当前的实现都是这样,但这并不意味着它是强制性的。

目前有许多不同的容器框架在使用,而且这个数字可能会增加。很难预测将来会使用什么方法来使应用程序不受容器的影响。我认为,为用户提供一种控制限制的方法,比你开发的每一个软件都有一个持续的维护任务要好。

 类似资料:
  • Hyperledger Composer支持创建Web、移动或原生Node.js应用程序。它包括composer-rest-server(本身基于LoopBack技术)为业务网络自动生成REST API,和hyperledger-composer,用于生成骨架Angular应用的Yeoman框架的代码生成插件。 另外,它还包含一组丰富的JavaScript API来构建原生Node.js应用程序。

  • 应用程序开发 应用是独立于蓝天采集器的程序,您可以使用任何php框架来开发,完全按照您自己的代码风格编写应用 使用“后台»工具&开发»开发»应用程序”可快速创建新的应用 应用创建好后可在“后台»云端»已下载»应用程序”中看到,创建的文件则在“根目录/app/标识名”中 注意:应用目录下的index.php为入口文件请勿修改,标识名.php为应用配置文件(建议不要直接修改,而是在“应用»管理»开发应

  • 我有一个java应用程序,需要部署在weblogic服务器中。我目前正在为该应用程序制作ear文件。我的ear文件中有一个ejb jar。我想将log4j2 jar添加到此应用程序中。所以我的文件夹结构是 目前,我已经将JAR放在APP-INF文件夹/lib和META-INF/application中。xml我把JAR放在了模块中。这是我的申请表。xml 但它不接受log4j罐子。有什么解决方案吗

  • 问题内容: 我尝试在具有/tmp/.X11-unix装载的容器docker中运行一些Qt应用程序。我在这里看到 这可能很困难。 因此,当我在容器docker中运行kdevelop时,它不起作用(我有一个空窗口)。但是如果我运行qtcreator很好。 我认为差异来自Qt版本(kdevelop在Qt4和qtcreator在Qt5中开发)。我所有其他的qt5应用程序都可以正常工作,但在qt4中却没有一

  • 问题内容: 我要做的是为我的Java应用程序构建一个docker映像,但是以下注意事项对于大多数编译语言都应适用。 在构建服务器上,我想为应用程序生成一个docker映像作为可交付成果。为此,我必须使用一些构建工具(通常是Gradle,Maven或Ant)来编译应用程序,然后将创建的JAR文件添加到docker映像中。因为我希望Docker映像仅执行JAR文件,所以我当然将从已安装Java的基本映

  • 但我的Dockerfile不再是独立的。它的工作取决于Docker外部发生的步骤。在我的Dockerfile中,我将有一个或语句,用于将JAR文件复制到映像中。如果事先没有创建jar,则此语句将失败。所以仅仅执行Dockerfile可能无法工作。如果您想要与仅使用当前Dockerfile构建的服务集成,比如DockerHub上的自动构建特性,那么这就会成为一个问题。 在这种情况下,创建映像的所有必