Introdução à parte de rede da infraestrutura em nuvem

Introdução à parte de rede da infraestrutura em nuvem

A computação em nuvem está penetrando cada vez mais profundamente em nossas vidas e provavelmente não existe uma única pessoa que não tenha usado nenhum serviço em nuvem pelo menos uma vez. Porém, o que é exatamente uma nuvem e como ela funciona, poucas pessoas sabem, mesmo no nível de uma ideia. O 5G já está se tornando uma realidade e a infraestrutura de telecomunicações está começando a passar de soluções de pilares para soluções em nuvem, assim como aconteceu quando passou de soluções totalmente de hardware para “pilares” virtualizados.

Hoje falaremos sobre o mundo interno da infraestrutura em nuvem, em particular veremos o básico da parte de rede.

O que é uma nuvem? A mesma virtualização – visualização de perfil?

Mais do que uma pergunta lógica. Não - isso não é virtualização, embora não pudesse ser feito sem ela. Vejamos duas definições:

Computação em nuvem (doravante denominada Nuvem) é um modelo para fornecer acesso amigável a recursos de computação distribuídos que devem ser implantados e lançados sob demanda com a menor latência possível e custo mínimo para o provedor de serviços.

virtualização - esta é a capacidade de dividir uma entidade física (por exemplo, um servidor) em várias entidades virtuais, aumentando assim a utilização de recursos (por exemplo, você tinha 3 servidores carregados em 25-30 por cento, após a virtualização você obtém 1 servidor carregado em 80-90 por cento). Naturalmente, a virtualização consome alguns recursos - você precisa alimentar o hipervisor, porém, como a prática tem mostrado, o jogo vale a pena. Um exemplo ideal de virtualização é o VMWare, que prepara perfeitamente as máquinas virtuais, ou por exemplo o KVM, que prefiro, mas é uma questão de gosto.

Usamos virtualização sem perceber, e até roteadores iron já usam virtualização - por exemplo, na versão mais recente do JunOS, o sistema operacional é instalado como uma máquina virtual em cima de uma distribuição Linux em tempo real (Wind River 9). Mas a virtualização não é a nuvem, mas a nuvem não pode existir sem virtualização.

A virtualização é um dos blocos de construção sobre os quais a nuvem é construída.

Criar uma nuvem simplesmente coletando vários hipervisores em um domínio L2, adicionar alguns manuais yaml para registrar vlans automaticamente por meio de algum tipo de ansible e inserir algo como um sistema de orquestração em tudo isso para criar máquinas virtuais automaticamente não funcionará. Será mais preciso, mas o Frankenstein resultante não é a nuvem de que necessitamos, embora possa ser o maior sonho de outros. Além disso, se você pegar o mesmo Openstack, ainda será essencialmente Frankenstein, mas tudo bem, não vamos falar sobre isso por enquanto.

Mas entendo que pela definição apresentada acima não está totalmente claro o que realmente pode ser chamado de nuvem.

Portanto, um documento do NIST (National Institute of Standards and Technology) traz 5 características principais que uma infraestrutura em nuvem deve ter:

Prestação de serviço mediante solicitação. O utilizador deve ter livre acesso aos recursos informáticos que lhe são atribuídos (como redes, discos virtuais, memória, núcleos de processador, etc.), e esses recursos devem ser fornecidos de forma automática – ou seja, sem intervenção do prestador de serviço.

Ampla disponibilidade de serviço. O acesso aos recursos deve ser fornecido por mecanismos padrão para permitir o uso tanto de PCs padrão quanto de thin clients e dispositivos móveis.

Combinando recursos em pools. Os pools de recursos devem ser capazes de fornecer recursos a vários clientes ao mesmo tempo, garantindo que os clientes estejam isolados e livres de influência mútua e competição por recursos. As redes também estão incluídas nos pools, o que indica a possibilidade de utilização de endereçamento sobreposto. Os pools devem ser capazes de escalar sob demanda. A utilização de pools permite fornecer o nível necessário de tolerância a falhas de recursos e abstração de recursos físicos e virtuais - o destinatário do serviço recebe simplesmente o conjunto de recursos que solicitou (onde esses recursos estão fisicamente localizados, em quantos servidores e switches - isso não importa para o cliente). No entanto, devemos ter em conta que o fornecedor deve garantir a reserva transparente destes recursos.

Adaptação rápida a diferentes condições. Os serviços devem ser flexíveis - fornecimento rápido de recursos, sua redistribuição, adição ou redução de recursos a pedido do cliente, e por parte do cliente deve haver a sensação de que os recursos da nuvem são infinitos. Para facilitar a compreensão, por exemplo, você não vê um aviso de que parte do espaço em disco no Apple iCloud desapareceu porque o disco rígido do servidor quebrou e as unidades quebraram. Além disso, da sua parte, as possibilidades deste serviço são quase ilimitadas - você precisa de 2 TB - não tem problema, você pagou e recebeu. Um exemplo semelhante pode ser dado com Google.Drive ou Yandex.Disk.

Possibilidade de medir o serviço prestado. Os sistemas em nuvem devem controlar e otimizar automaticamente os recursos consumidos, e esses mecanismos devem ser transparentes tanto para o usuário quanto para o provedor de serviços. Ou seja, você sempre pode verificar quantos recursos você e seus clientes estão consumindo.

Vale a pena considerar o fato de que esses requisitos são, em sua maioria, requisitos para uma nuvem pública, portanto, para uma nuvem privada (ou seja, uma nuvem lançada para as necessidades internas da empresa), esses requisitos podem ser ligeiramente ajustados. No entanto, ainda precisam ser feitas, caso contrário não obteremos todos os benefícios da computação em nuvem.

Por que precisamos de uma nuvem?

No entanto, qualquer tecnologia nova ou existente, qualquer novo protocolo é criado para alguma coisa (bem, exceto para RIP-ng, é claro). Ninguém precisa de um protocolo apenas por protocolo (bem, exceto RIP-ng, é claro). É lógico que a Nuvem seja criada para fornecer algum tipo de serviço ao usuário/cliente. Todos nós estamos familiarizados com pelo menos alguns serviços em nuvem, por exemplo Dropbox ou Google.Docs, e acredito que a maioria das pessoas os usa com sucesso - por exemplo, este artigo foi escrito usando o serviço em nuvem Google.Docs. Mas os serviços em nuvem que conhecemos são apenas parte das capacidades da nuvem – mais precisamente, são apenas um serviço do tipo SaaS. Podemos fornecer um serviço de nuvem de três maneiras: na forma de SaaS, PaaS ou IaaS. O serviço de que você precisa depende de seus desejos e capacidades.

Vejamos cada um em ordem:

Software como Serviço (SaaS) é um modelo para fornecer um serviço completo ao cliente, por exemplo, um serviço de e-mail como Yandex.Mail ou Gmail. Nesse modelo de prestação de serviços, você, como cliente, na verdade não faz nada além de utilizar os serviços - ou seja, não precisa pensar na configuração do serviço, em sua tolerância a falhas ou redundância. O principal é não comprometer a sua senha, o fornecedor deste serviço fará o resto por você. Do ponto de vista do provedor de serviços, ele é totalmente responsável por todo o serviço – desde o hardware do servidor e sistemas operacionais host até as configurações do banco de dados e do software.

Plataforma como serviço (PaaS) — ao utilizar este modelo, o provedor de serviço fornece ao cliente uma peça de trabalho para o serviço, por exemplo, vamos pegar um servidor Web. O provedor de serviços forneceu ao cliente um servidor virtual (na verdade, um conjunto de recursos, como RAM/CPU/Armazenamento/Redes, etc.), e ainda instalou o SO e software necessário neste servidor, porém, a configuração de tudo isso é feito pelo próprio cliente e pela execução do serviço o cliente responde. O prestador de serviço, tal como no caso anterior, é responsável pelo desempenho dos equipamentos físicos, dos hipervisores, da própria máquina virtual, da sua disponibilidade de rede, etc., mas o serviço em si já não é da sua responsabilidade.

Infraestrutura como serviço (IaaS) - essa abordagem já é mais interessante, aliás, o provedor de serviço fornece ao cliente uma infraestrutura virtualizada completa - ou seja, algum conjunto (pool) de recursos, como Núcleos de CPU, RAM, Redes, etc. o cliente - o que o cliente deseja fazer com esses recursos dentro do pool alocado (cota) - não é particularmente importante para o fornecedor. Quer o cliente pretenda criar o seu próprio vEPC ou mesmo criar uma minioperadora e prestar serviços de comunicação - sem dúvida - faça-o. Neste cenário, o prestador de serviços é responsável pelo provisionamento dos recursos, pela sua tolerância a falhas e disponibilidade, bem como pelo SO que lhe permite agrupar esses recursos e disponibilizá-los ao cliente com a capacidade de aumentar ou diminuir recursos a qualquer momento. a pedido do cliente. O próprio cliente configura todas as máquinas virtuais e outros enfeites por meio do portal e console de autoatendimento, incluindo a configuração de redes (exceto redes externas).

O que é OpenStack?

Nas três opções, o provedor de serviços precisa de um sistema operacional que permita a criação de uma infraestrutura em nuvem. Na verdade, com o SaaS, mais de uma divisão é responsável por todo o stack de tecnologias – existe uma divisão que é responsável pela infraestrutura – ou seja, ela fornece IaaS para outra divisão, essa divisão fornece SaaS para o cliente. OpenStack é um dos sistemas operacionais em nuvem que permite coletar vários switches, servidores e sistemas de armazenamento em um único pool de recursos, dividir esse pool comum em subpools (locatários) e fornecer esses recursos aos clientes pela rede.

OpenStack é um sistema operacional em nuvem que permite controlar grandes conjuntos de recursos de computação, armazenamento de dados e recursos de rede, provisionados e gerenciados via API usando mecanismos de autenticação padrão.

Em outras palavras, este é um conjunto de projetos de software livre projetados para criar serviços em nuvem (públicos e privados) - ou seja, um conjunto de ferramentas que permitem combinar servidores e equipamentos de comutação em um único conjunto de recursos, gerenciar esses recursos, proporcionando o nível necessário de tolerância a falhas.

No momento em que este artigo foi escrito, a estrutura do OpenStack se parecia com esta:
Introdução à parte de rede da infraestrutura em nuvem
Foto tirada de openstack.org

Cada um dos componentes incluídos no OpenStack executa uma função específica. Esta arquitetura distribuída permite incluir na solução o conjunto de componentes funcionais que necessita. No entanto, alguns componentes são componentes raiz e sua remoção levará à inoperabilidade total ou parcial da solução como um todo. Esses componentes são geralmente classificados como:

  • Painel — GUI baseada na Web para gerenciar serviços OpenStack
  • Pedra angular é um serviço de identidade centralizado que fornece funcionalidade de autenticação e autorização para outros serviços, bem como gerencia credenciais de usuários e suas funções.
  • Nêutron - um serviço de rede que fornece conectividade entre as interfaces de vários serviços OpenStack (incluindo conectividade entre VMs e seu acesso ao mundo exterior)
  • cinza — fornece acesso ao armazenamento em bloco para máquinas virtuais
  • nova — gerenciamento do ciclo de vida de máquinas virtuais
  • Relance — repositório de imagens e instantâneos de máquinas virtuais
  • rápido — fornece acesso ao objeto de armazenamento
  • Ceilômetro — um serviço que oferece a capacidade de coletar telemetria e medir os recursos disponíveis e consumidos
  • HEAT — orquestração baseada em modelos para criação e provisionamento automático de recursos

Uma lista completa de todos os projetos e sua finalidade pode ser visualizada aqui.

Cada componente OpenStack é um serviço que executa uma função específica e fornece uma API para gerenciar essa função e interagir com outros serviços do sistema operacional em nuvem para criar uma infraestrutura unificada. Por exemplo, Nova fornece gerenciamento de recursos de computação e uma API para acesso à configuração desses recursos, Glance fornece gerenciamento de imagens e uma API para gerenciá-los, Cinder fornece armazenamento de blocos e uma API para gerenciá-los, etc. Todas as funções estão interligadas de forma muito próxima.

No entanto, se você observar, todos os serviços executados no OpenStack são, em última análise, algum tipo de máquina virtual (ou contêiner) conectada à rede. Surge a pergunta: por que precisamos de tantos elementos?

Vamos examinar o algoritmo para criar uma máquina virtual e conectá-la à rede e ao armazenamento persistente no Openstack.

  1. Quando você cria uma solicitação para criar uma máquina, seja uma solicitação através do Horizon (Dashboard) ou uma solicitação através da CLI, a primeira coisa que acontece é a autorização da sua solicitação no Keystone - você pode criar uma máquina, ela tem o direito de usar esta rede, sua cota de projeto, etc.
  2. O Keystone autentica sua solicitação e gera um token de autenticação na mensagem de resposta, que será usado posteriormente. Após receber uma resposta da Keystone, a solicitação é enviada para Nova (nova api).
  3. Nova-api verifica a validade da sua solicitação entrando em contato com a Keystone usando o token de autenticação gerado anteriormente
  4. Keystone realiza autenticação e fornece informações sobre permissões e restrições com base neste token de autenticação.
  5. Nova-api cria uma entrada para a nova VM no banco de dados nova e passa a solicitação para criar a máquina para o nova-scheduler.
  6. O Nova-scheduler seleciona o host (nó do computador) no qual a VM será implantada com base nos parâmetros, pesos e zonas especificados. Um registro disso e o ID da VM são gravados no banco de dados nova.
  7. Em seguida, o nova-scheduler entra em contato com o nova-compute com uma solicitação para implantar uma instância. Nova-compute contata nova-conductor para obter informações sobre os parâmetros da máquina (nova-conductor é um elemento nova que atua como um servidor proxy entre nova-database e nova-compute, limitando o número de solicitações ao nova-database para evitar problemas com o banco de dados redução de carga de consistência).
  8. O Nova-conductor recebe as informações solicitadas do banco de dados nova e as passa para o nova-compute.
  9. Em seguida, o nova-compute chama o olhar para obter o ID da imagem. Glace valida a solicitação no Keystone e retorna as informações solicitadas.
  10. Nova-compute contata nêutrons para obter informações sobre parâmetros de rede. Semelhante ao Glance, o Neutron valida a solicitação no Keystone, após o qual cria uma entrada no banco de dados (identificador de porta, etc.), cria uma solicitação para criar uma porta e retorna as informações solicitadas para o nova-compute.
  11. A Nova-compute entra em contato com uma solicitação para alocar um volume para a máquina virtual. Semelhante ao Glance, o cidra valida a solicitação no Keystone, cria uma solicitação de criação de volume e retorna as informações solicitadas.
  12. Nova-compute contata a libvirt com uma solicitação para implantar uma máquina virtual com os parâmetros especificados.

Na verdade, uma operação aparentemente simples de criação de uma máquina virtual simples se transforma em um redemoinho de chamadas de API entre elementos da plataforma em nuvem. Além disso, como você pode ver, mesmo os serviços previamente designados também consistem em componentes menores entre os quais ocorre a interação. Criar uma máquina é apenas uma pequena parte do que a plataforma em nuvem permite fazer – existe um serviço responsável por balancear o tráfego, um serviço responsável pelo armazenamento de blocos, um serviço responsável pelo DNS, um serviço responsável por provisionar servidores bare metal, etc. A nuvem permite que você trate suas máquinas virtuais como um rebanho de ovelhas (em oposição à virtualização). Se algo acontecer com sua máquina em um ambiente virtual - você a restaura a partir de backups, etc., mas os aplicativos em nuvem são construídos de tal forma que a máquina virtual não desempenha um papel tão importante - a máquina virtual “morreu” - não há problema - acaba de ser criado um novo, o veículo é baseado no template e, como dizem, o esquadrão não percebeu a perda do lutador. Naturalmente, isso prevê a presença de mecanismos de orquestração - usando modelos Heat, você pode implantar facilmente uma função complexa que consiste em dezenas de redes e máquinas virtuais.

É sempre importante ter em mente que não existe infraestrutura em nuvem sem rede - cada elemento de uma forma ou de outra interage com outros elementos por meio da rede. Além disso, a nuvem possui uma rede absolutamente não estática. Naturalmente, a rede subjacente é ainda mais ou menos estática - novos nós e switches não são adicionados todos os dias, mas o componente de sobreposição pode e irá inevitavelmente mudar constantemente - novas redes serão adicionadas ou excluídas, novas máquinas virtuais aparecerão e as antigas serão morrer. E como você lembra da definição de nuvem dada no início do artigo, os recursos devem ser alocados ao usuário automaticamente e com o mínimo (ou melhor ainda, sem) intervenção do provedor de serviços. Ou seja, o tipo de fornecimento de recursos de rede que agora existe na forma de um front-end na forma de sua conta pessoal acessível via http/https e o engenheiro de rede de plantão Vasily como back-end não é uma nuvem, mesmo se Vasily tiver oito mãos.

