Como aplicar os 5 pilares do Well-Architected Framework com o EKS -Excelência Operacional

Introdução

Nesta série de posts, iremos demonstrar diversas técnicas e conceitos sobre como aplicar e usufruir dos benefícios do AWS Well-Architected framework com o Elastic Kubernetes Service, mais conhecido como EKS.

O nosso objetivo não é fornecer uma explicação detalhada do framework em si, mas sim dar uma visão ampla do mesmo para que possamos então aplicar os principais conceitos. Para um entendimento mais detalhado, recomendamos fortemente a leitura do guia oficial.

E por falar na documentação oficial, extraímos alguns trechos que descrevem bem sobre o que é e para o que serve o framework:

“O AWS Well-Architected Framework é um guia que descreve os principais conceitos, princípios de projeto e melhores práticas arquitetônicas para projetar e executar cargas de trabalho na nuvem.”

O AWS Well-Architected ajuda arquitetos de nuvem a criar infraestruturas seguras, resilientes, eficientes e de alta performance para aplicações e cargas de trabalho.

Dando continuidade a explicação, o framework é baseado em 5 pilares que abrangem de maneira ampla todos os aspectos necessários para que arquitetos possam desenhar e implementar soluções:

Para os que não conhecem, o AWS EKS é uma solução gerenciada na nuvem para orquestração de contêineres baseada em Kubernetes e é uma das soluções líderes de mercado nesta categoria. Em grande parte devido ao modelo oferecido e a evolução constante do serviço.

De maneira geral, podemos dizer que o EKS é um dos componentes que ajuda clientes a atingirem seus objetivos dentro de uma determinada arquitetura de solução (por exemplo micro-serviços, jobs de analytics, data streaming, etc).

O Kubernetes é visto por muitos como o padrão (de-facto) para orquestração de contêineres on-premises e na nuvem e é constituído por um vasto e (demasiadamente) complexo ecossistema. Prover abstração de infraestrutura não é uma tarefa trivial e traz responsabilidades importantes para os arquitetos e principalmente para os desenvolvedores.

Para poder tirar proveito das funcionalidades e do poder proporcionado pelo EKS precisamos levar em consideração diversos aspectos para garantir que tenhamos sucesso na adoção do mesmo. É exatamente neste ponto que um guia maduro de boas práticas pode nos orientar pelo processo.

Mas e como podemos aplicar e obter valor dos pilares do Well-Architected Framework dentro do ecossistema do EKS? É o que iremos demonstrar neste e nos próximos artigos, com dicas, técnicas e ferramentas que acreditamos que irão ajudá-lo a ter sucesso na jornada de adoção do EKS.

Mesmo que não haja conhecimento prévio do Well-Architected framework ou mesmo do próprio EKS, insights que poderão ser muito úteis serão apresentados de forma incremental.

Excelência Operacional no EKS

Dando início de fato a nossa série de posts, iremos abordar o pilar de excelência operacional.

Este pilar engloba princípios que ajudam empresas a facilitarem a operação dos seus workloads (aplicações, infraestrutura, etc) e garantirem que estes entreguem valor ao negócio, de maneira contínua e evolutiva.

Para facilitar o entendimento e demonstrar a necessidade da excelência operacional, iremos segregar a estrutura de um cluster EKS em 3 camadas e dentro de cada uma delas iremos falar sobre práticas para adoção do framework.

Nesta camada, temos a infraestrutura dos recursos específicos do nosso provedor de cloud, neste caso a AWS. Ou seja, toda a infraestrutura necessária que precisamos para suportar o nosso cluster Kubernetes e as aplicações que serão implantadas nele.

Alguns exemplos de recursos nesta camada são:

  • Network (VPC, Transit gateway)
  • Armazenamento de arquivos (S3, NFS)
  • Bancos de dados (RDS, DynamoDB)
  • Web application firewalls (WAF)
  • Conteúdos estáticos (CloudFront)
  • O próprio cluster EKS
  • Chaves de criptografia (KMS)
  • Identidade e acesso (IAM)

Precisamos ter meios de evoluir continuamente cada um dos serviços utilizados, de maneira incremental, reversível, padronizada e confiável.

Para atingir estes fins, iremos falar sobre um princípio crucial parte do nosso pilar: Efetuar as operações como código, neste caso, gerenciando a nossa infraestrutura como código.

Através da infraestrutura como código, temos a possibilidade de definir todos os nossos recursos e a dependência entre eles de maneira declarativa, evitando problemas causados por disparidades entre ambientes, alterações feitas sem a devida comunicação para a equipe, falta de visibilidade do todo, etc. Podemos ainda garantir que a nossa infraestrutura seja modular e desacoplada, fazendo com que seja possível evoluir partes específicas de maneira controlada e recorrente.

