O objetivo final do desenvolvimento de aplicativos é, obviamente, expor aplicativos na Internet. Para um desenvolvedor, o Kubernetes simplifica esse processo até certo ponto ao fornecer o controlador Ingress como mecanismo de roteamento de solicitações para o aplicativo. Mas nem tudo é tão self-service quanto você provavelmente gostaria: você ainda precisa de um registro no Sistema de Nomes de Domínio (DNS) para mapear o nome de domínio do aplicativo para o endereço IP do controlador Ingress e um certificado TLS para proteger conexões usando HTTPS. Na maioria das organizações, você não é o proprietário do DNS ou do TLS e, portanto, precisa coordenar com o grupo operacional (ou grupos!) que o possui.
As coisas não são necessariamente mais fáceis para os operadores. Na maioria das organizações, a necessidade de atualizar registros DNS é rara o suficiente para que os procedimentos – tanto as regras de negócios quanto as etapas técnicas reais – tendam a ser esparsos ou inexistentes. Isso significa que quando você precisa adicionar um registro DNS, primeiro precisa encontrar a documentação, perguntar a um colega ou (na pior das hipóteses) descobrir. Você também precisa garantir que está em conformidade com todas as regras de segurança corporativa e certificar-se de que a entrada esteja marcada corretamente para os firewalls.
Felizmente, existe uma maneira de facilitar a vida tanto dos desenvolvedores quanto dos operadores. Nesta postagem, mostramos como os operadores podem configurar uma implantação do Kubernetes para permitir o autoatendimento para desenvolvedores atualizarem registros DNS e gerarem certificados TLS em um ambiente Kubernetes. Ao construir a infraestrutura com antecedência, você pode garantir que todos os requisitos comerciais e técnicos necessários sejam atendidos.
Com a solução implementada, tudo o que um desenvolvedor precisa fazer para expor um aplicativo à Internet é criar um controlador Ingress seguindo um modelo fornecido que inclui um nome de domínio totalmente qualificado (FQDN) dentro de um domínio gerenciado pela instalação do Kubernetes. O Kubernetes usa o modelo para alocar um endereço IP para o controlador Ingress, criar o registro DNS A
para mapear o FQDN para o endereço IP e gerar certificados TLS para o FQDN e adicioná-los ao controlador Ingress. A limpeza é igualmente fácil: quando o Ingress é removido, os registros DNS são limpos.
A solução aproveita as seguintes tecnologias (fornecemos instruções de instalação e configuração abaixo):
Antes de configurar a solução, você precisa:
LoadBalancer
). A solução usa Linode, mas outros provedores de nuvem também funcionam.kubectl
como interface de linha de comando para Kubernetes.Também presumimos que você tenha um conhecimento básico do Kubernetes (como aplicar um manifesto, usar um gráfico Helm e emitir comandos kubectl
para visualizar a saída e solucionar problemas). Entender os conceitos básicos do Let's Encrypt é útil, mas não obrigatório; para uma visão geral, consulte nosso blog . Você também não precisa saber como o cert-manager funciona, mas se estiver interessado em como ele (e os certificados em geral) funcionam com o NGINX Ingress Controller, veja minha postagem recente, Automatizando o gerenciamento de certificados em um ambiente Kubernetes .
Testamos a solução no macOS e no Linux. Não testamos no Windows Subsystem for Linux versão 2 (WSL2), mas não prevemos problemas.
Observação: A solução foi concebida como uma prova de conceito de amostra e não para uso em produção. Em particular, ele não incorpora todas as melhores práticas de operação e segurança. Para obter informações sobre esses tópicos, consulte a documentação do cert-manager e do ExternalDNS .
Siga as etapas nestas seções para implantar a solução:
Clone o repositório do NGINX Ingress Controller:
$ git clone https://github.com/nginxinc/kubernetes-ingress.git Clonando em 'kubernetes-ingress'... remoto: Enumerando objetos: 45176, concluído. remoto: Contando objetos: 100% (373/373), concluído. remoto: Comprimindo objetos: 100% (274/274), concluído. remoto: Total 45176 (delta 173), reutilizado 219 (delta 79), pacote-reutilizado 44803 Recebendo objetos: 100% (45176/45176), 60,45 MiB | 26,81 MiB/s, concluído.
Resolução de deltas: 100% (26592/26592), concluído.
Verifique se você consegue se conectar ao cluster do Kubernetes.
$ kubectl cluster-info O plano de controle do Kubernetes está sendo executado em https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443 O KubeDNS está sendo executado em https://ba35bacf-b072-4600-9a04-e04...6a3d.us-west-2.linodelke.net:443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy Para depurar e diagnosticar melhor os problemas do cluster, use 'kubectl cluster-info dump'.
Usando o Helm, implante o NGINX Ingress Controller. Observe que estamos adicionando três opções de configuração não padronizadas :
controller.enableCustomResources
– Instrui o Helm a instalar as definições de recursos personalizados (CRDs) usadas para criar os recursos personalizados NGINX VirtualServer e VirtualServerRoute .controller.enableCertManager
– Configura o NGINX Ingress Controller para se comunicar com os componentes do cert-manager .controller.enableExternalDNS
– Configura o Ingress Controller para se comunicar com componentes ExternalDNS.$ helm install nginx-kic nginx-stable/nginx-ingress --namespace nginx-ingress --set controller.enableCustomResources=true --create-namespace --set controller.enableCertManager=true --set controller.enableExternalDNS=true NOME: nginx-kic ÚLTIMA IMPLANTAÇÃO: Dia Seg DD hh : mm : ss AAAA NAMESPACE: nginx-ingress STATUS: implantado REVISÃO: 1 CONJUNTO DE TESTES: Nenhuma NOTAS:
O NGINX Ingress Controller foi instalado.
Verifique se o NGINX Ingress Controller está em execução e anote o valor no campo EXTERNAL-IP
– é o endereço IP do NGINX Ingress Controller (aqui, www.xxx.yyy.zzz
). A saída é distribuída em duas linhas para maior legibilidade.
$ kubectl get services --namespace nginx-ingress NOME TIPO CLUSTER-IP ... nginx-kic-nginx-ingress LoadBalancer 10.128.152.88 ... ... IDADE DA(S) PORTA(S) IP EXTERNA(S) ... www.xxx.yyy.zzz 80:32457/TCP,443:31971/TCP 3h8m
Na solução, o cert-manager usa o tipo de desafio DNS-01 ao obter um certificado TLS, o que exige que o token da API do Cloudflare seja fornecido durante a criação do recurso ClusterIssuer . Na solução, o token da API é fornecido como um Kubernetes Secret .
Usando o Helm, implante o cert-manager :
$ helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.9.1 --set installCRDs=true NOME: cert-manager ÚLTIMA IMPLANTAÇÃO: Dia Seg DD hh : mm : ss AAAA NAMESPACE: cert-manager STATUS: implantado REVISÃO: 1 CONJUNTO DE TESTES: Nenhum NOTAS: cert-manager v1.9.1 foi implantado com sucesso!
Implante o token da API do Cloudflare como um segredo do Kubernetes, substituindo-o por <seu-token-API>
:
$ kubectl apply -f - <<EOFapiVersão: v1
tipo: Metadados secretos: nome: Namespace Cloudflare-api-token-secret: tipo cert-manager: Opaco
stringData:
api-token: "<seu-token-API>"
Fim do prazo de validade
secret/Cloudflare-api-token-secret criado
Crie um objeto ClusterIssuer, especificando Cloudflare-api-token-secret
(definido na etapa anterior) como o local para recuperar o token. Se desejar, você pode substituir example-issuer
no campo metadata.name
(e example-issuer-account-key
no campo spec.acme.privateKeySecretRef.name
) por um nome diferente.
$ kubectl apply -f - <<EOFapiVersão: cert-manager.io/v1
tipo: Metadados do ClusterIssuer: nome: example-issuer namespace: cert-manager especificação: acme: e-mail: example@example.com servidor: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: nome: example-issuer-account-key solucionadores: - dns01:
Cloudflare: apiTokenSecretRef: nome: Chave Cloudflare-api-token-secret: api-token EOF clusterissuer.cert-manager.io/example-issuer criado
Verifique se o ClusterIssuer está implantado e pronto (o valor no campo READY
é True
).
$ kubectl get clusterissuer NOME PRONTO IDADE exemplo-emissor Verdadeiro 3h9m
Assim como o cert-manager, o projeto ExternalDNS requer um token de API do Cloudflare para gerenciar o DNS. O mesmo token pode ser usado para ambos os projetos, mas isso não é obrigatório.
Crie os CRDs do ExternalDNS para o NGINX Ingress Controller para permitir a integração entre os projetos.
$ kubectl create -f ./kubernetes-ingress/deployments/common/crds/externaldns.nginx.org_dnsendpoints.yaml customresourcedefinition.apiextensions.k8s.io/dnsendpoints.externaldns.nginx.org criado
Crie o serviço DNS externo ( external-dns
). Como o manifesto é bastante longo, aqui o dividimos em duas partes. A primeira parte configura contas, funções e permissões:
external-dns
para gerenciar todas as operações de gravação e atualização para gerenciar o DNS.external-dns
) que define as permissões necessárias.$ kubectl apply -f - <<EOFapiVersão: v1
tipo: Metadados da conta de serviço: nome: external-dns --- apiVersion: rbac.authorization.k8s.io/v1 tipo: Metadados do ClusterRole: nome: external-dns regras: - apiGroups: [""] recursos: ["services","endpoints","pods"] verbos: ["get","watch","list"] - apiGroups: ["extensions","networking.k8s.io"] recursos: ["ingresses"] verbos: ["get","watch","list"] - apiGroups: ["externaldns.nginx.org"] recursos: ["dnsendpoints"] verbos: ["get","watch","list"] - apiGroups: ["externaldns.nginx.org"] recursos: ["dnsendpoints/status"] verbos: ["update"] - apiGroups: [""] recursos: ["nodes"] verbos: ["list","watch"] --- apiVersion: rbac.authorization.k8s.io/v1 tipo: ClusterRoleBinding metadados: nome: external-dns-viewer roleRef: apiGroup: rbac.authorization.k8s.io tipo: Nome do ClusterRole: external-dns assuntos: - tipo: Nome da conta de serviço: namespace external-dns: EOF padrão serviceaccount/external-dns criado clusterrole.rbac.authorization.k8s.io/external-dns criado clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer criado
A segunda parte do manifesto cria a implantação do ExternalDNS:
domain-filter
como example.com
.CF_API_TOKEN
para seu token de API do Cloudflare. Para <seu-token-API>
, substitua o token real ou um Segredo contendo o token. No último caso, você também precisa projetar o Secret no contêiner usando uma variável de ambiente.FREE_TIER
como "true"
(apropriado, a menos que você tenha uma assinatura paga do Cloudflare).$ kubectl apply -f - <<EOF
---
apiVersão: apps/v1
tipo: Metadados de implantação: nome: external-dns especificação: estratégia: tipo: Recriar seletor: matchLabels: aplicativo: external-dns modelo: metadados: rótulos: aplicativo: external-dns especificação: serviceAccountName: external-dns contêineres: - nome: external-dns imagem: k8s.gcr.io/external-dns/external-dns:v0.12.0 argumentos: - --source=service - --source=ingress - --source=crd - --crd-source-apiversion=externaldns.nginx.org/v1 - --crd-source-kind=DNSEndpoint - --domain-filter=example.com - --provider=Cloudflare env: - nome: CF_API_TOKEN
valor: "<seu-token-API>"
- nome: Valor FREE_TIER: "true" EOF serviceaccount/external-dns criado clusterrole.rbac.authorization.k8s.io/external-dns criado clusterrolebinding.rbac.authorization.k8s.io/external-dns-viewer criado deployment.apps/external-dns criado
Use o aplicativo de exemplo padrão do NGINX Ingress Controller chamado Cafe para fins de teste.
Implante o aplicativo Cafe.
$ kubectl apply -f ./kubernetes-ingress/examples/ingress-resources/complete-example/cafe.yaml deployment.apps/coffee criado service/coffee-svc criado deployment.apps/tea criado service/tea-svc criado
Implante o NGINX Ingress Controller para o aplicativo Cafe. Observe as seguintes configurações:
tipo: VirtualServer
– Estamos usando o recurso personalizado NGINX VirtualServer, não o recurso padrão do Kubernetes Ingress.spec.host
– Substitua cafe.example.com
pelo nome do host que você está implantando. O host deve estar dentro do domínio que está sendo gerenciado com ExternalDNS.spec.tls.cert-manager.cluster-issuer
– Se você estiver usando os valores especificados nesta postagem, este é example-issuer
. Se necessário, substitua o nome escolhido na Etapa 3 de Implantar cert‑manager .spec.externalDNS.enable
– O valor true
informa ao ExternalDNS para criar um registro DNS A.
Observe que o tempo que leva para essa etapa ser concluída depende muito do provedor de DNS, pois o Kubernetes está interagindo com a API de DNS do provedor.
$ kubectl apply -f - <<EOFapiVersão: k8s.nginx.org/v1
tipo: Metadados do VirtualServer: nome: cafe especificação: host: cafe.example.com tls: segredo: cafe-secret gerenciador de certificados: cluster-issuer: example-issuer externalDNS: enable: true upstreams: - nome: tea serviço: tea-svc porta: 80 - nome: serviço de café: coffee-svc porto: 80 rotas: - caminho: /tea ação: senha: chá - caminho: /coffee ação: senha: café EOF virtualserver.k8s.nginx.org/cafe criado
Verifique o registro DNS A
– em particular se no bloco ANSWER
SECTION
o FQDN (aqui, cafe.example.com
) está mapeado para o endereço IP correto ( www.xxx.yyy.zzz
).
$ dig cafe.example.com ; <<>> DiG 9.10.6 <<>> cafe.example.com ;; opções globais: +cmd ;; Resposta obtida: ;; ->>HEADER<<- opcode: CONSULTA, status: SEM ERRO, id: 22633 ;; sinalizadores: qr rd ra; CONSULTA: 1, RESPOSTA: 1, AUTORIDADE: 0, ADICIONAL: 1;; OPTAR PSEUDOSECÇÃO: ; EDS: versão: 0, sinalizadores:; udp: 4096 ;; SEÇÃO DE PERGUNTAS: ;cafe.example.com. EM UMA SEÇÃO DE RESPOSTAS: cafe.example.com. 279 IN A www.xxx.yyy.zzz ;; Tempo de consulta: 1 mseg ;; SERVIDOR: 2607:fb91:119b:4ac4:2e0: xxxx :fe1e:1359#53(2607:fb91:119b:4ac4:2e0: xxxx :fe1e:1359) ;; QUANDO: Dia Seg DD hh : mm : ss TZ AAAA ;; MSG TAMANHO rcvd: 67
Verifique se o certificado é válido (o valor no campo READY
é True
).
$ kubectl obter certificados NOME PRONTO SEGREDO IDADE cafe-secret Verdadeiro cafe-secret 8m51s
Verifique se você consegue acessar o aplicativo.
$ curl https://cafe.example.com/coffee Endereço do servidor: 10.2.2.4:8080 Nome do servidor: coffee-7c86d7d67c-lsfs6 Data: DD/Seg/AAAA:hh:mm:ss +TZ-offset URI: /café ID da solicitação: 91077575f19e6e735a91b9d06e9684cd $ curl https://cafe.example.com/tea Endereço do servidor: 10.2.2.5:8080 Nome do servidor: tea-5c457db9-ztpns Data: DD/Seg/AAAA:hh:mm:ss +TZ-offset URI: /tea ID da solicitação: 2164c245a495d22c11e900aa0103b00f
Muita coisa acontece nos bastidores quando a solução é implementada. O diagrama mostra o que acontece quando um desenvolvedor implanta o NGINX Ingress Controller com um recurso personalizado do NGINX VirtualServer. Observe que alguns detalhes operacionais são omitidos.
A
A
no DNSDada a complexidade do Kubernetes e dos componentes que estamos usando, é difícil fornecer um guia de solução de problemas abrangente. Dito isso, há algumas sugestões básicas para ajudar você a determinar o problema.
kubectl
get
e kubectl
describe
para validar a configuração de objetos implantados.kubectl
registros
<componente>
comando para visualizar arquivos de log para os vários componentes implantados.Se você ainda estiver tendo problemas, entre em contato conosco no Slack da Comunidade NGINX e peça ajuda! Temos uma comunidade vibrante e estamos sempre felizes em resolver problemas.
Para experimentar o NGINX Ingress Controller baseado no NGINX Plus, comece hoje mesmo seu teste gratuito de 30 dias ou entre em contato conosco para discutir seus casos de uso .
"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."