Category Archives: Containers

Kernel space – User space – Containers – Virtualisation

How many times I’ve heard “well, a container is like a super light-weight virtual machine“. And yes, true, I admit as well, that I was one of them.

But I wasn’t happy about this answer, so I did some researches and I think now I have a better understanding and I feel the pain of my friends where I was simplistically (and wrongly) saying that – public apologies 😛 🙂

 

So… let’s start…

 

Concept 1: Virtual memory.

Virtual memory is the collective memory used by processes (RAM, disk swap, etc).

Of this virtual memory, we have generally a separation beween 2 types:

  • kernel space: reserverd for the kernel and generally drivers
  • user space: for the applications, incluse libraries

This separation serves to provide memory protection and hardware protection from malicious or errant software behavior.

NOTE1: User space is not namespace.

 

NOTE2: FUSE is not really related with this topic, but could confuse someone. So, just to clarify: FUSE – (Filesystem in Userspace) is a software interface for Unix-like computer operating systems that lets non-privileged users create their own file systems without editing kernel code. This is achieved by running file system code in user space while the FUSE module provides only a “bridge” to the actual kernel interfaces.

Modern kernels have cgroups and namespace capabilities.

  • Cgroups can restrict what you can USE -> CPU, memory, storage, network, devices, etc. Also allows to ‘freeze’.
  • Namespace can restrict what you SEE -> PID, mnt, UID/GID, etc…

Containers runtimes (like LXC, Docker, etc…) are using cgroups and namespaces to create separate isolated user-space entities called ‘containers‘.
Containers have basically no overhead because they are using the same system calls to the host kernel => No need of emuation or virtual machine.

They use the same kernel of the host (this is a key difference with virtualisation). So, currently, you cannot run Windows containers on a Linux host. But you can still run different versions of Linux, as they all share the same kernel.

Virtualisation: fully isolated OS, running its own kernel.

  • Full virtualised: (eg. VMWare, Virtuabox, ESXi…). The OS in the VM is not aware to be a VM. Hypervisor emulates the hardware platform for the guest OS and then translates the hardware accesses requests to the physical hardware. Hypervisor provides the drivers to the guest OS.
    => higher overhead because hardware virtualisation BUT best isolation and security
  • Para virtualised: (XEN, KVM) the OS in the VM knows to be virtualised. Drivers are sending instructions directly to the hardware of the host, via the Hypervisor. Hardware is not virtualised BUT the OS runs in isolation.
    => better performance and ability to use recent hardware drivers directly BUT guest OS needs to be modified to use paravirtualised devices

NOTE: Emulation is not platform virtualisation (e.g. QEMU)
With emulation you can emulate different architectures (e.g. ARM/RISC…) on a host that has a differnt instruction set (eg. i386). Performances are cleary not ideal.


Main sources:

Docker and Kubernetes notes

[Raw notes from this free course: https://www.udacity.com/course/scalable-microservices-with-kubernetes–ud615 ]


Docker is one of the most famous container in use nowadays.

Docker container features/best practise:

  • is portable because you keep all what you need for your application in it (libraries etc) – always run the same, regardless of the environment;
  • reduce conflicts between teams running different software on the same infrastructure;
  • minimal: best practise is to keep as minimal as possible its content;
  • you can ‘freeze’ it and move to another host, if required (using the cgroup capability);
  • no hard coded values in it: variable passed during the deploy or pulled from a file mounted externally;
  • you can mount external storage;
  • you can expose a port -> for example you can have a web app listening on port 80. You can expose port 80 of your container so when you connect to the host’s port 80, traffic will be redirected to the container. This “port forwarding” is the container runtime’s job;
  • ‘Dockerfile’ is the configuration file for the container. You can speficy the image that you want to use (FROM …), which port to expose, the storage to mount etc;

COMMANDS:

 
Dockerfile

 

Push container to repository
Dockerhub -> default public (you can also have private)

docker tag -h
Add tag – then login and push

 


Create/Package container (5% of the work)

  • App configuration
  • Service Discovery
  • Managing Updates
  • Monitoring

Kubernetes -> Cluster like single machine
You need to describe the apps and how they interact between each others

POD
– collection of containers (possible multiple apps on different containers)
– shares network namespace (IP)
– shares storage volumes

=> created with conf files

Monitoring
Rediness -> container ready
Liveness -> app not working / restart app
Configmaps
Secrets

Services -> labels

Deployments
Desidered state

Scaling -> increase “replicas”

Rolling updates – CTO roll => deploy new version, get traffic, stop traffic prev version, remove prev verision (this per each POD)