BLOG

Plano de controle para Kubernetes PaaS distribuído

Ankur Singla Miniatura
Ankur Singla
Publicado em 15 de novembro de 2019

Este blog é o primeiro de uma série de blogs que abordam vários aspectos do que foi necessário para construir e operar nosso serviço SaaS :

  1. Plano de controle para Kubernetes PaaS distribuído
  2. Malha de serviço global para aplicativos distribuídos
  3. Segurança de plataforma para infraestrutura distribuída, aplicativos e dados
  4. Aplicação e segurança de rede de clusters distribuídos
  5. Observabilidade em uma plataforma distribuída globalmente
  6. Operações e SRE de uma plataforma distribuída globalmente
  7. Estrutura de serviço Golang para microsserviços distribuídos

Conforme descrito em nosso blog anterior , nossos clientes estão criando conjuntos complexos e diversos de soluções de negócios — como manufatura inteligente, análise forense de vídeo para segurança pública, negociação algorítmica, redes de telecomunicações 5G — e, portanto, precisamos oferecer uma experiência sempre ativa, conectada e confiável para esses aplicativos e seus usuários finais.

Como esses aplicativos podiam ser executados em vários clusters entre provedores de nuvem ou locais de ponta dos clientes, nossa equipe de plataforma teve que criar um plano de controle distribuído e um serviço PaaS para implantar, proteger e operar vários clusters Kubernetes multilocatários. Este plano de controle distribuído proporcionou muitos benefícios operacionais, de escala e de desempenho que abordaremos em nossa apresentação ( link do vídeo ) — por exemplo, como gerenciar milhares de clusters K8s de ponta com GitOps — e também como uma postagem de blog separada nas próximas semanas.

TL;DR (Resumo)

  • Não conseguimos encontrar uma solução simples de usar no mercado que pudesse resolver o problema de implantação, proteção e operação de vários clusters de aplicativos distribuídos entre provedores de nuvem, nuvens privadas ou vários locais de ponta.
     
  • Não conseguimos encontrar uma distribuição Kubernetes robusta ou PaaS (por exemplo, OpenShift, Cloud Foundry, etc.) que fornecesse um conjunto abrangente de serviços operacionais e de segurança necessários para clusters distribuídos — por exemplo, identidade baseada em PKI, RBAC e gerenciamento de acesso de usuário, segredos e gerenciamento de chaves entre provedores de nuvem, malha de serviços multicluster, logs de observabilidade e auditoria ou segurança de aplicativos e rede.
     
  • Anthos (Google), Azure Arc (Microsoft) e Rancher são estações de gerenciamento de vários clusters e pacotes de vários serviços diferentes; nossa análise foi que eles não teriam resolvido os requisitos operacionais, de dimensionamento, segurança e multilocação que tínhamos para serviços de aplicativos e infraestrutura em vários clusters.
     
  • Tivemos que construir nosso próprio plano de controle distribuído para nosso PaaS gerenciado, construído sobre o Kubernetes. Começamos com o Kubernetes vanilla e depois fizemos mudanças significativas para fornecer os serviços de plataforma necessários para nossas equipes de DevOps e SRE. Além disso, tivemos que construir um plano de controle para gerenciar um grande número de clusters distribuídos e fornecer multilocação em infraestrutura heterogênea (na borda, em nossa rede e em vários provedores de nuvem).

Kubernetes para gerenciamento de aplicativos: Por que e como

Escolhemos o Kubernetes (K8s) para ser o núcleo da nossa plataforma de gerenciamento de aplicativos distribuídos, pois ele fornece um rico conjunto de funcionalidades sem ser excessivamente prescritivo, o que nos dá flexibilidade para inovar em coisas que acreditamos serem importantes para nossos clientes. Usamos isso como base para começar a construir nosso serviço e, com a crescente popularidade dos K8s, também é mais fácil encontrar desenvolvedores e operadores familiarizados com eles.

