Sandbox

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

Este artigo aborda como fazer o sandbox no Bazel, instalar sandboxfs e depurar. seu ambiente de sandbox.

O sandbox é uma estratégia que restringe as permissões que isola os processos dos uns aos outros ou de recursos em um sistema. Para o Bazel, isso significa restringir o acesso ao sistema.

O sandbox do sistema de arquivos do Bazel executa processos em um diretório de trabalho que contém entradas conhecidas, de modo que compiladores e outras ferramentas não vejam o código-fonte arquivos que eles não devem acessar, a menos que saibam os caminhos absolutos para eles.

O sandbox não oculta o ambiente do host de forma alguma. Os processos podem acessar todos os arquivos no sistema de arquivos. No entanto, em plataformas que oferecem suporte ao namespaces, os processos não podem modificar nenhum arquivo fora do diretório de trabalho. Isso garante que o gráfico de build não tenha dependências ocultas que poderiam afetar a reprodutibilidade do build.

Mais especificamente, o Bazel constrói um diretório execroot/ para cada ação, que atua como o diretório de trabalho da ação no ambiente de execução. execroot/ contém todos os arquivos de entrada para a ação e serve como contêiner para qualquer das saídas geradas. O Bazel usa uma técnica fornecida pelo sistema operacional, contêineres no Linux e sandbox-exec no macOS, para restringir a ação no execroot/.

Motivos para usar o sandbox

  • Sem o sandbox de ações, o Bazel não sabe se uma ferramenta usa dados não declarados arquivos de entrada (arquivos que não estão explicitamente listados nas dependências de um ação). Quando um dos arquivos de entrada não declarados muda, o Bazel ainda acredita que a construção está atualizada e não recriará a ação. Isso pode resultam em um build incremental incorreto.

  • A reutilização incorreta de entradas de cache cria problemas durante o armazenamento em cache remoto. Um uma entrada de cache incorreta em um cache compartilhado afeta todos os desenvolvedores do projeto, e excluir permanentemente todo o cache remoto não é uma solução viável.

  • O sandbox imita o comportamento da execução remota, caso um build funcione bem. com sandbox, ele provavelmente também funcionará com a execução remota. Ao fazer a execução remota faz upload de todos os arquivos necessários (inclusive ferramentas locais), é possível de reduzir significativamente os custos de manutenção para clusters de compilação em comparação com sem precisar instalar as ferramentas em todas as máquinas do cluster querer testar um novo compilador ou fazer uma alteração em uma ferramenta existente.

Qual estratégia de sandbox usar

Você pode escolher que tipo de sandbox usar, se houver, com o sinalizações de estratégia. Como usar o sandboxed faz com que o Bazel escolha uma das implementações de sandbox listadas abaixo, preferir uma sandbox específica do SO ao menos hermético genérico. Os workers permanentes serão executados em um sandbox genérico se você passar a sinalização --worker_sandboxing.

A estratégia local (também conhecida como standalone) não faz nenhum tipo de sandbox. Ele simplesmente executa a linha de comando da ação com o diretório de trabalho definido como a execroot do seu espaço de trabalho.

processwrapper-sandbox é uma estratégia de sandbox que não requer nenhuma "avançado" recursos. Deve funcionar em qualquer sistema POSIX pronto para uso. Ela cria um diretório de sandbox que consiste em links simbólicos que apontam para o arquivos de origem, executa a linha de comando da ação com o conjunto de diretórios de trabalho para esse diretório em vez de execroot e, em seguida, move os artefatos de saída conhecidos do sandbox para o execroot e exclui o sandbox. Isso evita que de usar acidentalmente arquivos de entrada não declarados e do sobrecarregar o execroot com arquivos de saída desconhecidos.

linux-sandbox vai além e se baseia no processwrapper-sandbox. Semelhante ao que o Docker faz em segundo plano, ele usa Namespaces do Linux (namespaces de usuário, montagem, PID, rede e IPC) para isolar os do host. Ou seja, ele torna todo o sistema de arquivos somente leitura, exceto para o diretório do sandbox, para que a ação não possa modificar acidentalmente nada no no sistema de arquivos do host. Isso evita situações como um teste de bug com erro automático Use -rf no diretório $HOME. Também é possível impedir que a ação para acessar a rede. linux-sandbox usa namespaces PID para impedir a ação de ver quaisquer outros processos e eliminar com segurança todos os processos (até mesmo daemons geradas pela ação) no final.

O darwin-sandbox é semelhante, mas para macOS. Ele usa a ferramenta sandbox-exec da Apple. para ter praticamente o mesmo resultado que o sandbox do Linux.

Tanto o linux-sandbox quanto o darwin-sandbox não funcionam em um ambiente "aninhado" devido a restrições nos mecanismos fornecidos pelo sistema sistemas. Como o Docker também usa namespaces do Linux para o comando mágico de contêiner, não pode facilmente executar linux-sandbox dentro de um contêiner do Docker, a menos que você use docker run --privileged. No macOS, não é possível executar sandbox-exec em um que já está sendo colocado no sandbox. Nesses casos, o Bazel volta a usar processwrapper-sandbox automaticamente.

