Todos diziam para ir de serverless. Mantivemos o cluster Kubernetes que fica parado na maior parte do tempo
O conselho está em toda parte e soa obviamente certo. Você roda autenticação para tenants cujo tráfego é irregular. Você paga por um cluster Kubernetes vinte e quatro horas por dia. O Azure Container Apps escala você para zero e só cobra pelo que você usa. Pare de pagar por ociosidade.
Levamos a sério. Calculamos o custo de migrar para o Azure Container Apps, olhamos com atenção o que isso nos traria e ficamos no AKS. Aqui está o raciocínio, porque não é o que você adivinharia olhando o gráfico de utilização do cluster.
O conselho está certo, para uma carga de trabalho que não temos
Contêineres serverless encaixam perfeitamente no tratamento de requisições sem estado e em rajadas: cada requisição é independente, as instâncias são gado, e zero tráfego deveria significar zero conta. Isso descreve muitos backends web.
Não descreve um backplane de autenticação. O nosso não fica ocioso do jeito que um app sem estado fica ocioso. Ele detém a liderança do cluster e roda a camada de coordenação que decide qual réplica executa o trabalho singleton, como a varredura de retenção e a passagem de webhooks. (Esse líder agora elegemos com um lease de blob, não mais por gossip, o que é uma história à parte.) O cluster estar quieto não significa que não tem nada a fazer; significa que está pronto para validar o próximo token e para continuar sendo o líder. Quieto e ocioso não são o mesmo estado.
Eliminamos a conta de ociosidade sem nos mudar
Aqui está a parte que decidiu: o custo do qual tentávamos escapar tinha uma correção muito mais barata do que replataformar.
O que drenava o dinheiro eram nós rodando 24/7 enquanto o tráfego se concentrava no horário comercial. Então fizemos o cluster de dev se desalocar quando ninguém o usa (desligado à noite e nos fins de semana, de volta sob demanda) e trocamos o pool de nós para uma SKU mais barata. Isso eliminou a maior parte do gasto de ociosidade que o serverless prometia remover, e nos custou uma mudança de configuração em vez de uma migração. Quando a economia que você quer é alcançável no lugar, replataformar para perseguir o mesmo número é muito risco por uma diferença que você já capturou.
A lição se generaliza: precifique a correção antes de precificar a replataformação. "Pare de pagar por ociosidade" é um objetivo, não uma arquitetura, e a forma mais barata de atingi-lo costuma ser um scheduler e uma SKU, não um runtime novo.
O scale-to-zero briga com um backplane que precisa segurar um lease
Mesmo deixando o custo de lado, o scale-to-zero é ativamente errado para esta carga de trabalho de duas maneiras.
Primeiro, os cold starts caem no pior caminho possível. A requisição que paga o imposto do cold start é a de alguém tentando fazer login, e "seu login foi lento porque nosso serviço de autenticação estava dormindo" não é uma frase que você queira entregar.
Segundo, liderança e scale-to-zero estão em conflito direto. Você não consegue segurar um lease a partir de uma instância que foi escalada para fora de existência. Um backplane cujo trabalho inteiro é sempre ter exatamente um líder vivo não quer um runtime cujo trabalho inteiro é remover instâncias quando elas parecem quietas. Estaríamos brigando com o comportamento central da plataforma para preservar o nosso.
O runtime teria nos tirado três coisas que usamos
Migrar não é grátis nem mesmo onde funciona; você herda o sandbox do runtime gerenciado, e o nosso bloqueia coisas das quais dependemos:
- Twingate. Alcançamos recursos privados por meio de um conector Twingate. O sandbox de contêineres gerenciados não vai executá-lo, então estaríamos reinventando um acesso de rede privada que já temos.
- Nosso caminho de build. Partes do nosso pipeline se apoiam em Docker-in-Docker e
az acr buildcontra um registry privado, ambos proibidos pelo sandbox. Isso é um sistema de build a reconstruir, não apenas um alvo de deploy a trocar. - Controle cross-cloud. Rodamos um standby na AWS que valida tokens emitidos pelo primário no Azure, via JWKS federados, com a Cloudflare como árbitro de failover. Isso exige um controle de rede e de posicionamento que um runtime gerenciado esconde deliberadamente.
Cada uma dessas é uma gambiarra que teríamos de escrever só para voltar a onde já estamos. O verdadeiro custo da migração não é a virada; é reconquistar cada capacidade que o sandbox tira.
Economizar custo tem um rabo, e nós o pagamos
Ficar também não é livre de consequências, e o honesto é dizer isso. Desalocar nós à noite nos deu uma falha que nunca teríamos visto num cluster sempre ligado: uma corrida pelo token do primeiro pull de imagem em nós frios (aquela do issue 4052 do AKS) que de vez em quando travava um pod subindo depois que o cluster voltava a ligar. Corrigimos com um timeout de rollout mais longo e, em produção, não desalocando do jeito que o dev faz.
Essa é a verdadeira forma do trade-off. Todo caminho tem um rabo de modos de falha; a questão é se você consegue vê-los e corrigi-los. No AKS, a corrida de nós frios era inspecionável e corrigível. As classes de estranheza que você herda das entranhas de um runtime gerenciado são daquelas em que você abre um ticket de suporte e espera.
A regra que tiramos disso
Duas coisas, reaproveitáveis além de nós. Não migre para escapar de um custo que você pode matar onde está; precifique primeiro a correção no lugar, porque um scheduler e uma SKU mais barata vencem uma replataformação na maioria das vezes. E faça o runtime corresponder à forma da carga de trabalho: o serverless recompensa o sem estado e em rajadas e pune o com estado e sempre ligado, e um núcleo de autenticação que guarda suas chaves de assinatura e a liderança do seu cluster é firmemente do segundo tipo.
Não somos contra o serverless. Boa parte da nossa superfície sem estado ficaria bem nele. Mas a parte que guarda suas chaves e decide quem roda os jobs destrutivos vai continuar rodando em infraestrutura entediante, sempre ligada e inspecionável. Às vezes o cluster que parece ocioso é a opção barata, depois que você conta tudo o que teria de reconstruir para abandoná-lo.
A infraestrutura sempre ligada e inspecionável por trás dos seus logins é um recurso, não um descuido. É exatamente o que você delega quando roda a autenticação no Authagonal em vez de operar o backplane você mesmo.