Dito isso, implantar e gerenciar um grande número de clusters Kubernetes de nível de produção em um ambiente híbrido (várias nuvens, POPs de rede e locais de borda) não é muito fácil, pois não há soluções prontas para uso para Kubernetes que possam:

  1. Harmonizar recursos de infraestrutura heterogêneos com clustering automatizado, dimensionamento e provisionamento zero-touch; isso era especialmente doloroso na borda e em nossos PoPs de rede
  2. Forneça conectividade confiável e de alto desempenho em locais distintos — especialmente ao cruzar provedores de nuvem e vir de locais de ponta
  3. Resolva o problema de segurança de dados em trânsito, dados em repouso, segredos, chaves e rede... tudo apoiado por uma identidade PKI uniforme que funciona em edge, rede e nuvem
  4. Forneça verdadeira multilocação — isolamento de locatário e garantias de segurança — com a capacidade de executar cargas de trabalho de produção e desenvolvimento para necessidades internas e do cliente nos mesmos clusters
  5. Fornece observabilidade e operações em clusters distribuídos que se vinculam a políticas e intenções centralizadas, sem a necessidade de criar registros complexos e coleta de métricas

Após várias provas de conceito com vários provedores de nuvem e plataformas de código aberto como GKE, AKS, EKS e RKE, bem como OpenShift e Cloud Foundry, percebemos que nenhum deles poderia atender a todos os cinco requisitos acima. Como resultado, decidimos construir nosso próprio PaaS — começando com o Kubernetes “vanilla” e fizemos várias adições — para identidade, rede, segurança, multilocação, registro, métricas, etc. Embora usemos o Kubernetes para atender às nossas necessidades internas, tivemos que tomar algumas decisões difíceis, como não expor esses clusters do Kubernetes diretamente aos nossos usuários internos e/ou clientes para executar suas cargas de trabalho (mais sobre isso depois, pois a multilocação era um objetivo fundamental para nós).

Além de vários novos recursos que precisávamos adicionar, também havia a necessidade de executar nossas cargas de trabalho/serviços junto com as cargas de trabalho dos clientes em muitos locais na borda, em nossa rede e em nuvens públicas/privadas. Isso significava que precisávamos criar recursos adicionais para gerenciar vários clusters em vários ambientes... todos conectados usando nossa rede global e nossos gateways de aplicativos distribuídos para fornecer conectividade de nível de aplicativo e confiança zero entre esses clusters.

A parte difícil: Multi-locação e multi-cluster para Kubernetes

Criar e operar aplicativos executados em um único cluster do Kubernetes não é uma tarefa trivial, mesmo que consuma um cluster gerenciado pelo provedor de nuvem. É por isso que é comum que equipes de DevOps e SRE minimizem sua sobrecarga e não lidem com as complexidades de muitos clusters. É bastante comum ver equipes criarem um grande cluster do Kubernetes e colocarem todos os tipos de recursos dentro do mesmo cluster. Embora isso pareça ótimo porque eles podem simplificar as operações e executar o cluster para obter a máxima eficiência computacional e custo, essa não é a melhor ideia por vários motivos. Primeiro, as necessidades de cargas de trabalho de produção são muito diferentes das de desenvolvimento e teste e de preparação — cargas de trabalho de desenvolvimento instáveis podem causar problemas para cargas de trabalho de produção mais estáveis.

Além das necessidades de cargas de trabalho variadas, as limitações de segurança e isolamento do K8s são outro fator determinante para o multicluster. Uma abordagem típica para resolver a segurança e o isolamento de recursos do K8s é criar clusters independentes para cada locatário usando um modelo multilocatário. Embora isso possa ser viável na nuvem, não é possível executar vários clusters na borda. Os sites de ponta têm limitações de recursos de computação e armazenamento e largura de banda de rede restrita para enviar logs e métricas de cada cluster adicional para a nuvem central.

