Instructor Demo: Process Isolation
In this demo, we'll illustrate:
- What containerized process IDs look like inside versus outside of a namespace
- How to impose resource limitations on CPU and memory consumption of a containerized process
Exploring the PID Namespace
Start a simple container we can explore:
PS: node-0 Administrator> docker container run -d --name pinger ` microsoft/nanoserver:latest powershell ping -t 8.8.8.8Launch a child process inside this container to display all the processes running inside it:
PS: node-0 Administrator> docker container exec pinger powershell Get-Process Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName ------- ------ ----- ----- ------ -- -- ----------- 0 5 944 4364 0.02 4812 65 CExecSvc 0 5 636 1872 0.02 14264 65 csrss 0 0 0 4 0 0 Idle 0 18 3568 11296 0.25 5760 65 lsass 0 5 636 3084 0.03 13476 65 PING 0 38 43400 66500 1.72 9436 65 powershell 0 33 22788 44312 1.33 13184 65 powershell 0 9 1592 5756 0.13 12872 65 services 0 3 340 1144 0.02 15996 0 smss 0 15 12448 21192 5.98 4828 65 svchost 0 12 4996 9472 0.19 6412 65 svchost 0 8 1548 5788 0.06 11252 65 svchost 0 29 6000 16224 0.48 11308 65 svchost 0 9 1936 6428 0.06 13668 65 svchost 0 13 1756 6336 0.06 15040 65 svchost 0 15 9852 17896 0.42 15680 65 svchost 0 0 128 140 898.88 4 0 System 0 7 840 3916 0.02 8428 65 wininitIn Windows containers, a whole set of system processes need to run in order for the intended application process to be executed successfully. Just like a regular Windows process list, we see the root
Idleprocess at PID 0, and theSystemprocess at PID 4.Another way to achieve a similar result is to use
container top:PS: node-0 Administrator> docker container top pinger Name PID CPU Private Working Set smss.exe 15996 00:00:00.015 217.1kB csrss.exe 14264 00:00:00.015 397.3kB wininit.exe 8428 00:00:00.015 618.5kB services.exe 12872 00:00:00.125 1.372MB lsass.exe 5760 00:00:00.250 2.793MB svchost.exe 11252 00:00:00.062 1.176MB svchost.exe 15040 00:00:00.062 1.425MB svchost.exe 6412 00:00:00.187 3.715MB svchost.exe 4828 00:00:05.984 10.93MB svchost.exe 13668 00:00:00.062 1.692MB svchost.exe 11308 00:00:00.484 4.85MB svchost.exe 15680 00:00:00.421 8.266MB CExecSvc.exe 4812 00:00:00.015 757.8kB powershell.exe 13184 00:00:01.328 18.62MB PING.EXE 13476 00:00:00.031 487.4kBRun
Get-Processdirectly on your host. The ping process is visible there, but so are all the other processes on this machine; the container's namespaces isolated whatGet-Processreturns when executed as a child process within the container.List your containers to show that the
pingercontainer is still running:PS: node-0 Administrator> docker container lsKill the ping process by host PID, confirm with
Yto stop the process, and show the container has stopped:PS: node-0 Administrator>Stop-Process -Id [PID of ping] PS: node-0 Administrator>docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESKilling the ping process on the host also kills the container. Note using
Stop-Processis just for demonstration purposes here; never stop containers this way.
Imposing Resource Limitations
Open the Task Manager, either through the search bar or by typing
taskmgrin the command prompt.Start a container designed to simulate cpu and memory load:
PS: node-0 Administrator> docker container run -it training/winstress:ee2.1 powershellExecute a script inside your container to allocate memory as fast as possible:
PS C:\> .\saturate-mem.ps1You should see the
Memorycolumn on the Task Manager increase quickly, even turning red afterwhile. Then, this error message should be thrown (CTRL+c to break the loop):Exception of type 'System.OutOfMemoryException' was thrown. At C:\saturate-mem.ps1:2 char:37 + ... -lt 100000; $i++) { $mem_stress += ("a" * 1023MB) + ("b" * 1023MB) } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OperationStopped: (:) [], OutOfMemoryException + FullyQualifiedErrorId : System.OutOfMemoryExceptionNote this may even disrupt your RDP connection to your VM - failing to constrain resource consumption can be catastrophic.
CTRL+Cto kill this memory-saturating process. Then, exit and remove the container to release the allocated memory:PS: node-0 Administrator>docker container rm -f <container ID>Immediately, the memory in the Task Manager should drop.
Now, let's start a container with a memory limit:
PS: node-0 Administrator> docker container run ` -it -m 4096mb training/winstress:ee2.1 powershellRun the same script to generate memory pressure:
PS C:\> .\saturate-mem.ps1While the memory does increase in the Task Manager, allocations get cut off before the system memory is completely consumed.
CTRL+Cto kill the process, and exit the container again.Remove this container.
PS: node-0 win-stress>docker container rm -f <container ID>With the Task Manager still up and running, let's do the same thing but for processor consumption:
PS: node-0 Administrator> docker container run -it training/winstress:ee2.1 powershell PS C:\> .\saturate-cpu.ps1You should see the CPU column of the Task Manager increase quickly and turn red.
CTRL+Cto kill this CPU-burning process, andexitthe container. As soon as it exits, the CPU consumption percentage on the Task Manager should drop immediately.Start another container, but this time with a CPU limit:
PS: node-0 Administrator> docker container run ` -it --cpus="1" training/winstress:ee2.1 powershellExecute the script to overload the CPUs:
PS C:\> .\saturate-cpu.ps1While you will see the CPU consumption on the Task Manager increase, it will not increase as dramatically as it did before, as it is being limited by Window's control groups.
Exit and remove this container.
Conclusion
In this demo, we explored some of the most important technologies that make containerization possible: namespaces and control groups. The core message here is that containerized processes are just processes running on their host, isolated and constrained by these technologies. All the tools and management strategies you would use for conventional processes apply just as well for containerized processes.