Ao longo dos anos de existência do Pinterest, 300 milhões de usuários do serviço criaram mais de 200 bilhões de pinos em mais de 4 bilhões de placas. Para atender a esse exército de usuários e uma extensa base de conteúdo, o portal desenvolveu milhares de serviços, variando de microsserviços que várias CPUs podem suportar e terminando com monólitos gigantes que rodam em toda uma frota de máquinas virtuais. E então chegou o momento em que os olhos da empresa caíram nos k8s. O que o "cubo" parecia "Interesse"? Você aprenderá sobre isso na nossa tradução da publicação mais recente do blog de engenharia do Pinterest .
Portanto, centenas de milhões de usuários e centenas de bilhões de pinos. Para atender esse exército de usuários e uma extensa base de conteúdo, desenvolvemos milhares de serviços, desde microsserviços que podem ser manipulados por várias CPUs a monólitos gigantes que rodam em uma frota inteira de máquinas virtuais. Além disso, temos uma variedade de estruturas que também podem exigir recursos da CPU, memória ou acesso a E / S.
Para apoiar esse zoológico de ferramentas, a equipe de desenvolvimento enfrenta vários desafios:
- Os engenheiros não têm uma maneira unificada de executar um ambiente de trabalho. Serviços sem estado, serviços com estado e projetos em desenvolvimento ativo são baseados em pilhas de tecnologia completamente diferentes. Isso levou à criação de todo um curso de treinamento para engenheiros e também complica seriamente o trabalho de nossa equipe de infraestrutura.
- Os desenvolvedores com sua própria frota de máquinas virtuais criam uma enorme carga sobre os administradores internos. Como resultado, operações simples como atualizar o SO ou AMI duram semanas e meses. Isso leva a um aumento da carga de trabalho em situações aparentemente absolutamente cotidianas.
- Dificuldades na criação de ferramentas globais de gerenciamento de infraestrutura em cima das soluções existentes. A situação é complicada pelo fato de não ser fácil encontrar os proprietários de máquinas virtuais. Ou seja, não sabemos se é seguro extrair essas capacidades para trabalhar em outras partes de nossa infraestrutura.
Os sistemas de orquestração de contêineres são uma maneira de unificar o gerenciamento de carga de trabalho. Eles abrem o caminho para você aumentar a velocidade de desenvolvimento e simplificar o gerenciamento da infraestrutura, pois todos os recursos envolvidos no projeto são gerenciados por um sistema centralizado.
Figura 1: Prioridades da infraestrutura (confiabilidade, produtividade do desenvolvedor e eficiência).A equipe da Cloud Management Platform no Pinterest conheceu o K8s em 2017. No primeiro semestre de 2017, documentamos a maioria de nossas instalações de produção, incluindo a API e todos os nossos servidores web. Depois disso, avaliamos cuidadosamente os vários sistemas de orquestração de soluções de contêineres, construindo clusters e trabalhando com eles. Até o final de 2017, decidimos usar o Kubernetes. Era flexível o suficiente e com amplo suporte na comunidade de desenvolvedores.
Até o momento, criamos nossas próprias ferramentas de autoinicialização de cluster baseadas no Kops e transferimos para os componentes de infraestrutura existentes do Kubernetes, como rede, segurança, métricas, registro, gerenciamento de identidade e tráfego. Também implementamos um sistema de modelagem de carga de trabalho para o nosso recurso, cuja complexidade está oculta aos desenvolvedores. Agora, estamos focados em garantir a estabilidade do cluster, seu dimensionamento e conexão de novos clientes.
Kubernetes: maneira do Pinterest
A introdução ao Kubernetes em uma escala do Pinterest como uma plataforma que nossos engenheiros vão adorar é impressionante.
Como uma grande empresa, investimos fortemente em ferramentas de infraestrutura. Os exemplos incluem ferramentas de segurança que processam certificados e distribuem chaves, componentes de controle de tráfego, sistemas de descoberta de serviços, visibilidade e envio de logs e métricas. Tudo isso foi coletado por um motivo: seguimos o caminho normal de tentativa e erro e, portanto, queríamos integrar toda essa economia na nova infraestrutura do Kubernetes, em vez de reinventar a bicicleta velha em uma nova plataforma. Essa abordagem geralmente simplifica a migração, já que todo o suporte a aplicativos já existe, não precisa ser criado do zero.
Por outro lado, os modelos de previsão de carga no próprio Kubernetes (por exemplo, implantações, tarefas e kits Daemon) não são suficientes para o nosso projeto. Esses problemas de usabilidade são enormes barreiras para mudar para o Kubernetes. Por exemplo, ouvimos os desenvolvedores de serviços reclamarem de uma configuração de login ausente ou incorreta. Também encontramos o uso inadequado de mecanismos de modelo quando centenas de cópias foram criadas com a mesma especificação e tarefa, o que resultou em problemas de pesadelo com a depuração.
Também era muito difícil oferecer suporte a versões diferentes no mesmo cluster. Imagine a complexidade do suporte ao cliente se precisar trabalhar imediatamente em várias versões do mesmo tempo de execução, com todos os seus problemas, bugs e atualizações.
Recursos e controladores personalizados do Pinterest
Para facilitar a implementação do Kubernetes para nossos engenheiros, além de simplificar e acelerar a infraestrutura, desenvolvemos nossas próprias definições de recursos personalizados (CRD).
Os CRDs fornecem os seguintes recursos:
- Combinando vários recursos nativos do Kubernetes para fazê-los funcionar como um único carregamento. Por exemplo, o recurso PinterestService inclui uma implantação, serviço de login e mapa de configuração. Isso permite que os desenvolvedores não se preocupem com a configuração do DNS.
- Implemente o suporte necessário ao aplicativo. 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 CRD implementa todos os contêineres init necessários, variáveis de ambiente e especificações de pod. Isso fornece um nível de conforto fundamentalmente diferente para os desenvolvedores.
- Os controladores CRD também gerenciam o ciclo de vida de seus próprios recursos e aumentam a disponibilidade de depuração. Isso inclui concordar com as especificações desejadas e reais, atualizar o status do CRD e manter logs de eventos e muito mais. Sem o CRD, os desenvolvedores seriam forçados a gerenciar um grande conjunto de recursos, o que aumentaria apenas a probabilidade de erro.
Aqui está um exemplo do PinterestService e o recurso interno controlado por nosso controlador:

Como você pode ver acima, para oferecer suporte a um contêiner personalizado, precisamos integrar um contêiner de inicialização e vários complementos a ele para garantir segurança, visibilidade e trabalhar com o tráfego da rede. Além disso, criamos modelos de mapa de configuração e implementamos suporte para modelos de PVC para tarefas em lote, além de rastrear uma variedade de variáveis de ambiente para rastrear a identificação, consumo de recursos e coleta de lixo.
É difícil imaginar que os desenvolvedores desejem gravar esses arquivos de configuração manualmente sem o suporte a CRD, sem mencionar o suporte adicional e a depuração de configurações.
Implantação de aplicativo de fluxo de trabalho

A figura acima mostra como implantar um recurso personalizado do Pinterest em um cluster Kubernetes:
- Os desenvolvedores interagem com nosso cluster Kubernetes por meio da CLI e da interface do usuário.
- As ferramentas da CLI / UI extraem os arquivos YAML de configuração do fluxo de trabalho e outras propriedades de montagem (o mesmo identificador de versão) do Artifactory e os enviam para o Serviço de Envio de Tarefas. Esta etapa garante que apenas as versões de produção sejam entregues ao cluster.
- JSS é a porta de entrada para várias plataformas, incluindo Kubernetes. É aqui que ocorre a autenticação do usuário, a emissão de cotas e a verificação parcial de nossa configuração de CRD.
- Após verificar o CRD no lado JSS, as informações são enviadas para a API da plataforma k8s.
- Nosso controlador CRD monitora eventos em todos os recursos do usuário. Ele converte o CR em recursos nativos do k8s, adiciona os módulos necessários, define as variáveis de ambiente apropriadas e executa outros trabalhos auxiliares, o que garante aos aplicativos de usuário do contêiner suporte de infraestrutura suficiente.
- Em seguida, o controlador CRD transfere os dados recebidos para a API do Kubernetes, para que sejam processados pelo planejador e colocados em operação.
Nota : essa implantação de fluxo de trabalho de pré-lançamento foi criada para os primeiros usuários da nova plataforma k8s. Agora estamos finalizando esse processo para integrar-se totalmente ao nosso novo IC / CD. Isso significa que não podemos contar tudo relacionado ao Kubernetes. Esperamos compartilhar nossa experiência e informar a equipe sobre esse progresso em nossa próxima postagem no blog “Construindo uma plataforma de CI / CD para o Pinterest”.
Tipos de Recursos Especiais
Com base nas necessidades específicas do Pinterest, desenvolvemos os seguintes CRDs adequados para uma variedade de fluxos de trabalho:
- O PinterestService é um serviço sem estado de longa duração. Muitos de nossos principais sistemas são baseados em um conjunto de tais serviços.
- O JobSet modela trabalhos em lote de ciclo completo. O Pinterest tem um cenário comum, segundo o qual várias tarefas executam os mesmos contêineres em paralelo e independentemente de outros processos semelhantes.
- O PinterestCronJob é amplamente utilizado em conjunto com pequenas cargas periódicas. Este é um shell nativo cron com mecanismos de suporte do Pinterest responsáveis pela segurança, tráfego, logs e métricas.
- O PinterestDaemon inclui a infraestrutura do Daemon. Essa família continua a crescer à medida que adicionamos mais suporte aos nossos clusters.
- O PinterestTrainingJob se estende aos processos Tensorflow e Pytorch, fornecendo o mesmo nível de suporte on-line de todos os outros CRDs. Como o Pinterest está usando ativamente o Tensorflow e outros sistemas de aprendizado de máquina, tivemos um motivo para criar um CRD separado em torno deles.
Também estamos trabalhando no PinterestStatefulSet, que em breve será adaptado para data warehouses e outros sistemas com estado.
Suporte de tempo de execução
Quando o módulo do aplicativo é executado no Kubernetes, ele recebe automaticamente um certificado para se identificar. Este certificado é usado para acessar o armazenamento secreto ou se comunicar com outros serviços através do mTLS. Enquanto isso, o configurador de inicialização do contêiner e o Daemon farão o download de todas as dependências necessárias antes de iniciar o aplicativo de contêiner. Quando tudo estiver pronto, o tráfego do side-car e o Daemon registrarão o endereço IP do módulo em nosso Zookeeper para que os clientes possam encontrá-lo. Tudo isso funcionará, pois o módulo de rede foi configurado antes do lançamento do aplicativo.
A seguir, exemplos típicos de suporte à carga 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 como máquinas virtuais no nível do pod de side-car, nodal ou no Daemon. Garantimos que tudo isso seja implantado na estrutura da infraestrutura de gerenciamento e coordenado entre aplicativos, o que reduz significativamente a carga em termos de trabalho técnico e suporte ao cliente.
Teste e controle de qualidade
Reunimos 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 muitas mudanças antes de se tornar parte do cluster de produtos.
Além dos sistemas de teste, temos sistemas de monitoramento e aviso que monitoram constantemente o status dos componentes do sistema, consumo de recursos e outros indicadores importantes, notificando-nos apenas quando é necessária a intervenção humana.
Alternativas
Examinamos algumas alternativas para recursos personalizados, como controladores de acesso mutacional e sistemas de modelos. No entanto, todos eles estão repletos de sérias dificuldades no trabalho, por isso escolhemos o caminho da DRC.
Um controlador de tolerância à mutação foi usado para inserir carros laterais, uma variável de ambiente e outro suporte ao tempo de execução. No entanto, ele enfrentou vários problemas, por exemplo, com ligação de recursos e gerenciamento de seu ciclo de vida, quando esses problemas não surgem na DRC.
Nota: Os sistemas de gabarito, como os diagramas Helm, também são amplamente utilizados para executar aplicativos com configurações semelhantes. No entanto, nossos aplicativos de produção são muito diversos para gerenciá-los com modelos. Além disso, durante a implantação contínua, o uso de modelos gerará muitos erros.
Trabalho futuro
Agora, estamos lidando com uma carga mista em todos os nossos clusters. Para dar suporte a processos semelhantes de diferentes tipos e tamanhos, trabalhamos nas seguintes áreas:
- Um cluster de clusters distribui grandes aplicativos entre clusters para fornecer escalabilidade e estabilidade.
- Garantir estabilidade, escalabilidade e visibilidade do cluster para criar a conexão do aplicativo e seu SLA.
- Gerenciamento de recursos e cotas para que os aplicativos não entrem em conflito entre si e a escala do cluster seja controlada por nós.
- Nova plataforma de CI / CD para suportar e implantar aplicativos no Kubernetes.