Para lidar com o problema de vários clusters do Kubernetes, avaliamos o Rancher para gerenciamento centralizado de nossos clusters do Kubernetes (quando começamos, o Anthos e o Azure Arc não existiam) e o KubeFed. As duas abordagens disponíveis naquela época eram (e continuam sendo a mesma situação hoje):

  1. O gerenciamento de vários clusters (por exemplo, Rancher) a partir de um console central nos daria a capacidade de implantar vários clusters em qualquer local e executar operações de gerenciamento do ciclo de vida, como atualizações, reversão, etc. Alguns desses sistemas também deram a capacidade de endereçar um cluster individual com automação para configuração e implantação de aplicativos
     
  2. Outra abordagem é implantar um plano de controle de federação de cluster do Kubernetes (KubeFed), que pode fazer com que vários clusters físicos pareçam um único cluster. Este projeto estava apenas começando quando o procuramos e ainda hoje está apenas em estágio alfa.

Após o anúncio recente do GCP Anthos e do Azure Arc, reavaliamos nossa decisão original de criar um plano de controle distribuído e concluímos que mesmo essas duas novas ofertas não conseguiriam resolver dois problemas críticos com clusters distribuídos. Esses dois principais recursos que precisávamos para nossa plataforma eram:

  1. Gerenciar vários clusters como uma frota para resolver o problema de executar operações em todos os clusters ou em um grupo lógico de clusters — operações como configuração, implantação, métricas, etc. Isso é essencial, pois queremos reduzir a sobrecarga operacional para nossas equipes de SRE, melhorar a capacidade de depuração para nosso DevOps e melhorar a escalabilidade do nosso sistema.
     
  2. Capacidade de dividir um cluster físico individual do Kubernetes para multilocação sem precisar criar clusters físicos — isso é especialmente crítico em ambientes com recursos limitados, onde não queremos adicionar novos clusters físicos apenas para multilocação

Para resolver esses dois problemas, tivemos que criar uma nova técnica — plano de controle distribuído — para resolver a sobrecarga operacional de “vários” clusters e fornecer um equivalente a “vários clusters” para multilocação em ambientes com recursos limitados.

Plano de controle distribuído: Como alcançamos o Multi-Cluster Kubernetes

Nossa equipe de plataforma decidiu construir um plano de controle distribuído para o Kubernetes que expõe as APIs do Kubernetes para uso da nossa equipe. No entanto, essas APIs vêm de clusters "virtuais" que existem apenas em nosso plano de controle — um servidor de API K8s virtual (vK8s) para um cluster K8s virtual (conforme mostrado na Figura 1 ). Este plano de controle mapeia a intenção do usuário para vários clusters físicos do Kubernetes em execução em nossa borda, nossos POPs de rede e locais de nuvem pública. Esses clusters físicos são acessíveis somente ao nosso plano de controle distribuído, e não a nenhum locatário/usuário individual.

plano-de-controle-01
Figura 1: Plano de controle distribuído

Este plano de controle fornece a cada locatário um ou mais clusters de aplicativos “virtuais” onde eles podem implantar seus aplicativos e, com base na configuração, o plano de controle irá replicá-los e gerenciá-los em vários clusters físicos do Kubernetes. Além das operações de configuração e implantação, as operações de monitoramento também seguem esse cluster “virtual” sem a necessidade de construir ferramentas para coletar e dissecar dados de vários clusters físicos.

Vamos pegar um aplicativo de UI de exemplo chamado productpage, onde a intenção do usuário é executá-lo distribuído em 3 locais — pa2-par, ny8-nyc e ams9-ams com 2 réplicas em cada um deles. Conforme o usuário cria um objeto vK8s e o anexa a um cluster virtual, ele imediatamente provisiona um servidor de API vK8s que pode ser usado com o kubectl padrão.

Como próxima etapa, o usuário baixa o kubeconfig para este cluster virtual e cria um yaml padrão para descrever uma implantação do K8s para a página do produto.

Após a criação da especificação de implantação, o usuário pode prosseguir para criar uma implantação neste cluster virtual:

Agora, se o usuário verificar sua implantação, ele verá que 6 réplicas foram iniciadas, com 2 em cada local (pa2-par, ny8-nyc e ams9-ams).

A saída a seguir mostra 2 pods em execução em cada local com mapeamento para um nó físico específico

Este exemplo simples demonstra como é trivial obter replicação multicluster de qualquer aplicativo em minutos, sem qualquer sobrecarga de instalação e gerenciamento. Além de mapear a intenção, o plano de controle distribuído também fornece observabilidade para o cluster virtual e não para cada cluster individual.

Controle Distribuído e Gerenciamento Centralizado para Multi-Locação

Como você pode ver na Figura 2 , nosso plano de gerenciamento centralizado está sendo executado em dois provedores de nuvem pública (uma região cada) — um na AWS e um no Azure (para redundância). Este plano de gerenciamento permite que nosso SRE crie locatários com multilocação rígida — por exemplo, uma equipe de desenvolvimento trabalhando em nosso serviço VoltMesh pode ser um locatário e uma equipe de soluções para clientes trabalhando em POCs de clientes pode ser seu próprio locatário com seu próprio conjunto de usuários.

Figura 2: Multi-locação e multi-cluster

Cada um desses locatários pode criar muitos namespaces e atribuir um grupo de usuários para colaborar nesses namespaces. Esses namespaces não são namespaces do Kubernetes — eles são um limite de isolamento em nossa plataforma com regras RBAC e políticas de IAM para usuários.

Quando um usuário dentro de um namespace deseja criar um cluster de aplicativos, ele cria um objeto vK8s e isso, por sua vez, cria um servidor de API vK8s em nosso plano de gerenciamento. Usando este objeto vK8s, o usuário pode criar implantações, conjuntos com estado, PVCs, etc., e o plano de controle garantirá que essas operações aconteçam em um ou muitos clusters físicos, com base em sites associados ao objeto vK8s.

Como cada locatário e usuário está usando operações K8s padrão sem nenhuma modificação, isso permite que o sistema seja compatível com uma série de ferramentas populares entre os operadores — por exemplo, Spinnaker, Helm, Jenkins, etc.

Ganhos obtidos a partir de um plano de controle distribuído

A grande vantagem de um plano de controle distribuído é que ele resolveu a sobrecarga operacional para nossas equipes de SRE e DevOps. Agora eles podem executar operações (configuração, implantação, monitoramento, política, etc.) em um cluster virtual e o plano de controle mapeará automaticamente em vários clusters físicos. Além da simplificação operacional para múltiplos clusters, o plano de controle também resolveu o problema de segurança e isolamento para multilocação.

Este plano de controle distribuído também melhorou a produtividade dos desenvolvedores que desejam adicionar novos recursos à nossa plataforma — eles não precisam criar uma nova automação toda vez que adicionam novos recursos que impactam a configuração ou as operações em vários clusters. Eles usam o modelo de configuração baseado em intenção e o plano de controle sabe o que precisa ser feito. Além disso, eles podem continuar a interagir com esse objeto de cluster distribuído e múltiplo — kubernetes virtual — usando kubectl e não outra CLI.

Depois de executar isso em nossos ambientes de desenvolvimento, teste, preparação e produção por mais de um ano, percebemos que esse plano de controle distribuído globalmente (executado em nossos POPs de rede) também oferece vantagens significativas de escala, desempenho e confiabilidade — algo que não havíamos imaginado completamente em nossos primeiros dias. Abordaremos essa descoberta em nossa próxima apresentação na KubeCon e em uma postagem de blog separada nas próximas semanas.

Continua…

Esta série de blogs abordará vários aspectos do que foi necessário para construir e operar nosso serviço SaaS distribuído globalmente com muitos clusters de aplicativos na nuvem pública, nossos PoPs de rede privada e sites de ponta. O próximo é o Global Service Mesh para aplicativos distribuídos