- A Gitpod vem usando Kubernetes há 6 anos para construir sua "plataforma de ambientes de desenvolvimento remotos", dando suporte a 1,5 milhão de usuários e fornecendo milhares de ambientes de desenvolvimento por dia
- No entanto, percebeu que o Kubernetes não é adequado para construir ambientes de desenvolvimento
- Esta não é uma discussão sobre usar ou não Kubernetes para workloads de produção, nem sobre como criar a experiência do desenvolvedor para implantar aplicações em K8s
→ É uma história sobre como construir (ou não construir) ambientes de desenvolvimento na nuvem
[Por que os ambientes de desenvolvimento são especiais]
- Têm muito estado e são altamente interativos
- Não podem ser movidos entre nós
- Grandes volumes de código-fonte, cache de build, contêineres Docker, dados de teste etc. mudam com frequência, e o custo de migração é alto
- Ao contrário dos serviços de produção, há uma interação 1:1 entre o desenvolvedor e o ambiente
- Os desenvolvedores estão profundamente ligados ao código-fonte e às mudanças feitas
- Não gostam de perder alterações no código-fonte nem de ser bloqueados pelo sistema
- Ambientes de desenvolvimento são especialmente sensíveis a falhas
- Têm padrões imprevisíveis de uso de recursos
- Na maior parte do tempo não precisam de muita banda de CPU, mas podem precisar de vários núcleos em poucas centenas de ms
- Se for mais lento do que isso, o resultado é latência inaceitável e falta de resposta
- Exigem permissões e capacidades amplas
- Ao contrário dos workloads de produção, precisam de acesso root e da capacidade de baixar/instalar pacotes
- O que seria problema de segurança em workloads de produção é comportamento esperado em ambientes de desenvolvimento (acesso root, recursos de rede expandidos, mounts adicionais de sistema de arquivos etc.)
- Essas características os diferenciam de workloads típicos de aplicação e impactam fortemente as decisões de infraestrutura
[Sistema atual: Kubernetes]
- No início da Gitpod, o Kubernetes parecia a escolha ideal de infraestrutura
- Escalabilidade, orquestração de contêineres e um ecossistema rico combinavam bem com a visão de ambientes de desenvolvimento em nuvem
- Mas, com o aumento da escala e da base de usuários, surgiram dificuldades em segurança e gerenciamento de estado
- O Kubernetes foi projetado para executar workloads de aplicação bem controlados, não ambientes de desenvolvimento difíceis de domar
- Gerenciar Kubernetes em larga escala é complexo
- Serviços gerenciados como GKE e EKS aliviam parte do problema, mas trazem suas próprias restrições e limites
- Muitas equipes que querem operar CDE tendem a subestimar a complexidade do Kubernetes
- Isso levou a uma carga significativa de suporte no antigo produto self-hosted da Gitpod
Dificuldades no gerenciamento de recursos
- Alocação de CPU e memória é o maior desafio
- Compartilhar ambientes em um nó parece atraente, mas na prática o efeito de noisy neighbor é grande
- Problemas de CPU
- Ambientes de desenvolvimento podem quase não precisar de CPU e, de repente, precisar de muita
- Foram testadas soluções baseadas em CFS, controladores personalizados etc., mas a previsão é difícil
- Mesmo com limites estáticos de CPU, vários processos acabam competindo
- Gerenciamento de memória
- Alocar memória fixa é simples, mas limitante
- Overbooking pode levar ao encerramento de processos
- A introdução de espaço de swap reduziu um pouco a necessidade de overbooking
Otimização de desempenho de armazenamento
- IOPS e latência afetam a experiência no ambiente de desenvolvimento
- Foram testadas várias configurações para encontrar o equilíbrio entre velocidade, estabilidade, custo e desempenho
- SSD RAID 0
- Armazenamento em bloco como EBS e discos persistentes
- PVC
- Backup/restauração é uma operação cara
Autoscaling e otimização do tempo de inicialização
- Minimizar o tempo de inicialização era o objetivo número um
- Achavam que executar vários workspaces em um único nó melhoraria o tempo de inicialização por causa do cache compartilhado, mas não foi o caso
- O Kubernetes impõe um limite inferior ao tempo de inicialização
- Evolução dos métodos de scale-out
- Foram feitos experimentos com ghost workspaces, ballast pods etc. para scale-out
- A introdução de plugins de autoscaler melhorou bastante a estratégia de expansão
- Autoscaling proporcional para lidar com carga de pico
- Inicializar pods vazios permitia responder rapidamente a picos de demanda
- Várias tentativas para otimizar image pull
- Pré-pull com DaemonSet, maximização da reutilização de camadas, imagens pré-cozidas, Stargazer e lazy pulling, Registry-facade + IPFS
Complexidade de rede
- Controle de acesso aos ambientes de desenvolvimento
- Os ambientes precisam ser totalmente isolados entre si
- Políticas de rede ajudam, mas conforme o número de serviços cresce surgem problemas de confiabilidade
- Compartilhamento de largura de banda de rede
- Alguns CNIs suportam traffic shaping, mas isso vira mais um alvo de controle
Segurança e isolamento: equilibrando flexibilidade e proteção
- O maior desafio é oferecer um ambiente seguro sem tirar a flexibilidade do usuário
- Dar privilégios de root ao usuário tem muitos problemas
- User namespaces são uma solução mais granular
- Conversão de UID no sistema de arquivos, mounts mascarados de proc, suporte a FUSE, fornecimento de capacidades de rede, ativação do Docker
- Dificuldades na implementação de user namespaces
- Impacto de desempenho, problemas de compatibilidade, complexidade e suporte a versões do Kubernetes
[Experimentos com Micro VM]
- Ao sentir os limites do Kubernetes, a empresa começou a explorar tecnologias de micro VM (uVM) como Firecracker, Cloud Hypervisor e QEMU como um meio-termo
- Havia expectativa de manter as vantagens da conteinerização enquanto se melhorava o isolamento de recursos, a compatibilidade com outros workloads (como Kubernetes) e a segurança
- Vantagens das micro VMs
- Elas oferecem benefícios muito atraentes e alinhados aos objetivos de ambientes de desenvolvimento em nuvem
- Melhor isolamento de recursos: a capacidade de overbooking cai, mas o isolamento de recursos melhora em relação a contêineres. Como desaparece a disputa por recursos compartilhados de kernel, a previsibilidade de desempenho por ambiente de desenvolvimento aumenta
- Snapshots de memória e retomada rápida: o recurso
userfaultfddo Firecracker suporta snapshots de memória. Isso permite retomar quase instantaneamente a máquina inteira, incluindo processos em execução. Do ponto de vista do desenvolvedor, o ambiente inicia muito mais rápido e pode ser retomado exatamente de onde parou - Melhor fronteira de segurança: uVM pode servir como uma fronteira de segurança forte, tornando desnecessários os complexos mecanismos de user namespaces implementados no Kubernetes. Isso também pode ser totalmente compatível com uma gama mais ampla de workloads, inclusive conteinerização aninhada (executar Docker ou Kubernetes dentro do ambiente de desenvolvimento)
- Dificuldades das micro VMs
- No entanto, os experimentos com micro VMs revelaram vários desafios importantes
- Overhead: mesmo VMs leves causam mais overhead do que contêineres. Isso afeta tanto o desempenho quanto a utilização de recursos, o que é um ponto crítico em uma plataforma de ambientes de desenvolvimento em nuvem
- Conversão de imagem: converter imagens OCI em um sistema de arquivos utilizável por uVM exige soluções personalizadas. Isso complica o pipeline de gerenciamento de imagens e pode afetar o tempo de inicialização
- Limitações por tecnologia
- Firecracker: ausência de suporte a GPU (cada vez mais importante em alguns fluxos de trabalho de desenvolvimento), ausência de suporte a
virtiofs(limitando opções eficientes de compartilhamento de sistema de arquivos) - Cloud Hypervisor: ausência de suporte a
userfaultfd, o que torna snapshots e restauração mais lentos (anulando uma das principais vantagens da uVM)
- Firecracker: ausência de suporte a GPU (cada vez mais importante em alguns fluxos de trabalho de desenvolvimento), ausência de suporte a
- Problema de movimentação de dados: com uVM, foi preciso lidar com grandes snapshots de memória, o que dificultou ainda mais a movimentação de dados. Isso afeta tanto o agendamento quanto o tempo de inicialização, ambos elementos centrais da experiência do usuário em ambientes de desenvolvimento na nuvem
- Considerações de armazenamento: os experimentos de anexar volumes EBS a micro VMs abriram novas possibilidades, mas também novas dúvidas
- Armazenamento persistente: guardar o conteúdo do workspace em volumes anexados evita buscar repetidamente os dados no S3, com expectativa de melhorar o tempo de inicialização e reduzir o uso de rede
- Considerações de desempenho: compartilhar volumes de alta taxa de transferência entre workspaces pode melhorar o desempenho de I/O, mas também levanta preocupações sobre implementação eficaz de cotas, gerenciamento de latência e garantia de escalabilidade
- Lições dos experimentos com micro VM
- Embora micro VMs não tenham se tornado a principal solução de infraestrutura no fim, os experimentos trouxeram insights valiosos
- A empresa gostou da experiência de backup completo do workspace e de suspensão/retomada do estado de runtime para ambientes de desenvolvimento
- Pela primeira vez, passou a considerar sair do Kubernetes. Após esforços para integrar KVM e uVM aos pods, começou a explorar opções fora do Kubernetes
- O armazenamento voltou a ser reconhecido como elemento central para entregar, ao mesmo tempo, desempenho de inicialização consistente, workspaces estáveis (evitando perda de dados) e utilização ideal de máquinas
Kubernetes é extremamente desafiador como plataforma para ambientes de desenvolvimento
- Como mencionado antes, ambientes de desenvolvimento exigem um sistema que respeite sua natureza única e altamente stateful
- É preciso conceder aos desenvolvedores as permissões necessárias para serem produtivos, ao mesmo tempo garantindo limites seguros
- E tudo isso deve ser feito com baixo overhead operacional e sem comprometer a segurança
- Hoje é possível alcançar tudo isso com Kubernetes, mas a um custo significativo
- A empresa aprendeu da maneira difícil a diferença entre workloads de aplicação e workloads de sistema
- Kubernetes é incrivelmente excelente
- Conta com o apoio de uma comunidade apaixonada e construiu um ecossistema realmente rico
- Se você executa workloads de aplicação, Kubernetes continua sendo uma boa escolha
- Mas, para workloads de sistema como ambientes de desenvolvimento, Kubernetes impõe enormes desafios em segurança e overhead operacional
- Micro VMs e orçamentos claros de recursos ajudam, mas o custo passa a ser o fator dominante
- Por isso, depois de anos efetivamente redesenhando ao contrário e forçando ambientes de desenvolvimento a caber numa plataforma Kubernetes, a empresa deu um passo atrás para repensar como deveria ser a arquitetura de desenvolvimento do futuro
- Em janeiro de 2024, começou a construir isso e, em outubro, lançou o Gitpod Flex
- Mais de 6 anos de aprendizados duramente conquistados sobre como executar ambientes de desenvolvimento com segurança em escala de internet foram incorporados à base da arquitetura
O futuro dos ambientes de desenvolvimento
- No Gitpod Flex, a empresa herdou aspectos fundamentais do Kubernetes — a aplicação livre da teoria de controle e a API declarativa — enquanto simplificou a arquitetura e melhorou a base de segurança
- Ele orquestra ambientes de desenvolvimento usando um control plane fortemente inspirado no Kubernetes
- Introduz a camada de abstração necessária, específica para ambientes de desenvolvimento, e elimina a maior parte da complexidade desnecessária de infraestrutura
- Tudo isso com segurança zero trust como prioridade máxima
- Graças a essa nova arquitetura, tornou-se possível integrar dev containers de forma fluida
- Também se abriu a possibilidade de executar ambientes de desenvolvimento no desktop
- Como já não precisa carregar o peso pesado de uma plataforma Kubernetes, o Gitpod Flex pode ser implantado em self-hosting em menos de 3 minutos e em quantas regiões se quiser
- Isso oferece controle mais granular sobre conformidade e maior flexibilidade ao modelar fronteiras organizacionais e domínios
(Era originalmente outro texto, mas achei melhor trazer junto.)
Gitpod Flex
- A primeira plataforma de automação para ambientes de desenvolvimento zero trust
- Projetada para rodar em notebooks, nuvem e on-premises, mantendo código-fonte, dados e propriedade intelectual dentro de redes privadas
- Fornece os blocos de construção para automatizar o ciclo de vida do desenvolvimento de software, começando pelos ambientes de desenvolvimento
- Automations
- Tarefas e serviços programáveis definidos por repositório ou API
- Ajudam desenvolvedores a resolver por conta própria e permitem que equipes de produtividade de desenvolvimento centralizem melhorias nos ambientes de desenvolvimento
- Vão além da simples execução de scripts
- Permitem provisionar e popular bancos de dados, personalizar workflows de desenvolvimento, executar clusters efêmeros, configurar workflows de agentes baseados em LLM e aplicar centralmente políticas globais/regionais de segurança e conformidade
- Ambientes zero trust (Zero-trust environments)
- Todos os atores e serviços seguem o princípio de "nunca confiar, sempre verificar"
- Bloqueio completo de agentes maliciosos, grande redução da superfície de ataque e menor risco de malware ou vazamento de código
- Incluem avaliação contínua e verificação explícita, criptografia de nível empresarial validada, controle de acesso granular, controle total sobre a rede e trilha completa de auditoria
- O mais importante é manter código-fonte, dados e propriedade intelectual dentro de redes privadas
- Gitpod Desktop
- Permite padronizar e automatizar ambientes de desenvolvimento locais
- Suporte inicial ao Apple Silicon
- Oferece latência zero, uma alternativa mais rápida, leve e simples ao Docker Desktop para desenvolvimento, otimização de custos com computação local e recuperação de desastres contra interrupções na nuvem ou no endpoint
- Suporte a Development Container
- Integra completamente a especificação Dev Container
- Permite usar configurações Dev Container existentes sem alterações
- Oferece compatibilidade com VS Code e outras ferramentas compatíveis
- Permite trabalhar de forma consistente no local ou na nuvem
- A adoção do padrão Dev Container facilita definir, compartilhar e gerenciar ambientes de desenvolvimento
Será a base da automação do desenvolvimento de software pelos próximos 10 anos
- Pensamos de forma estreita demais sobre ambientes de desenvolvimento
- O ambiente de desenvolvimento é mais do que IDE, dependências e ferramentas: é o espaço fundamental onde o software é criado
- É onde acontecem prototipagem de código, formação por humanos e máquinas, testes, refatoração, compilação, empacotamento, assinatura e deploy
- Oferece acesso incomparável a contexto de desenvolvimento, workflows e insights, permitindo funções que outras plataformas de desenvolvimento não conseguem igualar
- Visão do produto
- Integração contínua (CI) se funde com o ambiente de desenvolvimento
- Atua como system of record do desenvolvimento de software
- Plataforma para a próxima geração de ferramentas para desenvolvedores
- Vai além de apenas melhorar práticas de programação: busca construir o meio mais rápido e seguro para empresas, de startups à Fortune 50, escalarem e terem sucesso na próxima década
3 comentários
Empresas coreanas que, usando segurança como desculpa, forçam o uso de desktops virtuais com especificação de 8 GB de memória. É amargo.
Já é difícil encontrar pessoas que manjem bem de Kubernetes, então fico pensando que vai ser ainda mais difícil achar gente disposta a entender e tentar as alternativas que estão sendo propostas aqui.
Comentários no Hacker News
Desenvolvedores devem ser donos da máquina de desenvolvimento que usam. Se for necessário um ambiente consistente, o desenvolvedor deve ter sua própria máquina e receber uma imagem de VM estável. Tentativas de mover o ambiente de desenvolvimento para um host remoto quase sempre fracassam. Fornecer hardware adequado ao desenvolvedor é mais custo-efetivo do que recursos remotos. É preciso dar suporte à execução da stack local, o que ajuda a manter a consistência por meio de contêineres. Ferramentas são necessárias para gerar dados no ambiente local, e isso pode ser automatizado. Há desvantagens no gerenciamento de dados, mas, na maioria das empresas, a capacidade de execução da equipe importa mais do que o código-fonte.
Usar Kubernetes para workloads de produção é uma questão separada; aqui o assunto é como construir ambientes de desenvolvimento na nuvem. Um artigo interessante sobre os trade-offs de engenharia e a complexidade do Kubernetes.
Explica os problemas do Kubernetes e as soluções que tentaram, mas falta explicar a alternativa que escolheram no fim. Menciona uma nova solução chamada Gitpod Flex, mas quase não há informações sobre ela.
Kubernetes é adequado para workloads stateless, mas, quando há estado, LXC é mais apropriado. O LXC pode ser clusterizado de forma semelhante ao K8S e expõe ferramentas ao plano de dados. Ele oferece instâncias de sistema semelhantes a VMs, com desempenho parecido ao de contêineres Docker. Usa sintaxe declarativa e pode servir como camada base de um cluster Kubernetes.
Ao construir uma solução de CI, escolher Kubernetes mostra que o problema não foi bem compreendido. Para fins de segurança, deveriam usar ferramentas como o Firecracker.
Kubernetes não é adequado para ambientes de desenvolvimento. Ambientes de desenvolvimento estão sempre em estado de mudança. Não entendo a necessidade de ambientes de desenvolvimento na nuvem. O objetivo de apps conteinerizados é evitar a necessidade de sincronizar ambientes de desenvolvimento entre equipes.
O artigo do Kubernetes menciona como único caso de uso uma combinação de workflows de baixa e alta latência. É difícil justificar considerar Kubernetes para o problema da Gitpod.
Trabalhei em um projeto semelhante ao Gitpod, e não faz sentido substituir Kubernetes por microVMs. Kubernetes pode orquestrar contêineres externos e pode ser usado para rodar microVMs. O maior problema está relacionado a storage.
Construir ambientes de desenvolvimento no Kubernetes é um desperdício. Quando o produto é self-hosted na infraestrutura do cliente, depuração e suporte ficam difíceis. Expor problemas de rede, memória, computação e storage aos engenheiros é eficaz. Kubernetes é um upgrade para equipes grandes.