Настройка ядра с помощью привилегированного Docker-контейнера


10

Я создаю контейнер для настройки параметров ядра для балансировщика нагрузки. Я бы предпочел развернуть эти изменения на хосте в образе, используя один привилегированный контейнер. Например:

docker run --rm --privileged ubuntu:latest sysctl -w net.core.somaxconn=65535

При тестировании изменения вступают в силу, но только для этого контейнера. У меня сложилось впечатление, что при полностью привилегированном контейнере изменения в / proc фактически изменят основную ОС.

$docker run --rm --privileged ubuntu:latest \
    sysctl -w net.core.somaxconn=65535
net.core.somaxconn = 65535

$ docker run --rm --privileged ubuntu:latest \
    /bin/bash -c "sysctl -a | grep somaxconn"
net.core.somaxconn = 128

Это как привилегированные контейнеры должны работать?

Я просто делаю что-то глупое?

Каков наилучший способ внести долгосрочные изменения?

Информация о версии:

Client version: 1.4.1
Client API version: 1.16
Go version (client): go1.3.3
Git commit (client): 5bc2ff8
OS/Arch (client): linux/amd64
Server version: 1.4.1
Server API version: 1.16
Go version (server): go1.3.3
Git commit (server): 5bc2ff8

Пример команды с смонтированным / proc:

$ docker run -v /proc:/proc ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000

$ docker run -v /proc:/proc --privileged ubuntu:latest \
    /bin/bash -c "sysctl -p /updates/sysctl.conf"
net.ipv4.ip_local_port_range = 2000 65000

$ docker run -v /proc:/proc ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000

$ docker run -v /proc:/proc --privileged ubuntu:latest \
    /bin/bash -c "sysctl -a | grep local_port"
net.ipv4.ip_local_port_range = 32768    61000

Нужно ли делать что-то глупое, например mount / proc как том?
allingeek

Пробовал монтировать / proc: / proc без удачи. Последующие вызовы sysctl -a возвращают исходные значения.
allingeek

Похоже, теперь он работает на Docker 18.09
Хайро Андрес Веласко Ромеро

Ответы:


8

Этот конкретный параметр находится под влиянием сетевого пространства имен, в котором работает Docker.

Как правило /proc, изменяются настройки, которые являются подходящими для всей системы, технически говоря, однако вы изменяете настройки, в /proc/netкоторых возвращаются результаты для каждого пространства имен сети.

Обратите внимание, что /proc/netна самом деле это символическая ссылка, /proc/self/netпоскольку она действительно отражает настройки пространства имен, в котором вы выполняете работу.


Поэтому, если я внесу эти изменения в контейнер с установленным / proc и хостом --net, я могу внести изменения в хост. Но если я понимаю ваш ответ, последующие контейнеры будут сохранять старые значения (загруженные из постоянных настроек хоста) в своем собственном пространстве имен. Мне нужно запустить этот контейнер с чем-то вроде CAP_NET_ADMIN, чтобы внести те же изменения во время выполнения в контейнере балансировщика нагрузки. Звучит правильно?
allingeek

Да, работа с CAP_NET_ADMIN не должна создавать проблемы, когда вы создали для него пространство имен.
Мэтью Ифе

Matthew_Ife Не проблема в этом случае, что контейнер, как ожидают, будет привилегированным. Мне кажется, что CAP_NET_ADMIN мог бы разрешить выход из ограничения докера (по крайней мере, контейнер мог бы перенастроить свой интерфейс для олицетворения другого контейнера)
Анхель

@Angel Это будет зависеть от того, какая ссылка настроена внутри докера. Как правило, следует помещать принудительное использование трафика в родительское пространство имен. Было бы невозможно переключить пространства имен в другое место, так как для этого вам нужен CAP_SYS_ADMIN.
Мэтью Ифе

Так что использование --net = host будет работать?
Хайро Андрес Веласко Ромеро

7

Docker 1.12+ имеет встроенную поддержку для настройки значений sysctl внутри контейнеров. Вот выдержка из документации :

Настройте параметры ядра пространства имен (sysctls) во время выполнения

--Sysctl устанавливает параметры ядра в пространстве имен (sysctls) в контейнере. Например, чтобы включить IP-пересылку в пространстве имен сети контейнеров, выполните следующую команду:

docker run --sysctl net.ipv4.ip_forward=1 someimage

Используя ваш пример, правильный способ поднять ставку net.core.somaxconnбудет:

docker run ... --sysctl net.core.somaxconn=65535 ...

3

Привилегированный контейнер все еще использует свое собственное пространство имен процесса для /proc. Что вы можете сделать, это установить реальное /procвнутри контейнера:

docker run --rm --privileged -v /proc:/host-proc ubuntu:latest \
  'echo 65535 > /host-proc/sys/net/core/somaxconn'

Просто попробовал это, и это не работает.
allingeek

Из всего, что я знаю о докере; Предполагается, что это будет автономный экземпляр, такой как тюрьма во FreeBSD, поэтому его можно легко перемещать, повторно развертывать и т. д. Вам не следует смешивать доклет с хост-ОС.
DutchUncle

2
Существует несколько допустимых случаев использования контейнеров --privileged, и это кажется идеальным случаем. Все контейнеры используют одно и то же ядро. Стандартные контейнеры mount / proc только для чтения.
allingeek

@allingeek CAP_NET_ADMIN действительно может быть отсутствующим битом.
Анхель

1
Попробовал с NET_ADMIN, и он все еще не работает - запустите докер --cap-add NET_ADMIN --net = host -v / proc: / proc_host ubuntu: 14.04 bash -c 'echo 1> / proc_host / sys / net / ipv4 / ip_forward»&& Sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 0
tomdee

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.