Detalhes da rede do Docker e combate real

1. Modo de rede padrão do Docker

Visualize todas as redes do Docker com o seguinte comando:

docker network ls

insira a descrição da imagem aqui

O Docker fornece quatro modos de rede por padrão, indicando:

  1. bridge: A rede padrão do container é o modo bridge (a rede construída por você também usa o modo bridge por padrão, e o padrão para iniciar o container é o modo bridge). Esse modo atribuirá e definirá o IP para cada contêiner, conectará o contêiner a uma ponte virtual docker0 e se comunicará com o host por meio da ponte docker0 e da configuração da tabela nat do Iptables.

  2. none: Nenhuma rede está configurada, o contêiner tem um namespace de rede independente, mas nenhuma configuração de rede é executada nele, como atribuir veth pair e conexões de ponte, configurar IP etc.

  3. host: O contêiner e o host compartilham o namespace Network. O contêiner não virtualizará sua própria placa de rede, configurará seu próprio IP etc., mas usará o IP e a porta do host.

  4. container: O container criado não criará sua própria placa de rede e configurará sua própria conexão de rede do container IP. Um contêiner compartilha um namespace de rede (IP compartilhado, intervalo de portas) com outro contêiner.

O contêiner usa o modo de rede de ponte por padrão. Usamos esta docker run --network=opção para especificar a rede usada pelo contêiner:

  • modo de host: especificado com --net=host.
  • nenhum modo: especificado com --net=none.
  • modo bridge: especificado com --net=bridge, a configuração padrão.
  • modo de contêiner: especificado com --net=container:NAME_or_ID.

1.1 modo de host

Breve descrição
do namespace: o Docker usa a tecnologia de namespaces do Linux para isolar recursos, como processo de isolamento de namespace PID, sistema de arquivos de isolamento de namespace de montagem, rede de isolamento de namespace de rede etc.

Um namespace de rede fornece um ambiente de rede independente, incluindo placas de rede, roteamento, regras Iptable, etc., que são isolados de outros namespaces de rede. Um contêiner do Docker geralmente recebe um namespace de rede separado.

Se o modo de host for usado ao iniciar o contêiner, o contêiner não obterá um namespace de rede independente, mas compartilhará um namespace de rede com o host. O contêiner não virtualizará sua própria placa de rede, configurará seu próprio IP etc., mas usará o IP e a porta do host. No entanto, outros aspectos do contêiner, como sistema de arquivos, lista de processos, etc., ainda estão isolados do host.

Os contêineres que usam o modo de host podem usar diretamente o endereço IP do host para se comunicar com o mundo externo. A porta de serviço dentro do contêiner também pode usar a porta do host sem NAT. A maior vantagem do host é que o desempenho da rede é melhor, mas o docker host has A porta usada não pode mais ser usada e o isolamento da rede não é bom. O diagrama de modelo do modo Host é mostrado na figura a seguir:
insira a descrição da imagem aqui
Nota: eth0 é o endereço de rede interno do host e 10.126.130.4 é o endereço de rede interno do host.

1.2 modo de contêiner

Esse modo especifica que os contêineres recém-criados compartilham um Namespace de rede com um contêiner existente, em vez de com o host. O contêiner recém-criado não criará sua própria placa de rede, configurará seu próprio IP, mas compartilhará o IP, intervalo de portas etc. com um contêiner especificado. Da mesma forma, além da rede, os dois contêineres são isolados de outros aspectos, como sistemas de arquivos, listas de processos, etc. Os processos dos dois contêineres podem se comunicar através do dispositivo lo NIC. O diagrama esquemático do modelo do modo Container é o seguinte:

insira a descrição da imagem aqui

1.3 modo nenhum

Com nenhum modo, o contêiner do Docker tem seu próprio namespace de rede, no entanto, nenhuma configuração de rede é feita para o contêiner do Docker. Em outras palavras, esse contêiner do Docker não possui placa de rede, IP, roteamento e outras informações. Precisamos adicionar placas de rede, configurar IP etc. ao contêiner do Docker.

Nesse modo de rede, o contêiner possui apenas a rede de loopback lo e nenhuma outra placa de rede. O modo none pode ser especificado com --network=none quando o contêiner é criado. Esse tipo de rede não pode ser conectado em rede e uma rede fechada pode garantir a segurança do contêiner.

Diagrama esquemático do modo Nenhum:

insira a descrição da imagem aqui

1.4 modo ponte

Quando o processo do Docker é iniciado, uma ponte virtual chamada docker0 é criada no host e o contêiner do Docker iniciado nesse host é conectado a essa ponte virtual. Uma ponte virtual funciona como um switch físico, para que todos os contêineres no host sejam conectados a uma rede de camada 2 por meio do switch.

Aloque um IP da sub-rede docker0 para o contêiner usar e defina o endereço IP do docker0 como o gateway padrão do contêiner. Crie um par de dispositivos veth pair da placa de rede virtual no host. O Docker coloca uma extremidade do dispositivo veth pair no contêiner recém-criado e o nomeia eth0 (a placa de rede do contêiner) e a outra extremidade é colocada no host, com um nome semelhante como vethxxx Name e adicione este dispositivo de rede à ponte docker0. Ele pode ser visualizado com o comando brctl show.

O modo de ponte é o modo de rede padrão do docker. Se você não escrever o parâmetro --net, será o modo de ponte. Ao usar o docker run -p, o docker realmente cria regras de DNAT em iptables para realizar a função de encaminhamento de porta. Você pode usar iptables -t nat -vnL para visualizar. O modo bridge é mostrado na figura a seguir:

insira a descrição da imagem aqui

Quando o servidor Docker for iniciado, uma ponte virtual chamada docker0 será criada no host e o contêiner do Docker iniciado nesse host será conectado a essa ponte virtual. A tecnologia usada pelo Docker0 é a tecnologia evth-pair. No modo de rede de ponte padrão, sempre que iniciarmos um contêiner do Docker, o Docker configurará um IP para o contêiner do Docker.

O contêiner do Docker conclui o processo de configuração de rede da ponte da seguinte maneira:

  1. Crie um par de dispositivos de veth pair de NIC virtual no host. Os dispositivos Veth sempre aparecem em pares e formam um canal de dados. Os dados entram de um dispositivo e saem do outro. Portanto, os dispositivos veth são frequentemente usados ​​para conectar dois dispositivos de rede.
  2. O Docker coloca uma extremidade do dispositivo veth pair no contêiner recém-criado e o nomeia eth0. A outra extremidade é colocada no host, chamada algo como veth65f9, e esse dispositivo de rede é adicionado à ponte docker0.
  3. Aloque um IP da sub-rede docker0 para o contêiner usar e defina o endereço IP do docker0 como o gateway padrão do contêiner.

Execute o comando ip addr, você pode ver que após instalar o Docker, o host padrão possui três endereços.

insira a descrição da imagem aqui

Como o Docker lida com o acesso à rede do contêiner? Inicie um contêiner, insira o contêiner usando ip addras configurações de rede de visualização

docker run -d -P --name tomcat01 tomcat:8.0

insira a descrição da imagem aqui

Você pode ver que, depois que o contêiner é iniciado, o Docker atribui ao contêiner um endereço IP no formato eth0@if262. O host executa ip addro comando para visualizar as alterações:insira a descrição da imagem aqui

Você pode ver que uma nova placa de rede será criada dentro do contêiner e do host Linux, e essas duas placas de rede estão emparelhadas. A técnica utilizada é evth-pair. evth-pair é um par de interfaces de dispositivos virtuais, eles aparecem em pares, um está conectado ao protocolo e o outro está conectado entre si. O evth-pair atua como uma ponte para conectar vários dispositivos de rede virtual.

==Os hosts Linux podem se conectar diretamente aos contêineres do Docker. Os contêineres e contêineres do Docker também podem ser conectados diretamente à rede. ==Os seguintes experimentos específicos verificam isso.

docker exec -it tomcat01 ip addr

insira a descrição da imagem aqui

Em seguida, inicie um contêiner do Tomcat e tente ver se a conexão de rede entre os contêineres foi bem-sucedida.

insira a descrição da imagem aqui
insira a descrição da imagem aqui

Tente pingar o container tomcat02 no container tomcat01, você pode ver que os dois containers podem ser conectados. O diagrama do modelo de interação de rede entre dois contêineres do Tomcat é o seguinte:

insira a descrição da imagem aqui
ilustrar:

Tanto o Tomcat01 quanto o Tomcat02 usam o roteador comum docker0. Todos os contêineres são roteados pelo docker0 sem especificar uma rede. O Docker atribuirá um endereço IP aleatório disponível ao nosso contêiner por padrão.

