BLOG | NGINX

Como simplificar o gerenciamento de tráfego de entrada e saída do Kubernetes

Miniatura de Kate Osborn
Kate Osborn
Publicado em 28 de junho de 2021

Uma das maneiras pelas quais uma malha de serviço pode realmente tornar mais complicado o gerenciamento de um ambiente Kubernetes é quando ela deve ser configurada separadamente do controlador Ingress . Configurações separadas não são apenas demoradas. Eles aumentam a probabilidade de erros de configuração que podem impedir o roteamento adequado do tráfego e até mesmo levar a vulnerabilidades de segurança (como agentes mal-intencionados obtendo acesso a aplicativos restritos) e experiências ruins (como clientes não conseguindo acessar aplicativos para os quais estão autorizados). Além do tempo que leva para executar configurações separadas, você acaba gastando mais tempo solucionando erros.

Você pode evitar esses problemas – e economizar tempo – integrando o NGINX Ingress Controller baseado no NGINX Plus com o NGINX Service Mesh para controlar o tráfego mTLS de entrada e saída. Nesta demonstração em vídeo, abordamos todas as etapas.

A documentação de suporte é referenciada nas seguintes seções:

Pré-requisitos (0:18)

Antes de iniciar a demonstração real, realizamos estes pré-requisitos:

  1. Instalou o plano de controle NGINX Server Mesh no cluster Kubernetes e configurou o mTLS e a política estrita para o service mesh .

  2. Instalou o NGINX Ingress Controller baseado no NGINX Plus como uma implantação (em vez de um DaemonSet) no cluster Kubernetes, habilitou o egress e o expôs como um serviço do tipo LoadBalancer .

    Observação:  A demonstração não funciona com o NGINX Ingress Controller baseado em código aberto NGINX. Para facilitar a leitura, nos referimos ao NGINX Ingress Controller baseado no NGINX Plus simplesmente como “NGINX Ingress Controller” no restante deste blog.

  3. Siga nossas instruções para baixar o aplicativo de exemplo bookinfo , injetar o sidecar do NGINX Service Mesh e implantar o aplicativo.

Como resultado da política rigorosa criada na Etapa 1, solicitações ao aplicativo bookinfo de clientes fora da malha são negadas no sidecar. Ilustramos isso na demonstração executando primeiro o seguinte comando para configurar o encaminhamento de porta:

> kubectl port-forward svc/product-page 9080Forwarding from 127.0.0.1:9080 -> 9080
Forwarding from [::1]:9080 -> 9080
Handling connection for 9080

Quando tentamos acessar o aplicativo, obtemos o código de status503 porque nossa máquina local não faz parte da malha de serviço:

> curl localhost:9080503

Implantando o NGINX Ingress Controller com o NGINX Service Mesh (1:50)

O primeiro estágio no processo de exposição de um aplicativo é implantar uma instância do NGINX Ingress Controller. Instruções correspondentes são fornecidas em nosso tutorial, Implantar com o NGINX Plus Ingress Controller para Kubernetes .

O NGINX fornece manifestos de implantação e DaemonSet para essa finalidade. Na demonstração, usamos o manifesto de implantação, nginx-plus-ingress.yaml . Inclui anotações para rotear o tráfego de entrada e saída pela mesma instância do NGINX Ingress Controller:

O manifesto permite a integração direta do NGINX Ingress Controller com o Spire, a autoridade de certificação (CA) do NGINX Service Mesh, eliminando a necessidade de injetar o sidecar do NGINX Service Mesh no NGINX Ingress Controller. Em vez disso, o NGINX Ingress Controller busca certificados e chaves diretamente do Spire CA para usar no mTLS com os pods na malha. O manifesto especifica o endereço do agente Spire:

e monta o soquete UNIX do agente Spire no pod do NGINX Ingress Controller:

A última coisa a ser observada sobre o manifesto é o argumento CLI -enable-internal-routes , que nos permite rotear para serviços de saída:

Antes de iniciar a demonstração, executamos o comando kubectl apply -f nginx-plus-ingress.yaml para instalar o NGINX Ingress Controller e, neste ponto, inspecionamos a implantação no namespace nginx-ingress . Conforme mostrado na coluna READY da saída a seguir, há apenas um contêiner para o pod do NGINX Ingress Controller, porque não o injetamos com um sidecar do NGINX Service Mesh.

Também implantamos um serviço do tipo LoadBalancer para expor o endereço IP externo do NGINX Ingress Controller (aqui, 35.233.133.188) fora do cluster. Acessaremos o aplicativo bookinfo de exemplo nesse endereço IP.

> kubectl get pods --namespace=nginx-ingressNAME                                 READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-867f954b8f0fzdrm   1/1     Running   0          3d3h

NAME                    TYPE           CLUSTER-IP      EXTERNAL-IP      ...
service-nginx-ingress   LoadBalancer   10.31.245.207   35.233.133.188   ...

      ... PORT(S)                      AGE
      ... 80:31469/TCP,443:32481/TCP   4d2h
...

Usando um recurso de entrada padrão do Kubernetes para expor o aplicativo (3:55)

Agora expomos o aplicativo bookinfo na malha, usando um recurso padrão do Kubernetes Ingress, conforme definido em bookinfo-ingress.yaml . Instruções correspondentes são fornecidas em nosso tutorial, Expor um aplicativo com o NGINX Plus Ingress Controller .

O recurso faz referência a um segredo do Kubernetes para o aplicativo bookinfo na linha 10 e inclui uma regra de roteamento que especifica que as solicitações para bookinfo.example.com são enviadas ao serviço productpage ( linhas 11–18 ). O Segredo é definido em bookinfo-secret.yaml :

Executamos este comando para carregar a chave e o certificado, que na demonstração é autoassinado:

> kubectl apply -f bookinfo-secret.yamlsecret/bookinfo-secret unchanged

Ativamos o recurso Ingress:

> kubectl apply -f bookinfo-ingress.yamlingress.networking.k8s.io/bookinfo-ingress deleted

e verifique se o Ingress Controller adicionou a rota definida no recurso, conforme confirmado pelo evento no final da saída:

> kubectl describe ingress bookinfo-ingress...
Events:
  Type    Reason          Age   From                      Message
  ----    ------          ----  ----                      -------
  Normal  AddedOrUpdated  5s    nginx-ingress-controller  Configuration for ...
        ...default/bookinfo-ingress was added or updated

Na demonstração, agora usamos um navegador para acessar o aplicativo bookinfo em https://bookinfo.example.com/ . (Adicionamos anteriormente um mapeamento no arquivo local /etc/hosts entre o endereço IP do serviço Ingress Controller – 35.233.133.188 na demonstração, conforme observado acima – e bookinfo.example.com . Para obter instruções, consulte a documentação .) As informações na seção Resenhas de livros da página mudam periodicamente conforme as solicitações passam pelas três versões do serviço de resenhas definido em bookinfo.yaml ( download ).

Em seguida, inspecionamos o tráfego de entrada nos clusters. Executamos o script generate-traffic.sh para fazer solicitações ao serviço productpage por meio do endereço IP público do NGINX Ingress Controller e, em seguida, executamos o comando nginx-meshctl top para monitorar o tráfego:

> nginxmesh-ctl top deploy/productpage-v1Deployment       Direction  Resource       Success Rate  P99    P90    P50   ...
productpage-v1  
                 To         details-v1     100.00%       3ms    3ms    2ms   
                 To         reviews-v2     100.00%       99ms   90ms   20ms
                 To         reviews-v3     100.00%       99ms   85ms   18ms
                 To         reviews-v1     100.00%       20ms   17ms   9ms
                 From       nginx-ingress  100.00%       192ms  120ms  38ms

      ... NumRequests 
      ... 14
      ... 5
      ... 5
      ... 12

