Construção Distribuída
A construção distribuída pode acelerar significativamente o processo de construção utilizando múltiplas máquinas. No entanto, para usuários comuns do NixOS, a construção distribuída pode não ser muito útil, já que o cache.nixos.org
fornece a grande maioria dos caches para a arquitetura x86_64
.
A construção distribuída é particularmente valiosa em cenários onde nenhum cache está disponível, tais como:
- Usuários de arquiteturas
RISC-V
ouARM64
, , especialmenteRISC-V
, pois há muito poucos caches para essas arquiteturas no repositório de cache oficial. A compilação local é frequentemente necessária. - Usuários que personalizam bastante seus sistemas. Os pacotes no repositório de cache oficial são construídos com configurações padrão. Se você modificar os parâmetros de construção, o cache oficial não é aplicável, e a compilação local é necessária. Por exemplo, em cenários de sistemas embarcados (embedded scenarios), a personalização do kernel subjacente, drivers, etc., é frequentemente exigida, levando à necessidade de compilação local.
Configurando a Construção Distribuída
Atualmente, não há documentação oficial para a construção distribuída. No entanto, forneci um exemplo de configuração de construção distribuída (um módulo NixOS) abaixo, junto com alguns documentos de referência recomendados no final desta seção.
nix
{ ... }: {
####################################################################
#
# Configuração do NixOS para Construção Remota / Construção Distribuída
#
####################################################################
# Definir o max-jobs local para 0 para forçar a construção remota (desabilitar a construção local).
# nix.settings.max-jobs = 0;
nix.distributedBuilds = true;
nix.buildMachines =
let
sshUser = "ryan";
# Caminho para a chave SSH na máquina local.
sshKey = "/home/ryan/.ssh/ai-idols";
systems = [
# Arquitetura nativa.
"x86_64-linux"
# Arquitetura emulada usando binfmt_misc e qemu-user.
"aarch64-linux"
"riscv64-linux"
];
# Todos os recursos de sistema disponíveis estão mal documentados aqui:
# https://github.com/NixOS/nix/blob/e503ead/src/libstore/globals.hh#L673-L687
supportedFeatures = [
"benchmark"
"big-parallel"
"kvm"
];
in
[
# O Nix parece sempre priorizar a construção remota.
# Para aproveitar a CPU de alto desempenho da máquina local, não defina o maxJobs do construtor remoto muito alto.
{
# Alguns dos meus construtores remotos estão rodando NixOS
# e têm o mesmo sshUser, sshKey, systems, etc.
inherit sshUser sshKey systems supportedFeatures;
# O hostName deve ser:
# 1. Um nome de host que pode ser resolvido por DNS.
# 2. O endereço IP do construtor remoto.
# 3. Um alias de host definido globalmente em /etc/ssh/ssh_config.
hostName = "aquamarine";
# max-jobs do construtor remoto.
maxJobs = 3;
# speedFactor é um número inteiro com sinal,
# mas parece que não é usado pelo Nix e não tem efeito.
speedFactor = 1;
}
{
inherit sshUser sshKey systems supportedFeatures;
hostName = "ruby";
maxJobs = 2;
speedFactor = 1;
}
{
inherit sshUser sshKey systems supportedFeatures;
hostName = "kana";
maxJobs = 2;
speedFactor = 1;
}
];
# Opcional: Útil quando o construtor tem uma conexão de internet mais rápida que a sua.
nix.extraOptions = ''
builders-use-substitutes = true
'';
# Definir os aliases de host para construtores remotos.
# Esta configuração será escrita em /etc/ssh/ssh_config.
programs.ssh.extraConfig = ''
Host ai
HostName 192.168.5.100
Port 22
Host aquamarine
HostName 192.168.5.101
Port 22
Host ruby
HostName 192.168.5.102
Port 22
Host kana
HostName 192.168.5.103
Port 22
'';
# Definir as chaves de host para construtores remotos para que o Nix possa verificar todos os construtores remotos.
# Esta configuração será escrita em /etc/ssh/ssh_known_hosts.
programs.ssh.knownHosts = {
# 星野 愛久愛海, Hoshino Aquamarine
aquamarine = {
hostNames = [ "aquamarine" "192.168.5.101" ];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDnCQXlllHoLX5EvU+t6yP/npsmuxKt0skHVeJashizE";
};
# 星野 瑠美衣, Hoshino Rubii
ruby = {
hostNames = [ "ruby" "192.168.5.102" ];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE7n11XxB8B3HjdyAsL3PuLVDZxWCzEOUTJAY8+goQmW";
};
# 有馬 かな, Arima Kana
kana = {
hostNames = [ "kana" "192.168.5.103" ];
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ3dDLOZERP1nZfRz3zIeVDm1q2Trer+fWFVvVXrgXM1";
};
};
}
Limitações
Aqui estão alguns problemas e limitações observados:
- Você não pode especificar quais hosts usar no momento da construção. Você só pode especificar uma lista de hosts no arquivo de configuração, e o Nix seleciona automaticamente os hosts disponíveis.
- Ao escolher um host, o Nix sempre prefere o host remoto em relação ao host local, mesmo que o host local tenha um desempenho melhor. Isso pode resultar na subutilização da CPU do host local.
- A menor unidade de construção distribuída é uma derivação (derivation). Ao construir pacotes grandes, outras máquinas podem permanecer ociosas por um longo período, esperando que o pacote grande seja construído. Isso pode levar ao desperdício de recursos.