Atualização 1

Atualização 1

Estou tentando configurar um docker swarm.

Preciso que meus nós se comuniquem via TLS.

Eu criei um certificado para o nó do gerenciador com extendedKeyUsage = serverAuth

Configurei o nó do gerenciador com o seguinte 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
}

Para testar isso, criei um certificado de cliente, usei-o para conectar-me à API do docker do meu laptop e consigo conectar-me com sucesso.

Agora preciso adicionar um nó de trabalho ao enxame.

Eu configurei da mesma forma que o nó gerenciador; com um daemon.json semelhante. Usei uma chave SSL com extendedKeyUsage = serverAuth e provei a conexão do cliente da mesma forma que no nó do gerenciador.

Então, no gerenciador, executei docker swarm init

Para juntar o nó de trabalho ao swarm eu uso o seguinte comando: docker swarm join --token XXX dockman.myhost.com:2376

Mas recebo um erro:

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"

Achei que poderia testá-lo ainda mais tentando conectar-me à API do docker no nó gerenciador do nó trabalhador:

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

O resultado é:

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

Este segundo teste me deu muito mais em que pensar. É claro que falhará porque estou tentando me conectar a um certificado de servidor e não a um certificado de cliente, mas não é exatamente isso que o docker swarm join está tentando fazer? Não faz sentido para mim colocar o certificado do cliente em daemon.json. Pesquisei no Google para criar um único certificado para servidor e cliente e é possível, mas parece ser uma má prática. Eu teria pensado que isso teria sido abordado no tutorial, se fosse necessário.

Eu estive preso neste ponto. Não consigo descobrir qual configuração de certificado é necessária.

eu tenho acompanhado https://github.com/docker/docker.github.io/blob/master/swarm/configure-tls.md Isso descreve a criação de certificados, mas não menciona a autenticação de cliente ou servidor.

Atualização 1

Encontrei um documento que dizia que os certificados precisam ser cliente e servidor

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

Então refiz o certificado do nó para ser cliente e servidor. Agora, o comando docker version funciona quando executado a partir do nó, mas não do swarm join.

Responder1

Você está misturando o modo Swarm ( docker swarme CLIs semelhantes) com o clássico Swarm baseado em contêiner (hospedado como um contêiner no docker hub). Estas são duas ferramentas diferentes.

Para os dois conjuntos de documentação, consulte:

Não há necessidade de fazer nenhuma configuração manual de TLS com o modo Swarm, está tudo integrado e as portas para o modo Swarm são diferentes das portas do soquete API do docker. Você não deseja expor a API do Docker na rede sem um bom motivo (esta é uma fonte comum de hacks), e o modo Swarm não é um motivo.

Portanto, você deve remover a -Hopção do dockerdcomando, juntamente com quaisquer opções de TLS existentes. Em seguida, execute docker swarm inito primeiro gerenciador que irá gerar as credenciais TLS e fornecer um token que inclui um hash dos certificados autoassinados. Em seguida, os outros gerentes e trabalhadores executam um docker swarm joinpara gerar os certificados do cliente, conectar-se ao gerente, validar o hash dos certificados do gerente do token e autenticar-se para o gerente com a parte secreta do token de junção.

O acima irá criptografar o plano de gerenciamento entre os gerentes e os trabalhadores. Para criptografar os dados transmitidos em redes sobrepostas entre trabalhadores, você precisa habilitar o IPSec nas redes sobrepostas que você cria:

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

A documentação sobre esse recurso está em:https://docs.docker.com/v17.09/engine/userguide/networking/overlay-security-model/

Responder2

Eu estava certo de que todos os certificados precisavam ser certificados de cliente e servidor para funcionar.

Passei então a encontrar outros problemas, sendo o principal deles que as máquinas virtuais no host que estou usando proíbem o uso da porta 4789, pois ela é usada pelo VMWare. Esta é a porta de caminho de dados padrão usada para a rede de sobreposição.

Tive que remover completamente todos os nós e gerenciadores do enxame (excluindo-o efetivamente) e reiniciá-lo usando o parâmetro data-path-port:

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

(Também especifiquei o endereço de anúncio como o IP de cada nó, mas não acho que isso fosse necessário)

É claro que todos os meus docker secrets, docker config e algumas das minhas redes docker foram perdidos neste processo e tiveram que ser recriados.

Depois de concluir isso e alterar o firewall para permitir a comunicação UDP entre os nós usando a porta do caminho de dados, as coisas funcionaram novamente.

Como a rede do enxame é criptografada, acho que tudo deveria estar funcionando.

informação relacionada