O modelo geral de interconexão de rede de contêineres, conforme mostrado na figura a seguir:

insira a descrição da imagem aqui

Todas as interfaces de rede no Docker são virtuais. Enquanto o contêiner for excluído, a ponte correspondente ao contêiner também será excluída.

2. Interconexão de contêineres

No cenário de implantação de microsserviço, o registro usa o nome do serviço para identificar exclusivamente o microsserviço, e o endereço IP correspondente ao microsserviço pode mudar quando estamos online e implantamos, portanto, precisamos usar o nome do contêiner para configurar a conexão de rede entre os contêineres . Isso pode ser feito com --link.

Em primeiro lugar, se a conexão não estiver definida, é impossível se conectar pelo nome do contêiner.
insira a descrição da imagem aqui

Vamos iniciar um contêiner Tomcat Tomcat03 e usar --link para conectar ao contêiner Tomcat02 já iniciado. Desta forma, o container Tomcat03 pode se conectar ao container Tomcat02 através do nome do container Tomcat02.
insira a descrição da imagem aqui
Mas, inversamente, o contêiner Tomcat02 não pode executar ping diretamente no contêiner Tomcat03 por meio do nome do contêiner Tomcat03.
insira a descrição da imagem aqui
Isso ocorre porque --linko princípio é adicionar o mapeamento do nome do contêiner e do endereço IP ao arquivo /etc/hosts no contêiner em execução especificado, da seguinte forma:

insira a descrição da imagem aqui
O contêiner tomcat02 não pode se conectar ao tomcat03 por meio do nome do contêiner porque o mapeamento entre o nome do contêiner tomcat03 e o endereço IP não é adicionado ao contêiner tomcat02.

insira a descrição da imagem aqui
Atualmente, a maneira de --link de configurar interconexões de contêiner está obsoleta. Como o docker0 não oferece suporte ao acesso ao nome do contêiner, mais redes personalizadas são selecionadas.

3. Rede personalizada

Por causa do docker0, ele não é acessível pelo nome do contêiner por padrão. Você precisa configurar a conexão através de --link. Esse tipo de operação é mais trabalhoso. A forma mais recomendada é customizar a rede. Todos os containers usam essa rede customizada, para que possam acessar uns aos outros através do nome do container.

Veja abaixo os comandos relacionados à rede

docker network --help

insira a descrição da imagem aqui
Veja os detalhes da ponte de rede padrão
insira a descrição da imagem aqui

Visualize os parâmetros relevantes do comando network create
insira a descrição da imagem aqui

Personalize uma rede abaixo

docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

insira a descrição da imagem aqui
Descrição do parâmetro:

 --driver bridge   #指定bridge驱动程序来管理网络
--subnet 192.168.0.0/16 #指定网段的CIDR格式的子网
--gateway 192.168.0.1 	#指定主子网的IPv4或IPv6网关

Depois que a rede mynet for criada com sucesso, verifique as informações da rede:

docker network inspect mynet

insira a descrição da imagem aqui

Em seguida, inicie dois contêineres, especifique a rede personalizada mynet e teste se o contêiner na rede personalizada pode acessar diretamente a rede por meio do nome do contêiner.

docker run -d -P --name tomcat-net-01 --net mynet tomcat 
docker run -d -P --name tomcat-net-02 --net mynet tomcat 
docker network inspect mynet

insira a descrição da imagem aqui

Vamos usar o nome do container para testar se a comunicação de rede entre o container tomcat-net-01 e o container tomcat-net-02 é normal.
insira a descrição da imagem aqui

Pode-se descobrir que, em nossa rede personalizada, os contêineres podem se comunicar por meio do nome do contêiner e do endereço IP. Nossa rede personalizada já nos ajudou a manter a comunicação de rede entre contêineres por padrão, que é a maneira recomendada de obter a interconexão de rede.

4. Interconexão entre redes Docker

Sem essa configuração, contêineres em redes diferentes não podem se conectar à rede. Conforme mostrado na figura, o diagrama do modelo de rede de duas redes diferentes docker0 e rede personalizada mynet:

insira a descrição da imagem aqui

Inicie o contêiner tomcat-01 na ponte de rede padrão e tente se conectar ao contêiner tomcat-net-01 na rede mynet.

insira a descrição da imagem aqui
Pode-se ver que não há conexão de rede. Se os containers entre diferentes redes Docker precisarem ser conectados, o container como chamador precisa registrar um ip na rede onde o chamado está localizado. Um docker connectcomando é necessário.

