PlataformaMáquinas de runner

Máquinas de runner

Jobs Windows, macOS e self-hosted, em máquinas que regista.

Há jobs que não correm no cluster. Um contentor Windows precisa do kernel NT e não existe num host Linux, e o macOS não conteineriza — por isso, para windows-latest e macos-latest, não existe pod em lado nenhum. Regista a máquina, e a plataforma chega lá por SSH.

app.equantic.space/config/maquinas-runner
windows-latestmacos-latest
win-runner-1windows/amd64runner@10.0.0.42A aceitar jobs
mac-mini-1macos/arm64runner@10.0.0.51A aceitar jobs
build-boxlinux/amd64runner@10.0.0.7A drenar
mac-studiomacos/arm64runner@10.0.0.52inalcançável
1As labels que o job pede
2Abre a sessão e pergunta
3A chave pública a instalar
Cada máquina mostra o que a plataforma sabe mesmo sobre ela: as labels a que responde e se alguma vez foi alcançada.

Quando precisa de uma

runs-onOnde corre
ubuntu-latest, uma imagem de contentorNo cluster. Nada a registar.
windows-latestNuma máquina Windows registada.
macos-latestNum Mac registado. A licença da Apple exige hardware Apple.
self-hostedNuma máquina registada de qualquer SO — é isso que a label quer dizer.

Um job cujas labels não correspondem a nenhuma máquina falha de imediato em vez de correr no sítio errado, e a anotação indica o que falta: nenhuma máquina para esse SO, uma máquina em drenagem ou uma label que nenhuma tem. O run falha em vez de dar sucesso a trabalho que nunca foi construído.

Registar uma máquina

Vá a Definições → Plataforma → Máquinas de runner e carregue em Registar máquina. Declara o que a máquina é: endereço, a conta com que o CI vai correr, o sistema, a arquitetura e quantos jobs aceita ao mesmo tempo.

Em momento algum lhe é pedida uma chave privada. A plataforma gera um par ed25519, cifra a metade privada em repouso com a mesma cifra dos secrets, e mostra apenas a pública.

É de propósito. Colar uma chave privada num formulário é passar a string mais perigosa que tem por uma página, um pedido e provavelmente a área de transferência — e a chave a que a maioria das pessoas pega é a própria chave de login, que dá muito mais do que correr CI.

Instalar a chave

O ecrã dá-lhe o comando do sistema daquela máquina, porque o destino é mesmo diferente.

No Linux e no macOS, o sítio do costume:

bash
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo 'ssh-ed25519 AAAA… eqs-mac-mini-1' >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

No Windows, não é esse sítio. Para qualquer conta do grupo Administrators, o OpenSSH lê um ficheiro da máquina inteira e ignora por completo o ~/.ssh/authorized_keys:

powershell
Add-Content -Path "$env:ProgramData\ssh\administrators_authorized_keys" -Value 'ssh-ed25519 AAAA… eqs-win-runner-1'
icacls "$env:ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"
No Windows, instalar na pasta do utilizador corre bem, não muda nada, e a ligação seguinte é recusada com Permission denied (publickey) — uma falha com ar de chave errada. Garanta também que o ficheiro acaba em mudança de linha: uma chave acrescentada a uma última linha sem terminador cola as duas numa entrada inválida, e a partir daí nada autentica.

Testar a ligação

O Testar abre uma sessão e pergunta à máquina o que ela é. Uma ida e volta responde a três coisas: o SSH funciona, existe ali uma shell POSIX, e qual é de facto esta máquina.

Uma máquina registada com o sistema errado falha o teste e diz porquê. Não é um problema de ligação, e é pior do que isso: o encaminhamento mandaria jobs windows-latest para uma caixa Linux, e cada um falharia num comando que não existe, sem nada a apontar de volta para o registo.

Quando o teste falha recebe o motivo tal e qual — ssh: connect to host 10.0.0.42 port 22: Operation timed out — em vez de um erro genérico. Uma máquina que nunca foi alcançada di-lo, o que é diferente de inalcançável.

O que a máquina precisa de ter

  • Um servidor SSH e uma conta sem privilégios para o CI correr.
  • Uma shell POSIX. No Windows isso é o Git for Windows, com o bash.exe dele definido como DefaultShell do OpenSSH — todos os steps passam por lá.
  • git e tar, que o Git for Windows já traz.

Mais nada. O runtime de Node de que as actions JavaScript precisam é colocado pela plataforma — construído para o sistema e a arquitetura daquela máquina — no primeiro job que lá correr.

Drenar e remover

Drenar termina os jobs em curso e não aceita novos: é o estado a usar antes de reiniciar ou actualizar a máquina. Remover faz a plataforma esquecê-la.

Remover não toca na máquina. O authorized_keys dela continua com a chave pública da plataforma até a tirar de lá.

O isolamento é mais fraco do que um contentor

Vale a pena dizê-lo sem rodeios. Um job numa máquina registada vê o que o job anterior deixou fora do workspace dele: a pasta pessoal, o /tmp, os pacotes instalados, o estado de qualquer daemon. Um contentor dá uma raiz nova de cada vez, e isto não dá.

O que está mitigado: a conta não tem privilégios, o workspace é por job, e a limpeza recusa qualquer caminho fora da raiz de trabalho. Use uma máquina registada para trabalho que correria descansado numa build box partilhada.