I want to talk about security in DevOps – also known as “DevSecOps”* – on this blog, but it’s going to have to wait for a subsequest post. I’ve been speaking at a few conferences and seminars recently on this topic, and I’ve started to preface the discussion with a quick question: “Who here understands what a container is?”. And you don’t get that many hands going up**. So I’ve started giving a little explanation of what containers*** are before going much further.
To be clear: can you do DevOps without containers? Can you do DevSecOps without containers? The answer to both is “yes”. But containers lend themselves so well to the DevOps approach – and to DevSecOps, it turns out – that even though it’s possible to do DevOps without them, I’m going to assume that most people will use them.
What is a container?
I was in a meeting with a number of colleagues a few months ago, and one of them was presenting on containers. Not everybody around the table was particularly expert in the technology, so he was starting simple. He made a statement, which said something like “There’s no mention of containers in the Linux kernel source code”. This, it turned out, was a dangerous statement to make, given some of the attendees, and within a few seconds, both my boss (sitting next to me) and I were downloading the recent kernel source tarballs and performing a count of the exact number of times that the word “container” occurred. It turned out that his statement wasn’t entirely correct. To give you an idea, I’ve just tried it on an old version that I happened to have on my laptop (4.9.2), and I got a result of 15,273 lines including the word “container”****. My boss and I had a bit of a smirk and ensured that we corrected him at the next break.
What my colleague meant to say – and he clarified later – is that the concept of a container doesn’t really exist as a clear element within the Linux kernel. In other words, containers use a number of abstractions, components, tools and mechanisms from the Linux kernel, but there’s nothing very special about these: they can be used for other purposes as well. So, there’s “no such thing as a container, according to the Linux kernel”.
What, then, is a container? Well, I come from a virtualisation – hypervisor and VM – background, and the way that I tend to think of it is that containers are both very much like and very much unlike VMs. I realise that this may initially not sound very helpful, but let me explain.
How is a container like a VM?
The main way in which a container is like a container is like a VM is that it’s a unit of execution. You bundle something up – an image – which you can then run on a suitably equipped host platform. Like a VM, it’s a workload on a host, and like a VM, it runs at the mercy of that host. Beyond providing workloads with the resources that they need to do their job (CPU cycles, networking, storage access, etc.), the host has a couple of jobs that it needs to do:
- protect workloads from each other, and make sure that a malicious, compromised or poorly written workload cannot affect the operation of any others;
- protect itself (the host) from workloads, and make sure that a malicious, compromised or poorly written workload cannot affect the operation of the host.
The ways that this is achieved for VMs and containers is fundamentally different, with isolation, with VMs being kept isolated by hypervisors making use of hardware capabilities, and containers being kept isolated via software controls provided by the Linux kernel******. These controls revolve around various “namespaces” which ensure that one container can’t see other containers’ files, users, network connections, etc. – nor those of the host. These can be supplemented by tools such as SELinux, which provide capabilities controls for further isolation of containers.
How is a container unlike a VM?
The problem with the description above is that if you’re even vaguely hypervisor-aware, you probably think that a container is just like a VM, and it really isn’t.
A container is, first and foremost *******, a packaging format. “WHAT?” you’re saying, “but you just said it was something that was executed.” Well, yes, but much of the reasons containers are so interesting is that it’s very easy to create the images from which they’re instantiated, and those images are typically much, much smaller than for VMs. For this reason, they take up very little memory, and can be spun up and spun down very, very quickly. Having a container that sits around for just a few minutes, or even seconds (OK, milliseconds, if you like) is an entirely sensible and feasible idea. For VMs, not so much.
Given that containers are so lightweight and easy to replace, people have started using them to create micro-services – minimal components split out of an application which can be used by one or many other micro-services to built whatever you want. Given that you only plan to put what you need for a particular function or service within a container, you’re now free to make it very small, which means that writing new ones and throwing away the old ones becomes very practicable. We’ll follow up on this when we talk about DevOps next time. We’ll also talk about some of the impacts this might have on security, and hence DevSecOps.
Hopefully this has been a useful intro, and you feel excited and motivated to learn more about DevSecOps next time. (And if you don’t, just pretend.)
*I think because SecDevOps reads oddly, and DevOpsSec tends to get pluralised, and then you’re on an entirely different topic.
**I should note that this isn’t just to British audiences, who are reserved and don’t like drawing attention to themselves: this is to Canadian and US audiences who, well … are different in that regard.
***I’m going to be talking about Linux containers: I’m aware there’s history here, so it’s worth noting. In case of pedantry.
**** I used grep -ir container linux-4.9.2 | wc -l in case you’re interested*****.
***** to be fair, a number of those uses, at a quick glance, have nothing to do with containers in the way we’re discussing them “Linux containers”, but refer to abstractions which can be said to container other elements, and are, therefore, logically referred to as containers.
****** there are clever ways to combine VMs and containers to benefit from the strengths of each – I’m not going to go into those today.
******* well, apart from the execution bit that we just covered, obviously.