Armazenamento em cache remoto

Informar um problema Mostrar fonte Por noite · 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Nesta página, abordamos o armazenamento em cache remoto, a configuração de um servidor para hospedar o cache e compilações em execução usando o cache remoto.

Um cache remoto é usado por uma equipe de desenvolvedores e/ou por uma integração contínua (CI) para compartilhar saídas de build. Se sua versão for reproduzível, o as saídas de uma máquina podem ser reutilizadas com segurança em outra, o que pode a tornar os builds significativamente mais rápidos.

Visão geral

Ele divide um build em etapas distintas, que são chamadas de ações. Cada ação tem entradas, nomes de saída, uma linha de comando e variáveis de ambiente. Obrigatório entradas e saídas esperadas são declaradas explicitamente para cada ação.

É possível configurar um servidor como cache remoto para saídas de build, que são saídas de ação. Essas saídas consistem em uma lista de nomes de arquivos de saída e hashes do conteúdo deles. Com um cache remoto, é possível reutilizar saídas de compilação com base no build de outro usuário, em vez de criar cada nova saída localmente.

Para usar o armazenamento em cache remoto:

  • Configurar um servidor como back-end do cache
  • Configurar a compilação do Bazel para usar o cache remoto
  • Usar o Bazel versão 0.10.0 ou mais recente

O cache remoto armazena dois tipos de dados:

  • O cache de ações, que é um mapa de hashes de ação para metadados de resultados de ações.
  • Um armazenamento endereçável de conteúdo (CAS) de arquivos de saída.

Observe que o cache remoto também armazena stdout e stderr para cada à ação. Portanto, inspecionar o stdout/stderr do Bazel não é um bom sinal para estimativa de ocorrências em cache.

Como um build usa o armazenamento em cache remoto

Depois que um servidor é definido como cache remoto, ele é usado em várias maneiras:

  • Ler e gravar no cache remoto
  • Ler e/ou gravar no cache remoto, exceto destinos específicos
  • Ler apenas do cache remoto
  • Não usar o cache remoto

Quando você executa uma versão do Bazel capaz de ler e gravar no cache remoto, O build segue estas etapas:

  1. O Bazel cria o gráfico de destinos que precisam ser compilados e depois cria uma lista de ações necessárias. Cada uma dessas ações declarou entradas e nomes de arquivos de saída.
  2. O Bazel verifica se há saídas de build na sua máquina local e reutiliza qualquer que ele encontrar.
  3. O Bazel verifica o cache para saídas de build atuais. Se a saída for encontrada, O Bazel recupera a saída. Isso é uma ocorrência em cache.
  4. Para as ações necessárias em que as saídas não foram encontradas, o Bazel executa a ações localmente e cria as saídas de compilação necessárias.
  5. Novas saídas de compilação são enviadas para o cache remoto.

Configurar um servidor como back-end do cache

Você precisa configurar um servidor para atuar como back-end do cache. Uma solicitação HTTP/1.1 pode tratar os dados dele como bytes opacos, e muitos outros servidores pode ser usado como back-end de armazenamento em cache remoto. do Bazel O protocolo de armazenamento em cache HTTP é o que dá suporte a recursos armazenamento em cache.

Você é responsável por escolher, configurar e manter o back-end de destino que vai armazenar as saídas em cache. Ao escolher um servidor, considere:

  • Velocidade da rede. Por exemplo, se sua equipe está no mesmo escritório, você pode quiser executar seu próprio servidor local.
  • Segurança. O cache remoto terá seus binários e, portanto, precisa ser seguro.
  • Facilidade de gerenciamento. Por exemplo, o Google Cloud Storage é um serviço totalmente gerenciado.

Há muitos back-ends que podem ser usados para um cache remoto. Veja algumas opções:

nginx

O nginx é um servidor da Web de código aberto. Com o [módulo WebDAV], pode ser usado como cache remoto para o Bazel. No Debian e no Ubuntu, é possível instalar nginx-extras. No macOS, o nginx está disponível via Homebrew:

brew tap denji/nginx
brew install nginx-full --with-webdav

Veja abaixo um exemplo de configuração para o nginx. Você precisará Mude /path/to/cache/dir para um diretório válido em que o nginx tenha permissão para gravar e ler. Talvez seja necessário mudar a opção client_max_body_size para uma um valor maior se você tiver arquivos de saída maiores. O servidor exige outras como a autenticação.

Exemplo de configuração para a seção server em nginx.conf:

location /cache/ {
  # The path to the directory where nginx should store the cache contents.
  root /path/to/cache/dir;
  # Allow PUT
  dav_methods PUT;
  # Allow nginx to create the /ac and /cas subdirectories.
  create_full_put_path on;
  # The maximum size of a single file.
  client_max_body_size 1G;
  allow all;
}

Bazel-remote

O bazel-remote é um cache de build remoto de código aberto que pode ser usado em sua infraestrutura. Ele já foi usado em produção de várias empresas desde o início de 2018. Observe que o projeto Bazel não fornecer suporte técnico para o bazel-remote.

Esse cache armazena conteúdos no disco e também fornece a coleta de lixo aplicar um limite superior de armazenamento e limpar os artefatos não utilizados. O cache é disponível como [docker image] e seu código está disponível GitHub. As APIs de cache remoto REST e gRPC são compatíveis.

Consulte a GitHub para conferir instruções de uso.

Google Cloud Storage

O [Google Cloud Storage] é um armazenamento de objetos totalmente gerenciado que oferece uma API HTTP compatível com o protocolo de armazenamento em cache remoto do Bazel. Ele exige que você tem uma conta do Google Cloud com faturamento ativado.

Para usar o Cloud Storage como cache:

  1. Crie um bucket de armazenamento. Selecione o local do bucket mais próximo de você, por exemplo, largura de banda da rede é importante para o cache remoto.

  2. Criar uma conta de serviço para o Bazel autenticar no Cloud Storage. Consulte Como criar uma conta de serviço.

  3. Gere uma chave JSON secreta e transmita-a ao Bazel para autenticação. Armazenamento a chave com segurança, já que qualquer pessoa com ela pode ler e gravar dados arbitrários de/para o bucket do GCS.

  4. Conecte-se ao Cloud Storage adicionando as seguintes sinalizações ao comando do Bazel:

    • Transmita o seguinte URL para o Bazel usando a flag: --remote_cache=https://storage.googleapis.com/bucket-name, em que bucket-name é o nome do bucket de armazenamento.
    • Transmita a chave de autenticação usando a sinalização: --google_credentials=/path/to/your/secret-key.json ou --google_default_credentials para usar a autenticação de aplicativos.
  5. É possível configurar o Cloud Storage para excluir arquivos antigos automaticamente. Para fazer isso, consulte Como gerenciar ciclos de vida de objetos.

Outros servidores

É possível configurar qualquer servidor HTTP/1.1 que ofereça suporte a PUT e GET como o endereço back-end. Os usuários relataram sucesso com back-ends de armazenamento em cache, como o Hazelcast, Apache httpd e AWS S3.

Autenticação

A partir da versão 0.11.0, o suporte à autenticação básica HTTP foi adicionado ao Bazel. É possível transmitir um nome de usuário e uma senha para o Bazel por meio do URL do cache remoto. O a sintaxe é https://username:password@hostname.com:port/path. Observe que A autenticação básica HTTP transmite o nome de usuário e a senha em texto simples pela e, por isso, é essencial usá-la sempre com HTTPS.

Protocolo de armazenamento em cache HTTP

O Bazel oferece suporte ao armazenamento em cache remoto via HTTP/1.1. O protocolo é conceitualmente simples: Os dados binários (BLOB) são enviados por solicitações PUT e baixados por solicitações GET. Os metadados do resultado da ação são armazenados no caminho /ac/, e os arquivos de saída são armazenados no caminho /cas/.

Por exemplo, considere um cache remoto executado em http://localhost:8080/cache. Uma solicitação ao Bazel para fazer o download de metadados de resultados de uma ação com o SHA256. O hash 01ba4719... ficará assim:

GET /cache/ac/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b HTTP/1.1
Host: localhost:8080
Accept: */*
Connection: Keep-Alive

Uma solicitação ao Bazel para fazer upload de um arquivo de saída com o hash SHA256 15e2b0d3... para o CAS ficará assim:

PUT /cache/cas/15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225 HTTP/1.1
Host: localhost:8080
Accept: */*
Content-Length: 9
Connection: Keep-Alive

0x310x320x330x340x350x360x370x380x39

Executar o Bazel usando o cache remoto

Para usar o cache remoto depois que um servidor é configurado como cache remoto, é necessário adicionar flags ao comando do Bazel. Consulte a lista de configurações e as sinalizações abaixo.

Talvez você também precise configurar a autenticação, que é específica para seu servidor escolhido.

Adicione essas sinalizações a um arquivo .bazelrc para não adicionar precisa especificá-los toda vez que executar o Bazel. Dependendo do seu projeto e dinâmica de equipe, é possível adicionar flags a um arquivo .bazelrc que seja:

  • Na sua máquina local
  • No espaço de trabalho do seu projeto, compartilhado com a equipe
  • No sistema de CI

