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:
Antes de iniciar a demonstração real, realizamos estes pré-requisitos:
Instalou o plano de controle NGINX Server Mesh no cluster Kubernetes e configurou o mTLS e a política estrita
para o service mesh .
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.
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
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
...
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
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
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:
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
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."