O Neutron, como serviço de rede, fornece uma API para gerenciar a parte de rede da infraestrutura em nuvem. O serviço capacita e gerencia a parte de rede do Openstack, fornecendo uma camada de abstração chamada Network-as-a-Service (NaaS). Ou seja, a rede é a mesma unidade virtual mensurável que, por exemplo, os núcleos virtuais da CPU ou a quantidade de RAM.

Mas antes de passarmos para a arquitetura da parte de rede do OpenStack, vamos considerar como essa rede funciona no OpenStack e por que a rede é uma parte importante e integrante da nuvem.

Portanto, temos duas VMs clientes RED e duas VMs clientes VERDES. Vamos supor que essas máquinas estejam localizadas em dois hipervisores desta forma:

Introdução à parte de rede da infraestrutura em nuvem

No momento trata-se apenas de virtualização de 4 servidores e nada mais, pois até agora tudo o que fizemos foi virtualizar 4 servidores, colocando-os em dois servidores físicos. E até agora eles nem estão conectados à rede.

Para fazer uma nuvem, precisamos adicionar vários componentes. Primeiro virtualizamos a parte da rede - precisamos conectar essas 4 máquinas em pares, e os clientes querem uma conexão L2. Você pode usar um switch e configurar um trunk em sua direção e resolver tudo usando uma bridge linux ou, para usuários mais avançados, openvswitch (voltaremos a isso mais tarde). Mas pode haver muitas redes, e passar constantemente L2 por meio de um switch não é a melhor ideia - existem diferentes departamentos, uma central de atendimento, meses de espera pela conclusão de um aplicativo, semanas de solução de problemas - no mundo moderno isso abordagem não funciona mais. E quanto mais cedo uma empresa entender isso, mais fácil será para ela avançar. Portanto, entre os hipervisores selecionaremos uma rede L3 através da qual nossas máquinas virtuais se comunicarão, e sobre esta rede L3 construiremos redes virtuais de sobreposição L2 onde será executado o tráfego de nossas máquinas virtuais. Você pode usar GRE, Geneve ou VxLAN como encapsulamento. Vamos nos concentrar neste último por enquanto, embora não seja particularmente importante.

Precisamos localizar o VTEP em algum lugar (espero que todos estejam familiarizados com a terminologia VxLAN). Como temos uma rede L3 vindo direto dos servidores, nada nos impede de colocar o VTEP nos próprios servidores, e o OVS (OpenvSwitch) é excelente para fazer isso. Como resultado, obtivemos este design:

Introdução à parte de rede da infraestrutura em nuvem

Como o tráfego entre VMs deve ser dividido, as portas para as máquinas virtuais terão números de VLAN diferentes. O número da tag desempenha uma função apenas dentro de um switch virtual, pois quando encapsulado em VxLAN podemos removê-lo facilmente, pois teremos um VNI.

Introdução à parte de rede da infraestrutura em nuvem

Agora podemos criar nossas máquinas e redes virtuais para eles sem problemas.

Porém, e se o cliente tiver outra máquina, mas estiver em uma rede diferente? Precisamos de enraizamento entre redes. Veremos uma opção simples quando o roteamento centralizado é usado - ou seja, o tráfego é roteado através de nós de rede dedicados especiais (bem, como regra, eles são combinados com nós de controle, então teremos a mesma coisa).

Parece nada complicado - criamos uma interface de ponte no nó de controle, direcionamos o tráfego para ele e de lá o roteamos para onde precisarmos. Mas o problema é que o cliente RED quer usar a rede 10.0.0.0/24, e o cliente VERDE quer usar a rede 10.0.0.0/24. Ou seja, começamos a cruzar espaços de endereço. Além disso, os clientes não querem que outros clientes possam acessar suas redes internas, o que faz sentido. Para separar as redes e o tráfego de dados do cliente, alocaremos um namespace separado para cada um deles. O namespace é na verdade uma cópia da pilha de rede do Linux, ou seja, os clientes no namespace RED são completamente isolados dos clientes do namespace GREEN (bem, o roteamento entre essas redes de clientes é permitido através do namespace padrão ou no equipamento de transporte upstream).

Ou seja, obtemos o seguinte diagrama:

Introdução à parte de rede da infraestrutura em nuvem

Os túneis L2 convergem de todos os nós de computação para o nó de controle. nó onde a interface L3 para essas redes está localizada, cada uma em um namespace dedicado para isolamento.

Porém, esquecemos o mais importante. A máquina virtual deve fornecer um serviço ao cliente, ou seja, deve possuir pelo menos uma interface externa através da qual possa ser acessada. Ou seja, precisamos sair para o mundo exterior. Existem diferentes opções aqui. Vamos fazer a opção mais simples. Adicionaremos uma rede para cada cliente, que será válida na rede do provedor e não se sobreporá a outras redes. As redes também podem se cruzar e observar diferentes VRFs no lado da rede do provedor. Os dados da rede também residirão no namespace de cada cliente. No entanto, eles ainda sairão para o mundo exterior através de uma interface física (ou ligação, que é mais lógica). Para separar o tráfego do cliente, o tráfego externo será marcado com uma etiqueta VLAN alocada ao cliente.

Como resultado, obtivemos este diagrama:

Introdução à parte de rede da infraestrutura em nuvem

Uma questão razoável é: por que não criar gateways nos próprios nós de computação? Isso não é um grande problema; além disso, se você ligar o roteador distribuído (DVR), funcionará. Neste cenário, estamos considerando a opção mais simples com um gateway centralizado, que é usado por padrão no Openstack. Para funções de alta carga, eles usarão um roteador distribuído e tecnologias de aceleração como SR-IOV e Passthrough, mas como dizem, essa é uma história completamente diferente. Primeiro, vamos tratar da parte básica e depois entraremos nos detalhes.

Na verdade, nosso esquema já funciona, mas existem algumas nuances:

  • Precisamos proteger de alguma forma nossas máquinas, ou seja, colocar um filtro na interface do switch voltada para o cliente.
  • Possibilita que uma máquina virtual obtenha automaticamente um endereço IP, para que você não precise sempre fazer login nela através do console e registrar o endereço.

Vamos começar com a proteção da máquina. Para isso você pode usar iptables banais, por que não.

Ou seja, agora nossa topologia ficou um pouco mais complicada:

Introdução à parte de rede da infraestrutura em nuvem

Vamos continuar. Precisamos adicionar um servidor DHCP. O local ideal para localizar servidores DHCP para cada cliente seria o nó de controle já mencionado acima, onde estão localizados os namespaces:

Introdução à parte de rede da infraestrutura em nuvem

No entanto, há um pequeno problema. E se tudo reiniciar e todas as informações sobre o aluguel de endereços no DHCP desaparecerem. É lógico que as máquinas recebam novos endereços, o que não é muito conveniente. Existem duas maneiras de sair aqui - usar nomes de domínio e adicionar um servidor DNS para cada cliente, então o endereço não será particularmente importante para nós (semelhante à parte de rede no k8s) - mas há um problema com redes externas, uma vez que endereços também podem ser emitidos neles via DHCP - você precisa de sincronização com servidores DNS na plataforma de nuvem e um servidor DNS externo, o que na minha opinião não é muito flexível, mas é bem possível. Ou a segunda opção é usar metadados - ou seja, salvar informações sobre o endereço emitido para a máquina para que o servidor DHCP saiba qual endereço emitir para a máquina se a máquina já tiver recebido um endereço. A segunda opção é mais simples e flexível, pois permite salvar informações adicionais sobre o carro. Agora vamos adicionar metadados do agente ao diagrama:

Introdução à parte de rede da infraestrutura em nuvem

Outra questão que também vale a pena discutir é a possibilidade de utilização de uma rede externa por todos os clientes, pois as redes externas, se precisarem ser válidas em toda a rede, serão difíceis - é preciso alocar e controlar constantemente a alocação dessas redes. A capacidade de usar uma única rede externa pré-configurada para todos os clientes será muito útil ao criar uma nuvem pública. Isto facilitará a implantação de máquinas porque não precisamos consultar um banco de dados de endereços e selecionar um espaço de endereço exclusivo para a rede externa de cada cliente. Além disso, podemos cadastrar uma rede externa antecipadamente e no momento da implantação só precisaremos associar endereços externos às máquinas clientes.

E aqui o NAT vem em nosso auxílio - apenas possibilitaremos que os clientes acessem o mundo externo através do namespace padrão usando a tradução NAT. Bem, aqui está um pequeno problema. Isso é bom se o servidor cliente atuar como cliente e não como servidor - ou seja, ele inicia em vez de aceitar conexões. Mas para nós será o contrário. Neste caso, precisamos fazer o NAT de destino para que ao receber o tráfego, o nó de controle entenda que esse tráfego é destinado à máquina virtual A do cliente A, o que significa que precisamos fazer uma tradução NAT de um endereço externo, por exemplo 100.1.1.1 .10.0.0.1, para um endereço interno 100. Neste caso, embora todos os clientes utilizem a mesma rede, o isolamento interno é totalmente preservado. Ou seja, precisamos fazer dNAT e sNAT no nó de controle. Usar uma única rede com endereços flutuantes ou redes externas, ou ambas ao mesmo tempo, depende do que você deseja trazer para a nuvem. Não adicionaremos endereços flutuantes ao diagrama, mas deixaremos as redes externas já adicionadas anteriormente - cada cliente possui sua própria rede externa (no diagrama são indicadas como vlan 200 e XNUMX na interface externa).

Como resultado, obtivemos uma solução interessante e ao mesmo tempo bem pensada, que possui uma certa flexibilidade, mas ainda não possui mecanismos de tolerância a falhas.

Em primeiro lugar, temos apenas um nó de controle - a sua falha levará ao colapso de todos os sistemas. Para corrigir esse problema, você precisa criar pelo menos um quorum de 3 nós. Vamos adicionar isso ao diagrama:

Introdução à parte de rede da infraestrutura em nuvem

Naturalmente, todos os nós são sincronizados e quando um nó ativo sai, outro nó assumirá suas responsabilidades.

O próximo problema são os discos das máquinas virtuais. No momento, eles estão armazenados nos próprios hipervisores, e em caso de problemas com o hipervisor, perdemos todos os dados - e a presença de um raid não vai ajudar aqui se perdermos não o disco, mas todo o servidor. Para fazer isso, precisamos fazer um serviço que funcione como front end para algum tipo de armazenamento. O tipo de armazenamento que será não é particularmente importante para nós, mas deve proteger nossos dados contra falhas do disco e do nó e, possivelmente, de todo o gabinete. Existem várias opções aqui - existem, claro, redes SAN com Fibre Channel, mas sejamos honestos - FC já é uma relíquia do passado - um análogo do E1 em transporte - sim, concordo, ainda é usado, mas somente onde for absolutamente impossível sem ele. Portanto, eu não implantaria voluntariamente uma rede FC em 2020, sabendo que existem outras alternativas mais interessantes. Embora cada um possa ter quem acredite que o FC com todas as suas limitações é tudo o que precisamos - não vou discutir, cada um tem a sua opinião. Porém, a solução mais interessante na minha opinião é usar um SDS, como o Ceph.

O Ceph permite construir uma solução de armazenamento de dados altamente disponível com diversas opções de backup possíveis, começando com códigos com verificação de paridade (análogo ao raid 5 ou 6) terminando com replicação completa de dados para discos diferentes, levando em consideração a localização dos discos em servidores e servidores em gabinetes, etc.

Para construir o Ceph, você precisa de mais 3 nós. A interação com o armazenamento também será realizada via rede por meio de serviços de armazenamento de blocos, objetos e arquivos. Vamos adicionar armazenamento ao esquema:

Introdução à parte de rede da infraestrutura em nuvem

Observação: você também pode criar nós de computação hiperconvergentes - esse é o conceito de combinar várias funções em um nó - por exemplo, armazenamento+computação - sem dedicar nós especiais para armazenamento ceph. Obteremos o mesmo esquema de tolerância a falhas - já que o SDS reservará dados com o nível de reserva que especificamos. No entanto, os nós hiperconvergentes são sempre um compromisso - já que o nó de armazenamento não apenas aquece o ar como parece à primeira vista (já que não há máquinas virtuais nele) - ele gasta recursos da CPU na manutenção do SDS (na verdade, ele faz tudo a replicação e recuperação após falhas de nós, discos, etc.). Ou seja, você perderá parte da potência do nó de computação se combiná-lo com armazenamento.

Tudo isso precisa ser gerenciado de alguma forma - precisamos de algo através do qual possamos criar uma máquina, uma rede, um roteador virtual, etc. Para fazer isso, adicionaremos um serviço ao nó de controle que funcionará como um painel - o o cliente poderá se conectar a este portal via http/https e fazer tudo o que precisar (bem, quase).

Como resultado, agora temos um sistema tolerante a falhas. Todos os elementos desta infra-estrutura devem ser geridos de alguma forma. Foi descrito anteriormente que Openstack é um conjunto de projetos, cada um dos quais fornece uma função específica. Como vemos, existem elementos mais do que suficientes que precisam ser configurados e controlados. Hoje falaremos sobre a parte da rede.

Arquitetura de nêutrons

No OpenStack, é o Neutron o responsável por conectar as portas das máquinas virtuais a uma rede L2 comum, garantindo o roteamento do tráfego entre VMs localizadas em redes L2 diferentes, bem como o roteamento externo, fornecendo serviços como NAT, IP flutuante, DHCP, etc.

Em alto nível, a operação do serviço de rede (a parte básica) pode ser descrita como segue.

Ao iniciar a VM, o serviço de rede:

  1. Cria uma porta para uma determinada VM (ou portas) e notifica o serviço DHCP sobre isso;
  2. Um novo dispositivo de rede virtual é criado (via libvirt);
  3. A VM se conecta às portas criadas na etapa 1;

Curiosamente, o trabalho da Neutron é baseado em mecanismos padrão familiares a todos que já mergulharam no Linux - namespaces, iptables, linux bridges, openvswitch, conntrack, etc.

Deve ser imediatamente esclarecido que o Neutron não é um controlador SDN.

O Neutron consiste em vários componentes interconectados:

Introdução à parte de rede da infraestrutura em nuvem

Servidor Openstack-neutron é um daemon que funciona com solicitações de usuários por meio da API. Este demônio não está envolvido no registro de nenhuma conexão de rede, mas fornece as informações necessárias para isso aos seus plugins, que então configuram o elemento de rede desejado. Os agentes Neutron em nós OpenStack são registrados no servidor Neutron.

Neutron-server é na verdade um aplicativo escrito em python, que consiste em duas partes:

  • Serviço REST
  • Plug-in Neutron (núcleo/serviço)

O serviço REST foi projetado para receber chamadas de API de outros componentes (por exemplo, uma solicitação para fornecer algumas informações, etc.)

Plugins são componentes/módulos de software plug-in que são chamados durante solicitações de API - ou seja, a atribuição de um serviço ocorre através deles. Os plug-ins são divididos em dois tipos - serviço e root. Via de regra, o plugin horse é o principal responsável por gerenciar o espaço de endereço e as conexões L2 entre VMs, e os plugins de serviço já fornecem funcionalidades adicionais, como VPN ou FW.

A lista de plugins disponíveis hoje pode ser visualizada, por exemplo aqui

Pode haver vários plugins de serviço, mas só pode haver um plugin de cavalo.

openstack-nêutron-ml2 é o plugin raiz padrão do Openstack. Este plugin possui arquitetura modular (diferentemente de seu antecessor) e configura o serviço de rede através de drivers conectados a ele. Veremos o plugin em si um pouco mais tarde, pois na verdade ele dá a flexibilidade que o OpenStack tem na parte de rede. O plugin raiz pode ser substituído (por exemplo, Contrail Networking faz essa substituição).

Serviço RPC (servidor coelhomq) — um serviço que fornece gerenciamento de filas e interação com outros serviços OpenStack, bem como interação entre agentes de serviços de rede.

Agentes de rede — agentes localizados em cada nó, através dos quais os serviços de rede são configurados.

Existem vários tipos de agentes.

O principal agente é Agente L2. Esses agentes são executados em cada um dos hipervisores, incluindo nós de controle (mais precisamente, em todos os nós que fornecem algum serviço aos locatários) e sua principal função é conectar máquinas virtuais a uma rede L2 comum, e também gerar alertas quando ocorrer algum evento ( por exemplo desabilitar/habilitar a porta).

