Как Docker достигает изоляции

контейнер Docker

Обзор

Технология контейнеризации популярна в современных облачных вычислениях, микросервисах и других системах, а Docker является типичной технологией контейнеризации.Для типичных технологий контейнеризации нам нужно ее понять, поэтому в этой статье я проанализирую Docker, как реализована технология изоляции, и в чем разница между Docker и виртуальными машинами? Далее начинаем постепенно приподнимать фату на нем.

Начните с запуска контейнера

Давайте запустим простой контейнер, начиная сbusyboxВозьмем образ в качестве примера. Это обычный набор инструментов Linux, который можно использовать для выполнения многих команд Linux. Мы используем его в качестве образа для запуска контейнера для просмотра внутренней среды контейнера. Выполнение заказа:

docker run -it --name demo_docker busybox /bin/sh

Эта команда означает: запуститьbusyboxDocker-контейнер образа,-itПредставление параметра обеспечивает интерактивную среду вывода/вывода для контейнера, то есть TTY./bin/shПредставляет команду или программу, которую контейнер запускает в интерактивном режиме.

изоляция процесса

После успешного выполнения мы войдем внутрь контейнера Docker и выполнимps -efПосмотреть прогресс

/ # ps -ef
PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
    8 root      0:00 ps -ef

использоватьtopКоманда для просмотра ресурсов процесса

Mem: 1757172K used, 106080K free, 190676K shrd, 129872K buff, 998704K cached
CPU:  0.0% usr  0.2% sys  0.0% nic 99.6% idle  0.0% io  0.0% irq  0.0% sirq
Load average: 0.00 0.01 0.05 2/497 9
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
    1     0 root     S     1300  0.0   1  0.0 /bin/sh
    9     1 root     R     1292  0.0   3  0.0 top

И мы просматриваем процесс, в данный момент исполняющий контейнер на хостеps -ef|grep busybox

root       5866   5642  0 01:19 pts/4    00:00:00 /usr/bin/docker-current run -it --name demo_docker busybox /bin/sh
root       5952   5759  0 01:20 pts/11   00:00:00 grep --color=auto busybox

Здесь мы можем знать, что для хостаdocker runВыполнение команды запускает просто процесс, егоpidэто 5866. Что касается самой программы-контейнера, то она изолирована, и внутри контейнера видны только ее собственные внутренние процессы, как это делает Docker? На самом деле он зависит от ядра Linux.NamespaceТехнология достижения, здесь я объединил программу C для моделирования процесса изоляции.

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mount.h>
/* 定义一个给 clone 用的栈,栈大小1M */
#define STACK_SIZE (1024 * 1024)
static char container_stack[STACK_SIZE];

char* const container_args[] = {
    "/bin/bash",
    NULL
};


int container_main(void* arg)
{
    printf("容器进程[%5d] ----进入容器!\n",getpid());
    mount("proc", "/proc", "proc", 0, NULL);
    /**执行/bin/bash */
    execv(container_args[0], container_args);
    printf("出错啦!\n");
    return 1;
}

int main()
{
    printf("宿主机进程[%5d] - 开始一个容器!\n",getpid());
    /* 调用clone函数 */
    int container_pid = clone(container_main, container_stack+STACK_SIZE,  CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL);
    /* 等待子进程结束 */
    waitpid(container_pid, NULL, 0);
    printf("宿主机 - 容器结束!\n");
    return 0;
}

Учитывая, что многие студенты не очень хорошо знакомы с языком C, я кратко объясню эту программу здесь.Эта программа в основном предназначена для выполненияclone()функция для клонирования процесса, и программа, выполняемая клоном, является нашейcontainer_mainфункция, то следующим параметром является пространство стека, затемCLONE_NEWPIDиCLONE_NEWNSУказывает категорию вызова пространства имен Linux, представляющую создание нового пространства имен процесса и монтирование пространства имен соответственно.

  • CLONE_NEWPIDвызовет внутреннюю перенумерацию исполняемой программыPID, то есть из1процесс начинается

  • CLONE_NEWNSНовая среда монтирования будет клонирована и перемонтирована путем перемонтирования внутри дочернего процесса.procПапка, которая может скрывать информацию о процессе родительского процесса.

Давайте запустим эту программу, чтобы увидеть эффект.

компилировать

gcc container.c -o container

воплощать в жизнь

[root@host1 luozhou]# ./container 
宿主机进程[ 6061] - 开始一个容器!
容器进程[    1] ----进入容器!

Здесь мы видим, что вывод этой программы появляется на главном компьютере.PIDда6061, с точки зрения клонированного дочернего процесса, этоPIDда1, мы выполняемps -efОзнакомьтесь со списком процессов