Usando um recurso NGINX VirtualServer para expor o aplicativo (6:45)

A seguir, mostramos uma maneira alternativa de expor um aplicativo, usando um recurso NGINX VirtualServer . É um recurso personalizado do NGINX Ingress Controller que oferece suporte ao tratamento de tráfego mais complexo, como divisão de tráfego e roteamento baseado em conteúdo.

Primeiro, excluímos o recurso padrão do Ingress:

> kubectl delete -f bookinfo-ingress.yamlingress.networking.k8s.io "bookinfo-ingress" deleted

Nosso arquivo bookinfo-vs.yaml configura o mTLS com o mesmo segredo do bookinfo-ingress.yaml ( linhas 7–8 ). As linhas 9 a 12 definem o serviço productpage como upstream, e as linhas 13 a 24, uma rota que envia todas as solicitações GET feitas em bookinfo.example.com para esse upstream. Para métodos HTTP diferentes de GET , ele retorna o código de status405 .

Aplicamos o recurso:

> kubectl apply -f bookinfo-vs.yamlvirtualserver.kubernetes.nginx.org/bookinfo-vs created

Em seguida, realizamos as mesmas etapas do recurso Ingress: executando o comando kubectl describe para confirmar a implantação correta e acessar o aplicativo em um navegador. Outra confirmação de que o aplicativo está funcionando corretamente é que ele rejeita o método POST :

> curl -k -X POST https://bookinfo.example.com/Method not allowed

Configurando uma rota de saída segura com o NGINX Ingress Controller (8:44)

Agora mostraremos como rotear o tráfego de saída por meio do NGINX Ingress Controller. Nosso tutorial Configurar uma rota de saída segura com o NGINX Plus Ingress Controller aborda o processo usando diferentes aplicativos de exemplo.

Já definimos um pod bash simples em bash.yaml e o implantamos no namespace padrão de onde estamos enviando solicitações. Conforme mostrado na coluna PRONTO desta saída, ele foi injetado com o sidecar do NGINX Service Mesh.

> kubectl get allNAME                        READY  STATUS    RESTARTS   AGE
pod/bash-6ccb678958-zsgm7   2/2    Running   0          77s

NAME                 TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.31.240.1   <none>        443/TCP   4d2h
...

Há vários casos de uso em que você pode querer habilitar solicitações de dentro do pod para um serviço de saída , que é qualquer entidade que não faça parte do NGINX Service Mesh. Exemplos são serviços implantados:

  • Fora do cluster
  • Em outro cluster
  • No mesmo cluster, mas não injetado com o sidecar NGINX Service Mesh

Na demonstração, estamos considerando o caso de uso final. Temos um aplicativo implantado no namespace legado , que não é controlado pelo NGINX Service Mesh e onde a injeção automática do sidecar do NGINX Service Mesh está desabilitada. Há apenas um pod em execução para o aplicativo.

> kubectl get all --namespaces=legacyNAME                          READY  STATUS    RESTARTS   AGE
pod/target-5f7bcb96c6-km9lz   1/1    Running   0          27m

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/target-svc   ClusterIP   10.31.245.213   <none>        80/TCP,443/TCP   27m
...

Lembre-se de que configuramos uma política mTLS rigorosa para o NGINX Service Mesh; como resultado, não podemos enviar solicitações diretamente do pod bash para o serviço de destino, porque os dois não podem se autenticar um com o outro. Quando tentamos, obtemos o código de status503 conforme ilustrado aqui:

> kubectl exec -it bash-6ccb678958-zsgm7 -c bash -- curl target-svc.legacycurl: (56) Recv failure: connection reset by peer
503command terminated with exit code 56

A solução é permitir que o pod bash envie tráfego de saída por meio do NGINX Ingress Controller. Descomentamos a anotação nas linhas 14–15 de bash.yaml :

