Tutorial do NGINX: reduza a latência do Kubernetes com escalonamento automático

NGINX | 15 de março de 2022

Este tutorial é um dos quatro que colocam em prática os conceitos de Microsserviços de março de 2022: redes no Kubernetes:

Quer orientações detalhadas sobre como usar o NGINX em ainda mais casos de uso de redes no Kubernetes? Baixe gratuitamente nosso eBook, Gerenciamento de tráfego do Kubernetes com o NGINX: um guia prático.

Sua organização criou um aplicativo no Kubernetes e agora ele está ficando popular! O número de visitantes passou de apenas alguns para centenas (e, às vezes, milhares) por dia. Mas há um problema... o aumento do tráfego está causando um gargalo, o que gera latência e tempos limite para seus clientes. Se você não conseguir melhorar a experiência, as pessoas deixarão de usar o aplicativo.

Você – o corajoso engenheiro de Kubernetes – tem uma solução. Você implanta um controlador Ingress para rotear o tráfego e configura uma política de escalonamento automático para que o número de pods do controlador Ingress aumente e diminua instantaneamente de acordo com as variações do tráfego. Agora, os pods do controlador Ingress lidam perfeitamente com os picos de tráfego – “Adeus, latência!” – e reduzem a escala para economizar recursos quando o tráfego diminui – “Olá, economia de custos!” Muito bem.

Visão geral do laboratório e do tutorial

Este blog acompanha o laboratório da Unidade 1 do Microservices March 2022 – Projetando clusters do Kubernetes para sites com alto tráfego, demonstrando como usar o NGINX Ingress Controller para expor um aplicativo e, em seguida, dimensionar automaticamente os pods do Ingress Controller em resposta ao alto tráfego.

Para seguir o tutorial, você precisa de uma máquina com:

  • 2 CPUs ou mais
  • 2 GB de memória livre
  • 20 GB de espaço livre em disco
  • Conexão com a internet
  • Gerenciador de contêineres ou máquinas virtuais, como Docker, Hyperkit, Hyper‑V, KVM, Parallels, Podman, VirtualBox ou VMware Fusion/Workstation
  • minikube instalado
  • Helm instalado
  • Uma configuração que permita abrir uma janela do navegador. Se isso não for possível, você precisará descobrir como acessar os serviços relevantes por meio de um navegador.

Para aproveitar ao máximo o laboratório e o tutorial, recomendamos que, antes de começar, você:

Este tutorial usa estas tecnologias:

As instruções de cada desafio incluem o texto completo dos arquivos YAML usados para configurar os aplicativos. Você também pode copiar o texto do nosso repositório no GitHub. Um link para o GitHub é fornecido junto com o texto de cada arquivo YAML.

Este tutorial inclui quatro desafios:

  1. Configure um aplicativo simples em um cluster Kubernetes
  2. Use o NGINX Ingress Controller para rotear o tráfego para o aplicativo
  3. Gerar e monitorar tráfego
  4. Dimensionar automaticamente o NGINX Ingress Controller

Desafio 1: configure um aplicativo simples em um cluster Kubernetes

Neste desafio, você vai criar um cluster do minikube e instalar o Podinfo como aplicativo de exemplo.

Crie um cluster do Minikube

Crie um cluster do minikube. Após alguns segundos, uma mensagem confirmará que a implantação foi bem-sucedida.

$ minikube start 🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default 

Instale o aplicativo Podinfo

Podinfo é uma “aplicação web desenvolvida em Go que demonstra as práticas recomendadas para executar microsserviços no Kubernetes”. Estamos usando-a como aplicação de exemplo por ocupar poucos recursos.

  1. Usando o editor de texto de sua preferência, crie um arquivo YAML chamado 1-deployment.yaml com o conteúdo a seguir (ou copie do GitHub). Ele define um Deployment com uma única réplica e um Service.
apiVersion: apps/v1 kind: Deployment 
metadata: 
  name: podinfo 