Ler e gravar no cache remoto

Confira quem pode fazer gravações no cache remoto. Talvez você queira apenas o sistema de CI possa fazer gravações no cache remoto.

Use a flag a seguir para ler e gravar no cache remoto:

build --remote_cache=http://your.host:port

Além de HTTP, os seguintes protocolos também são compatíveis: HTTPS, grpc e grpcs.

Além da sinalização acima, use a sinalização a seguir para ler somente os cache remoto:

build --remote_upload_local_results=false

Impedir que destinos específicos usem o cache remoto

Para impedir que destinos específicos usem o cache remoto, marque-os com uma tag no-remote-cache: Exemplo:

java_library(
    name = "target",
    tags = ["no-remote-cache"],
)

Excluir conteúdo do cache remoto

Excluir conteúdo do cache remoto faz parte do gerenciamento do seu servidor. A maneira como você exclui conteúdo do cache remoto depende do servidor que você tem configuradas como cache. Ao excluir saídas, exclua todo o cache, ou excluir saídas antigas.

As saídas em cache são armazenadas como um conjunto de nomes e hashes. Ao excluir não é possível distinguir qual saída pertence a um ser construído.

Você pode excluir conteúdo do cache para:

  • Criar um cache limpo após um cache ser envenenado
  • Reduza a quantidade de armazenamento usada excluindo saídas antigas

Soquetes Unix

O cache HTTP remoto oferece suporte à conexão por soquetes de domínio Unix. O comportamento é semelhante à sinalização --unix-socket do curl. Use o código a seguir para configurar o Unix socket de domínio:

   build --remote_cache=http://your.host:port
   build --remote_cache_proxy=unix:/path/to/socket

Esse recurso não é compatível com o Windows.

Cache de disco

O Bazel pode usar um diretório no sistema de arquivos como um cache remoto. Isso é útil para compartilhar artefatos de build ao alternar ramificações e/ou trabalhar em vários espaços de trabalho do mesmo projeto, como várias finalizações de compra. Como Como o Bazel não faz a coleta de lixo do diretório, automatize periódica desse diretório. Ative o cache de disco da seguinte forma:

build --disk_cache=path/to/build/cache

É possível transmitir um caminho específico do usuário à sinalização --disk_cache usando o alias ~. O Bazel vai substituir o diretório inicial do usuário atual. Isso é útil ao ativar o cache de disco para todos os desenvolvedores de um projeto por meio do fez check-in no arquivo .bazelrc.

Problemas conhecidos

Modificação do arquivo de entrada durante um build

Quando um arquivo de entrada é modificado durante um build, o Bazel pode fazer upload de arquivos no cache remoto. É possível ativar uma detecção de alterações com a sinalização --experimental_guard_against_concurrent_changes. não há problemas conhecidos e será ativado por padrão em uma versão futura. Consulte o [problema #3360] para conferir as atualizações. Evite modificar arquivos de origem durante uma ser construído.

Variáveis de ambiente vazando para uma ação

Uma definição de ação contém variáveis de ambiente. Isso pode ser um problema para o compartilhamento de ocorrências em cache remoto entre máquinas. Por exemplo, ambientes com variáveis $PATH diferentes não compartilham ocorrências em cache. Somente variáveis de ambiente explicitamente na lista de permissões via --action_env são incluídas em uma ação definição. Pacote Debian/Ubuntu do Bazel usado para instalar /etc/bazel.bazelrc com uma lista de permissões de variáveis de ambiente, incluindo $PATH. Se você estiver recebendo menos ocorrências em cache do que o esperado, verifique se o ambiente não tem uma versão /etc/bazel.bazelrc.

O Bazel não monitora ferramentas fora de um espaço de trabalho

No momento, o Bazel não monitora ferramentas fora de um espaço de trabalho. Pode ser um problema se, por exemplo, uma ação usar um compilador da /usr/bin/. Depois, dois usuários com diferentes compiladores instalados compartilharão incorretamente ocorrências em cache porque as saídas são diferentes, mas têm o mesmo hash de ação. Consulte problema 4558 para atualizações.

O estado incremental na memória é perdido ao executar builds dentro de contêineres do Docker Ele usa a arquitetura de servidor/cliente mesmo quando é executado em um único contêiner do Docker. No lado do servidor, o Bazel mantém um estado na memória que acelera os builds. Ao executar builds dentro de contêineres do Docker, como na CI, o estado na memória é perdido e o Bazel precisa recriá-lo antes de usar o cache remoto.