No mercado existem diversas ferramentas conhecidas para aplicar infraestrutura como código, dentre elas podemos destacar:

  • Terraform: Amplamente difundido, permite declarar a infraestrutura utilizando uma linguagem clara e objetiva chamada de HCL. Suporta os principais provedores de infra e possui uma comunidade extensa.
  • CDKTF e CDK: São duas bibliotecas que permitem escrever a infraestrutura utilizando linguagens de programação conhecidas e então através de um processo de transpilação os scripts reais são gerados (a primeira gera scripts Terraform e a segunda CloudFormation). Permitem a criação de building blocks reusáveis e facilitam a adoção para desenvolvedores que desejam permanecer trabalhando com a stack de domínio.
  • CloudFormation: É uma das soluções da própria AWS para provisionamento de infraestrutura. Utiliza de templates feitas em YAML ou JSON e tem a vantagem de ser orquestrado pela própria AWS, ou seja, a execução e o estado não são de responsabilidade do cliente.
  • Eksctl: É a ferramenta de linha de comando (cli) oficial para provisionamento de clusters EKS. Apesar de ser uma ferramenta específica para o EKS, a mencionamos devido a sua facilidade de utilização e maturidade.
  • AWS Controllers for Kubernetes (ACK): Este último é um pouco diferente dos demais da lista. O ACK puxa mais responsabilidades para dentro do cluster EKS (lembrando que não é um serviço específico para o EKS, pode ser implantado em qualquer cluster K8s) aonde podemos definir receitas que irão representar serviços reais da AWS e que serão provisionados pelo próprio ACK. Estas receitas podem fazer parte da camada de infraestrutura do cluster ou das aplicações (veremos mais adiante), estando sujeitos aos mesmos mecanismos e ciclo de vida.

Como boas práticas gerais, recomendamos:

  • Mantenha todos os seus scripts versionados e utilize mecanismos para aplicá-los de maneira automatizada. Uma ferramenta de orquestração como o Jenkins pode ser responsável por este passo.
  • Utilize mecanismos para validar os scripts antes mesmo da execução nos ambientes alvo. Ferramentas de teste de infraestrutura são comuns e ajudam a fortalecer a qualidade.
  • Aplique políticas para garantir padrões e limites. A engine Open Policy Agent pode ser utilizada para estes fins e alguns exemplos de políticas são: quais serviços da cloud podem ser provisionados, quais tipos de instância EC2, padronização tags, enforce de boas práticas como por exemplo habilitar proteção de deleção para instâncias RDS em ambiente produtivo, validar o range CIDR de uma VPC, etc.
  • Modularize os componentes da infraestrutura para garantir reusabilidade e também evolução contínua. Para isto pode ser adotado um modelo de segregação por responsabilidade (network, storage, compute) ou um modelo de share-nothing aonde cada stack possui todos os recursos necessários para executar um conjunto de aplicações (serverless, contêineres).
  • Sempre versione os seus módulos e sempre utilize versões específicas.

O serviço EKS da AWS, é responsável por provisionar o que chamamos de control plane (os componentes que fazem a orquestração dos workloads) do nosso cluster Kubernetes, além de gerenciar e suportar diversos aspectos para reduzir a carga operacional ao máximo para o cliente.

Porém, de acordo com a segregação de responsabilidades estabelecida, existem diversos aspectos de configuração do cluster que ficam sob responsabilidade do cliente, tais como:

  • Definir cotas, limites e valores padrão para os recursos implantados
  • Limitar quais e quantos itens podem ser criados em cada namespace
  • Gerenciar o tráfego de network
  • Monitorar a saúde do cluster
  • Definir prioridades para os workloads
  • Definir regras de autorização

Além destas políticas, o usuário terá que configurar, implantar e atualizar diversos componentes adicionais (também conhecidos com add-ons) que estendem as capacidades do cluster para atingir propósitos específicos, por exemplo:

  • Elasticidade — Cluster Autoscaler
  • Backups do cluster — Velero
  • Tráfego de entrada para os serviços HTTP expostos — NGINX Ingress Controller / ALB Ingress Controller
  • Registros de DNS para os serviços expostos — External DNS
  • Monitoramento e métricas — Prometheus Operator
  • Regras de network — Calico

Além de todos os pontos que mencionamos sobre a governança necessária, aqui precisamos garantir de maneira uniforme a imutabilidade do que foi aplicado e que o estado desejado (o que estabelecemos e configuramos) seja mantido.