spec: 
  selector: 
    matchLabels: 
      app: podinfo 
  template: 
    metadata: 
      labels: 
        app: podinfo 
    spec: 
      containers: 
      - name: podinfo 
        image: stefanprodan/podinfo 
        ports: 
        - containerPort: 9898 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: podinfo 
spec: 
  ports: 
    - port: 80 
      targetPort: 9898 
      nodePort: 30001 
  selector: 
    app: podinfo 
  type: LoadBalancer 
  1. Implante o aplicativo:
$ kubectl apply -f 1-deployment.yaml deployment.apps/podinfo created 
service/podinfo created
  1. Confirme se o pod do Podinfo foi implantado, conforme indicado pelo valor Running na coluna STATUS.
$ kubectl get podsNAME                       READY   STATUS   RESTARTS   AGE 
podinfo-5d76864686-rd2s5   1/1     Running  0          3m38s
  1. Abra o Podinfo em um navegador. A página greetings from podinfo indica que o Podinfo está em execução.
$ minikube service podinfo

Desafio 2: use o NGINX Ingress Controller para rotear o tráfego para o aplicativo

Neste desafio, você implanta o NGINX Ingress Controller e o configura para direcionar o tráfego para o aplicativo Podinfo.

Implantar o NGINX Ingress Controller

A maneira mais rápida de instalar o NGINX Ingress Controller é usando o Helm.

  1. Adicione o repositório do NGINX ao Helm:
$ helm repo add nginx-stable https://helm.nginx.com/stable 
  1. Baixe e instale o NGINX Ingress Controller baseado no NGINX Open Source, que é mantido pela F5 NGINX. A última linha da saída confirma que a instalação foi bem-sucedida.
$ helm install main nginx-stable/nginx-ingress \ --set controller.watchIngressWithoutClass=true \ --set controller.service.type=NodePort \ --set controller.service.httpPort.nodePort=30005 
NAME: main 
LAST DEPLOYED: Tue Mar 15 09:49:17 2022 
NAMESPACE: default 
STATUS: deployed 
REVISION: 1 
TEST SUITE: None 
NOTES: The NGINX Ingress Controller has been installed.
  1. Confirme se o pod do NGINX Ingress Controller foi implantado, conforme indicado pelo valor Running na coluna STATUS (para facilitar a leitura, a saída é exibida em duas linhas).
$ kubectl get podsNAME                                   READY   STATUS    ...
main-nginx-ingress-779b74bb8b-mtdkr    1/1     Running   ...
podinfo-5d76864686-fjncl               1/1     Running   ...

       ... RESTARTS   AGE
       ... 0          18s 
       ... 0        2m36s

Direcione o tráfego para seu aplicativo

  1. Usando o editor de texto de sua preferência, crie um arquivo YAML chamado 2-ingress.yaml com o conteúdo a seguir (ou copie do GitHub). Ele define o manifesto do Ingress necessário para direcionar o tráfego ao Podinfo.
apiVersion: networking.k8s.io/v1 kind: Ingress 
metadata: 
  name: podinfo 
spec: 
  ingressClassName: nginx 
  rules: 
    - host: "example.com" 
      http: 
        paths: 
          - backend: 
              service: 
                name: podinfo 
                port: 
                  number: 80 
            path: / 
            pathType: Prefix 
  1. Implante o recurso Ingress:
$ kubectl apply -f 2-ingress.yaml ingress.networking.k8s.io/podinfo created 

Desafio 3: gere e monitore o tráfego

Neste desafio, você observa o desempenho do NGINX Ingress Controller sob diferentes cargas de tráfego. Como etapas preparatórias, você lista as métricas disponíveis no NGINX Ingress Controller, implanta o Prometheus e instala o Locust. Em seguida, você usa o Locust para simular um pico de tráfego e acompanhar o impacto no desempenho no Prometheus.