O próximo agente, não menos importante, é Agente L3. Por padrão, este agente é executado exclusivamente em um nó de rede (muitas vezes o nó de rede é combinado com um nó de controle) e fornece roteamento entre redes de locatários (tanto entre suas redes quanto as redes de outros locatários, e é acessível ao mundo externo, fornecendo NAT, bem como serviço DHCP). Porém, ao usar um DVR (roteador distribuído), a necessidade de um plugin L3 também aparece nos nós de computação.

O agente L3 usa namespaces Linux para fornecer a cada locatário um conjunto de suas próprias redes isoladas e a funcionalidade de roteadores virtuais que roteiam o tráfego e fornecem serviços de gateway para redes da Camada 2.

banco de dados — um banco de dados de identificadores de redes, sub-redes, portas, pools, etc.

Na verdade, o Neutron aceita solicitações de API a partir da criação de quaisquer entidades de rede, autentica a solicitação, e através de RPC (se acessa algum plugin ou agente) ou REST API (se se comunica em SDN) transmite aos agentes (via plugins) o instruções necessárias para organizar o serviço solicitado.

Agora vamos passar para a instalação de teste (como ela é implantada e o que está incluso nela, veremos mais adiante na parte prática) e ver onde cada componente está localizado:

(overcloud) [stack@undercloud ~]$ openstack network agent list  
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| ID                                   | Agent Type         | Host                                | Availability Zone | Alive | State | Binary                    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| 10495de9-ba4b-41fe-b30a-b90ec3f8728b | Open vSwitch agent | overcloud-novacompute-1.localdomain | None              | :-)   | UP    | neutron-openvswitch-agent |
| 1515ad4a-5972-46c3-af5f-e5446dff7ac7 | L3 agent           | overcloud-controller-0.localdomain  | nova              | :-)   | UP    | neutron-l3-agent          |
| 322e62ca-1e5a-479e-9a96-4f26d09abdd7 | DHCP agent         | overcloud-controller-0.localdomain  | nova              | :-)   | UP    | neutron-dhcp-agent        |
| 9c1de2f9-bac5-400e-998d-4360f04fc533 | Open vSwitch agent | overcloud-novacompute-0.localdomain | None              | :-)   | UP    | neutron-openvswitch-agent |
| d99c5657-851e-4d3c-bef6-f1e3bb1acfb0 | Open vSwitch agent | overcloud-controller-0.localdomain  | None              | :-)   | UP    | neutron-openvswitch-agent |
| ff85fae6-5543-45fb-a301-19c57b62d836 | Metadata agent     | overcloud-controller-0.localdomain  | None              | :-)   | UP    | neutron-metadata-agent    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
(overcloud) [stack@undercloud ~]$ 

Introdução à parte de rede da infraestrutura em nuvem

Na verdade, essa é toda a estrutura do Neutron. Agora vale a pena dedicar algum tempo ao plugin ML2.

Camada Modular 2

Conforme mencionado acima, o plugin é um plugin raiz OpenStack padrão e possui uma arquitetura modular.

O antecessor do plugin ML2 possuía uma estrutura monolítica, o que não permitia, por exemplo, a utilização de uma mistura de diversas tecnologias em uma instalação. Por exemplo, você não poderia usar openvswitch e linuxbridge ao mesmo tempo - nem o primeiro nem o segundo. Por este motivo foi criado o plugin ML2 com sua arquitetura.

O ML2 possui dois componentes - dois tipos de drivers: drivers de tipo e drivers de mecanismo.

Digite drivers determinar as tecnologias que serão utilizadas para organizar as conexões de rede, por exemplo VxLAN, VLAN, GRE. Ao mesmo tempo, o driver permite a utilização de diferentes tecnologias. A tecnologia padrão é o encapsulamento VxLAN para redes sobrepostas e redes externas VLAN.

Os drivers de tipo incluem os seguintes tipos de rede:

Plano - rede sem marcação
VLAN - rede marcada
Locais de — um tipo especial de rede para instalações multifuncionais (tais instalações são necessárias para desenvolvedores ou para treinamento)
GRE — rede de sobreposição usando túneis GRE
VxLAN — rede de sobreposição usando túneis VxLAN

Motoristas de mecanismo definir ferramentas que garantam a organização das tecnologias especificadas no driver de tipo - por exemplo, openvswitch, sr-iov, opendaylight, OVN, etc.

Dependendo da implementação deste driver, serão utilizados agentes controlados pelo Neutron, ou serão utilizadas conexões a um controlador SDN externo, que cuida de todas as questões relacionadas à organização de redes L2, roteamento, etc.

Exemplo: se usarmos ML2 junto com OVS, então um agente L2 é instalado em cada nó computacional que gerencia o OVS. Porém, se usarmos, por exemplo, OVN ou OpenDayLight, então o controle do OVS fica sob sua jurisdição - o Neutron, através do plugin root, dá comandos ao controlador, e ele já faz o que foi mandado.

Vamos atualizar o Open vSwitch

No momento, um dos principais componentes do OpenStack é o Open vSwitch.
Ao instalar o OpenStack sem qualquer SDN de fornecedor adicional, como Juniper Contrail ou Nokia Nuage, o OVS é o principal componente de rede da rede em nuvem e, junto com iptables, conntrack, namespaces, permite organizar redes de sobreposição multilocação completas. Naturalmente, esse componente pode ser substituído, por exemplo, ao usar soluções SDN proprietárias (fornecedores) de terceiros.

OVS é um switch de software de código aberto projetado para uso em ambientes virtualizados como encaminhador de tráfego virtual.

No momento, o OVS possui funcionalidades muito decentes, que incluem tecnologias como QoS, LACP, VLAN, VxLAN, GENEVE, OpenFlow, DPDK, etc.

Nota: O OVS não foi inicialmente concebido como um soft switch para funções de telecomunicações altamente carregadas e foi mais projetado para funções de TI que exigem menos largura de banda, como servidor WEB ou servidor de correio. No entanto, o OVS está sendo desenvolvido e as implementações atuais do OVS melhoraram muito seu desempenho e capacidades, o que permite que seja utilizado por operadoras de telecomunicações com funções altamente carregadas, por exemplo, existe uma implementação do OVS com suporte para aceleração DPDK.

Existem três componentes importantes do OVS que você precisa conhecer:

  • Módulo do kernel — um componente localizado no espaço do kernel que processa o tráfego com base nas regras recebidas do elemento de controle;
  • vSwitch daemon (ovs-vswitchd) é um processo lançado no espaço do usuário responsável pela programação do módulo do kernel - ou seja, representa diretamente a lógica de funcionamento do switch
  • Servidor de banco de dados - um banco de dados local localizado em cada host executando o OVS, no qual a configuração é armazenada. Os controladores SDN podem se comunicar através deste módulo usando o protocolo OVSDB.

Tudo isso é acompanhado por um conjunto de utilitários de diagnóstico e gerenciamento, como ovs-vsctl, ovs-appctl, ovs-ofctl, etc.

Atualmente, o Openstack é amplamente utilizado pelas operadoras de telecomunicações para migrar funções de rede para ele, como EPC, SBC, HLR, etc. Algumas funções podem funcionar sem problemas com o OVS como estão, mas, por exemplo, o EPC processa o tráfego do assinante - então ele passa uma enorme quantidade de tráfego (agora os volumes de tráfego chegam a várias centenas de gigabits por segundo). Naturalmente, direcionar esse tráfego através do espaço do kernel (já que o encaminhador está localizado lá por padrão) não é a melhor ideia. Portanto, o OVS é frequentemente implantado inteiramente no espaço do usuário usando a tecnologia de aceleração DPDK para encaminhar o tráfego da NIC para o espaço do usuário, ignorando o kernel.

Nota: para uma nuvem implantada para funções de telecomunicações, é possível enviar o tráfego de um nó de computação contornando o OVS diretamente para o equipamento de comutação. Mecanismos SR-IOV e Passthrough são usados ​​para essa finalidade.

Como isso funciona em um layout real?

Bom, agora vamos passar para a parte prática e ver como tudo funciona na prática.

Primeiro, vamos implantar uma instalação simples do Openstack. Como não tenho um conjunto de servidores disponível para experimentos, montaremos o protótipo em um servidor físico a partir de máquinas virtuais. Sim, claro, tal solução não é adequada para fins comerciais, mas para ver um exemplo de como funciona a rede no Openstack, tal instalação é suficiente para os olhos. Além disso, tal instalação é ainda mais interessante para fins de treinamento - já que você pode pegar trânsito, etc.

Como só precisamos ver a parte básica, não podemos utilizar várias redes e sim levantar tudo utilizando apenas duas redes, sendo que a segunda rede neste layout será utilizada exclusivamente para acesso ao undercloud e servidor DNS. Não tocaremos em redes externas por enquanto - este é um tópico para um grande artigo separado.

Então, vamos começar em ordem. Primeiro, um pouco de teoria. Instalaremos o Openstack usando TripleO (Openstack no Openstack). A essência do TripleO é instalar o Openstack all-in-one (ou seja, em um nó), chamado undercloud, e então usar os recursos do Openstack implantado para instalar o Openstack destinado à operação, chamado overcloud. Undercloud usará sua capacidade inerente de gerenciar servidores físicos (bare metal) - o projeto Ironic - para provisionar hipervisores que desempenharão as funções de nós de computação, controle e armazenamento. Ou seja, não usamos nenhuma ferramenta de terceiros para implantar o Openstack - implantamos o Openstack usando o Openstack. Ficará muito mais claro à medida que a instalação avança, por isso não vamos parar por aí e seguir em frente.

Nota: Neste artigo, para simplificar, não usei isolamento de rede para redes Openstack internas, mas tudo é implantado usando apenas uma rede. Porém, a presença ou ausência de isolamento de rede não afeta a funcionalidade básica da solução - tudo funcionará exatamente da mesma forma que ao usar o isolamento, mas o tráfego fluirá na mesma rede. Para uma instalação comercial, é naturalmente necessário utilizar isolamento utilizando diferentes vlans e interfaces. Por exemplo, o tráfego de gerenciamento de armazenamento ceph e o próprio tráfego de dados (acesso da máquina aos discos, etc.) quando isolados utilizam sub-redes diferentes (Gerenciamento de armazenamento e Storage) e isso permite tornar a solução mais tolerante a falhas dividindo esse tráfego, por exemplo , em portas diferentes ou usando perfis de QoS diferentes para tráfego diferente, para que o tráfego de dados não comprima o tráfego de sinalização. No nosso caso, eles irão na mesma rede e na verdade isso não nos limita de forma alguma.

Nota: Como executaremos máquinas virtuais em um ambiente virtual baseado em máquinas virtuais, primeiro precisamos habilitar a virtualização aninhada.

Você pode verificar se a virtualização aninhada está habilitada ou não assim:


[root@hp-gen9 bormoglotx]# cat /sys/module/kvm_intel/parameters/nested
N
[root@hp-gen9 bormoglotx]# 

Se você vir a letra N, habilitamos o suporte para virtualização aninhada de acordo com qualquer guia que você encontrar na rede, por exemplo tal .

Precisamos montar o seguinte circuito a partir de máquinas virtuais:

Introdução à parte de rede da infraestrutura em nuvem

No meu caso, para conectar as máquinas virtuais que fazem parte da instalação futura (e consegui 7 delas, mas você pode sobreviver com 4 se não tiver muitos recursos), usei OpenvSwitch. Criei uma ponte ovs e conectei máquinas virtuais a ela por meio de grupos de portas. Para fazer isso, criei um arquivo xml como este:


[root@hp-gen9 ~]# virsh net-dumpxml ovs-network-1        
<network>
  <name>ovs-network-1</name>
  <uuid>7a2e7de7-fc16-4e00-b1ed-4d190133af67</uuid>
  <forward mode='bridge'/>
  <bridge name='ovs-br1'/>
  <virtualport type='openvswitch'/>
  <portgroup name='trunk-1'>
    <vlan trunk='yes'>
      <tag id='100'/>
      <tag id='101'/>
      <tag id='102'/>
    </vlan>
  </portgroup>
  <portgroup name='access-100'>
    <vlan>
      <tag id='100'/>
    </vlan>
  </portgroup>
  <portgroup name='access-101'>
    <vlan>
      <tag id='101'/>
    </vlan>
  </portgroup>
</network>

Três grupos de portas são declarados aqui - dois de acesso e um tronco (o último era necessário para o servidor DNS, mas você pode ficar sem ele ou instalá-lo na máquina host - o que for mais conveniente para você). A seguir, usando este modelo, declaramos o nosso via virsh net-define:


virsh net-define ovs-network-1.xml 
virsh net-start ovs-network-1 
virsh net-autostart ovs-network-1 

Agora editamos as configurações da porta do hipervisor:


[root@hp-gen9 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens1f0   
TYPE=Ethernet
NAME=ens1f0
DEVICE=ens1f0
TYPE=OVSPort
DEVICETYPE=ovs
OVS_BRIDGE=ovs-br1
ONBOOT=yes
OVS_OPTIONS="trunk=100,101,102"
[root@hp-gen9 ~]
[root@hp-gen9 ~]# cat /etc/sysconfig/network-scripts/ifcfg-ovs-br1 
DEVICE=ovs-br1
DEVICETYPE=ovs
TYPE=OVSBridge
BOOTPROTO=static
ONBOOT=yes
IPADDR=192.168.255.200
PREFIX=24
[root@hp-gen9 ~]# 

Nota: neste cenário, o endereço na porta ovs-br1 não estará acessível porque não possui uma tag vlan. Para corrigir isso, você precisa emitir o comando sudo ovs-vsctl set port ovs-br1 tag=100. Porém, após a reinicialização, essa tag desaparecerá (se alguém souber como fazê-la permanecer no lugar, ficarei muito grato). Mas isso não é tão importante, porque só precisaremos desse endereço durante a instalação e não precisaremos dele quando o Openstack estiver totalmente implantado.

A seguir, criamos uma máquina undercloud:


virt-install  -n undercloud --description "undercloud"  --os-type=Linux  --os-variant=centos7.0  --ram=8192  --vcpus=8  --disk path=/var/lib/libvirt/images/undercloud.qcow2,bus=virtio,size=40,format=qcow2 --network network:ovs-network-1,model=virtio,portgroup=access-100 --network network:ovs-network-1,model=virtio,portgroup=access-101 --graphics none  --location /var/lib/libvirt/boot/CentOS-7-x86_64-Minimal-2003.iso --extra-args console=ttyS0

Durante a instalação, você define todos os parâmetros necessários, como nome da máquina, senhas, usuários, servidores NTP, etc., você pode configurar imediatamente as portas, mas para mim pessoalmente, após a instalação, é mais fácil fazer login na máquina através o console e corrija os arquivos necessários. Se você já tem uma imagem pronta, pode usá-la ou fazer o que eu fiz - baixe a imagem mínima do Centos 7 e use-a para instalar a VM.

Após a instalação bem-sucedida, você deverá ter uma máquina virtual na qual poderá instalar o undercloud


[root@hp-gen9 bormoglotx]# virsh list
 Id    Name                           State
----------------------------------------------------
 6     dns-server                     running
 62    undercloud                     running

Primeiro, instale as ferramentas necessárias para o processo de instalação:

sudo yum update -y
sudo yum install -y net-tools
sudo yum install -y wget
sudo yum install -y ipmitool

Instalação sob nuvem

Criamos um usuário de pilha, definimos uma senha, adicionamos-a ao sudoer e damos a ele a capacidade de executar comandos root através do sudo sem precisar inserir uma senha:


useradd stack
passwd stack

echo “stack ALL=(root) NOPASSWD:ALL” > /etc/sudoers.d/stack
chmod 0440 /etc/sudoers.d/stack

Agora especificamos o nome completo do undercloud no arquivo hosts:


vi /etc/hosts

127.0.0.1   undercloud.openstack.rnd localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

A seguir, adicionamos repositórios e instalamos o software necessário:


sudo yum install -y https://trunk.rdoproject.org/centos7/current/python2-tripleo-repos-0.0.1-0.20200409224957.8bac392.el7.noarch.rpm
sudo -E tripleo-repos -b queens current
sudo -E tripleo-repos -b queens current ceph
sudo yum install -y python-tripleoclient
sudo yum install -y ceph-ansible

Observação: se você não planeja instalar o ceph, não será necessário inserir comandos relacionados ao ceph. Usei o lançamento do Queens, mas você pode usar qualquer outro que quiser.

Em seguida, copie o arquivo de configuração do undercloud para a pilha do diretório inicial do usuário:


cp /usr/share/instack-undercloud/undercloud.conf.sample ~/undercloud.conf

Agora precisamos corrigir este arquivo, ajustando-o à nossa instalação.

Você precisa adicionar estas linhas ao início do arquivo:

vi undercloud.conf
[DEFAULT]
undercloud_hostname = undercloud.openstack.rnd
local_ip = 192.168.255.1/24
network_gateway = 192.168.255.1
undercloud_public_host = 192.168.255.2
undercloud_admin_host = 192.168.255.3
undercloud_nameservers = 192.168.255.253
generate_service_certificate = false
local_interface = eth0
local_mtu = 1450
network_cidr = 192.168.255.0/24
masquerade = true
masquerade_network = 192.168.255.0/24
dhcp_start = 192.168.255.11
dhcp_end = 192.168.255.50
inspection_iprange = 192.168.255.51,192.168.255.100
scheduler_max_attempts = 10

Então, vamos às configurações:

undercloud_hostname — o nome completo do servidor undercloud, deve corresponder à entrada no servidor DNS

local_ip — endereço undercloud local para provisionamento de rede

gateway_de_rede — o mesmo endereço local, que servirá de gateway para acesso ao mundo externo durante a instalação de nós overcloud, também coincide com o ip local

undercloud_public_host — endereço API externo, qualquer endereço livre da rede de provisionamento é atribuído

undercloud_admin_host endereço API interno, qualquer endereço livre da rede de provisionamento é atribuído

servidores_undercloud_name - Servidor dns

gerar_service_certificate - esta linha é muito importante no exemplo atual, pois se você não configurá-la como false você receberá um erro durante a instalação, o problema está descrito no rastreador de bugs da Red Hat

interface_local interface no provisionamento de rede. Essa interface será reconfigurada durante a implantação do undercloud, portanto, você precisa ter duas interfaces no undercloud: uma para acessá-lo e a segunda para provisionamento

local_mtu - MTU. Como temos um laboratório de testes e tenho um MTU de 1500 nas portas do switch OVS, é necessário configurá-lo para 1450 para que os pacotes encapsulados em VxLAN possam passar

rede_cidr - rede de provisionamento

mascarada — usando NAT para acessar uma rede externa

rede_de_máscaras - rede que será NAT

dhcp_start — o endereço inicial do pool de endereços a partir do qual os endereços serão atribuídos aos nós durante a implantação overcloud

dhcp_end — o endereço final do pool de endereços a partir do qual os endereços serão atribuídos aos nós durante a implantação na nuvem

inspeção_iprange — um conjunto de endereços necessários para a introspecção (não deve se sobrepor ao conjunto acima)

agendador_max_attempts — número máximo de tentativas de instalação de overcloud (deve ser maior ou igual ao número de nós)

Após a descrição do arquivo, você pode dar o comando para implantar o undercloud:


openstack undercloud install

O procedimento leva de 10 a 30 minutos dependendo do seu ferro. No final das contas, você deverá ver uma saída como esta:

vi undercloud.conf
2020-08-13 23:13:12,668 INFO: 
#############################################################################
Undercloud install complete.

The file containing this installation's passwords is at
/home/stack/undercloud-passwords.conf.

There is also a stackrc file at /home/stack/stackrc.

These files are needed to interact with the OpenStack services, and should be
secured.

#############################################################################

Esta saída indica que você instalou o undercloud com sucesso e agora pode verificar o status do undercloud e prosseguir com a instalação do overcloud.

Se você olhar a saída do ifconfig, verá que uma nova interface de ponte apareceu

[stack@undercloud ~]$ ifconfig
br-ctlplane: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 192.168.255.1  netmask 255.255.255.0  broadcast 192.168.255.255
        inet6 fe80::5054:ff:fe2c:89e  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:2c:08:9e  txqueuelen 1000  (Ethernet)
        RX packets 14  bytes 1095 (1.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20  bytes 1292 (1.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

A implantação do Overcloud agora será realizada por meio desta interface.

Na saída abaixo você pode ver que temos todos os serviços em um nó:

(undercloud) [stack@undercloud ~]$ openstack host list
+--------------------------+-----------+----------+
| Host Name                | Service   | Zone     |
+--------------------------+-----------+----------+
| undercloud.openstack.rnd | conductor | internal |
| undercloud.openstack.rnd | scheduler | internal |
| undercloud.openstack.rnd | compute   | nova     |
+--------------------------+-----------+----------+

Abaixo está a configuração da parte da rede undercloud:


(undercloud) [stack@undercloud ~]$ python -m json.tool /etc/os-net-config/config.json 
{
    "network_config": [
        {
            "addresses": [
                {
                    "ip_netmask": "192.168.255.1/24"
                }
            ],
            "members": [
                {
                    "dns_servers": [
                        "192.168.255.253"
                    ],
                    "mtu": 1450,
                    "name": "eth0",
                    "primary": "true",
                    "type": "interface"
                }
            ],
            "mtu": 1450,
            "name": "br-ctlplane",
            "ovs_extra": [
                "br-set-external-id br-ctlplane bridge-id br-ctlplane"
            ],
            "routes": [],
            "type": "ovs_bridge"
        }
    ]
}
(undercloud) [stack@undercloud ~]$

Instalação na nuvem

No momento, temos apenas undercloud e não temos nós suficientes a partir dos quais o overcloud será montado. Portanto, em primeiro lugar, vamos implantar as máquinas virtuais de que necessitamos. Durante a implantação, o próprio undercloud instalará o sistema operacional e o software necessário na máquina overcloud - ou seja, não precisamos implantar completamente a máquina, mas apenas criar um disco (ou discos) para ela e determinar seus parâmetros - isto é Na verdade, obtemos um servidor vazio sem um sistema operacional instalado.

Vamos para a pasta com os discos de nossas máquinas virtuais e criamos discos do tamanho necessário:


cd /var/lib/libvirt/images/
qemu-img create -f qcow2 -o preallocation=metadata control-1.qcow2 60G
qemu-img create -f qcow2 -o preallocation=metadata compute-1.qcow2 60G
qemu-img create -f qcow2 -o preallocation=metadata compute-2.qcow2 60G
qemu-img create -f qcow2 -o preallocation=metadata storage-1.qcow2 160G
qemu-img create -f qcow2 -o preallocation=metadata storage-2.qcow2 160G

Como estamos operando como root, precisamos mudar o proprietário desses discos para não ter problemas de direitos:


[root@hp-gen9 images]# ls -lh
total 5.8G
drwxr-xr-x. 2 qemu qemu 4.0K Aug 13 16:15 backups
-rw-r--r--. 1 root root  61G Aug 14 03:07 compute-1.qcow2
-rw-r--r--. 1 root root  61G Aug 14 03:07 compute-2.qcow2
-rw-r--r--. 1 root root  61G Aug 14 03:07 control-1.qcow2
-rw-------. 1 qemu qemu  41G Aug 14 03:03 dns-server.qcow2
-rw-r--r--. 1 root root 161G Aug 14 03:07 storage-1.qcow2
-rw-r--r--. 1 root root 161G Aug 14 03:07 storage-2.qcow2
-rw-------. 1 qemu qemu  41G Aug 14 03:07 undercloud.qcow2
[root@hp-gen9 images]# 
[root@hp-gen9 images]# 
[root@hp-gen9 images]# chown qemu:qemu /var/lib/libvirt/images/*qcow2
[root@hp-gen9 images]# ls -lh
total 5.8G
drwxr-xr-x. 2 qemu qemu 4.0K Aug 13 16:15 backups
-rw-r--r--. 1 qemu qemu  61G Aug 14 03:07 compute-1.qcow2
-rw-r--r--. 1 qemu qemu  61G Aug 14 03:07 compute-2.qcow2
-rw-r--r--. 1 qemu qemu  61G Aug 14 03:07 control-1.qcow2
-rw-------. 1 qemu qemu  41G Aug 14 03:03 dns-server.qcow2
-rw-r--r--. 1 qemu qemu 161G Aug 14 03:07 storage-1.qcow2
-rw-r--r--. 1 qemu qemu 161G Aug 14 03:07 storage-2.qcow2
-rw-------. 1 qemu qemu  41G Aug 14 03:08 undercloud.qcow2
[root@hp-gen9 images]# 

Nota: se você não planeja instalar o ceph para estudá-lo, então os comandos não criam pelo menos 3 nós com pelo menos dois discos, mas no template indicam que serão usados ​​​​os discos virtuais vda, vdb, etc.

Ótimo, agora precisamos definir todas essas máquinas:


virt-install --name control-1 --ram 32768 --vcpus 8 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/control-1.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --network network:ovs-network-1,model=virtio,portgroup=trunk-1 --dry-run --print-xml > /tmp/control-1.xml  

virt-install --name storage-1 --ram 16384 --vcpus 4 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/storage-1.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --dry-run --print-xml > /tmp/storage-1.xml  

virt-install --name storage-2 --ram 16384 --vcpus 4 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/storage-2.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --dry-run --print-xml > /tmp/storage-2.xml  

virt-install --name compute-1 --ram 32768 --vcpus 12 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/compute-1.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --dry-run --print-xml > /tmp/compute-1.xml  

virt-install --name compute-2 --ram 32768 --vcpus 12 --os-variant centos7.0 --disk path=/var/lib/libvirt/images/compute-2.qcow2,device=disk,bus=virtio,format=qcow2 --noautoconsole --vnc  --network network:ovs-network-1,model=virtio,portgroup=access-100 --dry-run --print-xml > /tmp/compute-2.xml 

No final existe um comando -print-xml > /tmp/storage-1.xml, que cria um arquivo xml com a descrição de cada máquina na pasta /tmp/; se você não adicionar, não será capaz de identificar máquinas virtuais.

Agora precisamos definir todas essas máquinas em virsh:


virsh define --file /tmp/control-1.xml
virsh define --file /tmp/compute-1.xml
virsh define --file /tmp/compute-2.xml
virsh define --file /tmp/storage-1.xml
virsh define --file /tmp/storage-2.xml

[root@hp-gen9 ~]# virsh list --all
 Id    Name                           State
----------------------------------------------------
 6     dns-server                     running
 64    undercloud                     running
 -     compute-1                      shut off
 -     compute-2                      shut off
 -     control-1                      shut off
 -     storage-1                      shut off
 -     storage-2                      shut off

[root@hp-gen9 ~]#

Agora, uma pequena ressalva - o tripleO usa IPMI para gerenciar servidores durante a instalação e introspecção.

Introspecção é o processo de inspeção do hardware a fim de obter seus parâmetros necessários para posterior provisionamento dos nós. A introspecção é realizada por meio do ironic, serviço desenvolvido para funcionar com servidores bare metal.

Mas aqui está o problema: embora os servidores IPMI de hardware tenham uma porta separada (ou uma porta compartilhada, mas isso não é importante), as máquinas virtuais não possuem essas portas. Aqui uma muleta chamada vbmc vem em nosso auxílio - um utilitário que permite emular uma porta IPMI. Vale a pena prestar atenção a essa nuance principalmente para quem deseja montar tal laboratório em um hipervisor ESXI - para ser sincero, não sei se ele tem um análogo do vbmc, então vale a pena se perguntar sobre esse problema antes de implantar tudo .

Instale o vbmc:


yum install yum install python2-virtualbmc

Se o seu sistema operacional não conseguir encontrar o pacote, adicione o repositório:

yum install -y https://www.rdoproject.org/repos/rdo-release.rpm

Agora configuramos o utilitário. Tudo aqui é banal ao ponto da desgraça. Agora é lógico que não haja servidores na lista vbmc


[root@hp-gen9 ~]# vbmc list

[root@hp-gen9 ~]# 

Para que apareçam, devem ser declarados manualmente assim:


[root@hp-gen9 ~]# vbmc add control-1 --port 7001 --username admin --password admin
[root@hp-gen9 ~]# vbmc add storage-1 --port 7002 --username admin --password admin
[root@hp-gen9 ~]# vbmc add storage-2 --port 7003 --username admin --password admin
[root@hp-gen9 ~]# vbmc add compute-1 --port 7004 --username admin --password admin
[root@hp-gen9 ~]# vbmc add compute-2 --port 7005 --username admin --password admin
[root@hp-gen9 ~]#
[root@hp-gen9 ~]# vbmc list
+-------------+--------+---------+------+
| Domain name | Status | Address | Port |
+-------------+--------+---------+------+
| compute-1   | down   | ::      | 7004 |
| compute-2   | down   | ::      | 7005 |
| control-1   | down   | ::      | 7001 |
| storage-1   | down   | ::      | 7002 |
| storage-2   | down   | ::      | 7003 |
+-------------+--------+---------+------+
[root@hp-gen9 ~]#

Acho que a sintaxe do comando é clara sem explicação. No entanto, por enquanto todas as nossas sessões estão no status DOWN. Para que eles mudem para o status UP, você precisa habilitá-los:


[root@hp-gen9 ~]# vbmc start control-1
2020-08-14 03:15:57,826.826 13149 INFO VirtualBMC [-] Started vBMC instance for domain control-1
[root@hp-gen9 ~]# vbmc start storage-1 
2020-08-14 03:15:58,316.316 13149 INFO VirtualBMC [-] Started vBMC instance for domain storage-1
[root@hp-gen9 ~]# vbmc start storage-2
2020-08-14 03:15:58,851.851 13149 INFO VirtualBMC [-] Started vBMC instance for domain storage-2
[root@hp-gen9 ~]# vbmc start compute-1
2020-08-14 03:15:59,307.307 13149 INFO VirtualBMC [-] Started vBMC instance for domain compute-1
[root@hp-gen9 ~]# vbmc start compute-2
2020-08-14 03:15:59,712.712 13149 INFO VirtualBMC [-] Started vBMC instance for domain compute-2
[root@hp-gen9 ~]# 
[root@hp-gen9 ~]# 
[root@hp-gen9 ~]# vbmc list
+-------------+---------+---------+------+
| Domain name | Status  | Address | Port |
+-------------+---------+---------+------+
| compute-1   | running | ::      | 7004 |
| compute-2   | running | ::      | 7005 |
| control-1   | running | ::      | 7001 |
| storage-1   | running | ::      | 7002 |
| storage-2   | running | ::      | 7003 |
+-------------+---------+---------+------+
[root@hp-gen9 ~]#

E o toque final - você precisa corrigir as regras do firewall (ou desativá-lo completamente):


firewall-cmd --zone=public --add-port=7001/udp --permanent
firewall-cmd --zone=public --add-port=7002/udp --permanent
firewall-cmd --zone=public --add-port=7003/udp --permanent
firewall-cmd --zone=public --add-port=7004/udp --permanent
firewall-cmd --zone=public --add-port=7005/udp --permanent
firewall-cmd --reload

Agora vamos para o undercloud e verificar se tudo está funcionando. O endereço da máquina host é 192.168.255.200. No undercloud adicionamos o pacote ipmitool necessário durante a preparação para implantação:


[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power status          
Chassis Power is off
[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power on
Chassis Power Control: Up/On
[stack@undercloud ~]$ 

[root@hp-gen9 ~]# virsh list 
 Id    Name                           State
----------------------------------------------------
 6     dns-server                     running
 64    undercloud                     running
 65    control-1                      running

Como você pode ver, lançamos com sucesso o nó de controle via vbmc. Agora vamos desligar e seguir em frente:


[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power off
Chassis Power Control: Down/Off
[stack@undercloud ~]$ ipmitool -I lanplus -U admin -P admin -H 192.168.255.200 -p 7001 power status
Chassis Power is off
[stack@undercloud ~]$ 

[root@hp-gen9 ~]# virsh list --all
 Id    Name                           State
----------------------------------------------------
 6     dns-server                     running
 64    undercloud                     running
 -     compute-1                      shut off
 -     compute-2                      shut off
 -     control-1                      shut off
 -     storage-1                      shut off
 -     storage-2                      shut off

[root@hp-gen9 ~]#

A próxima etapa é a introspecção dos nós nos quais o overcloud será instalado. Para fazer isso, precisamos preparar um arquivo json com a descrição de nossos nós. Observe que, diferentemente da instalação em servidores simples, o arquivo indica a porta na qual o vbmc está sendo executado para cada máquina.


[root@hp-gen9 ~]# virsh domiflist --domain control-1 
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:20:a2:2f
-          network    ovs-network-1 virtio      52:54:00:3f:87:9f

[root@hp-gen9 ~]# virsh domiflist --domain compute-1
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:98:e9:d6

[root@hp-gen9 ~]# virsh domiflist --domain compute-2
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:6a:ea:be

[root@hp-gen9 ~]# virsh domiflist --domain storage-1
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:79:0b:cb

[root@hp-gen9 ~]# virsh domiflist --domain storage-2
Interface  Type       Source     Model       MAC
-------------------------------------------------------
-          network    ovs-network-1 virtio      52:54:00:a7:fe:27

Nota: o nó de controle possui duas interfaces, mas neste caso isso não é importante, nesta instalação uma será suficiente para nós.

Agora preparamos o arquivo json. Precisamos indicar o endereço papoula da porta através da qual será feito o provisionamento, os parâmetros dos nós, dar-lhes nomes e indicar como chegar ao ipmi:


{
    "nodes":[
        {
            "mac":[
                "52:54:00:20:a2:2f"
            ],
            "cpu":"8",
            "memory":"32768",
            "disk":"60",
            "arch":"x86_64",
            "name":"control-1",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7001"
        },
        {
            "mac":[
                "52:54:00:79:0b:cb"
            ],
            "cpu":"4",
            "memory":"16384",
            "disk":"160",
            "arch":"x86_64",
            "name":"storage-1",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7002"
        },
        {
            "mac":[
                "52:54:00:a7:fe:27"
            ],
            "cpu":"4",
            "memory":"16384",
            "disk":"160",
            "arch":"x86_64",
            "name":"storage-2",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7003"
        },
        {
            "mac":[
                "52:54:00:98:e9:d6"
            ],
            "cpu":"12",
            "memory":"32768",
            "disk":"60",
            "arch":"x86_64",
            "name":"compute-1",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7004"
        },
        {
            "mac":[
                "52:54:00:6a:ea:be"
            ],
            "cpu":"12",
            "memory":"32768",
            "disk":"60",
            "arch":"x86_64",
            "name":"compute-2",
            "pm_type":"pxe_ipmitool",
            "pm_user":"admin",
            "pm_password":"admin",
            "pm_addr":"192.168.255.200",
            "pm_port":"7005"
        }
    ]
}

Agora precisamos preparar imagens irônicas. Para fazer isso, baixe-os via wget e instale:

(undercloud) [stack@undercloud ~]$ sudo wget https://images.rdoproject.org/queens/delorean/current-tripleo-rdo/overcloud-full.tar --no-check-certificate
(undercloud) [stack@undercloud ~]$ sudo wget https://images.rdoproject.org/queens/delorean/current-tripleo-rdo/ironic-python-agent.tar --no-check-certificate
(undercloud) [stack@undercloud ~]$ ls -lh
total 1.9G
-rw-r--r--. 1 stack stack 447M Aug 14 10:26 ironic-python-agent.tar
-rw-r--r--. 1 stack stack 1.5G Aug 14 10:26 overcloud-full.tar
-rw-------. 1 stack stack  916 Aug 13 23:10 stackrc
-rw-r--r--. 1 stack stack  15K Aug 13 22:50 undercloud.conf
-rw-------. 1 stack stack 2.0K Aug 13 22:50 undercloud-passwords.conf
(undercloud) [stack@undercloud ~]$ mkdir images/
(undercloud) [stack@undercloud ~]$ tar -xpvf ironic-python-agent.tar -C ~/images/
ironic-python-agent.initramfs
ironic-python-agent.kernel
(undercloud) [stack@undercloud ~]$ tar -xpvf overcloud-full.tar -C ~/images/                       
overcloud-full.qcow2
overcloud-full.initrd
overcloud-full.vmlinuz
(undercloud) [stack@undercloud ~]$ 
(undercloud) [stack@undercloud ~]$ ls -lh images/
total 1.9G
-rw-rw-r--. 1 stack stack 441M Aug 12 17:24 ironic-python-agent.initramfs
-rwxr-xr-x. 1 stack stack 6.5M Aug 12 17:24 ironic-python-agent.kernel
-rw-r--r--. 1 stack stack  53M Aug 12 17:14 overcloud-full.initrd
-rw-r--r--. 1 stack stack 1.4G Aug 12 17:18 overcloud-full.qcow2
-rwxr-xr-x. 1 stack stack 6.5M Aug 12 17:14 overcloud-full.vmlinuz
(undercloud) [stack@undercloud ~]$

Fazendo upload de imagens para o undercloud:

(undercloud) [stack@undercloud ~]$ openstack overcloud image upload --image-path ~/images/
Image "overcloud-full-vmlinuz" was uploaded.
+--------------------------------------+------------------------+-------------+---------+--------+
|                  ID                  |          Name          | Disk Format |   Size  | Status |
+--------------------------------------+------------------------+-------------+---------+--------+
| c2553770-3e0f-4750-b46b-138855b5c385 | overcloud-full-vmlinuz |     aki     | 6761064 | active |
+--------------------------------------+------------------------+-------------+---------+--------+
Image "overcloud-full-initrd" was uploaded.
+--------------------------------------+-----------------------+-------------+----------+--------+
|                  ID                  |          Name         | Disk Format |   Size   | Status |
+--------------------------------------+-----------------------+-------------+----------+--------+
| 949984e0-4932-4e71-af43-d67a38c3dc89 | overcloud-full-initrd |     ari     | 55183045 | active |
+--------------------------------------+-----------------------+-------------+----------+--------+
Image "overcloud-full" was uploaded.
+--------------------------------------+----------------+-------------+------------+--------+
|                  ID                  |      Name      | Disk Format |    Size    | Status |
+--------------------------------------+----------------+-------------+------------+--------+
| a2f2096d-c9d7-429a-b866-c7543c02a380 | overcloud-full |    qcow2    | 1487475712 | active |
+--------------------------------------+----------------+-------------+------------+--------+
Image "bm-deploy-kernel" was uploaded.
+--------------------------------------+------------------+-------------+---------+--------+
|                  ID                  |       Name       | Disk Format |   Size  | Status |
+--------------------------------------+------------------+-------------+---------+--------+
| e413aa78-e38f-404c-bbaf-93e582a8e67f | bm-deploy-kernel |     aki     | 6761064 | active |
+--------------------------------------+------------------+-------------+---------+--------+
Image "bm-deploy-ramdisk" was uploaded.
+--------------------------------------+-------------------+-------------+-----------+--------+
|                  ID                  |        Name       | Disk Format |    Size   | Status |
+--------------------------------------+-------------------+-------------+-----------+--------+
| 5cf3aba4-0e50-45d3-929f-27f025dd6ce3 | bm-deploy-ramdisk |     ari     | 461759376 | active |
+--------------------------------------+-------------------+-------------+-----------+--------+
(undercloud) [stack@undercloud ~]$

Verificando se todas as imagens foram carregadas


(undercloud) [stack@undercloud ~]$  openstack image list
+--------------------------------------+------------------------+--------+
| ID                                   | Name                   | Status |
+--------------------------------------+------------------------+--------+
| e413aa78-e38f-404c-bbaf-93e582a8e67f | bm-deploy-kernel       | active |
| 5cf3aba4-0e50-45d3-929f-27f025dd6ce3 | bm-deploy-ramdisk      | active |
| a2f2096d-c9d7-429a-b866-c7543c02a380 | overcloud-full         | active |
| 949984e0-4932-4e71-af43-d67a38c3dc89 | overcloud-full-initrd  | active |
| c2553770-3e0f-4750-b46b-138855b5c385 | overcloud-full-vmlinuz | active |
+--------------------------------------+------------------------+--------+
(undercloud) [stack@undercloud ~]$

Mais uma coisa: você precisa adicionar um servidor DNS:


(undercloud) [stack@undercloud ~]$ openstack subnet list
+--------------------------------------+-----------------+--------------------------------------+------------------+
| ID                                   | Name            | Network                              | Subnet           |
+--------------------------------------+-----------------+--------------------------------------+------------------+
| f45dea46-4066-42aa-a3c4-6f84b8120cab | ctlplane-subnet | 6ca013dc-41c2-42d8-9d69-542afad53392 | 192.168.255.0/24 |
+--------------------------------------+-----------------+--------------------------------------+------------------+
(undercloud) [stack@undercloud ~]$ openstack subnet show f45dea46-4066-42aa-a3c4-6f84b8120cab
+-------------------+-----------------------------------------------------------+
| Field             | Value                                                     |
+-------------------+-----------------------------------------------------------+
| allocation_pools  | 192.168.255.11-192.168.255.50                             |
| cidr              | 192.168.255.0/24                                          |
| created_at        | 2020-08-13T20:10:37Z                                      |
| description       |                                                           |
| dns_nameservers   |                                                           |
| enable_dhcp       | True                                                      |
| gateway_ip        | 192.168.255.1                                             |
| host_routes       | destination='169.254.169.254/32', gateway='192.168.255.1' |
| id                | f45dea46-4066-42aa-a3c4-6f84b8120cab                      |
| ip_version        | 4                                                         |
| ipv6_address_mode | None                                                      |
| ipv6_ra_mode      | None                                                      |
| name              | ctlplane-subnet                                           |
| network_id        | 6ca013dc-41c2-42d8-9d69-542afad53392                      |
| prefix_length     | None                                                      |
| project_id        | a844ccfcdb2745b198dde3e1b28c40a3                          |
| revision_number   | 0                                                         |
| segment_id        | None                                                      |
| service_types     |                                                           |
| subnetpool_id     | None                                                      |
| tags              |                                                           |
| updated_at        | 2020-08-13T20:10:37Z                                      |
+-------------------+-----------------------------------------------------------+
(undercloud) [stack@undercloud ~]$ 
(undercloud) [stack@undercloud ~]$ neutron subnet-update f45dea46-4066-42aa-a3c4-6f84b8120cab --dns-nameserver 192.168.255.253                                    
neutron CLI is deprecated and will be removed in the future. Use openstack CLI instead.
Updated subnet: f45dea46-4066-42aa-a3c4-6f84b8120cab
(undercloud) [stack@undercloud ~]$

Agora podemos dar o comando para introspecção:

(undercloud) [stack@undercloud ~]$ openstack overcloud node import --introspect --provide inspection.json 
Started Mistral Workflow tripleo.baremetal.v1.register_or_update. Execution ID: d57456a3-d8ed-479c-9a90-dff7c752d0ec
Waiting for messages on queue 'tripleo' with no timeout.


5 node(s) successfully moved to the "manageable" state.
Successfully registered node UUID b4b2cf4a-b7ca-4095-af13-cc83be21c4f5
Successfully registered node UUID b89a72a3-6bb7-429a-93bc-48393d225838
Successfully registered node UUID 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e
Successfully registered node UUID bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8
Successfully registered node UUID 766ab623-464c-423d-a529-d9afb69d1167
Waiting for introspection to finish...
Started Mistral Workflow tripleo.baremetal.v1.introspect. Execution ID: 6b4d08ae-94c3-4a10-ab63-7634ec198a79
Waiting for messages on queue 'tripleo' with no timeout.
Introspection of node b89a72a3-6bb7-429a-93bc-48393d225838 completed. Status:SUCCESS. Errors:None
Introspection of node 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e completed. Status:SUCCESS. Errors:None
Introspection of node bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 completed. Status:SUCCESS. Errors:None
Introspection of node 766ab623-464c-423d-a529-d9afb69d1167 completed. Status:SUCCESS. Errors:None
Introspection of node b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 completed. Status:SUCCESS. Errors:None
Successfully introspected 5 node(s).
Started Mistral Workflow tripleo.baremetal.v1.provide. Execution ID: f5594736-edcf-4927-a8a0-2a7bf806a59a
Waiting for messages on queue 'tripleo' with no timeout.
5 node(s) successfully moved to the "available" state.
(undercloud) [stack@undercloud ~]$

Como você pode ver na saída, tudo foi concluído sem erros. Vamos verificar se todos os nós estão no estado disponível:


(undercloud) [stack@undercloud ~]$ openstack baremetal node list
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
| UUID                                 | Name      | Instance UUID | Power State | Provisioning State | Maintenance |
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
| b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 | control-1 | None          | power off   | available          | False       |
| b89a72a3-6bb7-429a-93bc-48393d225838 | storage-1 | None          | power off   | available          | False       |
| 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e | storage-2 | None          | power off   | available          | False       |
| bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 | compute-1 | None          | power off   | available          | False       |
| 766ab623-464c-423d-a529-d9afb69d1167 | compute-2 | None          | power off   | available          | False       |
+--------------------------------------+-----------+---------------+-------------+--------------------+-------------+
(undercloud) [stack@undercloud ~]$ 

Se os nós estiverem em um estado diferente, geralmente gerenciável, algo deu errado e você precisa consultar o log e descobrir por que isso aconteceu. Lembre-se que neste cenário estamos utilizando virtualização e pode haver bugs associados ao uso de máquinas virtuais ou vbmc.

A seguir, precisamos indicar qual nó executará qual função – ou seja, indicar o perfil com o qual o nó irá implantar:


(undercloud) [stack@undercloud ~]$ openstack overcloud profiles list
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| Node UUID                            | Node Name | Provision State | Current Profile | Possible Profiles |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 | control-1 | available       | None            |                   |
| b89a72a3-6bb7-429a-93bc-48393d225838 | storage-1 | available       | None            |                   |
| 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e | storage-2 | available       | None            |                   |
| bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 | compute-1 | available       | None            |                   |
| 766ab623-464c-423d-a529-d9afb69d1167 | compute-2 | available       | None            |                   |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
(undercloud) [stack@undercloud ~]$ openstack flavor list
+--------------------------------------+---------------+------+------+-----------+-------+-----------+
| ID                                   | Name          |  RAM | Disk | Ephemeral | VCPUs | Is Public |
+--------------------------------------+---------------+------+------+-----------+-------+-----------+
| 168af640-7f40-42c7-91b2-989abc5c5d8f | swift-storage | 4096 |   40 |         0 |     1 | True      |
| 52148d1b-492e-48b4-b5fc-772849dd1b78 | baremetal     | 4096 |   40 |         0 |     1 | True      |
| 56e66542-ae60-416d-863e-0cb192d01b09 | control       | 4096 |   40 |         0 |     1 | True      |
| af6796e1-d0c4-4bfe-898c-532be194f7ac | block-storage | 4096 |   40 |         0 |     1 | True      |
| e4d50fdd-0034-446b-b72c-9da19b16c2df | compute       | 4096 |   40 |         0 |     1 | True      |
| fc2e3acf-7fca-4901-9eee-4a4d6ef0265d | ceph-storage  | 4096 |   40 |         0 |     1 | True      |
+--------------------------------------+---------------+------+------+-----------+-------+-----------+
(undercloud) [stack@undercloud ~]$

Especifique o perfil para cada nó:


openstack baremetal node set --property capabilities='profile:control,boot_option:local' b4b2cf4a-b7ca-4095-af13-cc83be21c4f5
openstack baremetal node set --property capabilities='profile:ceph-storage,boot_option:local' b89a72a3-6bb7-429a-93bc-48393d225838
openstack baremetal node set --property capabilities='profile:ceph-storage,boot_option:local' 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e
openstack baremetal node set --property capabilities='profile:compute,boot_option:local' bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8
openstack baremetal node set --property capabilities='profile:compute,boot_option:local' 766ab623-464c-423d-a529-d9afb69d1167

Vamos verificar se fizemos tudo corretamente:


(undercloud) [stack@undercloud ~]$ openstack overcloud profiles list
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| Node UUID                            | Node Name | Provision State | Current Profile | Possible Profiles |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
| b4b2cf4a-b7ca-4095-af13-cc83be21c4f5 | control-1 | available       | control         |                   |
| b89a72a3-6bb7-429a-93bc-48393d225838 | storage-1 | available       | ceph-storage    |                   |
| 20a16cc0-e0ce-4d88-8f17-eb0ce7b4d69e | storage-2 | available       | ceph-storage    |                   |
| bfc1eb98-a17a-4a70-b0b6-6c0db0eac8e8 | compute-1 | available       | compute         |                   |
| 766ab623-464c-423d-a529-d9afb69d1167 | compute-2 | available       | compute         |                   |
+--------------------------------------+-----------+-----------------+-----------------+-------------------+
(undercloud) [stack@undercloud ~]$

Se tudo estiver correto, damos o comando para implantar overcloud:

openstack overcloud deploy --templates --control-scale 1 --compute-scale 2  --ceph-storage-scale 2 --control-flavor control --compute-flavor compute  --ceph-storage-flavor ceph-storage --libvirt-type qemu

Numa instalação real serão naturalmente utilizados templates customizados, no nosso caso isso complicará muito o processo, pois cada edição no template deverá ser explicada. Como foi escrito anteriormente, mesmo uma simples instalação será suficiente para vermos como funciona.

Nota: a variável --libvirt-type qemu é necessária neste caso, pois usaremos virtualização aninhada. Caso contrário, você não conseguirá executar máquinas virtuais.

Agora você tem cerca de uma hora, ou talvez mais (dependendo das capacidades do hardware) e só pode esperar que após esse tempo você veja a seguinte mensagem:


2020-08-14 08:39:21Z [overcloud]: CREATE_COMPLETE  Stack CREATE completed successfully

 Stack overcloud CREATE_COMPLETE 

Host 192.168.255.21 not found in /home/stack/.ssh/known_hosts
Started Mistral Workflow tripleo.deployment.v1.get_horizon_url. Execution ID: fcb996cd-6a19-482b-b755-2ca0c08069a9
Overcloud Endpoint: http://192.168.255.21:5000/
Overcloud Horizon Dashboard URL: http://192.168.255.21:80/dashboard
Overcloud rc file: /home/stack/overcloudrc
Overcloud Deployed
(undercloud) [stack@undercloud ~]$

Agora você tem uma versão quase completa do openstack, na qual pode estudar, experimentar, etc.

Vamos verificar se tudo está funcionando corretamente. Na pilha do diretório inicial do usuário há dois arquivos - um stackrc (para gerenciar o undercloud) e o segundo overcloudrc (para gerenciar o overcloud). Esses arquivos devem ser especificados como fonte, pois contêm informações necessárias para autenticação.


(undercloud) [stack@undercloud ~]$ openstack server list
+--------------------------------------+-------------------------+--------+-------------------------+----------------+--------------+
| ID                                   | Name                    | Status | Networks                | Image          | Flavor       |
+--------------------------------------+-------------------------+--------+-------------------------+----------------+--------------+
| fd7d36f4-ce87-4b9a-93b0-add2957792de | overcloud-controller-0  | ACTIVE | ctlplane=192.168.255.15 | overcloud-full | control      |
| edc77778-8972-475e-a541-ff40eb944197 | overcloud-novacompute-1 | ACTIVE | ctlplane=192.168.255.26 | overcloud-full | compute      |
| 5448ce01-f05f-47ca-950a-ced14892c0d4 | overcloud-cephstorage-1 | ACTIVE | ctlplane=192.168.255.34 | overcloud-full | ceph-storage |
| ce6d862f-4bdf-4ba3-b711-7217915364d7 | overcloud-novacompute-0 | ACTIVE | ctlplane=192.168.255.19 | overcloud-full | compute      |
| e4507bd5-6f96-4b12-9cc0-6924709da59e | overcloud-cephstorage-0 | ACTIVE | ctlplane=192.168.255.44 | overcloud-full | ceph-storage |
+--------------------------------------+-------------------------+--------+-------------------------+----------------+--------------+
(undercloud) [stack@undercloud ~]$ 


(undercloud) [stack@undercloud ~]$ source overcloudrc 
(overcloud) [stack@undercloud ~]$ 
(overcloud) [stack@undercloud ~]$ openstack project list
+----------------------------------+---------+
| ID                               | Name    |
+----------------------------------+---------+
| 4eed7d0f06544625857d51cd77c5bd4c | admin   |
| ee1c68758bde41eaa9912c81dc67dad8 | service |
+----------------------------------+---------+
(overcloud) [stack@undercloud ~]$ 
(overcloud) [stack@undercloud ~]$ 
(overcloud) [stack@undercloud ~]$ openstack network agent list  
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| ID                                   | Agent Type         | Host                                | Availability Zone | Alive | State | Binary                    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
| 10495de9-ba4b-41fe-b30a-b90ec3f8728b | Open vSwitch agent | overcloud-novacompute-1.localdomain | None              | :-)   | UP    | neutron-openvswitch-agent |
| 1515ad4a-5972-46c3-af5f-e5446dff7ac7 | L3 agent           | overcloud-controller-0.localdomain  | nova              | :-)   | UP    | neutron-l3-agent          |
| 322e62ca-1e5a-479e-9a96-4f26d09abdd7 | DHCP agent         | overcloud-controller-0.localdomain  | nova              | :-)   | UP    | neutron-dhcp-agent        |
| 9c1de2f9-bac5-400e-998d-4360f04fc533 | Open vSwitch agent | overcloud-novacompute-0.localdomain | None              | :-)   | UP    | neutron-openvswitch-agent |
| d99c5657-851e-4d3c-bef6-f1e3bb1acfb0 | Open vSwitch agent | overcloud-controller-0.localdomain  | None              | :-)   | UP    | neutron-openvswitch-agent |
| ff85fae6-5543-45fb-a301-19c57b62d836 | Metadata agent     | overcloud-controller-0.localdomain  | None              | :-)   | UP    | neutron-metadata-agent    |
+--------------------------------------+--------------------+-------------------------------------+-------------------+-------+-------+---------------------------+
(overcloud) [stack@undercloud ~]$