Em seguida aplicamos a nova configuração:

> kubectl apply -f bash.yamldeployment.apps/bash configured

e verifique se um novo pod bash foi iniciado:

> kubectl get podsNAME                    READY  STATUS        RESTARTS   AGE
bash-678c8b4579-7sfml   2/2    Running       0          6s
bash-6ccb678958-zsgm7   2/2    Terminating   0          3m28s

Agora, quando executamos o mesmo comando kubectl exec de antes, para enviar uma solicitação do pod bash para o serviço de destino, obtemos o código de status404 em vez de503 . Isso indica que o pod bash enviou com sucesso a solicitação ao NGINX Ingress Controller, mas este não sabe para onde encaminhá-la porque nenhuma rota está definida.

Criamos a rota necessária com a seguinte definição de recurso Ingress em legacy-route.yaml . A anotação de rota interna na linha 7 significa que o serviço de destino não é exposto à Internet, mas apenas às cargas de trabalho no NGINX Service Mesh.

Ativamos o novo recurso e confirmamos que o NGINX Ingress Controller adicionou a rota definida no recurso:

> kubectl apply -f legacy-route.yamlingress.networking.k8s.io/target-internal-route created
> kubectl describe ingress target-internal-route -n legacy
...
Events:
  Type    Reason          Age   From                      Message
  ----    ------          ----  ----                      -------
  Normal  AddedOrUpdated  6s    nginx-ingress-controller  Configuration for ...
        ...legacy/target-internal-route was added or updated

Agora, quando executamos o comando kubectl exec , alcançamos o serviço de destino:

{"req": {"method": "GET"                "url": "/",
                "host": "target-svc.legacy",
                "remoteAddr": "10.28.2.76:56086"}}

Uma vantagem de rotear o tráfego de saída por meio do NGINX Ingress Controller é que você pode controlar exatamente quais serviços externos podem ser acessados de dentro do cluster – são apenas aqueles para os quais você define uma rota.

Uma última coisa que mostramos na demonstração é como monitorar o tráfego de saída. Executamos o comando kubectl exec para enviar várias solicitações e, em seguida, executamos este comando:

> nginxmesh-ctl top deploy/nginx-ingress -n nginx-ingressDeployment      Direction  Resource  Success Rate  P99  P90  P50  NumRequests
nginx-ingress  
                To         target    100.00%       1ms  1ms  1ms  9
                From       bash      100.00%       0ms  0ms  0ms  9

Diga “Não” à Latência – Experimente o NGINX Service Mesh com o NGINX Ingress Controller

Muitas malhas de serviço oferecem opções de gateway de entrada e saída, mas achamos que você apreciará um benefício adicional da integração com o NGINX: menor latência. A maioria das malhas exige que um sidecar seja injetado no controlador Ingress, o que exige que o tráfego faça um salto extra em seu caminho para seus aplicativos. Os segundos são importantes, e esse salto extra que torna suas experiências digitais mais lentas pode fazer com que os clientes procurem outro lugar. O NGINX Service Mesh não adiciona latência desnecessária porque não injeta um sidecar no NGINX Ingress Controller. Em vez disso, ao integrar-se diretamente com o Spire, a CA da malha, o NGINX Ingress Controller se torna parte do NGINX Service Mesh. O NGINX Ingress Controller simplesmente busca certificados e chaves do agente Spire e os usa para participar da troca de certificados mTLS com pods em malha.

Existem duas versões do NGINX Ingress Controller para Kubernetes: NGINX Open Source e NGINX Plus. Para implantar o NGINX Ingress Controller com o NGINX Service Mesh conforme descrito neste blog, você deve usar a versão NGINX Plus, que está disponível para um teste gratuito de 30 dias .

O NGINX Service Mesh é totalmente gratuito e está disponível para download imediato , podendo ser implantado em menos de 10 minutos! Para começar, confira a documentação e nos conte como foi via GitHub .


"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."