1

Till now, I was with the idea that container technology (ex: docker) provides the required isolation and OS-Level virtualisation. And the applications running in the container are restricted by - namespaces, cgroups, apparmour/selinux, capabilities and they have no way to figure out the host environment they are in. But seems this understanding is not 100% correct.

As on wiki -OS-level virtualization

OS-level virtualization is an operating system paradigm in which the kernel allows the existence of multiple isolated user space instances. Such instances, called containers (LXC, Solaris containers, Docker), Zones (Solaris containers), virtual private servers (OpenVZ), partitions, virtual environments (VEs), virtual kernels (DragonFly BSD), or jails (FreeBSD jail or chroot jail),1 may look like real computers from the point of view of programs running in them. A computer program running on an ordinary operating system can see all resources (connected devices, files and folders, network shares, CPU power, quantifiable hardware capabilities) of that computer. However, programs running inside of a container can only see the container's contents and devices assigned to the container.

From above quote, It seems it only adds isolation and abstraction and nothing like virtualiztion.

As Java team had to add container support to JVM so it does not look in to the host env directly but instead limits ITSELF to the isolations/abstraction provided by docker.
References:

  1. Java (prior to JDK8 update 131) applications running in docker container CPU / Memory issues? with excellent answer explaining JVM support for linux containers.

Linux container support first appeared in JDK 10 and then ported to 8u191,

  1. How to prevent Java from exceeding the container memory limits?

Does this mean that a C program running in container environment has a way to bypass the restriction and access/read the host env details. Ofcourse, when it tries (i.e uses this information) to do any thing beyond what the container is allowed to do, the container engine might kill the process of the container itself.

So, If I am developing an C/C++ application which requests/queries for host resources like CPU/MEM/Devices etc, is it my responsibility that the application runs as expected in container environments by adding container support.

Vamsh
  • 234
  • 8

2 Answers2

1

Although I doubt this will be a popular answer, my view is that applications that might ever run in a container environment must be provided with ways to specify resource limits explicitly. It's a mistake to rely on information queried from the system.

Containers are not full virtualization environments, and generally do not conceal the underlying platform completely. While containers might be, and generally are, isolated from their host at the network, filesystem, and user level, that doesn't mean they are truly independent. A typical problem I encounter is that a container can't get it's own contribution to the system's load average -- only the load average of the host.

The fact that there is not full virtualization does not mean that the host cannot enforce limits -- it generally can, and does. But it means that the container cannot easily find what they are -- not in a robust, platform-neutral way.

Various heuristics are available to the container. For example, it might be able to parse /proc/self/cgroup. This may, or may not, give useful information, depending on the implementation. This approach is only ever going to give useful information if the host is using control groups -- most current implementations do, but that doesn't mean it's mandatory.

There are a number of different container frameworks in current use, and that number is likely to increase. It's going to be difficult to predict what methods will have to be used in future, to make an application container-proof. Better, I think, to provide a way for the user to control limits, than to have an ongoing maintenance task for every piece of software you develop.

Kevin Boone
  • 3,705
  • 1
  • 7
  • 14
1

In a container environment, it often winds up working better to build small interconnected containers that can run multiple copies. Then you can size the environment to the workload, instead of sizing the workload to its environment.

An easier example to think about is a worker process that handles asynchronous tasks. In a non-container environment, a typical setup would be to ask the host how many cores it has, then launch that many threads. This doesn't translate well into containers, exactly because of the sorts of issues you cite. Instead, it's usually better to have your worker process be single-threaded, but then launch as many copies of it as you need to do the work.

If in particular you're running Kubernetes in a cloud environment, there are some real advantages to doing this. In a Kubernetes Deployment you can specify the number of replicas: of a container, and dynamically change that, so you're not tied to the hardware configuration at all. You can use a Kubernetes piece called the horizontal pod autoscaler to automatically set the deployment count based on the queue length. You can use a different Kubernetes piece called the cluster autoscaler to automatically request more cloud compute nodes when the workload gets too big for the current cluster. Underlying this is a basic assumption that individual containers (Kubernetes Pods) are small, stateless, and behave the same on any hardware setup.

The JVM memory limit question you cite faces a similar problem. The default JVM behavior is to use 25% of system memory for the heap, but now the question becomes, how do you decide how much memory that is in the face of per-container resource constraints? Most application runtimes don't have a system-dependent hard memory limit like this, though; you talk about C programs, and malloc() will work fine until you hit the kernel-enforced (either physical or cgroup) memory limit.

So, If I am developing an C/C++ application which requests/queries for host resources like CPU/MEM/Devices ...

...it is inappropriate to run this inside an isolation system like Docker. Run it directly on the host.

David Maze
  • 67,477
  • 12
  • 66
  • 91
  • late to my own party.. sorry. David, i get your point `it is inappropriate to run this inside an isolation system like Docker. Run it directly on the host.`. This exploration is to understand "under the hood" things - so I know what a good solution is and what is not. – Vamsh Dec 11 '20 at 14:36