Minha instalação ainda requer um pequeno toque - adicionar uma rota no controlador, já que a máquina com a qual estou trabalhando está em uma rede diferente. Para fazer isso, vá para control-1 na conta heat-admin e registre a rota


(undercloud) [stack@undercloud ~]$ ssh [email protected]         
Last login: Fri Aug 14 09:47:40 2020 from 192.168.255.1
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ sudo ip route add 10.169.0.0/16 via 192.168.255.254

Bem, agora você pode ir para o horizonte. Todas as informações – endereços, login e senha – estão no arquivo /home/stack/overcloudrc. O diagrama final fica assim:

Introdução à parte de rede da infraestrutura em nuvem

Aliás, em nossa instalação os endereços das máquinas foram emitidos via DHCP e, como você pode ver, são emitidos “ao acaso”. Você pode definir estritamente no modelo qual endereço deve ser anexado a qual máquina durante a implantação, se necessário.

Como o tráfego flui entre máquinas virtuais?

Neste artigo, veremos três opções para passar o tráfego

  • Duas máquinas em um hipervisor em uma rede L2
  • Duas máquinas em hipervisores diferentes na mesma rede L2
  • Duas máquinas em redes diferentes (rooting entre redes)

Casos com acesso ao mundo exterior através de uma rede externa, utilizando endereços flutuantes, bem como roteamento distribuído, consideraremos na próxima vez, por enquanto focaremos no tráfego interno.

