4 ms·
None, really. Well, it depends what you're asking precisely. In order to explain, let me share an analogy that I've been thinking about, as a way to describe co
by jcrites 9y ago
None, really. Well, it depends what you're asking precisely. In order to explain, let me share an analogy that I've been thinking about, as a way to describe containers:
When you launch processes on Linux, you can choose for all the processes to share memory with each other (in which case we call them threads), or the processes can have separate memory. We call this capability "virtual memory", and it allows processes to pretend that they and the kernel are the only software running on the physical machine. (For example, every process might think that it can write to the memory address 0x08048000, but in fact that address is virtualized and mapped by the kernel to some different physical memory address.)
Though we take it for granted, this memory isolation between processes was the first form of kernel namespace. Modern Linux now has many of these namespaces, which can provide a virtualized view of the file system, network, IPC, uids, and so on. "Containers", then, are processes that employ many of these namespaces to provide isolation from others on the system. (To extend the analogy: just like regular processes think they have their own memory, containerized processes can have their own file system with a distinct /tmp, distinct process id namespace, or namespace of users that exist on the system. Every process can run as PID=1 if it wants, within its own PID namespace.)
These namespace primitives, from which containers are made, are present on modern Linux systems whether one chooses to employ them or not. The primary downsides to consider are efficiency of the system, and the complexity of managing it. If your system (CPU & OS kernel) implements virtual memory efficiently, then there isn’t much downside to using it. The same is probably true for most kernel name spaces, though file system and networking virtualization can have a performance hit if not configured with care.
Kernel namespaces are a core feature of Linux and can be taken advantage of without using technologies that are specifically "container-oriented". For example, consider systemd: it provides a comprehensive set of parameters for employing namespace features in processes that it launches. Parameters like PrivateTmp=yes or PrivateDevices= [1] will virtualize just one part of the system (/tmp or /dev and such, respectively). PrivateUsers= and PrivateNetwork= allow you to launch with a new user or network namespace. It's really that easy to employ namespaces: add a line to your application's unit file.
When you look at container technology as a set of system primitives, then it makes sense to consider employing them individually. They don't have to be used in an all-or-nothing way. You might give your daemon access to the regular network
with a private file system, or you might use the regular file system too while virtualizing just /tmp and /dev. You can isolate processes in whatever way makes sense, and share whatever resources make sense. If a process doesn't need access to the network, and doesn't need a shared /tmp with the rest of the system, then there's little downside to giving the process its own namespace. Indeed, I expect it will increasingly be considered a best practice for services to isolate themselves according to the principle of least privilege. This reduces the chance that components will interact with each other in unexpected and undesired ways, and may have some security benefits.
(If the question is about using Docker or some other specific technology as part of a development and/or deployment process, then that's a different topic. Specific technology suites have tradeoffs beyond those of kernel namespaces.)
[1] https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp= https://www.freedesktop.org/software/systemd/man/systemd.exe...
- vog 9y ago> The primary downsides to consider are efficiency of the system, and the complexity of managing it This shouldn't be underestimated, though! I agree that efficiency is a no-brainer for almost all purposes, especially compared to other forms of virtualization like KVM. But: Managing the complexity can be tough, it sometimes feels like creating all low-level firewall rules by hand for a large network. Well, for firewalls you have stuff like firewall generators, in the context of containers these are projects like Docker or LXD. But they share the same downsides: You may have trouble to see what happens behind the scenes. The largest risk here, however, is not the working time spent to learn and apply that stuff. It is a false sense of security where your complex system might, in the end, to have holes which you assumed should not exist. For example, not many people are aware that if the user can start docker instances, they are effectively root. (One might argue that this is more a failure of docker than of containers. But then, why do people use complex monsters like docker in the first place? Because managing plain containers is a pain and other complex building around containers have their downsides, too.)
- fatherlinnux 9y agoWe are building a lot of tools to simplify run/build move [1][2][3]: [1]: Run within Kubernetes: https://github.com/kubernetes-incubator/cri-o https://github.com/kubernetes-incubator/cri-o [2]: Run Standalone: https://github.com/projectatomic/libpod/blob/master/docs/podman.1.md https://github.com/projectatomic/libpod/blob/master/docs/pod... [3]: Build: https://www.projectatomic.io/blog/2017/11/getting-started-with-buildah/ https://www.projectatomic.io/blog/2017/11/getting-started-wi... [4]: Move: https://rhelblog.redhat.com/2017/05/11/skopeo-copy-to-the-rescue/ https://rhelblog.redhat.com/2017/05/11/skopeo-copy-to-the-re...
- jstimpfle 9y agoGood arguments. Though there is one difference I can see between virtualizing memory and virtualizing other resources, like the file system or the network. (note, I'm pretty much a container newbie). Process memory has traditionally been an "implementation detail" of the process. It typically doesn't need to be shared, the addresses do not need to be fixed, etc. (Shared memory is an exception of course). Resource like the file system or network, on the other hand are mostly shared. It does matter to the outside world through which port the program is reachable, it matters where it puts its files, etc. Again, there are exceptions of course, like temporary files. Now the question is how can we pull out the configuration, like "what port must the program listen on?", and decide these tasks centrally. The container solution is (if I understand correctly) that the program will always listen on port 80, but the container configuration diverts that port to be accessible to the outside world as 8080, etc. I predict that this is going to be a failure in the same sense that OOP has been a failure (if you agree with me on that point). It becomes a tangled mess of layers and indirections, and incredibly hard to debug. Instead I think it is much cleaner to make the configurations like, "What port should I listen on?", "Where can I put my temporary files", easily accessible to the program. The program should not be required to define its own configuration for all the problems which containers want to deal with today. Instead it should import this configuration from a central location through a well-known interface. There must be a simple convention where these decisions can be configured. The configuration must be easily accessible to A) the system, B) the program, C) the administrator. It's been customary to put configurations in text files for a long time, and that's mostly good. However what's been missing is that most programs have had their own configuration file written in a custom syntax and stored in a location that are not easily known by the rest of the system. The system is not really aware that the program is configured e.g. to listen on port 80. And the administrator needs to learn new configuration files for every program. I'm not proposing a central registry where all the cruft of the system should accumulate. Instead, just for the concepts that are shared by many programs -- the resources which containers virtualize today -- should be configured through a system-wide API.