
1. Introdução
Bom dia a todos. Sou desenvolvedor Python em uma empresa que lida com soluções complexas para automatizar processos de negócios, desenvolvendo para resolver tarefas únicas, análises e consultoria. Minhas responsabilidades incluem o desenvolvimento e manutenção da arquitetura de microsserviços. E hoje eu gostaria de dizer como estamos lutando com microsserviços e por que a unificação é tão importante para eles.
Não é segredo que essa abordagem para o desenvolvimento de produtos está cada vez mais capturando o mercado. E quanto mais mergulhamos neles, mais é necessário não esquecer as regras básicas para trabalhar com eles. Para estruturar nossa experiência na criação de produtos para microsserviços, foi decidido escrever uma série de artigos sobre como generalizar alguns aspectos do desenvolvimento para todos os serviços.
Uma dessas regras é a unificação. Em nossa empresa, a maioria dos produtos consiste em várias linguagens e tecnologias heterogêneas. Em todo esse estande, você deve pensar em como generalizar os princípios básicos de todos os microsserviços para facilitar o suporte, a configuração e o desenvolvimento conveniente. Isso será discutido na série desses artigos.
Peço a todos os interessados em gato.
O problema
Talvez a primeira coisa que você encontre no desenvolvimento de um serviço seja seus métodos de configuração. Na arquitetura de microsserviço, esse problema se torna ainda mais agudo.
Imagine que você tem duas dezenas de serviços e precisa alterar um parâmetro em cada um. Por exemplo, desative o uso do CORS. Como o sistema é multicomponente e construído em microsserviços, para um gerenciamento conveniente, é melhor usar uma abordagem uniforme na configuração de todos os módulos. Portanto, você precisa usar a mesma abordagem ao configurar cada módulo.
Você pode dizer que o desenvolvedor de cada serviço deve fazer isso, mas e se todas as suas configurações estiverem armazenadas no mesmo Kubernetes, onde não pode ser fornecido a todos os desenvolvedores? Os pobres DevOps serão forçados a gastar muito tempo apenas aprendendo os serviços e seus métodos de configuração. E esse procedimento será repetido com a atualização de serviços, especialmente se alguém quiser tentar algo novo nas configurações de serviço. Com essa abordagem, a equipe passa constantemente parte do tempo trabalhando com configurações e não desenvolvendo novos recursos, corrigindo bugs etc.
Apenas neste caso, é necessário um método de configuração geral que não esteja vinculado a um idioma ou tecnologia específica e permitirá que você configure todos os serviços com diferenças mínimas na estrutura geral da configuração. Para esta tarefa, desenvolvemos um sistema para configurar “módulos” (serviços) usando arquivos yaml, a capacidade de armazenar configurações para diferentes estágios (dev / prod / local etc) e dividir tudo em diferentes blocos relacionados a certas coisas.
Especificação
Você pode falar muito sobre onde e como usá-lo, mas proponho ir direto à especificação desse método de configuração. Como se costuma dizer, a teoria é boa e a prática é ainda melhor.
Requisitos de sistema
Vamos começar definindo nosso sistema e os requisitos para ele.
- Cada módulo é um componente independente no contêiner
- Podemos passar variáveis de ambiente para o contêiner
- Não podemos alterar a configuração em tempo real sem reiniciar o serviço (criando um novo contêiner).
- Todas as ações de fallback (como alternar para o banco de dados de backup) são executadas fora do componente e são transparentes para ele.
Requisitos do método de configuração
Agora vamos decidir o que queremos ver em nosso método de configuração para satisfazer todos os requisitos.
- O tipo do arquivo de configuração é o YAML da estrutura especificada. O YAML foi escolhido por nós por vários motivos:
- Capacidade de escrever comentários e uma estrutura conveniente, diferente do JSON
- Capacidade de descrever matrizes em contraste com ENV
- Fora da caixa pode ser usado para inclusão a partir de values.yaml no leme (Kubernetes)
- Os arquivos de configuração devem mesclar na árvore de configuração
- A configuração deve ser específica do estágio. Cada estágio tem seu próprio conjunto completo. Aqui vale a pena fazer algumas reservas para esclarecer:
- Você não pode reutilizar os valores das variáveis de outro estágio , exceto o estágio de padrões , que é reservado aos valores padrão.
- Ao carregar a configuração, é necessário fazer uma mesclagem recursiva da camada de configuração a partir do estágio especificado, além dos padrões, com a prioridade da camada do estágio especificado. Valores (matrizes, etc.) não devem ser combinados.
- Se houver vários arquivos de configuração para um estágio, as chaves neles deverão ser mescladas e, portanto, devem ser exclusivas uma em relação à outra.
- O estágio atual usado deve ser determinado pelo valor da variável de ambiente "STAGE". A alteração de uma variável em uma instância em execução de um serviço não é pretendida.
- O caminho absoluto para o diretório de configuração deve ser determinado pelo valor da variável de ambiente “CONFIG_PATH”. Por conveniência, é possível um fallback se não houver variável em um determinado caminho padrão, o que deve ser indicado na documentação do módulo. Nesse caso, o caminho especificado deve ser relativo à raiz do diretório do aplicativo.
Exemplos de configuração
Suponha que tenhamos um serviço que precise armazenar configurações para conectar-se ao Postgres, bem como algumas informações sobre nós mesmos
Primeiro, você precisa definir uma configuração para STAGE = padrões. Nele, descreveremos a estrutura geral, além de tornar os dados independentes do estágio.
padrões
# configuration/defaults/service.yaml defaults: version: 1.0.0 name: "config-example" # configuration/defaults/redis.yaml defaults: redis: host: "host" db: 0 port: 6379 password: "password"
dev
# configuration/dev/redis.yaml dev: redis: host: "localhost" password: "hard_pwd"
Configuração resultante
version: 1.0.0 name: "config-example" redis: host: "localhost" db: 0 port: 6379 password: "hard_pwd"
Conclusões
De uma maneira tão esperta, resolvemos o problema de configurar serviços em nosso zoológico e levamos tudo a uma visão comum. Este exemplo é apenas um ponto de partida e pode ser modificado para as especificidades do seu projeto.
Para aqueles que estão interessados neste método de configuração de forma simples:
Nossos pacotes para diferentes linguagens de programação Para que a ajuda por escrito se torne um agradecimento especial a
Roque ,
SMGladkovskiy