Para verificar, vamos montar o seguinte diagrama:

Introdução à parte de rede da infraestrutura em nuvem

Criamos 4 máquinas virtuais - 3 em uma rede L2 - net-1 e mais 1 na rede net-2

(overcloud) [stack@undercloud ~]$ nova list --tenant 5e18ce8ec9594e00b155485f19895e6c             
+--------------------------------------+------+----------------------------------+--------+------------+-------------+-----------------+
| ID                                   | Name | Tenant ID                        | Status | Task State | Power State | Networks        |
+--------------------------------------+------+----------------------------------+--------+------------+-------------+-----------------+
| f53b37b5-2204-46cc-aef0-dba84bf970c0 | vm-1 | 5e18ce8ec9594e00b155485f19895e6c | ACTIVE | -          | Running     | net-1=10.0.1.85 |
| fc8b6722-0231-49b0-b2fa-041115bef34a | vm-2 | 5e18ce8ec9594e00b155485f19895e6c | ACTIVE | -          | Running     | net-1=10.0.1.88 |
| 3cd74455-b9b7-467a-abe3-bd6ff765c83c | vm-3 | 5e18ce8ec9594e00b155485f19895e6c | ACTIVE | -          | Running     | net-1=10.0.1.90 |
| 7e836338-6772-46b0-9950-f7f06dbe91a8 | vm-4 | 5e18ce8ec9594e00b155485f19895e6c | ACTIVE | -          | Running     | net-2=10.0.2.8  |
+--------------------------------------+------+----------------------------------+--------+------------+-------------+-----------------+
(overcloud) [stack@undercloud ~]$ 

Vamos ver em quais hipervisores as máquinas criadas estão localizadas:

(overcloud) [stack@undercloud ~]$ nova show f53b37b5-2204-46cc-aef0-dba84bf970c0 | egrep "hypervisor_hostname|instance_name|hostname"
| OS-EXT-SRV-ATTR:hostname             | vm-1                                                     |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | overcloud-novacompute-0.localdomain                      |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000001                                        |
(overcloud) [stack@undercloud ~]$ nova show fc8b6722-0231-49b0-b2fa-041115bef34a | egrep "hypervisor_hostname|instance_name|hostname"
| OS-EXT-SRV-ATTR:hostname             | vm-2                                                     |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | overcloud-novacompute-1.localdomain                      |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000002                                        |
(overcloud) [stack@undercloud ~]$ nova show 3cd74455-b9b7-467a-abe3-bd6ff765c83c | egrep "hypervisor_hostname|instance_name|hostname"
| OS-EXT-SRV-ATTR:hostname             | vm-3                                                     |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | overcloud-novacompute-0.localdomain                      |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000003                                        |
(overcloud) [stack@undercloud ~]$ nova show 7e836338-6772-46b0-9950-f7f06dbe91a8 | egrep "hypervisor_hostname|instance_name|hostname"
| OS-EXT-SRV-ATTR:hostname             | vm-4                                                     |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | overcloud-novacompute-1.localdomain                      |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000004                                        |

(sobrenuvem) [stack@undercloud ~]$
As máquinas vm-1 e vm-3 estão localizadas no nó computacional-0, as máquinas vm-2 e vm-4 estão localizadas no nó computacional-1.

Além disso, foi criado um roteador virtual para permitir o roteamento entre as redes especificadas:

(overcloud) [stack@undercloud ~]$ openstack router list  --project 5e18ce8ec9594e00b155485f19895e6c
+--------------------------------------+----------+--------+-------+-------------+-------+----------------------------------+
| ID                                   | Name     | Status | State | Distributed | HA    | Project                          |
+--------------------------------------+----------+--------+-------+-------------+-------+----------------------------------+
| 0a4d2420-4b9c-46bd-aec1-86a1ef299abe | router-1 | ACTIVE | UP    | False       | False | 5e18ce8ec9594e00b155485f19895e6c |
+--------------------------------------+----------+--------+-------+-------------+-------+----------------------------------+
(overcloud) [stack@undercloud ~]$ 

O roteador possui duas portas virtuais, que funcionam como gateways para redes:

(overcloud) [stack@undercloud ~]$ openstack router show 0a4d2420-4b9c-46bd-aec1-86a1ef299abe | grep interface
| interfaces_info         | [{"subnet_id": "2529ad1a-6b97-49cd-8515-cbdcbe5e3daa", "ip_address": "10.0.1.254", "port_id": "0c52b15f-8fcc-4801-bf52-7dacc72a5201"}, {"subnet_id": "335552dd-b35b-456b-9df0-5aac36a3ca13", "ip_address": "10.0.2.254", "port_id": "92fa49b5-5406-499f-ab8d-ddf28cc1a76c"}] |
(overcloud) [stack@undercloud ~]$ 

Mas antes de vermos como o tráfego flui, vejamos o que temos atualmente no nó de controle (que também é um nó de rede) e no nó de computação. Vamos começar com o nó de computação.


[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-vsctl show
[heat-admin@overcloud-novacompute-0 ~]$ sudo sudo ovs-appctl dpif/show
system@ovs-system: hit:3 missed:3
  br-ex:
    br-ex 65534/1: (internal)
    phy-br-ex 1/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/2: (internal)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
  br-tun:
    br-tun 65534/3: (internal)
    patch-int 1/none: (patch: peer=patch-tun)
    vxlan-c0a8ff0f 3/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.15)
    vxlan-c0a8ff1a 2/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.26)
[heat-admin@overcloud-novacompute-0 ~]$

No momento, o nó possui três pontes ovs - br-int, br-tun, br-ex. Entre eles, como vemos, existe um conjunto de interfaces. Para facilitar a compreensão, vamos representar graficamente todas essas interfaces no diagrama e ver o que acontece.

Introdução à parte de rede da infraestrutura em nuvem

Observando os endereços para os quais os túneis VxLAN são elevados, pode-se ver que um túnel é elevado para computar-1 (192.168.255.26), o segundo túnel olha para controlar-1 (192.168.255.15). Mas o mais interessante é que o br-ex não possui interfaces físicas, e se você observar quais fluxos estão configurados, verá que essa ponte só pode derrubar tráfego no momento.


