O Ingress é um recurso do Kubernetes que permite acessar serviços dentro do cluster via HTTP e HTTPS. Ele fornece roteamento com base em URLs, domínios e outros parâmetros.
Neste artigo, vamos explorar o uso do Nginx Ingress com três Deployments Nginx simulando três serviços diferentes. Também configuraremos um certificado SSL para proteger a conexão.
Primeiro, é necessário instalar o Nginx Ingress no cluster.
No painel de gerenciamento do cluster:
Após a instalação, verifique se o Ingress está funcionando corretamente executando:
kubectl get pods -n ingress-nginx
Certifique-se de que todos os pods estejam com o status Running.
Vamos considerar um exemplo de uso do NGINX Ingress. Implantaremos três Deployments baseados em imagens Nginx, cada um simulando um serviço separado.
Para cada Deployment, criaremos um Service do tipo ClusterIP — o tipo padrão no Kubernetes — que fornece um IP interno dentro do cluster. Esse tipo de serviço não é acessível diretamente de fora do cluster; no entanto, pode ser exposto externamente usando um Ingress.
Para facilitar, criaremos um namespace separado para conter todos os manifests:
kubectl create namespace ingress-example
Para diferenciar os serviços, criaremos um ConfigMap contendo três páginas HTML distintas.
Crie o arquivo configmap.yaml com o seguinte conteúdo:
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>
Em seguida, vamos definir os Deployments.
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: index.html
---
apiVersion: v1
kind: Service
metadata:
name: service1
namespace: ingress-example
spec:
selector:
app: service1
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Explicação do manifesto:
replicas: 2 especifica que dois pods Nginx estarão em execução.selector e template.metadata.labels definem como o Service localizará os pods.volumeMounts e volumes são usados para montar o arquivo service1.html do ConfigMap no diretório padrão de conteúdo do Nginx.ClusterIP significa que o serviço ficará acessível apenas dentro do cluster por meio de um IP interno. Para acesso externo, usaremos o Ingress.Os manifests de service2 e service3 são semelhantes, diferindo apenas no nome do serviço e no arquivo HTML utilizado.
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: index.html
---
apiVersion: v1
kind: Service
metadata:
name: service2
namespace: ingress-example
spec:
selector:
app: service2
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
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: 80
type: ClusterIP
Aplique os manifests:
kubectl apply -f configmap.yaml
kubectl apply -f service1-deployment.yaml
kubectl apply -f service2-deployment.yaml
kubectl apply -f service3-deployment.yaml
Verifique o status dos pods:
kubectl get pods -n ingress-example
Todos devem estar com o status Running.
Com o Ingress, definiremos qual tráfego (com base em domínios e caminhos) será redirecionado para os serviços correspondentes.
Crie o manifesto ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: ingress-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
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: 80
- host: ingress2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service3
port:
number: 80
Explicação do manifesto:
rules.host especifica o domínio ao qual o Ingress será vinculado.paths define as regras de roteamento:
ingress1.example.com/service1 → service1ingress1.example.com/service2 → service2ingress2.example.com/ → service3Aplique o manifesto:
kubectl apply -f ingress.yaml
Para acessar o Nginx Ingress a partir de uma rede externa, criaremos um Service do tipo LoadBalancer, que fará o balanceamento de carga e fornecerá um IP externo.
Prepare o manifesto loadbalancer.yaml:
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
spec:
selector:
app.kubernetes.io/name: ingress-nginx
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
type: LoadBalancer
Aplique:
kubectl apply -f loadbalancer.yaml
Aguarde a criação do load balancer e verifique se ele recebeu um IP externo:
kubectl get services -n ingress-nginx
O IP externo será exibido na coluna EXTERNAL-IP.
Adicione esse IP externo como registros A no DNS dos domínios ingress1.example.com e ingress2.example.com.
Após a propagação do DNS, você poderá acessar:
http://ingress1.example.com/service1 — exibirá "Welcome to Service 1!"http://ingress1.example.com/service2 — exibirá "Welcome to Service 2!"http://ingress2.example.com/ — exibirá "Welcome to Service 3!"Para garantir uma conexão segura no Nginx Ingress, adicione um certificado SSL existente como Secret do Kubernetes e especifique esse secret no manifesto do Ingress.
Se quiser automatizar a emissão e renovação de certificados (por exemplo, com Let’s Encrypt), use o cert-manager.
Salve localmente os arquivos:
tls.key (chave privada)tls.crt (certificado)Certifique-se de que o certificado não esteja expirado e corresponda aos domínios que você deseja proteger.
Para adicionar o certificado ao cluster, codifique os arquivos em Base64:
base64 -w 0 ./tls.crt
base64 -w 0 ./tls.key
Depois, crie o arquivo tls-secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: ingress-example-tls
namespace: ingress-example
type: kubernetes.io/tls
data:
tls.crt: |-
<BASE64_ENCODED_CERTIFICATE>
tls.key: |-
<BASE64_ENCODED_KEY>
Aplique:
kubectl apply -f tls-secret.yaml
Verifique se os valores não estão vazios:
kubectl describe secret ingress-example-tls -n ingress-example
Atualize o ingress.yaml adicionando a seção tls e referenciando o secret criado:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: ingress-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- ingress1.example.com
- ingress2.example.com
secretName: ingress-example-tls
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: 80
- host: ingress2.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service3
port:
number: 80
Agora, ao acessar ingress1.example.com ou ingress2.example.com via HTTPS, o navegador usará o certificado armazenado no secret ingress-example-tls. Isso garante que o tráfego para seus serviços esteja protegido.
Se você tiver vários certificados para domínios diferentes, crie um Secret para cada um (por exemplo, example.com e example.org) e adicione uma seção tls separada para cada domínio:
spec:
tls:
- hosts:
- example.com
secretName: example-com-tls
- hosts:
- example.org
secretName: example-org-tls