Saturday, March 4, 2017

#Docker containers versus #K8S pod

#Docker containers versus #K8S pod

I’m writing this small article for all you #docker, #kubernetes and #real_hackers in order to understand how K8S pods and docker containers relate.

All my testing has been done on a small K8S cluster that is easily created via Google Cloud Engine. There are a lot’s of tutorials around to get things started.

Once you have a cluster, you can deploy a simple pod like this through means of kubeclt (example from https://kubernetes.io/docs/tasks/kubectl/get-shell-running-container/)

kubectl create -f https://k8s.io/docs/tasks/kubectl/shell-demo.yaml
 
 
Verify if the pod is started, which IP was assigned and what node of the cluster we’re using:
kubectl get pods -o wide

Well now, SSH into the K8S node via the console. You can identify the node from previous command (Remember, kubectl is talking to the K8S master node). Once you have a console on the respective node:
 
docker ps

The output will show quite a lot of containers, but identify the ones containing “shell-demo”
 
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6aefa4147d06 nginx “nginx -g ‘daemon off” About an hour ago Up About an hour 
 k8s_nginx.6e1f6ec8_shell-demo_default_e9e26eef-0006–11e7-aded-42010a8001be_8f315325
 
3cb9ae6edfee gcr.io/google_containers/pause-amd64:3.0 “/pause” About an hour ago Up About an hour 
 k8s_POD.d8dbe16c_shell-demo_default_e9e26eef-0006–11e7-aded-42010a8001be_4c955228


When you look carefully, there are 2 containers running. A container running ‘pause’ as one running our nginx image (specified in shell-demo.yaml)


The cr.io/google_containers/pause-amd64:3.0 is actually a container doing very little, except providing the namespaces (Process, Network, Mount, Hostname, Shared Memory)

In K8S, containers that are related together are organized in pods. All containers share the same network namespace and so the IP address. So how is this organized?

When a pod is created, the 3cb9ae6edfee gcr.io/google_containers/pause-amd64:3.0 container is started. It acquires an IP address from the K8S overlay network. Once this container is active, our demo-shell app (nginx) container is started in a particular way, probably something similar to
 
docker run -d --net container:id_of_pause_container --ipc container:id_of_pause_container nginx

So could we add a container and link it to the pod? Let’s figure out the IP address of the pod.
 
kubectl get pods -o wide

Now lets run a tcpdump container that will link to pod (see https://medium.com/@xxradar/how-to-tcpdump-effectively-in-docker-2ed0a09b5406) to build it and for more options.
 
 
docker run -it --net=container:id_of_pause_container tcpdump
 
ex. docker run -it --net=container:3cb9ae6edfee tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
13:25:59.239352 IP 10.128.0.2.49046 > 10.0.0.7.80: Flags [S], seq 3950690280, win 28400, options [mss 1420,sackOK,TS val 9598868 ecr 0,nop,wscale 7], length 0
13:25:59.239393 IP 10.0.0.7.80 > 10.128.0.2.49046: Flags [S.], seq 3158946458, ack 3950690281, win 28160, options [mss 1420,sackOK,TS val 9599163 ecr 9598868,nop,wscale 7], length 0
13:25:59.239947 IP 10.128.0.2.49046 > 10.0.0.7.80: Flags [.], ack 1, win 222, options [nop,nop,TS val 9598869 ecr 9599163], length 0
13:25:59.239977 IP 10.128.0.2.49046 > 10.0.0.7.80: Flags ...

Some other tricks
 
ex. docker run -it --net=container:3cb9ae6edfee busybox ifconfig
eth0      Link encap:Ethernet  HWaddr 0A:58:0A:00:00:07 
inet addr:10.0.0.7  Bcast:0.0.0.0  Mask:255.255.255.0 
inet6 addr: fe80::cd7:6ff:fe31:6442/64 Scope:Link ...
 
 
ex. docker run -it --net=container:3cb9ae6edfee busybox netstat -a
Active Internet connections (servers and established)Proto Recv-Q Send-Q Local Address Foreign Address         State 
tcp        0      0 0.0.0.0:80              0.0.0.0:*    
  
I think it is even possible the share the process namespace
 
docker run -it --net=container:3cb9ae6edfee --pid=host busybox ps

The previous example shares the process namespace of the entire host and it seems to work, but this next example fails, I think due to a bug in Docker v1.11. It should be solved in a later version of docker.
 
docker run -it --net=container:3cb9ae6edfee --pid=container:3cb9ae6edfee busybox

So … learn docker the hard way !! K8S is a very cool solution, as well as SWARM in my opinion, but it use among other things, containers in ‘special’ way. For my understanding, K8S adds a lot of features and does things differently, but when you boil down to the container level you will understand the magic !