[heat-admin@overcloud-novacompute-0 ~]$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 192.168.255.19  netmask 255.255.255.0  broadcast 192.168.255.255
        inet6 fe80::5054:ff:fe6a:eabe  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:6a:ea:be  txqueuelen 1000  (Ethernet)
        RX packets 2909669  bytes 4608201000 (4.2 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1821057  bytes 349198520 (333.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[heat-admin@overcloud-novacompute-0 ~]$ 

Como você pode ver na saída, o endereço é parafusado diretamente na porta física e não na interface da ponte virtual.


[heat-admin@overcloud-novacompute-0 ~]$  sudo ovs-appctl fdb/show br-ex
 port  VLAN  MAC                Age
[heat-admin@overcloud-novacompute-0 ~]$  sudo ovs-ofctl dump-flows br-ex
 cookie=0x9169eae8f7fe5bb2, duration=216686.864s, table=0, n_packets=303, n_bytes=26035, priority=2,in_port="phy-br-ex" actions=drop
 cookie=0x9169eae8f7fe5bb2, duration=216686.887s, table=0, n_packets=0, n_bytes=0, priority=0 actions=NORMAL
[heat-admin@overcloud-novacompute-0 ~]$ 

Pela primeira regra, tudo que veio da porta phy-br-ex deve ser descartado.
Na verdade, atualmente não há outro lugar para o tráfego entrar nesta ponte, exceto a partir desta interface (a interface com br-int) e, a julgar pelas quedas, o tráfego BUM já voou para a ponte.

Ou seja, o tráfego só pode sair deste nó através do túnel VxLAN e nada mais. Porém, se você ligar o DVR, a situação mudará, mas trataremos disso em outra ocasião. Ao usar o isolamento de rede, por exemplo, usando vlans, você não terá uma interface L3 na vlan 0, mas várias interfaces. Porém, o tráfego VxLAN sairá do nó da mesma forma, mas também encapsulado em algum tipo de vlan dedicada.

Resolvemos o nó de computação, vamos passar para o nó de controle.


[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl dpif/show
system@ovs-system: hit:930491 missed:825
  br-ex:
    br-ex 65534/1: (internal)
    eth0 1/2: (system)
    phy-br-ex 2/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/3: (internal)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
  br-tun:
    br-tun 65534/4: (internal)
    patch-int 1/none: (patch: peer=patch-tun)
    vxlan-c0a8ff13 3/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.19)
    vxlan-c0a8ff1a 2/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.26)
[heat-admin@overcloud-controller-0 ~]$

Na verdade, podemos dizer que tudo é igual, mas o endereço IP não está mais na interface física, mas sim na ponte virtual. Isso é feito porque esta porta é a porta pela qual o tráfego sairá para o mundo exterior.


[heat-admin@overcloud-controller-0 ~]$ ifconfig br-ex
br-ex: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 192.168.255.15  netmask 255.255.255.0  broadcast 192.168.255.255
        inet6 fe80::5054:ff:fe20:a22f  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:20:a2:2f  txqueuelen 1000  (Ethernet)
        RX packets 803859  bytes 1732616116 (1.6 GiB)
        RX errors 0  dropped 63  overruns 0  frame 0
        TX packets 808475  bytes 121652156 (116.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl fdb/show br-ex
 port  VLAN  MAC                Age
    3   100  28:c0:da:00:4d:d3   35
    1     0  28:c0:da:00:4d:d3   35
    1     0  52:54:00:98:e9:d6    0
LOCAL     0  52:54:00:20:a2:2f    0
    1     0  52:54:00:2c:08:9e    0
    3   100  52:54:00:20:a2:2f    0
    1     0  52:54:00:6a:ea:be    0
[heat-admin@overcloud-controller-0 ~]$ 

Esta porta está vinculada à ponte br-ex e como não há tags vlan nela, esta porta é uma porta tronco na qual todas as vlans são permitidas, agora o tráfego sai sem tag, conforme indicado por vlan-id 0 no saída acima.

Introdução à parte de rede da infraestrutura em nuvem

Todo o resto no momento é semelhante ao nó de computação - as mesmas pontes, os mesmos túneis indo para dois nós de computação.

Não consideraremos nós de armazenamento neste artigo, mas para compreensão é necessário dizer que a parte de rede desses nós é banal ao ponto da desgraça. No nosso caso, existe apenas uma porta física (eth0) com um endereço IP atribuído e pronto. Não há túneis VxLAN, pontes de túneis, etc. - não há nenhum ovs, pois não há sentido nisso. Ao usar o isolamento de rede, este nó terá duas interfaces (portas físicas, bodny, ou apenas duas vlans - não importa - depende do que você deseja) - uma para gerenciamento, a segunda para tráfego (escrita no disco da VM , lendo do disco, etc.)

Descobrimos o que temos nos nós na ausência de quaisquer serviços. Agora vamos lançar 4 máquinas virtuais e ver como o esquema descrito acima muda - devemos ter portas, roteadores virtuais, etc.

Até agora nossa rede está assim:

Introdução à parte de rede da infraestrutura em nuvem

Temos duas máquinas virtuais em cada nó do computador. Usando computacional-0 como exemplo, vamos ver como tudo está incluído.


[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh list 
 Id    Name                           State
----------------------------------------------------
 1     instance-00000001              running
 3     instance-00000003              running

[heat-admin@overcloud-novacompute-0 ~]$ 

A máquina possui apenas uma interface virtual - tap95d96a75-a0:

[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap95d96a75-a0 bridge     qbr95d96a75-a0 virtio      fa:16:3e:44:98:20

[heat-admin@overcloud-novacompute-0 ~]$ 

Esta interface aparece na ponte Linux:

[heat-admin@overcloud-novacompute-0 ~]$ sudo brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242904c92a8       no
qbr5bd37136-47          8000.5e4e05841423       no              qvb5bd37136-47
                                                        tap5bd37136-47
qbr95d96a75-a0          8000.de076cb850f6       no              qvb95d96a75-a0
                                                        tap95d96a75-a0
[heat-admin@overcloud-novacompute-0 ~]$ 

Como você pode ver na saída, existem apenas duas interfaces na ponte - tap95d96a75-a0 e qvb95d96a75-a0.

Aqui vale a pena nos determos um pouco nos tipos de dispositivos de rede virtual no OpenStack:
vtap - interface virtual anexada a uma instância (VM)
qbr - ponte Linux
qvb e qvo - par vEth conectado à ponte Linux e ponte Open vSwitch
br-int, br-tun, br-vlan — Abra pontes vSwitch
patch-, int-br-, phy-br- - Abra interfaces de patch vSwitch conectando pontes
qg, qr, ha, fg, sg - Abra portas vSwitch usadas por dispositivos virtuais para conectar-se ao OVS

Como você entende, se tivermos uma porta qvb95d96a75-a0 na ponte, que é um par vEth, então em algum lugar existe sua contraparte, que logicamente deveria ser chamada de qvo95d96a75-a0. Vamos ver quais portas estão no OVS.


[heat-admin@overcloud-novacompute-0 ~]$ sudo sudo ovs-appctl dpif/show
system@ovs-system: hit:526 missed:91
  br-ex:
    br-ex 65534/1: (internal)
    phy-br-ex 1/none: (patch: peer=int-br-ex)
  br-int:
    br-int 65534/2: (internal)
    int-br-ex 1/none: (patch: peer=phy-br-ex)
    patch-tun 2/none: (patch: peer=patch-int)
    qvo5bd37136-47 6/6: (system)
    qvo95d96a75-a0 3/5: (system)
  br-tun:
    br-tun 65534/3: (internal)
    patch-int 1/none: (patch: peer=patch-tun)
    vxlan-c0a8ff0f 3/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.15)
    vxlan-c0a8ff1a 2/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.26)
[heat-admin@overcloud-novacompute-0 ~]$ 

Como podemos ver, a porta está em br-int. O Br-int atua como um switch que encerra as portas da máquina virtual. Além de qvo95d96a75-a0, a porta qvo5bd37136-47 está visível na saída. Esta é a porta para a segunda máquina virtual. Como resultado, nosso diagrama agora fica assim:

Introdução à parte de rede da infraestrutura em nuvem

Uma questão que deve interessar imediatamente ao leitor atento - qual é a ponte Linux entre a porta da máquina virtual e a porta OVS? O fato é que para proteger a máquina são utilizados grupos de segurança, que nada mais são do que iptables. OVS não funciona com iptables, então essa “muleta” foi inventada. No entanto, está se tornando obsoleto - está sendo substituído pelo conntrack em novos lançamentos.

Ou seja, em última análise, o esquema fica assim:

Introdução à parte de rede da infraestrutura em nuvem

Duas máquinas em um hipervisor em uma rede L2

Como essas duas VMs estão localizadas na mesma rede L2 e no mesmo hipervisor, o tráfego entre elas fluirá logicamente localmente através do br-int, já que ambas as máquinas estarão na mesma VLAN:


[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap95d96a75-a0 bridge     qbr95d96a75-a0 virtio      fa:16:3e:44:98:20

[heat-admin@overcloud-novacompute-0 ~]$ 
[heat-admin@overcloud-novacompute-0 ~]$ 
[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000003
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap5bd37136-47 bridge     qbr5bd37136-47 virtio      fa:16:3e:83:ad:a4

[heat-admin@overcloud-novacompute-0 ~]$ 
[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-appctl fdb/show br-int 
 port  VLAN  MAC                Age
    6     1  fa:16:3e:83:ad:a4    0
    3     1  fa:16:3e:44:98:20    0
[heat-admin@overcloud-novacompute-0 ~]$ 

Duas máquinas em hipervisores diferentes na mesma rede L2

Agora vamos ver como será o tráfego entre duas máquinas na mesma rede L2, mas localizadas em hipervisores diferentes. Para ser sincero, nada mudará muito, apenas o tráfego entre hipervisores passará pelo túnel vxlan. Vejamos um exemplo.

Endereços das máquinas virtuais entre as quais observaremos o tráfego:

[heat-admin@overcloud-novacompute-0 ~]$ sudo virsh domiflist instance-00000001
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap95d96a75-a0 bridge     qbr95d96a75-a0 virtio      fa:16:3e:44:98:20

[heat-admin@overcloud-novacompute-0 ~]$ 


[heat-admin@overcloud-novacompute-1 ~]$ sudo virsh domiflist instance-00000002
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tape7e23f1b-07 bridge     qbre7e23f1b-07 virtio      fa:16:3e:72:ad:53

[heat-admin@overcloud-novacompute-1 ~]$ 

Vemos a tabela de encaminhamento em br-int em computar-0:

[heat-admin@overcloud-novacompute-0 ~]$  sudo ovs-appctl fdb/show br-int | grep fa:16:3e:72:ad:53
    2     1  fa:16:3e:72:ad:53    1
[heat-admin@overcloud-novacompute-0 ~]

O tráfego deve ir para a porta 2 – vamos ver que tipo de porta é:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl show br-int | grep addr
 1(int-br-ex): addr:7e:7f:28:1f:bd:54
 2(patch-tun): addr:0a:bd:07:69:58:d9
 3(qvo95d96a75-a0): addr:ea:50:9a:3d:69:58
 6(qvo5bd37136-47): addr:9a:d1:03:50:3d:96
 LOCAL(br-int): addr:1a:0f:53:97:b1:49
[heat-admin@overcloud-novacompute-0 ~]$

Isso é patch-tun - ou seja, a interface em br-tun. Vamos ver o que acontece com o pacote no br-tun:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl dump-flows br-tun | grep fa:16:3e:72:ad:53
 cookie=0x8759a56536b67a8e, duration=1387.959s, table=20, n_packets=1460, n_bytes=138880, hard_timeout=300, idle_age=0, hard_age=0, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:72:ad:53 actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:2
[heat-admin@overcloud-novacompute-0 ~]$ 

O pacote é empacotado em VxLAN e enviado para a porta 2. Vamos ver aonde leva a porta 2:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl show br-tun | grep addr   
 1(patch-int): addr:b2:d1:f8:21:96:66
 2(vxlan-c0a8ff1a): addr:be:64:1f:75:78:a7
 3(vxlan-c0a8ff0f): addr:76:6f:b9:3c:3f:1c
 LOCAL(br-tun): addr:a2:5b:6d:4f:94:47
[heat-admin@overcloud-novacompute-0 ~]$

Este é um túnel vxlan no computado-1:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-appctl dpif/show | egrep vxlan-c0a8ff1a
    vxlan-c0a8ff1a 2/4: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.19, remote_ip=192.168.255.26)
[heat-admin@overcloud-novacompute-0 ~]$

Vamos para computar-1 e ver o que acontece a seguir com o pacote:

[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-appctl fdb/show br-int | egrep fa:16:3e:44:98:20
    2     1  fa:16:3e:44:98:20    1
[heat-admin@overcloud-novacompute-1 ~]$ 

Mac está na tabela de encaminhamento br-int em computa-1 e, como pode ser visto na saída acima, é visível através da porta 2, que é a porta para br-tun:

[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-ofctl show br-int | grep addr   
 1(int-br-ex): addr:8a:d7:f9:ad:8c:1d
 2(patch-tun): addr:46:cc:40:bd:20:da
 3(qvoe7e23f1b-07): addr:12:78:2e:34:6a:c7
 4(qvo3210e8ec-c0): addr:7a:5f:59:75:40:85
 LOCAL(br-int): addr:e2:27:b2:ed:14:46

Bem, então vemos que em br-int no computado-1 existe uma papoula de destino:

[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-appctl fdb/show br-int | egrep fa:16:3e:72:ad:53
    3     1  fa:16:3e:72:ad:53    0
[heat-admin@overcloud-novacompute-1 ~]$ 

Ou seja, o pacote recebido voará para a porta 3, atrás da qual já existe uma máquina virtual instância-00000003.

A beleza de implantar o Openstack para aprendizagem em infraestrutura virtual é que podemos capturar facilmente o tráfego entre hipervisores e ver o que está acontecendo com ele. Isto é o que faremos agora, execute o tcpdump na porta vnet em direção ao compute-0:


[root@hp-gen9 bormoglotx]# tcpdump -vvv -i vnet3
tcpdump: listening on vnet3, link-type EN10MB (Ethernet), capture size 262144 bytes

*****************omitted*******************

04:39:04.583459 IP (tos 0x0, ttl 64, id 16868, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.19.39096 > 192.168.255.26.4789: [no cksum] VXLAN, flags [I] (0x08), vni 22
IP (tos 0x0, ttl 64, id 8012, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.1.85 > 10.0.1.88: ICMP echo request, id 5634, seq 16, length 64
04:39:04.584449 IP (tos 0x0, ttl 64, id 35181, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.26.speedtrace-disc > 192.168.255.19.4789: [no cksum] VXLAN, flags [I] (0x08), vni 22
IP (tos 0x0, ttl 64, id 59124, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.1.88 > 10.0.1.85: ICMP echo reply, id 5634, seq 16, length 64
	
*****************omitted*******************

A primeira linha mostra que Patek do endereço 10.0.1.85 vai para o endereço 10.0.1.88 (tráfego ICMP) e é encapsulado em um pacote VxLAN com vni 22 e o pacote vai do host 192.168.255.19 (compute-0) para o host 192.168.255.26 .1 (computação-XNUMX). Podemos verificar se o VNI corresponde ao especificado em ovs.

Vamos voltar a esta linha actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:2. 0x16 é vni no sistema numérico hexadecimal. Vamos converter este número para o 16º sistema:


16 = 6*16^0+1*16^1 = 6+16 = 22

Ou seja, vni corresponde à realidade.

A segunda linha mostra o tráfego de retorno, bom, não adianta explicar, está tudo claro aí.

Duas máquinas em redes diferentes (roteamento entre redes)

O último caso hoje é o roteamento entre redes dentro de um projeto usando um roteador virtual. Estamos considerando um caso sem DVR (veremos isso em outro artigo), portanto o roteamento ocorre no nó da rede. No nosso caso, o nó da rede não está localizado em uma entidade separada e está localizado no nó de controle.

Primeiro, vamos ver se o roteamento funciona:

$ ping 10.0.2.8
PING 10.0.2.8 (10.0.2.8): 56 data bytes
64 bytes from 10.0.2.8: seq=0 ttl=63 time=7.727 ms
64 bytes from 10.0.2.8: seq=1 ttl=63 time=3.832 ms
^C
--- 10.0.2.8 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 3.832/5.779/7.727 ms

Como neste caso o pacote deve ir até o gateway e ser roteado lá, precisamos descobrir o endereço poppy do gateway, para o qual olhamos a tabela ARP na instância:

$ arp
host-10-0-1-254.openstacklocal (10.0.1.254) at fa:16:3e:c4:64:70 [ether]  on eth0
host-10-0-1-1.openstacklocal (10.0.1.1) at fa:16:3e:e6:2c:5c [ether]  on eth0
host-10-0-1-90.openstacklocal (10.0.1.90) at fa:16:3e:83:ad:a4 [ether]  on eth0
host-10-0-1-88.openstacklocal (10.0.1.88) at fa:16:3e:72:ad:53 [ether]  on eth0

Agora vamos ver para onde deve ser enviado o tráfego com destino (10.0.1.254) fa:16:3e:c4:64:70:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-appctl fdb/show br-int | egrep fa:16:3e:c4:64:70
    2     1  fa:16:3e:c4:64:70    0
[heat-admin@overcloud-novacompute-0 ~]$ 

Vejamos onde a porta 2 leva:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl show br-int | grep addr
 1(int-br-ex): addr:7e:7f:28:1f:bd:54
 2(patch-tun): addr:0a:bd:07:69:58:d9
 3(qvo95d96a75-a0): addr:ea:50:9a:3d:69:58
 6(qvo5bd37136-47): addr:9a:d1:03:50:3d:96
 LOCAL(br-int): addr:1a:0f:53:97:b1:49
[heat-admin@overcloud-novacompute-0 ~]$ 

Tudo é lógico, o trânsito vai para br-tun. Vamos ver em qual túnel vxlan ele será envolvido:

[heat-admin@overcloud-novacompute-0 ~]$ sudo ovs-ofctl dump-flows br-tun | grep fa:16:3e:c4:64:70
 cookie=0x8759a56536b67a8e, duration=3514.566s, table=20, n_packets=3368, n_bytes=317072, hard_timeout=300, idle_age=0, hard_age=0, priority=1,vlan_tci=0x0001/0x0fff,dl_dst=fa:16:3e:c4:64:70 actions=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:3
[heat-admin@overcloud-novacompute-0 ~]$ 

A terceira porta é um túnel vxlan:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl show br-tun | grep addr
 1(patch-int): addr:a2:69:00:c5:fa:ba
 2(vxlan-c0a8ff1a): addr:86:f0:ce:d0:e8:ea
 3(vxlan-c0a8ff13): addr:72:aa:73:2c:2e:5b
 LOCAL(br-tun): addr:a6:cb:cd:72:1c:45
[heat-admin@overcloud-controller-0 ~]$ 

Que olha para o nó de controle:

[heat-admin@overcloud-controller-0 ~]$ sudo sudo ovs-appctl dpif/show | grep vxlan-c0a8ff1a
    vxlan-c0a8ff1a 2/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.26)
[heat-admin@overcloud-controller-0 ~]$ 

O tráfego chegou ao nó de controle, então precisamos ir até ele e ver como acontecerá o roteamento.

Como você se lembra, o nó de controle interno parecia exatamente igual ao nó de computação - as mesmas três pontes, apenas o br-ex tinha uma porta física através da qual o nó poderia enviar tráfego para fora. A criação de instâncias alterou a configuração dos nós de computação - linux bridge, iptables e interfaces foram adicionados aos nós. A criação de redes e de um roteador virtual também deixou sua marca na configuração do nó de controle.

Portanto, é óbvio que o endereço MAC do gateway deve estar na tabela de encaminhamento br-int do nó de controle. Vamos verificar se ele está lá e para onde está olhando:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl fdb/show br-int | grep fa:16:3e:c4:64:70
    5     1  fa:16:3e:c4:64:70    1
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$  sudo ovs-ofctl show br-int | grep addr
 1(int-br-ex): addr:2e:58:b6:db:d5:de
 2(patch-tun): addr:06:41:90:f0:9e:56
 3(tapca25a97e-64): addr:fa:16:3e:e6:2c:5c
 4(tap22015e46-0b): addr:fa:16:3e:76:c2:11
 5(qr-0c52b15f-8f): addr:fa:16:3e:c4:64:70
 6(qr-92fa49b5-54): addr:fa:16:3e:80:13:72
 LOCAL(br-int): addr:06:de:5d:ed:44:44
[heat-admin@overcloud-controller-0 ~]$ 

O Mac é visível na porta qr-0c52b15f-8f. Se voltarmos à lista de portas virtuais no Openstack, este tipo de porta é usada para conectar vários dispositivos virtuais ao OVS. Para ser mais preciso, qr é uma porta para o roteador virtual, que é representado como um namespace.

Vamos ver quais namespaces estão no servidor:

[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns
qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe (id: 2)
qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638 (id: 1)
qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 (id: 0)
[heat-admin@overcloud-controller-0 ~]$ 

Até três cópias. Mas a julgar pelos nomes, você pode adivinhar o propósito de cada um deles. Voltaremos às instâncias com ID 0 e 1 posteriormente, agora estamos interessados ​​no namespace qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe:


[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns exec qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe ip route
10.0.1.0/24 dev qr-0c52b15f-8f proto kernel scope link src 10.0.1.254 
10.0.2.0/24 dev qr-92fa49b5-54 proto kernel scope link src 10.0.2.254 
[heat-admin@overcloud-controller-0 ~]$ 

Este namespace contém dois internos que criamos anteriormente. Ambas as portas virtuais foram adicionadas ao br-int. Vamos verificar o endereço mac da porta qr-0c52b15f-8f, pois o tráfego, a julgar pelo endereço mac de destino, foi para esta interface.

[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns exec qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe ifconfig qr-0c52b15f-8f
qr-0c52b15f-8f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.0.1.254  netmask 255.255.255.0  broadcast 10.0.1.255
        inet6 fe80::f816:3eff:fec4:6470  prefixlen 64  scopeid 0x20<link>
        ether fa:16:3e:c4:64:70  txqueuelen 1000  (Ethernet)
        RX packets 5356  bytes 427305 (417.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5195  bytes 490603 (479.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[heat-admin@overcloud-controller-0 ~]$ 

Ou seja, neste caso tudo funciona de acordo com as leis do roteamento padrão. Como o tráfego é destinado ao host 10.0.2.8, ele deve sair pela segunda interface qr-92fa49b5-54 e passar pelo túnel vxlan até o nó de computação:


[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns exec qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe arp
Address                  HWtype  HWaddress           Flags Mask            Iface
10.0.1.88                ether   fa:16:3e:72:ad:53   C                     qr-0c52b15f-8f
10.0.1.90                ether   fa:16:3e:83:ad:a4   C                     qr-0c52b15f-8f
10.0.2.8                 ether   fa:16:3e:6c:ad:9c   C                     qr-92fa49b5-54
10.0.2.42                ether   fa:16:3e:f5:0b:29   C                     qr-92fa49b5-54
10.0.1.85                ether   fa:16:3e:44:98:20   C                     qr-0c52b15f-8f
[heat-admin@overcloud-controller-0 ~]$ 

Tudo é lógico, sem surpresas. Vamos ver onde o endereço poppy do host 10.0.2.8 é visível em br-int:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-appctl fdb/show br-int | grep fa:16:3e:6c:ad:9c
    2     2  fa:16:3e:6c:ad:9c    1
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl show br-int | grep addr
 1(int-br-ex): addr:2e:58:b6:db:d5:de
 2(patch-tun): addr:06:41:90:f0:9e:56
 3(tapca25a97e-64): addr:fa:16:3e:e6:2c:5c
 4(tap22015e46-0b): addr:fa:16:3e:76:c2:11
 5(qr-0c52b15f-8f): addr:fa:16:3e:c4:64:70
 6(qr-92fa49b5-54): addr:fa:16:3e:80:13:72
 LOCAL(br-int): addr:06:de:5d:ed:44:44
[heat-admin@overcloud-controller-0 ~]$ 

Como esperado, o tráfego vai para br-tun, vamos ver para qual túnel o tráfego vai em seguida:

[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl dump-flows br-tun | grep fa:16:3e:6c:ad:9c
 cookie=0x2ab04bf27114410e, duration=5346.829s, table=20, n_packets=5248, n_bytes=498512, hard_timeout=300, idle_age=0, hard_age=0, priority=1,vlan_tci=0x0002/0x0fff,dl_dst=fa:16:3e:6c:ad:9c actions=load:0->NXM_OF_VLAN_TCI[],load:0x63->NXM_NX_TUN_ID[],output:2
[heat-admin@overcloud-controller-0 ~]$
[heat-admin@overcloud-controller-0 ~]$ sudo ovs-ofctl show br-tun | grep addr
 1(patch-int): addr:a2:69:00:c5:fa:ba
 2(vxlan-c0a8ff1a): addr:86:f0:ce:d0:e8:ea
 3(vxlan-c0a8ff13): addr:72:aa:73:2c:2e:5b
 LOCAL(br-tun): addr:a6:cb:cd:72:1c:45
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-controller-0 ~]$ sudo sudo ovs-appctl dpif/show | grep vxlan-c0a8ff1a
    vxlan-c0a8ff1a 2/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.26)
[heat-admin@overcloud-controller-0 ~]$ 

O tráfego entra no túnel para computar-1. Bem, tudo é simples no compute-1 - do br-tun o pacote vai para o br-int e de lá para a interface da máquina virtual:

[heat-admin@overcloud-controller-0 ~]$ sudo sudo ovs-appctl dpif/show | grep vxlan-c0a8ff1a
    vxlan-c0a8ff1a 2/5: (vxlan: egress_pkt_mark=0, key=flow, local_ip=192.168.255.15, remote_ip=192.168.255.26)
[heat-admin@overcloud-controller-0 ~]$ 
[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-appctl fdb/show br-int | grep fa:16:3e:6c:ad:9c
    4     2  fa:16:3e:6c:ad:9c    1
[heat-admin@overcloud-novacompute-1 ~]$ sudo ovs-ofctl show br-int | grep addr                  
 1(int-br-ex): addr:8a:d7:f9:ad:8c:1d
 2(patch-tun): addr:46:cc:40:bd:20:da
 3(qvoe7e23f1b-07): addr:12:78:2e:34:6a:c7
 4(qvo3210e8ec-c0): addr:7a:5f:59:75:40:85
 LOCAL(br-int): addr:e2:27:b2:ed:14:46
[heat-admin@overcloud-novacompute-1 ~]$ 

Vamos verificar se esta é realmente a interface correta:

[heat-admin@overcloud-novacompute-1 ~]$ brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02429c001e1c       no
qbr3210e8ec-c0          8000.ea27f45358be       no              qvb3210e8ec-c0
                                                        tap3210e8ec-c0
qbre7e23f1b-07          8000.b26ac0eded8a       no              qvbe7e23f1b-07
                                                        tape7e23f1b-07
[heat-admin@overcloud-novacompute-1 ~]$ 
[heat-admin@overcloud-novacompute-1 ~]$ sudo virsh domiflist instance-00000004
Interface  Type       Source     Model       MAC
-------------------------------------------------------
tap3210e8ec-c0 bridge     qbr3210e8ec-c0 virtio      fa:16:3e:6c:ad:9c

[heat-admin@overcloud-novacompute-1 ~]$

Na verdade, analisamos todo o pacote. Acho que você percebeu que o tráfego passou por diferentes túneis vxlan e saiu com diferentes VNIs. Vamos ver que tipo de VNI são esses, após o que coletaremos um dump na porta de controle do nó e garantiremos que o tráfego flua exatamente como descrito acima.
Portanto, o túnel para computar-0 possui as seguintes ações=load:0->NXM_OF_VLAN_TCI[],load:0x16->NXM_NX_TUN_ID[],output:3. Vamos converter 0x16 para o sistema numérico decimal:


0x16 = 6*16^0+1*16^1 = 6+16 = 22

O túnel para computar-1 tem o seguinte VNI:actions=load:0->NXM_OF_VLAN_TCI[],load:0x63->NXM_NX_TUN_ID[],output:2. Vamos converter 0x63 para o sistema numérico decimal:


0x63 = 3*16^0+6*16^1 = 3+96 = 99

Bem, agora vamos dar uma olhada no despejo:

[root@hp-gen9 bormoglotx]# tcpdump -vvv -i vnet4 
tcpdump: listening on vnet4, link-type EN10MB (Ethernet), capture size 262144 bytes

*****************omitted*******************

04:35:18.709949 IP (tos 0x0, ttl 64, id 48650, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.19.41591 > 192.168.255.15.4789: [no cksum] VXLAN, flags [I] (0x08), vni 22
IP (tos 0x0, ttl 64, id 49042, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.1.85 > 10.0.2.8: ICMP echo request, id 5378, seq 9, length 64
04:35:18.710159 IP (tos 0x0, ttl 64, id 23360, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.15.38983 > 192.168.255.26.4789: [no cksum] VXLAN, flags [I] (0x08), vni 99
IP (tos 0x0, ttl 63, id 49042, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.1.85 > 10.0.2.8: ICMP echo request, id 5378, seq 9, length 64
04:35:18.711292 IP (tos 0x0, ttl 64, id 43596, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.26.42588 > 192.168.255.15.4789: [no cksum] VXLAN, flags [I] (0x08), vni 99
IP (tos 0x0, ttl 64, id 55103, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.2.8 > 10.0.1.85: ICMP echo reply, id 5378, seq 9, length 64
04:35:18.711531 IP (tos 0x0, ttl 64, id 8555, offset 0, flags [DF], proto UDP (17), length 134)
    192.168.255.15.38983 > 192.168.255.19.4789: [no cksum] VXLAN, flags [I] (0x08), vni 22
IP (tos 0x0, ttl 63, id 55103, offset 0, flags [none], proto ICMP (1), length 84)
    10.0.2.8 > 10.0.1.85: ICMP echo reply, id 5378, seq 9, length 64
	
*****************omitted*******************

O primeiro pacote é um pacote vxlan do host 192.168.255.19 (compute-0) para o host 192.168.255.15 (control-1) com vni 22, dentro do qual um pacote ICMP é empacotado do host 10.0.1.85 para o host 10.0.2.8. Conforme calculamos acima, vni corresponde ao que vimos na saída.

O segundo pacote é um pacote vxlan do host 192.168.255.15 (control-1) para o host 192.168.255.26 (compute-1) com vni 99, dentro do qual um pacote ICMP é empacotado do host 10.0.1.85 para o host 10.0.2.8. Conforme calculamos acima, vni corresponde ao que vimos na saída.

Os próximos dois pacotes são tráfego de retorno de 10.0.2.8 e não de 10.0.1.85.

Ou seja, no final obtivemos o seguinte esquema de nó de controle:

Introdução à parte de rede da infraestrutura em nuvem

Parece que é isso? Esquecemos de dois namespaces:

[heat-admin@overcloud-controller-0 ~]$ sudo  ip netns
qrouter-0a4d2420-4b9c-46bd-aec1-86a1ef299abe (id: 2)
qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638 (id: 1)
qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 (id: 0)
[heat-admin@overcloud-controller-0 ~]$ 

Como falamos sobre a arquitetura da plataforma em nuvem, seria bom se as máquinas recebessem endereços automaticamente de um servidor DHCP. Estes são dois servidores DHCP para nossas duas redes 10.0.1.0/24 e 10.0.2.0/24.

Vamos verificar se isso é verdade. Há apenas um endereço neste namespace - 10.0.1.1 - o endereço do próprio servidor DHCP, e também está incluído no br-int:

[heat-admin@overcloud-controller-0 ~]$ sudo ip netns exec qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 ifconfig
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 1  bytes 28 (28.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1  bytes 28 (28.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tapca25a97e-64: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.0.1.1  netmask 255.255.255.0  broadcast 10.0.1.255
        inet6 fe80::f816:3eff:fee6:2c5c  prefixlen 64  scopeid 0x20<link>
        ether fa:16:3e:e6:2c:5c  txqueuelen 1000  (Ethernet)
        RX packets 129  bytes 9372 (9.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 49  bytes 6154 (6.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Vamos ver se os processos contendo qdhcp-67a3798c-32c0-4c18-8502-2531247e3cc2 em seu nome no nó de controle:


[heat-admin@overcloud-controller-0 ~]$ ps -aux | egrep qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638 
root      640420  0.0  0.0   4220   348 ?        Ss   11:31   0:00 dumb-init --single-child -- ip netns exec qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638 /usr/sbin/dnsmasq -k --no-hosts --no-resolv --pid-file=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/pid --dhcp-hostsfile=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/host --addn-hosts=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/addn_hosts --dhcp-optsfile=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/opts --dhcp-leasefile=/var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/leases --dhcp-match=set:ipxe,175 --local-service --bind-dynamic --dhcp-range=set:subnet-335552dd-b35b-456b-9df0-5aac36a3ca13,10.0.2.0,static,255.255.255.0,86400s --dhcp-option-force=option:mtu,1450 --dhcp-lease-max=256 --conf-file= --domain=openstacklocal
heat-ad+  951620  0.0  0.0 112944   980 pts/0    S+   18:50   0:00 grep -E --color=auto qdhcp-7d541e74-1c36-4e1d-a7c4-0968c8dbc638
[heat-admin@overcloud-controller-0 ~]$ 

Existe tal processo e com base nas informações apresentadas no output acima, podemos, por exemplo, ver o que temos atualmente para alugar:

[heat-admin@overcloud-controller-0 ~]$ cat /var/lib/neutron/dhcp/7d541e74-1c36-4e1d-a7c4-0968c8dbc638/leases
1597492111 fa:16:3e:6c:ad:9c 10.0.2.8 host-10-0-2-8 01:fa:16:3e:6c:ad:9c
1597491115 fa:16:3e:76:c2:11 10.0.2.1 host-10-0-2-1 *
[heat-admin@overcloud-controller-0 ~]$

Como resultado, obtemos o seguinte conjunto de serviços no nó de controle:

Introdução à parte de rede da infraestrutura em nuvem

Bem, lembre-se: são apenas 4 máquinas, 2 redes internas e um roteador virtual... Não temos redes externas aqui agora, vários projetos diferentes, cada um com suas próprias redes (sobrepostas), e temos um roteador distribuído foi desligado e, no final, havia apenas um nó de controle na bancada de testes (para tolerância a falhas deve haver um quorum de três nós). É lógico que no comércio tudo é “um pouco” mais complicado, mas neste exemplo simples entendemos como deve funcionar - se você tem 3 ou 300 namespaces é claro que é importante, mas do ponto de vista do funcionamento de todo o estrutura, nada mudará muito... embora até você não conecte algum SDN de fornecedor. Mas essa é uma história completamente diferente.

Espero que tenha sido interessante. Se você tiver algum comentário/acréscimo, ou em algum lugar onde eu menti abertamente (sou humano e minha opinião sempre será subjetiva) - escreva o que precisa ser corrigido/adicionado - nós corrigiremos/acrescentaremos tudo.

Concluindo, gostaria de dizer algumas palavras sobre a comparação do Openstack (tanto vanilla quanto de fornecedor) com a solução em nuvem da VMWare - essa pergunta me foi feita com muita frequência nos últimos anos e, falando francamente, estou já cansado disso, mas ainda assim. Na minha opinião é muito difícil comparar estas duas soluções, mas podemos dizer com certeza que existem desvantagens em ambas as soluções e ao escolher uma solução é necessário pesar os prós e os contras.

Se o OpenStack é uma solução voltada para a comunidade, então a VMWare tem o direito de fazer apenas o que quiser (leia - o que é lucrativo para ela) e isso é lógico - porque é uma empresa comercial acostumada a ganhar dinheiro com seus clientes. Mas há um grande e gordo MAS - você pode sair do OpenStack, por exemplo da Nokia, e com poucas despesas mudar para uma solução de, por exemplo, Juniper (Contrail Cloud), mas é improvável que você consiga sair do VMWare . Para mim, essas duas soluções são assim - Openstack (fornecedor) é uma gaiola simples na qual você é colocado, mas você tem uma chave e pode sair a qualquer momento. VMWare é uma gaiola de ouro, o dono tem a chave da gaiola e isso vai custar muito caro.

Não estou promovendo nem o primeiro produto nem o segundo - você escolhe o que precisa. Mas se eu tivesse essa escolha, escolheria ambas as soluções - VMWare para a nuvem de TI (baixa carga, fácil gerenciamento), OpenStack de algum fornecedor (Nokia e Juniper fornecem soluções prontas para uso muito boas) - para a nuvem de Telecom. Eu não usaria o Openstack para TI pura - é como atirar em pardais com um canhão, mas não vejo nenhuma contra-indicação para usá-lo além da redundância. No entanto, usar VMWare em telecomunicações é como transportar pedra britada em um Ford Raptor - é bonito por fora, mas o motorista precisa fazer 10 viagens em vez de uma.

Na minha opinião, a maior desvantagem do VMWare é o seu total fechamento - a empresa não lhe dará nenhuma informação sobre como funciona, por exemplo, vSAN ou o que está no kernel do hipervisor - simplesmente não é lucrativo para isso - ou seja, você vai nunca se torne um especialista em VMWare - sem o suporte do fornecedor, você está condenado (muitas vezes encontro especialistas em VMWare que ficam perplexos com questões triviais). Para mim, VMWare é comprar um carro com o capô trancado - sim, você pode ter especialistas que podem trocar a correia dentada, mas só quem lhe vendeu essa solução pode abrir o capô. Pessoalmente, não gosto de soluções nas quais não consigo me encaixar. Você dirá que talvez não precise entrar nos bastidores. Sim, isso é possível, mas olharei para você quando precisar montar uma grande função na nuvem de 20 a 30 máquinas virtuais, 40 a 50 redes, metade das quais deseja sair e a segunda metade pede Aceleração SR-IOV, caso contrário, você precisará de mais algumas dúzias desses carros - caso contrário, o desempenho não será suficiente.

Existem outros pontos de vista, então só você pode decidir o que escolher e, o mais importante, você será responsável pela sua escolha. Esta é apenas a minha opinião - uma pessoa que viu e tocou em pelo menos 4 produtos - Nokia, Juniper, Red Hat e VMWare. Ou seja, tenho algo para comparar.

Fonte: habr.com

Adicionar um comentário