Olá!
Meu nome é Sergey, sou engenheiro de infraestrutura na equipe da API da plataforma tinkoff.ru.
Neste artigo, falarei sobre os problemas que nossa equipe enfrentou ao preparar balanceadores baseados em para vários projetos. Também apresentarei uma ferramenta que nos ajudou a superar a maior parte deles.
Nginx é um servidor proxy multifuncional e em constante evolução. Ele se destaca pela grande quantidade de módulos, . Cada projeto impõe requisitos específicos ao funcionalidade do balanceador e à versão do Nginx (por exemplo, a presença do http/2 e o proxying de grpc), bem como à composição de seus módulos.
Queremos ver uma versão atualizada com o conjunto de módulos necessário, funcionando sob uma distribuição específica do Linux. No nosso caso, são sistemas baseados em deb e rpm. A opção de contêineres não é considerada neste artigo.
Queremos alterar rapidamente a funcionalidade de nossos balanceadores. E aqui surge imediatamente a questão - como conseguir isso, gastando o mínimo de recursos? E seria ainda melhor estabelecer um processo onde pudéssemos definir um número fixo de parâmetros de entrada e obter, como resultado, um artefato na forma de um pacote deb/rpm para o sistema operacional desejado.
Assim, podemos formular uma série de problemas:
- Nem sempre há pacotes com a versão mais recente do Nginx.
- Não há pacotes com os módulos necessários.
- Compilar e montar o pacote manualmente consome muito tempo e é simplesmente cansativo.
- Não há descrição de como cada instância do Nginx foi compilada.
Para resolver esses problemas, surge a necessidade de uma ferramenta que aceitasse uma especificação em um formato legível e compilasse um pacote Nginx com a funcionalidade necessária com base nessa especificação.
Não encontrando uma opção adequada para nós nas vastidões do GitHub, decidimos criar nossa própria ferramenta - .
Especificações
Em nossa ferramenta, queríamos criar uma descrição da especificação em forma de código, que então poderia ser armazenada em um repositório Git. Para isso, escolhemos um formato familiar para esse tipo de coisa - yaml. Exemplo de especificação:
nginx_version: 1.14.1
output_package: deb
modules:
- module:
name: nginx-auth-ldap
git_url: https://github.com/kvspb/nginx-auth-ldap.git
git_branch: master
dependencies:
- libldap2-dev
- module:
name: ngx_http_substitutions_filter_module
git_url: https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git
- module:
name: headers-more-nginx-module
web_url: https://github.com/openresty/headers-more-nginx-module/archive/v0.261.zip
- module:
name: nginx-module-vts
git_url: https://github.com/vozlt/nginx-module-vts.git
git_tag: v0.1.18
- module:
name: ngx_devel_kit
git_url: https://github.com/simplresty/ngx_devel_kit.git
git_tag: v0.3.0
- module:
name: ngx_cache_purge
git_url: https://github.com/FRiCKLE/ngx_cache_purge.git
- module:
name: ngx_http_dyups_module
git_url: https://github.com/yzprofile/ngx_http_dyups_module.git
- module:
name: nginx-brotli
git_url: https://github.com/eustas/ngx_brotli.git
git_tag: v0.1.2
- module:
name: nginx_upstream_check_module
git_url: https://github.com/yaoweibin/nginx_upstream_check_module.git
- module:
name: njs
git_url: https://github.com/nginx/njs.git
git_tag: 0.2.5
config_folder_path: nginx
Aqui, indicamos que queremos ver o pacote deb com a versão Nginx 1.14.2 e o conjunto necessário de módulos. A seção de módulos é opcional. Para cada um deles, é possível especificar:
- Nome.
- Endereço onde pode ser obtido:
- Repositório Git. É possível também especificar o branch ou tag.
- Link da web para o arquivo compactado.
- Link local para o arquivo compactado.
Alguns módulos requerem a instalação de dependências adicionais, por exemplo, para o nginx-auth-ldap é necessário ter o libldap2-dev instalado. As dependências necessárias também podem ser especificadas ao descrever o módulo.
Ambiente
Em nossa ferramenta, é possível rapidamente obter um ambiente com as utilidades necessárias para compilar, construir pacotes e outros softwares auxiliares. O contêiner Docker com tudo necessário é a melhor escolha (já existem alguns exemplos de arquivos Docker no repositório para ubuntu e centos).
Depois que a especificação está elaborada e o ambiente preparado, iniciamos nosso construtor, instalando previamente suas dependências:
pip3 install -r requirements.txt
./main.py build -f [config_file].yaml -r [revision_number]
O número de revisão aqui é opcional e serve para versionar as compilações. Ele é registrado nas metadatas do pacote, o que permite atualizá-lo facilmente nos servidores.
É possível acompanhar o que está acontecendo pelos logs. Aqui está um exemplo dos principais pontos:
builder - INFO - Analisando arquivo yaml: example.config.yaml
builder - INFO - Baixando scripts para pacote deb de compilação
builder - INFO - Baixando src do nginx...
builder - INFO - --> http://nginx.org/download/nginx-1.14.1.tar.gz
builder - INFO - Baixando módulos de terceiros...
builder - INFO - O módulo nginx-auth-ldap será baixado por branch
builder - INFO - -- Concluído: nginx-auth-ldap
builder - INFO - -- Concluído: ngx_http_substitutions_filter_module
builder - INFO - O módulo headers-more-nginx-module será baixado
builder - INFO - O módulo nginx-module-vts será baixado por tag
builder - INFO - -- Concluído: nginx-module-vts
builder - INFO - O módulo ngx_devel_kit será baixado por tag
builder - INFO - -- Concluído: ngx_devel_kit
builder - INFO - -- Concluído: ngx_cache_purge
builder - INFO - -- Concluído: ngx_http_dyups_module
builder - INFO - Baixando dependências
builder - INFO - Criando pacote .deb
builder - INFO - Executando 'dh_make'...
builder - INFO - Executando 'dpkg-buildpackage'...
dpkg-deb: criando pacote 'nginx' em '../nginx_1.14.1-1_amd64.deb'.
Com apenas alguns comandos, criamos o ambiente e a montagem necessária do Nginx, e o pacote aparece no diretório de onde o script foi iniciado.
Incorporação
Também podemos incorporar nossa ferramenta em processos de CI/CD. Qualquer uma das muitas CI existentes atualmente pode ajudar, por exemplo ou .
Assim, a cada alteração na especificação no repositório Git, a construção do artefato é executada automaticamente. O número da revisão é vinculado ao contador de execuções de build.
Gastando um pouco mais de tempo, podemos configurar o envio do artefato para um repositório local de pacotes, Nexus, Artifactory e assim por diante.
Um benefício adicional é que o arquivo de configuração yaml pode ser integrado ao Ansible ou outro sistema de configuração automática, e de lá podemos pegar o número da versão e o tipo de pacote que desejamos implantar.
O que vem a seguir
O projeto ainda não está concluído. Aqui está no que estamos trabalhando agora:
- Estamos expandindo a capacidade de configuração, mas mantendo-a o mais simples possível. Não queremos definir mil parâmetros se precisamos apenas de dois, e o restante é adequado por padrão. Isso inclui os flags de compilação (atualmente, eles podem ser alterados no arquivo de configuração interno src/config.py), os caminhos de instalação e o usuário para execução.
- Adicionando opções de envio automático do pacote para vários repositórios de artefatos.
- Execução de comando do usuário ao carregar o módulo (por exemplo, para uso é necessário aplicar um patch de uma versão específica primeiro)
- Adicionando a execução de testes:
- O pacote é instalado corretamente.
- O Nginx tem a versão correta e foi compilado com os flags e módulos necessários.
- Os caminhos necessários, contas e assim por diante são criados.
Mas você já pode usar essa ferramenta agora e também sugerir melhorias — bem-vindo!
Fonte: habr.com
