Обновление 1

Обновление 1

Я пытаюсь настроить Docker Swarm.

Мне нужно, чтобы мои узлы взаимодействовали через TLS.

Я создал сертификат для управляющего узла с extendedKeyUsage = serverAuth

Я настроил узел менеджера с помощью следующего daemon.json:

{
    "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
    "tlscacert": "/var/docker/ca.pem",
    "tlscert": "/var/docker/server-cert.pem",
    "tlskey": "/var/docker/server-key.pem",
    "tlsverify": true
}

Чтобы проверить это, я создал клиентский сертификат, использовал его для подключения к API Docker с моего ноутбука, и мне удалось успешно подключиться.

Теперь мне нужно добавить один рабочий узел в рой.

Я настроил его так же, как и узел менеджера; с похожим daemon.json. Я использовал ключ SSL с extendedKeyUsage = serverAuth и подтвердил клиентское соединение так же, как и на узле менеджера.

Затем в менеджере я запустил docker swarm init

Чтобы присоединить рабочий узел к рою, я использую следующую команду: docker swarm join --token XXX dockman.myhost.com:2376

Но я получаю ошибку:

Error response from daemon: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate"

Я подумал, что могу протестировать это дальше, попытавшись подключиться к API Docker на узле-менеджере из рабочего узла:

sudo docker --tlsverify --tlscacert=/var/docker/ca.pem --tlscert=./server-cert.pem --tlskey=./server-key.pem -H=127.0.0.1:2376 version

Результат:

Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false
The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: Get https://127.0.0.1:2376/v1.40/version: remote error: tls: bad certificate

Этот второй тест дал мне много пищи для размышлений. Конечно, он не сработает, потому что я пытаюсь подключиться с помощью сертификата сервера, а не клиентского, но разве это не то, что пытается сделать docker swarm join? Мне не кажется целесообразным помещать клиентский сертификат в daemon.json. Я погуглил, что можно сделать один сертификат и для сервера, и для клиента, и это возможно, но, похоже, это плохая практика. Я бы подумал, что это было бы рассмотрено в руководстве, если бы это было необходимо.

Я застрял на этом этапе. Я не могу понять, какая настройка сертификата требуется.

Я следил за https://github.com/docker/docker.github.io/blob/master/swarm/configure-tls.md Здесь описывается создание сертификатов, но вообще не упоминается аутентификация клиента или сервера.

Обновление 1

Я нашел документ, в котором говорится, что сертификаты должны быть клиентскими и серверными.

https://hub.docker.com/_/swarm/

Поэтому я переделал сертификат узла, чтобы он был и клиентом, и сервером. Теперь команда docker version работает при запуске с узла, но не с swarm join.

решение1

Вы путаете Swarm Mode ( docker swarmи подобные CLI) с классическим контейнерным Swarm (размещенным как контейнер на Docker Hub). Это два разных инструмента.

Для двух комплектов документации см.:

Нет необходимости выполнять какую-либо ручную настройку TLS с Swarm Mode, все встроено, а порты для Swarm Mode отличаются от портов для сокета API docker. Вы не хотите выставлять API docker в сеть без веской причины (это распространенный источник взломов), а Swarm Mode — это не причина.

Поэтому вам следует удалить -Hопцию команды dockerdвместе с любыми опциями TLS там. Затем запустите docker swarm initна первом менеджере, который сгенерирует учетные данные TLS и выдаст токен, включающий хэш самоподписанных сертификатов. Затем другие менеджеры и рабочие запустят , docker swarm joinчтобы сгенерировать клиентские сертификаты, подключиться к менеджеру, проверить хэш сертификатов менеджера из токена и аутентифицировать себя для менеджера с помощью секретной части токена присоединения.

Вышеуказанное зашифрует плоскость управления между менеджерами и рабочими. Чтобы зашифровать данные, передаваемые в оверлейных сетях между рабочими, вам необходимо включить IPSec в созданных вами оверлейных сетях:

docker network create --opt encrypted --driver overlay app-overlay-net

Документация по этой функции находится по адресу:https://docs.docker.com/v17.09/engine/userguide/networking/overlay-security-model/

решение2

Я был прав, что для работы сертификаты должны быть как клиентскими, так и серверными.

Затем я столкнулся с другими проблемами, главная из которых заключается в том, что виртуальные машины на хосте, который я использую, запрещают использование порта 4789, поскольку он используется VMWare. Это порт пути данных по умолчанию, используемый для сети наложения.

Мне пришлось полностью удалить все узлы и менеджеры из роя (фактически удалив его) и заново подключить его с использованием параметра data-path-port:

docker swarm init --data-path-port=7777

(Я также указал рекламный адрес в качестве IP-адреса для каждого узла, но не думаю, что это было необходимо)

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

После того, как я это сделал и изменил настройки брандмауэра, чтобы разрешить UDP-связь между узлами с использованием data-path-port, все снова заработало.

Поскольку роевая сеть зашифрована, я думаю, все должно работать.

Связанный контент