Se preferir receber um erro de compilação, por exemplo, para não criar acidentalmente com uma estratégia de execução menos rígida — modificar explicitamente a lista de execução estratégias que o Bazel tenta usar (por exemplo, bazel build --spawn_strategy=worker,linux-sandbox).

A execução dinâmica geralmente exige o uso do sandbox para execução local. Para desativar, transmita a sinalização --experimental_local_lockfree_output. Execução dinâmica silenciosa workers persistentes para sandboxes.

Desvantagens do sandbox

  • O sandbox tem custos adicionais de configuração e desmontagem. Qual é o tamanho desse custo depende de muitos fatores, incluindo o formato do build e o desempenho do SO do host. Para Linux, as versões em sandbox raramente passam do que alguns por cento mais devagar. Definir --reuse_sandbox_directories pode reduzir o custo de configuração e desmontagem.

  • O sandbox desativa efetivamente qualquer cache que a ferramenta possa ter. Você pode mitigar isso usando workers permanentes o custo de garantias mais fracas de sandbox.

  • Os workers multiplex exigem suporte explícito do worker para serem colocados no sandbox. Os workers que não oferecem suporte ao sandbox multiplex são executados como workers singleplex em execução dinâmica, o que pode aumentar o custo de memória.

sandboxfs

O sandboxfs é um sistema de arquivos FUSE que expõe uma visualização arbitrária dos objetos sistema de arquivos subjacente sem penalidades de tempo. O Bazel usa sandboxfs para gerar execroot/ instantaneamente para cada ação, evitando o custo de emitir milhares de chamadas do sistema. Observe que mais E/S dentro de execroot/ pode mais lento devido à sobrecarga do FUSE.

Instalar sandboxfs

Siga as etapas abaixo para instalar o sandboxfs e executar um build do Bazel com ele:

Fazer download

Fazer o download e instalar sandboxfs para que o binário sandboxfs fique no PATH.

Run sandboxfs

  1. (Somente macOS) Instale o OSXFUSE.
  2. (Somente macOS) Execute:

    sudo sysctl -w vfs.generic.osxfuse.tunables.allow_other=1
    

    Você precisará fazer isso após a instalação e após cada reinicialização para garantir serviços principais do sistema macOS funcionam com sandboxfs.

  3. Execute uma versão do Bazel com --experimental_use_sandboxfs.

    bazel build target --experimental_use_sandboxfs
    

Solução de problemas

Se você vir local em vez de darwin-sandbox ou linux-sandbox como uma para as ações executadas, isso pode significar que o sandbox está desativado. Transmita --genrule_strategy=sandboxed --spawn_strategy=sandboxed para ativá-la.

Depuração

Siga as estratégias abaixo para depurar problemas com o sandbox.

Namespaces desativados

Em algumas plataformas, como Google Kubernetes Engine (em inglês) nós de cluster ou Debian, os namespaces de usuário serão desativados por padrão devido a questões de segurança. Se o arquivo /proc/sys/kernel/unprivileged_userns_clone existe e contém um 0, é possível ativar namespaces de usuário executando:

   sudo sysctl kernel.unprivileged_userns_clone=1

Falhas na execução de regras

O sandbox pode não executar regras devido à configuração do sistema. Se aparecer um mensagem como namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory, tente desativar o sandbox com --strategy=Genrule=local para de regras gerais e --spawn_strategy=local para outras regras.

Depuração detalhada para falhas de build

Se o build falhar, use --verbose_failures e --sandbox_debug para fazer O Bazel mostra o comando exato que foi executado quando o build falhou, incluindo a parte que configura o sandbox.

Exemplo de mensagem de erro:

ERROR: path/to/your/project/BUILD:1:1: compilation of rule
'//path/to/your/project:all' failed:

Sandboxed execution failed, which may be legitimate (such as a compiler error),
or due to missing dependencies. To enter the sandbox environment for easier
debugging, run the following command in parentheses. On command failure, a bash
shell running inside the sandbox will then automatically be spawned

namespace-sandbox failed: error executing command
  (cd /some/path && \
  exec env - \
    LANG=en_US \
    PATH=/some/path/bin:/bin:/usr/bin \
    PYTHONPATH=/usr/local/some/path \
  /some/path/namespace-sandbox @/sandbox/root/path/this-sandbox-name.params --
  /some/path/to/your/some-compiler --some-params some-target)

Agora é possível inspecionar o diretório do sandbox gerado e ver quais arquivos o Bazel criou e execute o comando novamente para saber como ele se comporta.

O Bazel não exclui o diretório do sandbox quando você usa --sandbox_debug: A menos que você esteja depurando ativamente, desative --sandbox_debug porque ela enche o disco com o passar do tempo.