Para atingir estes objetivos, seguem algumas práticas e técnicas sugeridas:

  • Mantenha todos os add-ons e manifests de políticas e configurações sob versionamento no mesmo repositório e garanta que a aplicação destes seja executada de forma automatizada. Nós aconselhamos o modelo GitOps para tal fim, com isso temos o repositório Git como ponto único de referência (source of truth) e nos beneficiamos dos mecanismos nativos do mesmo como auditoria, segurança, pull requests, etc. Como ferramenta nós recomendamos o Flux CD devido ao fato do mesmo ser recomendado pela própria AWS para promover a cultura GitOps e está evoluindo a passos largos juntamente com a comunidade (Flux v2).
  • Utilize Helm charts para obter versões estáveis e validadas para cada add-on. O Flux CD possui um componente adicional chamado de Helm Operator, que é capaz de aplicar os conceitos de GitOps para as Helm Releases versionadas no seu repositório.
  • Sempre utilize versões fixas para todos os add-ons instalados.
  • Monitore a saúde de todos os componentes instalados no seu cluster. O Prometheus Operator é a nossa recomendação como tecnologia, devido ao seu extenso ecossistema, resiliência e fácil utilização. Um dos componentes provisionados por ele é o Alert Manager, que irá gerar notificações sobre problemas encontrados através das regras configuradas. Uma dica importante é integrar esta ferramenta ao canal de comunicação utilizado pela sua equipe (Slack, Discord, Telegram, etc.), isto irá fornecer feedbacks contínuos e dará visibilidade ao ambiente. Praticamente todos os componentes atuantes possuem webhooks que podem ser utilizadas para estes fins.

E por fim nesta última camada temos as aplicações em si que serão executadas no nosso cluster. O Kubernetes trabalha com um modelo declarativo aonde o usuário especifica através de um conjunto de manifests (receitas por assim dizer) todas as informações que o cluster precisa para executar o workload.

Estes manifests dentre diversas outras informações, especificam:

  • Qual repositório/imagem/tag Docker contém o workload
  • Quais os recursos de CPU e memória
  • Quais variáveis de ambiente serão utilizadas
  • Quais volumes serão montados
  • Como identificar se o workload está saudável
  • Quantas réplicas devem ser executadas
  • Como será exposto o tráfego para o workload
  • Qual o nível de privilégio que o workload precisa para executar adequadamente

Dentre as boas práticas e dicas que sugerimos para esta camada, se destacam:

  • Dependendo do tamanho e das responsabilidades atribuídas aos seus times de desenvolvimento, mantenha os manifests versionados junto das aplicações.
  • Utilize um modelo de push-based através de um pipeline de entrega para obter maior controle sobre todos os estágios necessários. Para a ferramenta de orquestração do pipeline aconselhamos o Jenkins, pela sua maturidade e flexibilidade.
  • Utilize uma ferramenta para templating dos seus manifests, com isso você irá melhorar a legibilidade e reusabilidade. Kustomize e Helm são ótimos exemplos de ferramentas (o Helm pode ser utilizado apenas para renderização da template dependendo do cenário).
  • Estabelecer e aplicar políticas de boas práticas antes mesmo dos manifests serem aplicados no ambiente alvo. A engine Open Policy Agent é fortemente recomendada para definir e aplicar estas regras aos manifests. Exemplos de políticas que podem ser estabelecidas neste pilar do framework são: labels padronizadas, versionamento correto das imagens (sempre pinadas e nunca apontando para a latest), definição de recursos utilizados (QoS Guaranteed ou Burstable), obrigar o uso de probes para garantir a saúde do workload, etc.
  • Faça backups frequentemente dos namespaces que contém os seus workloads. Uma ferramenta que faz este trabalho com excelência é o Velero, que pode ser configurado para utilizar um armazenamento de baixo custo e altamente durável como o S3. Pode também agendar automaticamente a execução destes backups e inclusive suporta efetuar backups não apenas dos manifests mas também dos volumes persistentes utilizados.

Como podemos ver, existem diversas partes móveis que requerem configurações, ajustes, atualizações, governança, etc. Estas partes móveis precisam de meios para que possamos operacionalizá-las de forma coerente.

Agradecemos a sua leitura e esperamos que algumas das dicas mostradas aqui sejam de grande valia.

Até o próximo artigo, em que falaremos sobre o pilar de Eficiência de Performance.

Cloud Specialists providing professional services with DevOps, BigData, Cloud Native Applications and Security. https://www.3bit.com.br/3bit

Cloud Specialists providing professional services with DevOps, BigData, Cloud Native Applications and Security. https://www.3bit.com.br/3bit