Como você já descobriu, um controlador Ingress é um pod comum do Kubernetes que combina um proxy reverso (no nosso caso, o NGINX) com código para integração com o Kubernetes. Se o seu aplicativo recebe muito tráfego, provavelmente será necessário aumentar o número de réplicas do pod do NGINX Ingress Controller para evitar a latência causada quando ele fica sobrecarregado.

Liste as métricas disponíveis

Para saber quando e quanto escalar, você precisa de informações precisas sobre o desempenho do NGINX Ingress Controller. Neste tutorial, a métrica do NGINX usada para determinar quando escalar é o número de conexões ativas (nginx_connections_active). Aqui, você verifica se o NGINX Ingress Controller monitora essa métrica.

O NGINX Ingress Controller expõe várias métricas: 8 métricas com o modelo baseado no NGINX Open Source que estamos usando neste tutorial e mais de 80 métricas com o modelo baseado no NGINX Plus.

  1. Obtenha o endereço IP do pod do NGINX Ingress Controller para poder consultar sua lista de métricas. O endereço aparece no campo IP e, neste caso, é 172.17.0.4. (Para facilitar a leitura, as colunas RESTARTS e AGE foram omitidas, e a saída foi dividida em duas linhas.)
$ kubectl get pods -o wide NAME                                  READY   STATUS    ...
main-nginx-ingress-779b74bb8b-6hdwx   1/1     Running   ...
podinfo-5d76864686-nl8ws              1/1     Running   ...

    ... IP           NODE       NOMINATED NODE  READINESS GATES 
    ... 172.17.0.4   minikube   <none>          <none> 
    ... 172.17.0.3   minikube   <none>          <none>
  1. Crie um pod temporário do BusyBox com um shell em um host dentro do cluster do Kubernetes:
$ kubectl run -ti --rm=true busybox --image=busyboxIf you don't see a command prompt, try pressing enter. 
/ # 
  1. Liste as métricas geradas pelo NGINX Ingress Controller e verifique se elas incluem nginx_connections_active. Em <IP_address> insira o valor obtido na Etapa 1.
/# wget -qO- <IP_address>:9113/metrics
  1. Saia do shell para retornar ao servidor Kubernetes.
/# exit 

Implantar o Prometheus

Agora que você sabe que o NGINX Ingress Controller monitora a métrica nginx_connections_active, você precisa de uma ferramenta para coletar (“fazer scraping”) as métricas — este tutorial usa o Prometheus.

Assim como no caso do NGINX Ingress Controller, o Helm é a maneira mais rápida de instalar o Prometheus.

  1. Adicione o repositório do Prometheus ao Helm:
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
  1. Baixe e instale o Prometheus:
$ helm install prometheus prometheus-community/prometheus \ --set server.service.type=NodePort --set server.service.nodePort=30010
  1. Verifique a instalação, que geralmente leva até 60 segundos para ser concluída. No exemplo de saída a seguir, o comando de verificação foi executado apenas alguns segundos após o comando helm install e, por isso, vemos a instalação em andamento, com ContainerCreating informado no campo STATUS para alguns pods do Prometheus. A instalação estará concluída quando todos os pods apresentarem o status Running. (A saída está distribuída em duas linhas para facilitar a leitura.)
$ kubectl get podsNAME                                           READY  ...
main-nginx-ingress-779b74bb8b-mtdkr            1/1    ...
podinfo-5d76864686-fjncl                       1/1    ...
prometheus-alertmanager-d6d94cf4b-85ww5        0/2    ...
prometheus-kube-state-metrics-7cd8f95cb-86hhs  0/1    ...
prometheus-node-exporter-gqxfz                 1/1    ...
prometheus-pushgateway-56745d8d8b-qnwcb        0/1    ...
prometheus-server-b78c9449f-kwhzp              0/2    ...

      ... STATUS             RESTARTS  AGE 
      ... Running            0         3m23s 
      ... Running            0         5m41s 
      ... ContainerCreating  0         7s
      ... Running            0         7s
      ... Running            0         7s
      ... ContainerCreating  0         7s
      ... ContainerCreating  0         7s
  1. Abra o Prometheus. Em um ambiente minikube, execute o comando a seguir, que abrirá o painel do Prometheus no navegador padrão.
