Configurar Serviços Públicos e Privados com Duas Instâncias do Traefik
Quando um cluster Kubernetes hospeda serviços voltados para a internet e serviços internos ao mesmo tempo, a abordagem mais limpa é dividir o tráfego de entrada no nível do ingress controller. Para isso, você pode implantar duas instâncias separadas do Traefik: uma para lidar com o ingress público e outra para o ingress privado.
Este guia apresenta essa configuração passo a passo. Você vai implantar dois releases Helm do Traefik com IngressClasses diferentes e, em seguida, rotear o tráfego para os serviços públicos e internos.
Como funciona Copiar link
Duas instâncias independentes do Traefik são executadas no cluster:
traefik-publicprocessa apenas recursos Ingress comingressClassName: publictraefik-privateprocessa apenas recursos Ingress comingressClassName: private
Cada instância cria seu próprio serviço do tipo LoadBalancer com parâmetros diferentes:
- O Traefik público recebe um IP externo e aceita tráfego da internet
- O Traefik privado cria um load balancer interno sem IP público, acessível apenas dentro da rede privada
Dessa forma, você pode usar um único cluster tanto para aplicações externas quanto internas, sem misturar seus pontos de entrada.
Pré-requisitos Copiar link
Antes de começar, certifique-se de que você tem:
- helm instalado
- Um cluster Kubernetes em execução
- Acesso à rede privada do cluster para testar o ingress privado (por exemplo, via um servidor em nuvem separado na mesma rede)
Configurar o Traefik Copiar link
As duas instâncias do Traefik são implantadas a partir do mesmo chart Helm, mas com arquivos de values separados.
Configuração do Traefik público Copiar link
Crie um arquivo chamado traefik-public-values.yaml com o seguinte conteúdo:
fullnameOverride: traefik-public
ingressClass:
enabled: true
isDefaultClass: false
name: public
service:
enabled: true
type: LoadBalancer
providers:
kubernetesCRD:
enabled: true
allowCrossNamespace: false
ingressClass: public
kubernetesIngress:
enabled: true
ingressClass: public
publishedService:
enabled: trueEsse arquivo configura a instância pública do Traefik para processar recursos ingress da classe public e criar um LoadBalancer padrão com IP externo.
Parâmetros importantes:
ingressClass.name: public define o nome da classe que os recursos Ingress públicos vão referenciarproviders.kubernetesCRD.ingressClasseproviders.kubernetesIngress.ingressClassrestringem o Traefik apenas aos recursos da sua própria classepublishedService.enabled: truepermite a publicação correta do endereço do serviço de ingress
Configuração do Traefik privado Copiar link
Crie um arquivo chamado traefik-private-values.yaml com o seguinte conteúdo:
fullnameOverride: traefik-private
ingressClass:
enabled: true
isDefaultClass: false
name: private
service:
enabled: true
type: LoadBalancer
annotations:
k8s.hostman.com/attached-loadbalancer-no-external-ip: "true"
providers:
kubernetesCRD:
enabled: true
allowCrossNamespace: false
ingressClass: private
kubernetesIngress:
enabled: true
ingressClass: private
publishedService:
enabled: trueEsse arquivo configura a instância privada do Traefik para processar recursos ingress da classe private e criar um load balancer interno sem IP público.
O parâmetro principal aqui é k8s.hostman.com/attached-loadbalancer-no-external-ip: "true", que instrui a plataforma a provisionar um load balancer interno sem endereço IP público.
Instalar as duas instâncias do Traefik Copiar link
Adicione o repositório Helm do Traefik:
helm repo add traefik https://helm.traefik.io/traefik
helm repo updateImplante a instância pública:
helm install traefik-public traefik/traefik \
-n traefik-public --create-namespace \
-f traefik-public-values.yamlImplante a instância privada:
helm install traefik-public traefik/traefik \
-n traefik-public --create-namespace \
-f traefik-public-values.yamlApós a instalação, verifique se os serviços do tipo LoadBalancer foram criados:
kubectl get svc -n traefik-public
kubectl get svc -n traefik-privateO comportamento esperado é diferente para cada instância:
traefik-publicdeve receber um endereço IP externotraefik-privatenão receberá IP externo, pois utiliza um load balancer interno
Você também pode acompanhar o status dos load balancers pelo painel de controle da Hostman. Aguarde a conclusão do provisionamento antes de prosseguir.
Nessa etapa, confirme também que as duas classes de ingress estão registradas no cluster:
kubectl get ingressclassA saída deve listar tanto public quanto private.
Rotear tráfego para serviços públicos e privados Copiar link
Com as duas instâncias do Traefik em execução, basta definir o ingressClassName adequado em cada manifesto Ingress.
Para um serviço público:
spec:
ingressClassName: publicPara um serviço privado:
spec:
ingressClassName: privateTodo o tráfego será roteado automaticamente pelo ingress controller correspondente.
Exemplo prático Copiar link
Os manifestos abaixo demonstram a configuração completa. O exemplo inclui:
- Dois serviços públicos:
service1eservice2 - Um serviço privado:
service3 - Dois recursos Ingress com
IngressClassesdiferentes
ConfigMap com páginas HTML de teste
Crie config-map.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: service-config
namespace: ingress-example
data:
service1.html: |
<html>
<head><title>Service 1</title></head>
<body><h1>Welcome to Service 1!</h1></body>
</html>
service2.html: |
<html>
<head><title>Service 2</title></head>
<body><h1>Welcome to Service 2!</h1></body>
</html>
service3.html: |
<html>
<head><title>Service 3</title></head>
<body><h1>Welcome to Service 3!</h1></body>
</html>Serviço público service1
Crie service1-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: service1
namespace: ingress-example
spec:
replicas: 2
selector:
matchLabels:
app: service1
template:
metadata:
labels:
app: service1
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /usr/share/nginx/html
volumes:
- name: config-volume
configMap:
name: service-config
items:
- key: service1.html
path: service1.html
---
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: ingress-example
spec:
selector:
app: service1
ports:
- protocol: TCP
port: 80
targetPort: 80Serviço público service2
Crie service2-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: service2
namespace: ingress-example
spec:
replicas: 2
selector:
matchLabels:
app: service2
template:
metadata:
labels:
app: service2
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /usr/share/nginx/html
volumes:
- name: config-volume
configMap:
name: service-config
items:
- key: service2.html
path: service2.html
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: ingress-example
spec:
selector:
app: service2
ports:
- protocol: TCP
port: 80
targetPort: 80Serviço privado service3
Crie service3-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: service3
namespace: ingress-example
spec:
replicas: 2
selector:
matchLabels:
app: service3
template:
metadata:
labels:
app: service3
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /usr/share/nginx/html
volumes:
- name: config-volume
configMap:
name: service-config
items:
- key: service3.html
path: index.html
---
apiVersion: v1
kind: Service
metadata:
name: service3
namespace: ingress-example
spec:
selector:
app: service3
ports:
- protocol: TCP
port: 80
targetPort: 80Ingress público
Crie ingress-public.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-public-ingress
namespace: ingress-example
spec:
ingressClassName: public
rules:
- host: ingress1.example.com
http:
paths:
- path: /service1
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
- path: /service2
pathType: Prefix
backend:
service:
name: service2
port:
number: 80Observe que spec.ingressClassName está definido como public, o que significa que este Ingress será processado pelo ingress controller público.
Ingress privado
Crie ingress-private.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-private-ingress
namespace: ingress-example
spec:
ingressClassName: private
rules:
- host: ingress2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service3
port:
number: 80Aqui spec.ingressClassName está definido como private, portanto este Ingress será processado pelo ingress controller privado.
Aplicar os manifestos
Crie o namespace ingress-example:
kubectl create namespace ingress-exampleAplique todos os manifestos:
kubectl apply -f config-map.yaml
kubectl apply -f service1-deployment.yaml
kubectl apply -f service2-deployment.yaml
kubectl apply -f service3-deployment.yaml
kubectl apply -f ingress-public.yaml
kubectl apply -f ingress-private.yamlVerifique se os deployments, serviços e recursos de ingress foram criados:
kubectl get deploy,svc,ingress -n ingress-exampleVocê deve ver três serviços, três deployments e dois recursos de ingress. Se algum estiver faltando, o manifesto correspondente não foi aplicado ou contém um erro.
Com essa configuração:
- Requisições para
ingress1.example.com/service1...são roteadas para oservice1 - Requisições para
ingress1.example.com/service2...são roteadas para oservice2 - Requisições para
ingress2.example.com/são roteadas para oservice3, acessível apenas dentro da rede privada via load balancer interno do Traefik
Verificar a configuração Copiar link
Antes de enviar requisições de teste, confirme que cada ingress tem a classe correta atribuída:
kubectl describe ingress example-public-ingress -n ingress-example
kubectl describe ingress example-private-ingress -n ingress-exampleCertifique-se de que example-public-ingress exibe Ingress Class: public e example-private-ingress exibe Ingress Class: private. Se a classe não corresponder, o Traefik não vai processar esse recurso.
Quando o load balancer público tiver um IP externo, teste as rotas:
curl http://ingress1.example.com/service1.html \
--resolve ingress1.example.com:80:PUBLIC_LB_EXTERNAL_IP
curl http://ingress1.example.com/service2.html \
--resolve ingress1.example.com:80:PUBLIC_LB_EXTERNAL_IPOnde PUBLIC_LB_EXTERNAL_IP é o IP externo atribuído ao load balancer público.
Se você receber um erro 404, verifique se está usando o hostname ingress1.example.com e os caminhos /service1 ou /service2.
Para testar o serviço privado, execute o comando abaixo a partir de uma máquina dentro da mesma rede privada do cluster:
curl http://ingress2.example.com/ \
--resolve ingress2.example.com:80:PRIVATE_LB_IPOnde PRIVATE_LB_IP é o IP privado do load balancer interno.
Você deve receber uma página HTML servida pelo service3.
Se a rota privada não responder, confirme que a requisição está partindo de dentro da rede privada. Tráfego externo não consegue alcançar esse ingress, mesmo que os recursos no cluster estejam configurados corretamente.