[root@host1 luozhou]# ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 01:46 pts/2    00:00:00 /bin/bash
root         10      1  0 01:48 pts/2    00:00:00 ps -ef

Мы обнаружили, что запущен только процесс внутри контейнера, а затем выполнитьtopЗаказ


   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                  
     1 root      20   0  115576   2112   1628 S   0.0  0.1   0:00.00 bash                                                                                                     
    11 root      20   0  161904   2124   1544 R   0.0  0.1   0:00.00 top  

В результате тоже только 2 процесса информации.

Это основной принцип процесса изоляции контейнера.Доккер в основном использует технологию ядра Linux для достижения изоляции.На самом деле, включая изоляцию файлов, о которой я расскажу позже, изоляция ресурсов передается под новым пространством имен.mountУстановлен для изоляции.

Изоляция файлов

Я полагаю, что после понимания изоляции процессов у вас уже сложилось общее впечатление об изолированном геймплее контейнеров Docker.Давайте посмотрим, как изолирована файловая система внутри Docker, то есть вы выполняете внутри Docker.lsПоказывает, как появились папки и файлы.

Возьмем в качестве примера предыдущую команду Docker, выполнимls

bin   dev   etc   home  proc  root  run   sys   tmp   usr   var

Мы обнаружили, что эти папки уже содержатся внутри контейнера, так откуда же они берутся? мы выполняем сначалаdocker infoДавайте посмотрим, какая файловая система используется нашим Docker?

Server Version: 1.13.1
Storage Driver: overlay2

Моя версия 1.13.1 и драйвер хранилищаoverlay2, Разные драйвера хранилища ведут себя в Docker по-разному, но принципы схожи, давайте посмотрим, как Docker используетoverlay2изменить так много папок. Как мы упоминали ранее, Docker монтируется по mount, сначала мы находим идентификатор экземпляра нашего контейнера.

воплощать в жизньdocker ps -a |grep demo_docker

c0afd574aea7        busybox                         "/bin/sh"                42 minutes ago      Up 42 minutes 

Затем мы ищем информацию о монтировании в соответствии с нашим идентификатором контейнера и выполняемcat /proc/mounts | grep c0afd574aea7

shm /var/lib/docker/containers/c0afd574aea716593ceb4466943bbd13e3a081bf84da0779ee43600de0df384b/shm tmpfs rw,context="system_u:object_r:container_file_t:s0:c740,c923",nosuid,nodev,noexec,relatime,size=65536k 0 0

Здесь есть информация о маунте, но эта запись не является нашей целью, нам нужно найтиoverlay2Информация о монтировании, так что здесь нам также нужно выполнить команду:cat /proc/mounts | grep system_u:object_r:container_file_t:s0:c740,c923

overlay /var/lib/docker/overlay2/9c9318031bc53dfca45b6872b73dab82afcd69f55066440425c073fe681109d3/merged overlay rw,context="system_u:object_r:container_file_t:s0:c740,c923",relatime,lowerdir=/var/lib/docker/overlay2/l/FWESUOVO6DYTXBBJIQBPUWLN6K:/var/lib/docker/overlay2/l/XPKQU6AMUX3AKLAX2BR6V4JQ3R,upperdir=/var/lib/docker/overlay2/9c9318031bc53dfca45b6872b73dab82afcd69f55066440425c073fe681109d3/diff,workdir=/var/lib/docker/overlay2/9c9318031bc53dfca45b6872b73dab82afcd69f55066440425c073fe681109d3/work 0 0
shm /var/lib/docker/containers/c0afd574aea716593ceb4466943bbd13e3a081bf84da0779ee43600de0df384b/shm tmpfs rw,context="system_u:object_r:container_file_t:s0:c740,c923",nosuid,nodev,noexec,relatime,size=65536k 0 0

здесьoverlayКрепление не связано с идентификатором контейнера, поэтому мы не можем найти его напрямую по идентификатору контейнера.overlayДля получения информации о монтаже, вот помощьcontextдеассоциативный, поэтому мы проходимcontextСодержимое найдет адрес, который мы монтируем. Давайте войдем в каталог, чтобы увидеть результаты

[root@host1 l]# ls /var/lib/docker/overlay2/9c9318031bc53dfca45b6872b73dab82afcd69f55066440425c073fe681109d3/merged
bin  dev  etc  home  proc  root  run  sys  tmp  usr  var

Мы обнаружили, что это согласуется с каталогом нашего контейнера, мы создаем новый каталог в этом каталоге, а затем смотрим, появится ли новый каталог внутри контейнера.

文件系统隔离
изоляция файловой системы