$ minikube service prometheus-server
  1. Uma página como a mostrada a seguir confirma que o servidor está funcionando.
  2. Digite nginx_ingress_nginx_connections_active na barra de pesquisa para ver o valor atual da métrica de conexões ativas. Você verá uma conexão ativa, o que faz sentido, pois implantou um pod do NGINX Ingress Controller.

Instale o Locust

Na próxima seção, você usará o Locust, uma ferramenta de código aberto para testes de carga, a fim de simular um pico de tráfego e acompanhar o desempenho do NGINX Ingress Controller no Prometheus. Aqui, você implantará o Locust.

  1. Usando o editor de texto de sua preferência, crie um arquivo YAML chamado 3-locust.yaml com o conteúdo a seguir (ou copie-o do GitHub). Os objetos Deployment e Service definem o pod do Locust. O objeto ConfigMap define um script chamado locustfile.py, que gera solicitações a serem enviadas ao pod, incluindo os cabeçalhos corretos.
apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: locust-script 
data: 
  locustfile.py: |- 
    from locust import HttpUser, task, between 

    class QuickstartUser(HttpUser): 
        wait_time = between(0.7, 1.3) 

        @task 
        def hello_world(self): 
            self.client.get("/", headers={"Host": "example.com"}) 
--- 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: locust 
spec: 
  selector: 
    matchLabels: 
      app: locust 
  template: 
    metadata: 
      labels: 
        app: locust 
    spec: 
      containers: 
        - name: locust 
          image: locustio/locust 
          ports: 
            - containerPort: 8089 
          volumeMounts: 
            - mountPath: /home/locust 
              name: locust-script 
      volumes: 
        - name: locust-script 
          configMap: 
            name: locust-script 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: locust 
spec: 
  ports: 
    - port: 8089 
      targetPort: 8089 
      nodePort: 30015 
  selector: 
    app: locust 
  type: LoadBalancer 
  1. Implante o Locust:
$ kubectl apply -f 3-locust.yaml configmap/locust-script created 
deployment.apps/locust created 
service/locust created 

Simule um pico de tráfego e observe o efeito no desempenho

  1. Abra o Locust em um navegador.
$ minikube service locust
  1. Insira os seguintes valores nos campos:
    • Número de usuários – 1000
    • Taxa de geração – 10
    • Host – http://main-nginx-ingress
  2. Clique no botão Iniciar enxame para enviar tráfego ao aplicativo Podinfo.
  3. Retorne ao painel do Prometheus para ver como o NGINX Ingress Controller responde. Talvez seja necessário executar uma nova consulta para nginx_ingress_nginx_connections_active para visualizar alguma alteração. Conforme mostrado na captura de tela a seguir, o único pod do NGINX Ingress Controller tem dificuldade para processar o aumento do tráfego sem elevar a latência à medida que um grande número de conexões é estabelecido. O gráfico do Prometheus revela que cerca de 100 conexões ativas por pod do NGINX Ingress Controller é o ponto crítico para um pico de latência. Você pode usar essas informações para determinar quando é necessário aumentar o número de pods do NGINX Ingress Controller para evitar o aumento da latência.

Desafio 4: dimensionar automaticamente o NGINX Ingress Controller

No desafio final, você cria uma configuração que dimensiona automaticamente os recursos à medida que o volume de tráfego aumenta. O tutorial usa o KEDA para o dimensionamento automático, portanto, primeiro você o instala e cria uma política que define quando e como o dimensionamento ocorre. Assim como no Desafio 3, você usa o Locust para simular um pico de tráfego e o Prometheus para observar o desempenho do NGINX Ingress Controller quando o dimensionamento automático está habilitado.

Instale o KEDA

