Ao longo dos anos, o Pinterest teve 300 milhões de usuários que criaram mais de 200 bilhões de pins em mais de 4 bilhões de painéis. Para atender a esse exército de usuários e a vasta base de conteúdo, o portal desenvolveu milhares de serviços, começando por microsserviços, que podem ser geridos por algumas CPUs, até gigantescos monolitos que operam em toda uma frota de máquinas virtuais. E chegou o momento em que a empresa voltou seu olhar para o k8s. O que fez com que o ‘cubo’ chamasse a atenção do Pinterest? Você descobrirá lendo nossa tradução do recente artigo do .

Assim, centenas de milhões de usuários e centenas de bilhões de pins. Para atender a esse exército de usuários e a vasta base de conteúdo, nós desenvolvemos milhares de serviços, começando por microsserviços, que podem ser geridos por algumas CPUs, até gigantescos monolitos que operam em toda uma frota de máquinas virtuais. Além disso, temos diversos frameworks que também podem exigir recursos de CPU, memória ou acesso a operações de entrada e saída.
Durante o suporte a esse zoológico de ferramentas, a equipe de desenvolvimento enfrenta uma série de problemas:
- Os engenheiros não têm uma maneira unificada de iniciar o ambiente de trabalho. Serviços sem estado, serviços com estado e projetos em fase de desenvolvimento estão baseados em pilhas tecnológicas completamente diferentes. Isso levou à criação de um curso de formação para os engenheiros, além de complicar seriamente o trabalho da nossa equipe de infraestrutura.
- Desenvolvedores, que possuem sua própria frota de máquinas virtuais, criam uma enorme carga para os administradores internos. Como resultado, operações simples, como atualização do SO ou AMI, se estendem por semanas e meses. Isso resulta em um aumento da carga em situações que, à primeira vista, parecem absolutamente cotidianas.
- Dificuldades em criar ferramentas de gerenciamento de infraestrutura globais sobre soluções já existentes. A situação é ainda mais complicada pelo fato de que encontrar os proprietários das máquinas virtuais não é fácil. Isso significa que não sabemos se é seguro extrair esses recursos para trabalhar em outras áreas da nossa infraestrutura.
Sistemas de orquestração de contêineres são uma forma de unificar a gestão de cargas de trabalho. Eles abrem caminho para aumentar a velocidade de desenvolvimento e simplificar a gestão da infraestrutura, pois todos os recursos envolvidos no projeto são geridos por um único sistema centralizado.

Figura 1: Prioridades da infraestrutura (confiabilidade, desempenho dos desenvolvedores e eficiência).
A equipe de Cloud Management Platform do Pinterest conheceu o K8s em 2017. Na primeira metade de 2017, documentamos a maior parte das nossas capacidades de produção, incluindo API e todos os nossos servidores web. Em seguida, realizamos uma avaliação cuidadosa de diferentes sistemas de orquestração de soluções de contêineres, construção de clusters e operação com eles. No final de 2017, decidimos utilizar o Kubernetes. Ele era flexível o suficiente e amplamente suportado pela comunidade de desenvolvedores.
Até o momento, criamos nossas próprias ferramentas de inicialização do cluster com base no Kops e migramos componentes existentes da infraestrutura para o Kubernetes — como rede, segurança, métricas, gerenciamento de registros, gestão de identidades e tráfego. Também implementamos um sistema de modelagem de cargas de trabalho para nosso recurso, cuja complexidade é oculta dos desenvolvedores. Agora, estamos focados em garantir a estabilidade do cluster, sua escalabilidade e a inclusão de novos clientes.
Kubernetes: o caminho do Pinterest
O início do trabalho com o Kubernetes em grande escala no Pinterest como uma plataforma que seria amada por nossos engenheiros resultou em muitos desafios.
Como uma grande empresa, investimos recursos significativos em ferramentas de infraestrutura. Um exemplo são as ferramentas de segurança, que gerenciam certificados e distribuem chaves, componentes de controle de tráfego, sistemas de descoberta de serviços, componentes de visibilidade e envio de registros e métricas. Tudo isso foi reunido não por acaso: passamos por um caminho normal de tentativas e erros, e, portanto, queríamos integrar toda essa estrutura na nova infraestrutura do Kubernetes em vez de reinventar a roda antiga em uma nova plataforma. Essa abordagem, de forma geral, simplificou a migração, já que todo o suporte a aplicativos já existe e não precisa ser criado do zero.
Por outro lado, os modelos de previsão de carga no próprio Kubernetes (como implantações, jobs e sets de Daemon) são insuficientes para o nosso projeto. Esses problemas de usabilidade representam enormes obstáculos à transição para o Kubernetes. Por exemplo, ouvimos desenvolvedores de serviços reclamando sobre a falta ou configuração inadequada do acesso. Também encontramos um uso incorreto de modelos, quando eram criadas centenas de cópias com especificações e tarefas idênticas, o que resultava em problemas de depuração aterradores.
Além disso, foi muito difícil manter diferentes versões em um mesmo cluster. Imagine a complexidade do suporte ao cliente se você precisar trabalhar com várias versões do mesmo ambiente de execução, com todos os seus problemas, bugs e atualizações.
Recursos personalizados e controladores do Pinterest
Para facilitar o processo de implementação do Kubernetes para nossos engenheiros, além de simplificar a infraestrutura e acelerar seu funcionamento, desenvolvemos nossas próprias definições de recursos personalizados (CRD).
As CRDs oferecem as seguintes funcionalidades:
- Integração de diversos recursos nativos do Kubernetes, para que funcionem como uma única carga. Por exemplo, o recurso PinterestService inclui a implantação, o serviço de entrada e o config map. Isso permite que os desenvolvedores não se preocupem com a configuração do DNS.
- Implementação do suporte necessário a aplicativos. O usuário deve se concentrar apenas na especificação do contêiner de acordo com sua lógica de negócios, enquanto o controlador da CRD implementa todos os init-containers, variáveis de ambiente e especificações do pod necessárias. Isso proporciona um nível de conforto fundamentalmente diferente para os desenvolvedores.
- Os controladores de CRDs também gerenciam o ciclo de vida de seus próprios recursos e melhoram a disponibilidade da depuração. Isso inclui a sincronização das especificações desejadas e reais, a atualização do status da CRD e o registro de eventos, entre outros. Sem as CRDs, os desenvolvedores seriam forçados a gerenciar um conjunto numeroso de recursos, o que aumentaria apenas a probabilidade de erro.
Aqui está um exemplo do PinterestService e de um recurso interno que é gerenciado pelo nosso controlador:

Como pode ser visto acima, para suportar o contêiner do usuário, precisamos integrar um contêiner de inicialização e vários complementos para garantir segurança, visibilidade e operabilidade com o tráfego da rede. Além disso, criamos modelos de mapas de configuração e implementamos suporte para modelos de PVC para tarefas em lote, bem como rastreamento de várias variáveis de ambiente para monitoramento de identificação, consumo de recursos e coleta de "lixo".
É difícil imaginar que os desenvolvedores queiram escrever esses arquivos de configuração manualmente sem o suporte do CRD, muito menos realizar manutenção e depuração das configurações.
Fluxo de trabalho de implantação de aplicativos

A figura acima mostra como implantar um recurso personalizado do Pinterest em um cluster Kubernetes:
- Os desenvolvedores interagem com nosso cluster Kubernetes através da CLI e da interface do usuário.
- As ferramentas CLI / UI extraem arquivos YAML de configuração do fluxo de trabalho e outras propriedades de construção (a mesma ID de versão) do Artifactory, em seguida, os enviam para o Serviço de Submissão de Tarefas. Essa etapa garante que somente versões funcionais sejam entregues ao cluster.
- O JSS é um gateway para várias plataformas, incluindo Kubernetes. Aqui ocorre a autenticação do usuário, a atribuição de quotas e a verificação parcial da configuração do nosso CRD.
- Após a verificação do CRD no lado do JSS, as informações são enviadas para a API da plataforma k8s.
- Nosso controlador CRD monitora eventos em todos os recursos personalizados. Ele transforma o CR em recursos nativos do k8s, adiciona os módulos necessários, define as variáveis de ambiente pertinentes e realiza outras tarefas auxiliares, garantindo assim um suporte de infraestrutura adequado para os aplicativos personalizados em contêiner.
- Então, o controlador CRD envia os dados recebidos para a API do Kubernetes para que sejam processados pelo agendador e colocados em operação.
Nota: este fluxo de trabalho de pré-lançamento para deployment foi criado para os primeiros usuários da nova plataforma k8s. Atualmente, estamos em processo de aprimoramento desse processo para nos integrar completamente com nosso novo CI/CD. Isso significa que não podemos compartilhar tudo relacionado ao Kubernetes. Estamos ansiosos para compartilhar nossa experiência e falar sobre o progresso da equipe nessa área em nossa próxima postagem no blog "Construindo uma plataforma de CI/CD para Pinterest".
Tipos de recursos especiais
Com base nas necessidades específicas do Pinterest, desenvolvemos os seguintes CRDs que se adequam a diferentes fluxos de trabalho:
- PinterestService — são serviços stateless que já operam há bastante tempo. Muitos dos nossos sistemas principais são baseados em um conjunto desses serviços.
- PinterestJobSet modela tarefas em lote de ciclo completo. No Pinterest, há um cenário comum em que várias tarefas executam os mesmos contêineres em paralelo, independentemente de outros processos semelhantes.
- PinterestCronJob é amplamente utilizado em conjunto com pequenas cargas de trabalho periódicas. É uma camada sobre a funcionalidade nativa do cron, com mecanismos de suporte do Pinterest que cuidam da segurança, tráfego, logs e métricas.
- PinterestDaemon inclui daemons de infraestrutura. Esta família continua a crescer à medida que adicionamos mais suporte para nossos clusters.
- PinterestTrainingJob abrange processos Tensorflow e Pytorch, proporcionando o mesmo nível de suporte durante a execução que outros CRDs. Como o Pinterest utiliza ativamente Tensorflow e outros sistemas de aprendizado de máquina, tínhamos razões para construir um CRD separado em torno deles.
Também estamos trabalhando no PinterestStatefulSet, que em breve será adaptado para armazenamento de dados e outros sistemas stateful.
Suporte ao ambiente de execução
Quando um módulo de aplicativos é iniciado no Kubernetes, ele recebe automaticamente um certificado para se identificar. Este certificado é usado para acessar um repositório de segredos ou para se comunicar com outros serviços via mTLS. Enquanto isso, o configurador de inicialização de contêineres e o Daemon carregam todas as dependências necessárias antes de iniciar o aplicativo em contêiner. Quando tudo estiver pronto, o sidecar de tráfego e o Daemon registrarão o endereço IP do módulo em nosso Zookeeper, para que os clientes possam descobri-lo. Tudo isso funcionará, pois o módulo de rede foi configurado antes do início do aplicativo.
Acima estão exemplos típicos de suporte a cargas de trabalho em tempo de execução. Para outros tipos de cargas de trabalho, pode ser necessário um suporte ligeiramente diferente, mas todos eles são apresentados na forma de sidecar em nível de pod, nos nós ou por Daemons em nível de máquinas virtuais. Estamos garantindo que tudo isso seja implantado dentro da infraestrutura de gerenciamento e esteja alinhado entre os aplicativos, o que, em última análise, reduz significativamente a carga em termos de trabalho técnico e suporte ao cliente.
Testes e QA
Construímos um pipeline de teste de ponta a ponta sobre a infraestrutura de teste existente do Kubernetes. Esses testes se aplicam a todos os nossos clusters. Nosso pipeline passou por várias reformulações antes de se tornar parte do cluster de produto.
Além dos sistemas de teste, temos sistemas de monitoramento e alerta que acompanham constantemente o estado dos componentes do sistema, o consumo de recursos e outros indicadores importantes, nos notificando somente quando há necessidade de intervenção humana.
Alternativas
Consideramos algumas alternativas aos recursos personalizados, como controladores de acesso mutacional e sistemas de template. No entanto, todas elas envolvem dificuldades significativas em sua implementação, então optamos pelo caminho do CRD.
O controlador de acesso mutacional foi utilizado para introduzir sidecars, variáveis de ambiente e outros suportes durante a execução. No entanto, ele enfrentava vários problemas, como vinculação de recursos e gerenciamento de seu ciclo de vida, enquanto no CRD esses problemas não ocorrem.
Nota: Sistemas de templates, como os diagramas Helm, também são amplamente utilizados para iniciar aplicações com configurações semelhantes. No entanto, nossas aplicações de trabalho são muito diversas para serem gerenciadas por templates. Além disso, durante a implantação contínua com o uso de templates, haverá muitos erros.
Trabalho em andamento
Atualmente, estamos lidando com uma carga de trabalho mista em todos os nossos clusters. Para suportar processos de diferentes tipos e tamanhos, estamos trabalhando nas seguintes direções:
- Um conjunto de clusters distribui grandes aplicações entre diferentes clusters para garantir escalabilidade e estabilidade.
- Garantir a estabilidade, escalabilidade e visibilidade do cluster para estabelecer a conexão entre a aplicação e seu SLA.
- Gerenciamento de recursos e cotas, para que as aplicações não entrem em conflito entre si, enquanto o tamanho do cluster é controlado de nossa parte.
- Nova plataforma CI/CD para suporte e implantação de aplicações no Kubernetes.
Fonte: habr.com
