Configure reescritas de URL, TLS, mTLS, versões canário e o cert-manager para o NGINX Ingress.
Pré-requisitos
Verifique os seguintes itens:
Um cluster ACK gerenciado criado.
O controlador NGINX Ingress instalado e em execução.
O kubectl conectado ao cluster.
Um Deployment e um Service implantados no cluster.
Métodos de configuração do NGINX
O controlador NGINX Ingress no ACK é totalmente compatível com a versão upstream open source. Há três métodos disponíveis:
|
Método |
Escopo |
Referência |
|
Annotation |
Ingress individual: modifique um YAML de Ingress específico |
|
|
ConfigMap |
Todos os Ingresses: modifique o ConfigMap |
|
|
Modelo personalizado do NGINX |
Controle total: personalize o modelo do NGINX quando outros métodos forem insuficientes |
Configurar redirecionamento de URL
Por padrão, o controlador NGINX Ingress encaminha requisições usando o caminho completo. Se o caminho do backend for diferente, use a annotation nginx.ingress.kubernetes.io/rewrite-target para reescrevê-lo.
As versões 0.22.0 e posteriores do controlador NGINX Ingress exigem expressões regulares com grupos de captura no caminho, usadas em conjunto com a annotation rewrite-target .
Aplique o modelo correspondente à versão do Kubernetes do seu cluster.
Kubernetes 1.19 e posteriores
cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: foo.bar.com
namespace: default
annotations:
# Rewrite the request path: strip the /svc prefix and forward the remainder to the backend.
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /svc(/|$)(.*)
backend:
service:
name: web1-service
port:
number: 80
pathType: ImplementationSpecific
EOF
Kubernetes 1.19 ou anterior
cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: foo.bar.com
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /svc(/|$)(.*)
backend:
serviceName: web1-service
servicePort: 80
EOF
Verify the configuration:
-
Obtenha o endereço IP do Ingress.
kubectl get ingressSaída esperada:
NAME CLASS HOSTS ADDRESS PORTS AGE foo.bar.com nginx foo.bar.com 172.16.XX.XX 80 46m -
Envie uma requisição usando o endereço IP do Ingress obtido em
ADDRESS.curl -k -H "Host: foo.bar.com" http://<ADDRESS>/svc/fooSaída esperada:
web1: /fooO prefixo
/svcé removido e o backend recebe/foo.
Configurar regras de reescrita
A annotation nginx.ingress.kubernetes.io/rewrite-target lida com reescritas básicas de caminho. Para reescritas avançadas, use annotations de snippet para injetar configurações personalizadas do NGINX diretamente:
|
Annotation |
Bloco alvo |
Caso de uso |
|
|
Bloco |
Reescritas e redirecionamentos no nível do servidor |
|
|
Bloco |
Reescritas no nível de localização e cabeçalhos personalizados |
Exemplo:
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
rewrite ^/v4/(.*)/card/query http://foo.bar.com/v5/#!/card/query permanent;
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^/v6/(.*)/card/query http://foo.bar.com/v7/#!/card/query permanent;
Verifique o snippet no arquivo nginx.conf gerado:
kubectl exec nginx-ingress-controller-xxxxx --namespace kube-system -- cat /etc/nginx/nginx.conf
# Replace xxxxx with the actual pod name.
O server-snippet aparece no bloco server {} e o configuration-snippet no bloco location {}:
# start server foo.bar.com
server {
server_name foo.bar.com;
listen 80;
listen [::]:80;
set $proxy_upstream_name "-";
# server-snippet
rewrite ^/v4/(.*)/card/query http://foo.bar.com/v5/#!/card/query permanent;
...
# configuration-snippet
rewrite ^/v6/(.*)/card/query http://foo.bar.com/v7/#!/card/query permanent;
...
}
# end server foo.bar.com
Configure snippets globais com server-snippet no ConfigMap. Consulte a documentação do módulo de reescrita do NGINX para obter a sintaxe completa de rewrite.
Configurar um certificado TLS para o Ingress
Anexe um certificado TLS a um Ingress para habilitar HTTPS.
O domínio do certificado TLS deve corresponder ao valor host do Ingress. Uma incompatibilidade impede o carregamento do certificado pelo controlador.
Etapa 1: Criar o certificado e o Secret.
-
Gere um certificado autoassinado e uma chave privada.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout tls.key -out tls.crt \ -subj "/CN=foo.bar.com/O=foo.bar.com" -
Armazene o certificado e a chave em um Secret do Kubernetes.
kubectl create secret tls tls-test-ingress --key tls.key --cert tls.crt
Etapa 2: Criar um Ingress que referencie o Secret.
Kubernetes 1.19 e posteriores
cat <<EOF | kubectl create -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-test-ingress
spec:
tls:
- hosts:
- foo.bar.com
secretName: tls-test-ingress # Reference the Secret created above.
rules:
- host: tls-test-ingress.com
http:
paths:
- path: /foo
backend:
service:
name: web1-svc
port:
number: 80
pathType: ImplementationSpecific
EOF
Kubernetes 1.19 ou anterior
cat <<EOF | kubectl create -f -
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: test-test-ingress
spec:
tls:
- hosts:
- foo.bar.com
secretName: tls-test-ingress
rules:
- host: tls-test-ingress.com
http:
paths:
- path: /foo
backend:
serviceName: web1-svc
servicePort: 80
EOF
Atualize o arquivo hosts ou o DNS para resolver tls-test-ingress.com para o IP do Ingress. Acesse o serviço em https://tls-test-ingress.com/foo.
Configurar autenticação mútua TLS
O mTLS exige que servidor e cliente apresentem certificados durante o handshake TLS.
O mTLS é aplicado por host. Caminhos diferentes sob o mesmo host não podem ter configurações separadas.
Quatro annotations controlam o mTLS:
|
Annotation |
Descrição |
|
|
Habilita a verificação do certificado do cliente. Valores: |
|
|
O |
|
|
A profundidade máxima da cadeia de certificados do cliente. Padrão: |
|
|
Se definido como |
Etapa 1: Criar uma autoridade certificadora (CA) autoassinada.
openssl req -x509 -sha256 -newkey rsa:4096 \
-keyout ca.key -out ca.crt \
-days 356 -nodes \
-subj '/CN=Fern Cert Authority'
Saída esperada:
Generating a 4096 bit RSA private key
...
writing new private key to 'ca.key'
Etapa 2: Criar um certificado de servidor.
-
Gere a solicitação de assinatura de certificado (CSR).
openssl req -new -newkey rsa:4096 \ -keyout server.key -out server.csr \ -nodes -subj '/CN=foo.bar.com' -
Assine a CSR com a CA para gerar o certificado do servidor.
openssl x509 -req -sha256 -days 365 \ -in server.csr -CA ca.crt -CAkey ca.key \ -set_serial 01 -out server.crtSaída esperada:
Signature ok subject=/CN=foo.bar.com Getting CA Private Key
Etapa 3: Criar um certificado de cliente.
-
Gere a CSR do cliente.
openssl req -new -newkey rsa:4096 \ -keyout client.key -out client.csr \ -nodes -subj '/CN=Fern' -
Assine a CSR do cliente com a CA.
openssl x509 -req -sha256 -days 365 \ -in client.csr -CA ca.crt -CAkey ca.key \ -set_serial 02 -out client.crtSaída esperada:
Signature ok subject=/CN=Fern Getting CA Private Key
Etapa 4: Confirmar a presença de todos os arquivos de certificado.
ls
Saída esperada:
ca.crt ca.key client.crt client.csr client.key server.crt server.csr server.key
Etapa 5: Criar Secrets para os certificados da CA e do servidor.
kubectl create secret generic ca-secret --from-file=ca.crt=ca.crt
kubectl create secret generic tls-secret --from-file=tls.crt=server.crt --from-file=tls.key=server.key
Etapa 6: Criar o NGINX Ingress com as annotations de mTLS.
Kubernetes 1.19 e posteriores
cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret"
nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
name: nginx-test
namespace: default
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
service:
name: http-svc
port:
number: 80
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- foo.bar.com
secretName: tls-secret
EOF
Kubernetes 1.19 ou anterior
cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret"
nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
name: nginx-test
namespace: default
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: http-svc
servicePort: 80
path: /
tls:
- hosts:
- foo.bar.com
secretName: tls-secret
EOF
Etapa 7: Criar ou atualizar o arquivo /etc/hosts.
Obtenha o endereço IP do Ingress e adicione-o ao arquivo /etc/hosts.
kubectl get ing
Saída esperada:
NAME HOSTS ADDRESS PORTS AGE
nginx-test foo.bar.com 39.102.XX.XX 80, 443 4h42m
echo "39.102.XX.XX foo.bar.com" | sudo tee -a /etc/hosts
Verify the configuration:
-
Sem certificado de cliente: o servidor rejeita a requisição.
curl --cacert ./ca.crt https://foo.bar.comSaída esperada:
<html> <head><title>400 No required SSL certificate was sent</title></head> <body> <center><h1>400 Bad Request</h1></center> <center>No required SSL certificate was sent</center> <hr><center>nginx/1.19.0</center> </body> </html> -
Com certificado de cliente: a requisição é bem-sucedida.
curl --cacert ./ca.crt --cert ./client.crt --key ./client.key https://foo.bar.comSaída esperada: a página inicial padrão do nginx (
Welcome to nginx!).
Encaminhar requisições HTTPS para containers de backend
Por padrão, o controlador NGINX Ingress encaminha tráfego HTTP para os backends. Para backends HTTPS, adicione a annotation nginx.ingress.kubernetes.io/backend-protocol: "HTTPS".
Kubernetes 1.19 e posteriores
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: backend-https
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
tls:
- hosts:
- <your-host-name>
secretName: <your-secret-cert-name>
rules:
- host: <your-host-name>
http:
paths:
- path: /
backend:
service:
name: <your-service-name>
port:
number: <your-service-port>
pathType: ImplementationSpecific
Kubernetes 1.19 ou anterior
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: backend-https
annotations:
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
tls:
- hosts:
- <your-host-name>
secretName: <your-secret-cert-name>
rules:
- host: <your-host-name>
http:
paths:
- path: /
backend:
serviceName: <your-service-name>
servicePort: <your-service-port>
Substitua os espaços reservados pelos seus valores:
|
Espaço reservado |
Descrição |
|
|
Seu nome de domínio |
|
|
O Secret que contém seu certificado TLS |
|
|
Nome do seu Service de backend |
|
|
Porta do seu Service de backend |
Usar expressões regulares para nomes de domínio
O Kubernetes não suporta expressões regulares nos campos de host do Ingress por padrão. Use a annotation nginx.ingress.kubernetes.io/server-alias para adicionar aliases de servidor baseados em regex ao arquivo nginx.conf.
Etapa 1: Criar um Ingress com um alias de servidor regex.
Este exemplo corresponde a qualquer nome de host no formato www.<digits>.example.com e abc.example.com.
Kubernetes 1.19 e posteriores
cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-regex
namespace: default
annotations:
nginx.ingress.kubernetes.io/server-alias: '~^www\.\d+\.example\.com$, abc.example.com'
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
service:
name: http-svc1
port:
number: 80
pathType: ImplementationSpecific
EOF
Kubernetes 1.19 ou anterior
cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-regex
namespace: default
annotations:
nginx.ingress.kubernetes.io/server-alias: '~^www\.\d+\.example\.com$, abc.example.com'
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: http-svc1
servicePort: 80
EOF
Etapa 2: Verificar se os aliases estão ativos no nginx.conf.
-
Obtenha o nome do pod do controlador NGINX Ingress.
kubectl get pods -n kube-system | grep nginx-ingress-controllerSaída esperada:
nginx-ingress-controller-77cd987c4c-c**** 1/1 Running 0 1h nginx-ingress-controller-77cd987c4c-x**** 1/1 Running 0 1h -
Inspecione a configuração gerada.
kubectl exec -n kube-system nginx-ingress-controller-77cd987c4c-c**** cat /etc/nginx/nginx.conf | grep -C3 "foo.bar.com"Saída esperada — a diretiva
server_namelista todos os aliases:server { server_name foo.bar.com abc.example.com ~^www\.\d+\.example\.com$ ; listen 80 ; listen 443 ssl http2 ;
Etapa 3: Obter o endereço IP do Ingress.
kubectl get ing
Saída esperada:
NAME HOSTS ADDRESS PORTS AGE
ingress-regex foo.bar.com 101.37.XX.XX 80 11s
Etapa 4: Testar todos os nomes de host correspondentes.
Substitua <IP_ADDRESS> pelo endereço obtido na etapa anterior.
curl -H "Host: foo.bar.com" <IP_ADDRESS>/foo # /foo
curl -H "Host: www.123.example.com" <IP_ADDRESS>/foo # /foo
curl -H "Host: www.321.example.com" <IP_ADDRESS>/foo # /foo
Especificar nomes de domínio curinga
Os NGINX Ingresses suportam nativamente nomes de domínio curinga. Este exemplo corresponde a qualquer subdomínio de ingress-regex.com.
Etapa 1: Criar um Ingress com um host curinga.
Kubernetes 1.19 e posteriores
cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-regex
namespace: default
spec:
rules:
- host: "*.ingress-regex.com"
http:
paths:
- path: /foo
backend:
service:
name: http-svc1
port:
number: 80
pathType: ImplementationSpecific
EOF
Kubernetes 1.19 ou anterior
cat <<-EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-regex
namespace: default
spec:
rules:
- host: "*.ingress-regex.com"
http:
paths:
- path: /foo
backend:
serviceName: http-svc1
servicePort: 80
EOF
Etapa 2: Verificar o server_name no nginx.conf.
kubectl exec -n kube-system <nginx-ingress-pod-name> cat /etc/nginx/nginx.conf | grep -C3 "ingress-regex.com"
Substitua <nginx-ingress-pod-name> pelo nome real do pod.
Saída esperada (versões mais antigas do controlador):
# start server *.ingress-regex.com
server {
server_name *.ingress-regex.com ;
listen 80;
listen [::]:80;
...
}
# end server *.ingress-regex.com
Saída esperada (versões mais recentes do controlador):
## start server *.ingress-regex.com
server {
server_name ~^(?<subdomain>[\w-]+)\.ingress-regex\.com$ ;
listen 80;
listen [::]:80;
...
}
## end server *.ingress-regex.com
Etapa 3: Obter o endereço IP do Ingress.
kubectl get ing
Saída esperada:
NAME HOSTS ADDRESS PORTS AGE
ingress-regex *.ingress-regex.com 101.37.XX.XX 80 11s
Etapa 4: Testar a correspondência curinga.
Substitua <IP_ADDRESS> pelo endereço obtido na etapa anterior.
curl -H "Host: abc.ingress-regex.com" <IP_ADDRESS>/foo # /foo
curl -H "Host: 123.ingress-regex.com" <IP_ADDRESS>/foo # /foo
curl -H "Host: a1b1.ingress-regex.com" <IP_ADDRESS>/foo # /foo
Usar annotations para versões canário
Versões canário direcionam um subconjunto do tráfego para uma nova versão do serviço. Todas as configurações canário exigem a annotation nginx.ingress.kubernetes.io/canary: "true" no Ingress canário.
Estas annotations controlam a divisão de tráfego, avaliadas na seguinte ordem: baseada em cabeçalho → baseada em cookie → baseada em peso.
|
Annotation |
Valores |
Comportamento quando a condição não é atendida |
|
|
Inteiro de 0 a 100 (porcentagem) |
N/A — atua como último fallback |
|
|
Qualquer nome de cabeçalho |
Se o cabeçalho estiver ausente ou não corresponder nem a |
|
|
String personalizada (usada com |
Se o valor do cabeçalho não corresponder, passa para a próxima regra por precedência |
|
|
Nome do cookie |
O valor do cookie deve ser |
Versão canário baseada em peso
Direciona 20% do tráfego para o Service canário:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
Versão canário baseada em cabeçalho
Se o cabeçalho ack for always, o tráfego será roteado para o canário. Se for never, o canário é ignorado. Outros valores retornam ao peso (50%):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "50"
nginx.ingress.kubernetes.io/canary-by-header: "ack"
Versão canário baseada em cabeçalho com valor personalizado
Se o cabeçalho ack for igual a alibaba, o tráfego será roteado para o canário. Outros valores retornam ao peso (20%):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
nginx.ingress.kubernetes.io/canary-by-header: "ack"
nginx.ingress.kubernetes.io/canary-by-header-value: "alibaba"
Versão canário baseada em cookie
Se nenhuma regra de cabeçalho corresponder e o cookie hangzhou_region for always, o tráfego será roteado para o canário. Outros casos retornam ao peso (20%):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
nginx.ingress.kubernetes.io/canary-by-header: "ack"
nginx.ingress.kubernetes.io/canary-by-header-value: "alibaba"
nginx.ingress.kubernetes.io/canary-by-cookie: "hangzhou_region"
Os valores de cookie devem seralwaysounever. Valores personalizados não são suportados.
Para um tutorial completo, consulte Usar o controlador NGINX Ingress para implementar versões canário e implantações blue-green.
Obter um certificado TLS gratuito com o cert-manager
O cert-manager automatiza o provisionamento e a renovação de certificados TLS via Let's Encrypt no Kubernetes.
Este YAML destina-se a clusters ASK (Serverless Kubernetes). Para clusters ACK, consulte o guia de instalação do cert-manager .
Implantar o cert-manager
kubectl apply -f https://raw.githubusercontent.com/AliyunContainerService/serverless-k8s-examples/master/cert-manager/ask-cert-manager.yaml
Verificar se os pods do cert-manager estão em execução
kubectl get pods -n cert-manager
Saída esperada:
NAME READY STATUS RESTARTS AGE
cert-manager-1 1/1 Running 0 2m11s
cert-manager-cainjector 1/1 Running 0 2m11s
cert-manager-webhook 1/1 Running 0 2m10s
Criar um ClusterIssuer
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod-http01
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: <your_email_name@gmail.com> # Replace with your email address.
privateKeySecretRef:
name: letsencrypt-http01
solvers:
- http01:
ingress:
class: nginx
EOF
Confirmar se o ClusterIssuer está pronto
kubectl get clusterissuer
Saída esperada:
NAME READY AGE
letsencrypt-prod-http01 True 17s
Criar um Ingress que solicite um certificado
O nome de domínio deve atender às seguintes condições:
Ter no máximo 64 caracteres
Não ser um nome de domínio curinga
Ser publicamente acessível via HTTP (necessário para o desafio ACME HTTP-01)
Kubernetes 1.19 e posteriores
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-tls
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod-http01"
spec:
tls:
- hosts:
- <your_domain_name> # Replace with your domain name.
secretName: ingress-tls
rules:
- host: <your_domain_name> # Replace with your domain name.
http:
paths:
- path: /
backend:
service:
name: <your_service_name> # Replace with your Service name.
port:
number: <your_service_port> # Replace with your Service port.
pathType: ImplementationSpecific
EOF
Kubernetes 1.19 ou anterior
cat <<EOF | kubectl apply -f -
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-tls
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod-http01"
spec:
tls:
- hosts:
- <your_domain_name>
secretName: ingress-tls
rules:
- host: <your_domain_name>
http:
paths:
- path: /
backend:
serviceName: <your_service_name>
servicePort: <your_service_port>
EOF
Monitorar a emissão do certificado
kubectl get cert
Saída esperada (a emissão pode levar alguns minutos):
NAME READY SECRET AGE
ingress-tls True ingress-tls 52m
Se READY não for True, inspecione o certificado para obter detalhes:
kubectl describe cert ingress-tls
Procure por uma seção Events semelhante a:
Events:
Type Reason Age From Message
---- ------ --- ---- -------
Normal Requested 64s cert-manager Created new CertificateRequest resource "ingress-tls-xxxxx"
Normal Issuing 40s cert-manager The certificate has been successfully issued
Verificar o Secret do certificado
kubectl get secret ingress-tls
Saída esperada:
NAME TYPE DATA AGE
ingress-tls kubernetes.io/tls 2 2m
Acesse https://<your_domain_name> para confirmar que o HTTPS está ativo.