KEDA, um escalonador automático orientado a eventos para Kubernetes, integra um servidor de métricas (o componente que armazena e transforma métricas para o Kubernetes) e pode consumir métricas diretamente do Prometheus (assim como de outras ferramentas). Ele cria um Horizontal Pod Autoscaler (HPA) com essas métricas, faz a ponte com as métricas coletadas pelo Prometheus e as fornece ao Kubernetes.

Assim como no caso do NGINX Ingress Controller e do Prometheus, o tutorial usa o Helm para instalar o KEDA.

  1. Adicione o KEDA ao repositório do Helm:
$ helm repo add kedacore https://kedacore.github.io/charts 
"kedacore" has been added to your repositories 
  1. Instale o KEDA:
$ helm install keda kedacore/keda NAME: keda 
NAMESPACE: default 
STATUS: deployed 
REVISION: 1 
TEST SUITE: None
  1. Verifique se o KEDA está sendo executado como dois pods. (Para facilitar a leitura, alguns valores na coluna NAME foram abreviados. Além disso, a coluna RESTARTS foi omitida; o valor é 0 para todos os pods.)
$ kubectl get pods NAME                                    READY  STATUS     AGE 
keda-operator-8644dcdb79-492x5 1/1 Running 59s keda-operator-metrics-apiserver-66d... 1/1 Running 59s 
locust-77c699c94d-dvb5n                 1/1    Running  8m59s 
main-nginx-ingress-779b74bb8b-v7ggw     1/1    Running    48m 
podinfo-5d76864686-c98rb                1/1    Running    50m 
prometheus-alertmanager-d6d94cf4b-8...  2/2    Running    37m 
prometheus-kube-state-metrics-7cd8f...  1/1    Running    37m 
prometheus-node-exporter-j4qf4          1/1    Running    37m 
prometheus-pushgateway-56745d8d8b-9n4nl 1/1    Running    37m 
prometheus-server-b78c9449f-6ktn9       2/2    Running    37m

Crie uma política de escalonamento automático

Agora, use a definição de recurso personalizado (CRD) ScaledObject do KEDA para definir os parâmetros que determinam como o NGINX Ingress Controller é dimensionado. A configuração a seguir:

  • Aciona o dimensionamento automático com base no valor da métrica nginx_connections_active coletada pelo Prometheus
  • Implanta um novo pod quando cada pod existente atinge 100 conexões ativas
  • Dimensiona automaticamente os pods do NGINX Ingress Controller, de um único pod até 20 pods

Siga estas etapas:

  1. Usando o editor de texto de sua preferência, crie um arquivo YAML chamado 4-scaled-object.yaml com o conteúdo a seguir (ou copie do GitHub). Ele define um ScaledObject do KEDA.
apiVersion: keda.sh/v1alpha1 kind: ScaledObject 
metadata: 
 name: nginx-scale 
spec: 
 scaleTargetRef: 
   kind: Deployment 
   name: main-nginx-ingress 
minReplicaCount: 1 
maxReplicaCount: 20 
cooldownPeriod: 30 
pollingInterval: 1 
triggers: 
- type: prometheus 
  metadata: 
    serverAddress: http://prometheus-server 
    metricName: nginx_connections_active_keda 
    query: | 
      sum(avg_over_time(nginx_ingress_nginx_connections_active{app="main-nginx-ingress"}[1m])) 
    threshold: "100" 
  1. Implante o ScaledObject:
$ kubectl apply -f 4-scaled-object.yaml scaledobject.keda.sh/nginx-scale created 

Simule um pico de tráfego e observe o efeito do escalonamento automático no desempenho