Изображение выше проверяет содержимое файла внутри контейнера и смонтированного/var/lib/docker/overlay2/ID/mergedСледующее последовательно, что является основным принципом изоляции файловой системы Docker.

ограничения в ресурсах

Учащиеся, которые играли в Docker, должны знать, что Docker по-прежнему может ограничивать использование ресурсов, таких как ЦП и память, так как же реализована эта часть? Вот еще одна концепция LinuxCgroupsтехнология, это важное средство установки лимитов ресурсов для процессов, в Linux все является файлом, поэтомуCgroupsТехнология также отражена в документе, мы выполняемmount -t cgroupты можешь видетьCgroupsгоры

cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_prio,net_cls)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuacct,cpu)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset)

Мы видим, что смонтированные выше каталоги включают в себяcpuиmemoryТогда мы предполагаем, что информация об ограничениях, вероятно, настроена в соответствии с этой папкой. Давайте запустим контейнер для проверки и выполнения команды:

docker run -d --name='cpu_set_demo' --cpu-period=100000 --cpu-quota=20000 busybox md5sum /dev/urandom 

Эта команда означает, что нам нужно запустить контейнер, который всегда генерирует случайные числа для расчета md5, чтобы потреблять процессор,--cpu-period=100000 --cpu-quota=20000Указывает, что использование ЦП ограничено 20%, подробное описание этих двух параметров можно нажатьздесь

进程top
процесс сверху

Мы посмотрели на потребление процесса и обнаружили, что только что запущенные ресурсы контейнера действительно ограничены 20%, что говорит о том, что параметр лимита ЦП Docker работает, что соответствует нашемуcgroupКак устроена папка? Точно так же конфигурация здесь должна быть связана с идентификатором экземпляра контейнера, а мой путь к файлу находится в/sys/fs/cgroup/cpu/system.slice/docker-5bbf589ae223b347c0d10b7e97cd1461ef82149a6d7fb144e8b01fcafecad036.scopeВниз,5bbf589ae223b347c0d10b7e97cd1461ef82149a6d7fb144e8b01fcafecad036Это идентификатор контейнера, который мы начали.

Перейдите в указанную выше папку и просмотрите установленные нами параметры:

[root@host1]# cat cpu.cfs_period_us
100000
[root@host1]# cat cpu.cfs_quota_us 
20000

Выяснилось, что наши параметры настройки запуска контейнера одинаковы, то есть использование процессора контейнера здесь ограничено значением файла. Здесь следует отметить, что расположение файлов Docker Cgroup в разных версиях Linux может быть разным, а некоторые находятся в/sys/fs/cgroup/cpu/docker/ID/Вниз.

Отличия от традиционной технологии виртуальных машин

После предыдущего анализа ограничений процессов, файловой системы и ресурсов у вас есть общее представление о принципе изоляции Docker, так в чем же разница между ним и традиционной технологией виртуальных машин? Вот картина разницы между Docker и виртуальными машинами в Интернете.

图片来源极客时间
Источник изображения Geek Time

Эта картинка должна четко показать разницу между технологией виртуальной машины и технологией Docker.Технология виртуальной машины полностью виртуализирует отдельную систему, и эта система обрабатывает различные запущенные запросы приложений, поэтому она действительно влияет на производительность.Говорят, что она влияет. Технология Docker полностью реализована за счет использования функций ядра Linux, технологии Namespace и Cgroup. По сути, приложение, которое вы запускаете в контейнере, по-прежнему является обычным процессом для хоста или напрямую запланировано хостом. потери производительности очень малы, что также является важным преимуществом технологии Docker.

Поскольку технология Docker все еще является обычным процессом, изоляция не очень тщательная, и она по-прежнему использует ядро ​​хост-машины, которое не так высоко, как виртуальные машины, с точки зрения уровня изоляции и безопасности, что также является ее недостатком.

Суммировать

В этой статье я на практике проверил принцип изоляции контейнерной технологии Docker в процессе, файловой системе и ограничении ресурсов и, наконец, сравнил разницу между виртуальной машиной и технологией Docker. поэтому у него есть преимущества в производительности, а у виртуальных машин есть преимущества высокой изоляции и безопасности из-за полной виртуальной системы, и у обоих есть преимущества и недостатки. Тем не менее, контейнеризация - это текущая тенденция. Я считаю, что с развитием технологий текущая проблема неполной изоляции может быть решена. Это не мечта выйти на глобальный уровень с контейнеризацией.

Ссылаться на

  1. people.RedHat.com/VG O давление/бояться...
  2. docs.docker.com/v17.09/ eng я ...
  3. rottweiler.net/articles/25…