O seguinte configura o contêiner tomcat-01 para se conectar à rede mynet. E verifique os detalhes da rede do mynet, você pode ver que um endereço IP está atribuído ao contêiner tomcat-01.

docker network connect mynet tomcat-01

insira a descrição da imagem aqui

Após a conclusão da configuração, podemos implementar a interconexão de contêineres entre diferentes redes.

insira a descrição da imagem aqui

5. Exercício prático de rede Docker

5.1 Implantação de cluster Redis

O seguinte implanta o cluster Redis com três mestres e três escravos, conforme mostrado na figura
insira a descrição da imagem aqui

Primeiro pare todos os contêineres

docker rm -f $(docker ps -aq)

insira a descrição da imagem aqui

Crie uma rede personalizada com o nome da rede redis

docker network create redis --subnet 172.38.0.0/16

insira a descrição da imagem aqui
Crie seis informações de configuração do Redis com o seguinte script:

for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379 
bind 0.0.0.0
cluster-enabled yes 
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

insira a descrição da imagem aqui
Em seguida, inicie seis contêineres Redis e defina as montagens de volume de dados do contêiner correspondentes.

#第1个Redis容器
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
    -v /mydata/redis/node-1/data:/data \
    -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第2个Redis容器
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
    -v /mydata/redis/node-2/data:/data \
    -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第3个Redis容器
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
    -v /mydata/redis/node-3/data:/data \
    -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第4个Redis容器
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
    -v /mydata/redis/node-4/data:/data \
    -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第5个Redis容器
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
    -v /mydata/redis/node-5/data:/data \
    -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#第6个Redis容器
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
    -v /mydata/redis/node-6/data:/data \
    -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
    -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf

Ou inicie 6 contêineres Redis de uma só vez via script:

for port in $(seq 1 6); \
do
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
done

Execute o script acima e os resultados são os seguintes: Em seguida,
insira a descrição da imagem aqui
insira o contêiner redis-1 para criar um cluster

redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1

Ver informações do cluster

redis-cli -c
cluster info

insira a descrição da imagem aqui
Visualize as informações do nó cluster nodes, você pode ver claramente a relação mestre-escravo do nó Redis.
insira a descrição da imagem aqui

Teste se a replicação mestre-escravo entra em vigor, defina uma chave, você pode ver que somos redirecionados para o nó Redis-3 e o nó Redis-3 lida com essa operação.
insira a descrição da imagem aqui

Crie uma nova sessão, pare o serviço de contêiner Redis-3, reconecte o cliente Redis-cli, obtenha k1 novamente e redirecione-o para o nó escravo Redis-4 do nó Redis-3 para processamento.

insira a descrição da imagem aqui

5.2 Espelho de embalagem do projeto SpringBoot

A imagem de empacotamento do projeto SpringBoot é dividida nas cinco etapas a seguir
(1) Construir o projeto SpringBoot
Construir o projeto Spring Boot mais simples na ideia, escrever uma interface e iniciar o projeto para testar se ele pode ser chamado normalmente.


/**
 * @author ethan
 * @since 2020-04-22 20:26:31
 */
@RestController
public class HelloController {
    
    

    @GetMapping("/hello")
    public String hello(){
    
    
        return "Hello World!";
    }
}

(2) Empacote o aplicativo
Use o pacote do Maven para empacotar o projeto Spring Boot e gerar um pacote jar
insira a descrição da imagem aqui

(3) Write Dockerfile
Write Dockerfile, o conteúdo é o seguinte

FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

(4) Construir a imagem
Envie o pacote jar empacotado e o Dockerfile escrito para o servidor e
insira a descrição da imagem aqui
use o comando build para construir a imagem

 docker build -t demo .

insira a descrição da imagem aqui

(5) Solte e execute
Após concluir a construção da imagem, execute a imagem para testar se a interface /hello pode ser acessada normalmente.

 docker run -d -p 8080:8080 demo
 curl localhost:8080/hello

insira a descrição da imagem aqui

Referência:
1. https://www.bilibili.com/video/BV1og4y1q7M4
2. Explicação detalhada da rede Docker - princípio
3. Docker quatro modos de rede

Acho que você gosta

Origin blog.csdn.net/huangjhai/article/details/120425457
Recomendado
Clasificación