Para realmente testar a eficácia do dimensionamento automático, você dobra o número de conexões em comparação com o Desafio 3.

  1. Volte ao servidor do Locust no navegador. Insira os valores a seguir nos campos e clique no botão Start swarming:
    • Número de usuários – 2000
    • Taxa de geração – 10
    • Host – http://main-nginx-ingress
  2. Volte aos painéis do Prometheus e do Locust. A caixa rosa abaixo do gráfico do Prometheus mostra o número de pods do NGINX Ingress Controller aumentando e diminuindo conforme o escalonamento.
  3. Volte ao terminal e inspecione manualmente o HPA do KEDA. O campo REPLICAS na saída mostra o número atual de réplicas de pods implantadas. (A saída está distribuída em duas linhas para facilitar a leitura.)
$ kubectl get hpa
NAME                  REFERENCE                      ... 
keda-hpa-nginx-scale  Deployment/main-nginx-ingress  ... 

    ... TARGETS           MINPODS   MAXPODS   REPLICAS   AGE 
    ... 101500m/100 (avg) 1         20        10         2m45s

Próximos passos

Há uma possível limitação quando o dimensionamento automático se baseia apenas no número de conexões ativas. Se, mesmo com o dimensionamento, o NGINX Ingress Controller ficar tão sobrecarregado a ponto de precisar descartar conexões, o dimensionador automático detectará menos conexões ativas, interpretará isso como uma redução nas solicitações e diminuirá o número de réplicas. Isso pode piorar o desempenho, mas o uso de uma combinação de métricas pode evitar que isso aconteça. Por exemplo, nginxplus_connections_dropped (disponível com o NGINX Ingress Controller baseado no NGINX Plus) monitora essas conexões de clientes descartadas.

Para experimentar o NGINX Ingress Controller com o NGINX Plus e o NGINX App Protect, inicie sua avaliação gratuita de 30 dias hoje mesmo ou entre em contato conosco para conversar sobre seus casos de uso.

Para experimentar o NGINX Ingress Controller com o NGINX Open Source, você pode obter o código-fonte da versão, ou baixar um contêiner pré-compilado do DockerHub.


Compartilhar

Publicações relacionadas no blog

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade
NGINX | 10/10/2024

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade

Descubra como o F5 NGINX One aprimora o gerenciamento e a observabilidade de ambientes híbridos e multicloud ao oferecer um console web centralizado baseado em SaaS, com insights em tempo real, conformidade automatizada e gerenciamento simplificado de configurações.

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa
NGINX | 17/06/2024

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa

Descubra como transformar uma definição de esquema OpenAPI em uma configuração NGINX totalmente funcional, operando como um API Gateway com a segurança de um Web Application Firewall e um Portal do Desenvolvedor, usando uma abordagem declarativa de API.

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor
NGINX | 14/07/2021

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor

Picos de tráfego e sobrecarga de servidores são preocupações sérias para varejistas online em qualquer época, mas especialmente durante a “Cyber Season” de compras de fim de ano. Detalhamos como você pode aproveitar as soluções de entrega de aplicações de nível de produção da NGINX para se preparar para aumentos repentinos de tráfego.

Distribuição segura de chaves privadas SSL com o NGINX
NGINX | 02/04/2019

Distribuição segura de chaves privadas SSL com o NGINX

Descrevemos três maneiras progressivamente mais seguras de proteger chaves privadas SSL ao configurar o NGINX para processar tráfego HTTPS: permitir acesso de leitura apenas ao usuário root, criptografar as chaves com senhas armazenadas separadamente e distribuir as senhas a partir de um repositório central.

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX
NGINX | 24/05/2018

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX

O módulo JavaScript do NGINX lançado com o NGINX Plus R15 oferece suporte a subsolicitações, possibilitando uma classe totalmente nova de casos de uso para o NGINX Plus. Este exemplo completo também usa a API do NGINX Plus e os módulos de chave-valor para converter solicitações de API dos clientes em solicitações separadas para as APIs dos microsserviços que compõem um aplicativo.

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus
NGINX | 19/04/2016

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus

Confira dicas para evitar o esgotamento de portas efêmeras com ajustes no kernel do Linux, conexões keepalive e conexões vinculadas dinamicamente a endereços IP locais.