Informazioni su kube-dns per GKE

Se esegui applicazioni in cluster Standard, kube-dns è il provider DNS predefinito che ti aiuta ad attivare il Service Discovery e la comunicazione. Questo documento descrive come gestire il DNS con kube-dns, inclusi architettura, configurazione e best practice per ottimizzare la risoluzione DNS all'interno dell'ambiente GKE.

Questo documento è rivolto a sviluppatori, amministratori e architetti responsabili della gestione del DNS in GKE. Per informazioni sui ruoli e sulle attività comuni in Google Cloud, consulta Ruoli utente e attività comuni di GKE.

Prima di iniziare, assicurati di conoscere i servizi Kubernetes e i concetti generali di DNS.

Informazioni sull'architettura kube-dns

kube-dns opera all'interno del cluster GKE per abilitare la risoluzione DNS tra pod e servizi.

Il seguente diagramma mostra come interagiscono i pod con il servizio kube-dns:

Figura 1: diagramma che mostra come i pod inviano query DNS al servizio `kube-dns`, supportato dai pod `kube-dns`. I pod `kube-dns` gestiscono
la risoluzione DNS interna e inoltrano le query esterne ai server DNS
upstream.

Componenti chiave

kube-dns include i seguenti componenti chiave:

  • kube-dns Pod: questi pod eseguono il software del server kube-dns. Nello spazio dei nomi kube-system vengono eseguite più repliche di questi pod, che forniscono alta affidabilità e ridondanza.
  • Servizio kube-dns: la tabella seguente confronta i limiti di scalabilità e configurazione delle versioni legacy e basate su CoreDNS di kube-dns:
    Funzionalità Legacy (kube-dns 1.35 e versioni precedenti) kube-dns su CoreDNS (1.36 e versioni successive)
    Endpoint awareness Consapevole di un massimo di 1000 endpoint per servizio. Se un servizio ha più di 1000 pod, kube-dns non è a conoscenza degli endpoint aggiuntivi. Conosce tutti gli endpoint. Questa versione utilizza EndpointSlices per garantire la correttezza e migliorare l'efficienza per i servizi di grandi dimensioni.
    Server dei nomi upstream Limitato a 3 Supporta fino a 15
    Connessioni TCP in uscita simultanee Limitato a 200 Supporta fino a 1500
  • kube-dns-autoscaler: questo pod regola il numero di repliche di kube-dns in base alle dimensioni del cluster, che includono il numero di nodi e core della CPU. Questo approccio contribuisce a garantire che kube-dns possa gestire carichi di query DNS variabili.

Risoluzione DNS interna

Quando un pod deve risolvere un nome DNS all'interno del dominio del cluster, ad esempio myservice.my-namespace.svc.cluster.local, si verifica la seguente procedura:

  1. Configurazione DNS del pod:kubelet su ogni nodo configura il file /etc/resolv.conf del pod. Questo file utilizza ClusterIP del servizio kube-dns come server dei nomi.
  2. Query DNS:il pod invia una query DNS al servizio kube-dns.
  3. Risoluzione del nome:

    • GKE 1.36 o versioni successive:l'implementazione basata su CoreDNS utilizza EndpointSlice in modo che kube-dns sia a conoscenza di tutti i pod in un servizio. Ciò migliora la correttezza e l'efficienza per i servizi su larga scala.
    • GKE versione 1.35 o precedenti: kube-dns risolve i nomi in base alla versione precedente dell'API Cloud Endpoints, che è limitata a 1000 endpoint. Se un servizio ha più di 1000 pod di backend, kube-dns non conosce gli endpoint aggiuntivi.
  4. Comunicazione:il pod utilizza l'indirizzo IP risolto per comunicare con il servizio di destinazione.

Risoluzione DNS esterna

Quando un pod deve risolvere un nome DNS esterno o un nome al di fuori del dominio del cluster, kube-dns funge da resolver ricorsivo. Inoltra la query ai server DNS upstream configurati nel file ConfigMap. Puoi anche configurare resolver personalizzati per domini specifici, noti anche come domini stub. Questa configurazione indica a kube-dns di inoltrare le richieste per questi domini a server DNS upstream specifici.

Configura il DNS del pod

In GKE, l'agente kubelet su ogni nodo configura le impostazioni DNS per i pod in esecuzione su quel nodo.

Configurare il file /etc/resolv.conf

Quando GKE crea un pod, l'agente kubelet modifica il file /etc/resolv.conf del pod. Questo file configura il server DNS per la risoluzione dei nomi e specifica i domini di ricerca. Per impostazione predefinita, kubelet configura il pod in modo che utilizzi il servizio DNS interno del cluster, kube-dns, come server dei nomi. Inoltre, compila i domini di ricerca nel file. Questi domini di ricerca ti consentono di utilizzare nomi non qualificati nelle query DNS. Ad esempio, se un pod esegue una query su myservice, Kubernetes tenta prima di risolvere myservice.default.svc.cluster.local, poi myservice.svc.cluster.local e poi altri domini dall'elenco search.

L'esempio seguente mostra una configurazione /etc/resolv.conf predefinita:

nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local c.my-project-id.internal google.internal
options ndots:5

Questo file contiene le seguenti voci:

  • nameserver: definisce il ClusterIP del servizio kube-dns.
  • search: definisce i domini di ricerca aggiunti ai nomi non qualificati durante le ricerche DNS.
  • options ndots:5: imposta la soglia in base alla quale GKE considera un nome come completo. Un nome è considerato completo se contiene cinque o più punti.

I pod configurati con hostNetwork: true ereditano la configurazione DNS dall'host e non eseguono query direttamente su kube-dns, a meno che non utilizzino ClusterFirstWithHostNet dnsPolicy.

Personalizza kube-dns

kube-dns fornisce una risoluzione DNS predefinita solida. Puoi personalizzarne il comportamento per esigenze specifiche, ad esempio migliorando l'efficienza della risoluzione o utilizzando resolver DNS preferiti. Sia i domini stub sia i server dei nomi upstream vengono configurati modificando il ConfigMap kube-dns nello spazio dei nomi kube-system.

Modifica il ConfigMap kube-dns

Per modificare ConfigMap kube-dns:

  1. Apri ConfigMap per la modifica:

    kubectl edit configmap kube-dns -n kube-system
    
  2. Nella sezione data, aggiungi i campi stubDomains e upstreamNameservers come segue:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      labels:
        addonmanager.kubernetes.io/mode: EnsureExists
      name: kube-dns
      namespace: kube-system
    data:
      stubDomains: |
        {
          "example.com": [
            "8.8.8.8",
            "8.8.4.4"
          ],
          "internal": [ # Required if your upstream nameservers can't resolve GKE internal domains
            "169.254.169.254" # IP of the metadata server
          ]
        }
      upstreamNameservers: |
        [
          "8.8.8.8", # Google Public DNS
          "8.8.4.4" # Google Public DNS Backup
        ]
    
  3. Salva ConfigMap. kube-dns ricarica automaticamente la configurazione.

Domini stub

I domini stub ti consentono di definire resolver DNS personalizzati per domini specifici. Quando un pod esegue una query per un nome all'interno di questo dominio stub, kube-dns inoltra la query al resolver specificato anziché utilizzare il meccanismo di risoluzione predefinito.

Includi una sezione stubDomains nel kube-dns ConfigMap.

Questa sezione specifica il dominio e i server dei nomi upstream corrispondenti. kube-dns inoltra quindi le query per i nomi all'interno di quel dominio ai server designati. Ad esempio, puoi indirizzare tutte le query DNS per internal.mycompany.com a 192.168.0.10, aggiungere "internal.mycompany.com": ["192.168.0.10"] a stubDomains.

Quando imposti un resolver personalizzato per un dominio stub, ad esempio example.com, kube-dns inoltra tutte le richieste di risoluzione dei nomi per quel dominio, inclusi i sottodomini come *.example.com, ai server specificati.

Server dei nomi upstream

Puoi configurare kube-dns per utilizzare server dei nomi upstream personalizzati per risolvere nomi di dominio esterni. Questa configurazione indica a kube-dns di inoltrare tutte le richieste DNS, ad eccezione di quelle per il dominio interno del cluster (*.cluster.local), ai server upstream designati. I domini interni come metadata.internal e *.google.internal potrebbero non essere risolvibili dai tuoi server upstream personalizzati. Se abiliti Workload Identity Federation for GKE o hai carichi di lavoro che dipendono da questi domini, aggiungi un dominio stub per internal in ConfigMap. Utilizza 169.254.169.254, l'indirizzo IP del server dei metadati, come resolver per questo dominio stub.

Gestire un deployment personalizzato di kube-dns

In un cluster Standard, kube-dns viene eseguito come deployment. Un deployment kube-dns personalizzato significa che tu, in qualità di amministratore del cluster, puoi controllare il deployment e personalizzarlo in base alle tue esigenze, anziché utilizzare il deployment fornito da GKE predefinito.

Motivi per una distribuzione personalizzata

Valuta la possibilità di eseguire un deployment personalizzato di kube-dns per i seguenti motivi:

  • Allocazione delle risorse:ottimizza le risorse di CPU e memoria per i pod kube-dns per ottimizzare le prestazioni nei cluster con traffico DNS elevato.
  • Versione dell'immagine:utilizza una versione specifica dell'immagine kube-dns o passa a un provider DNS alternativo come CoreDNS.
  • Configurazione avanzata:personalizza i livelli di logging, i criteri di sicurezza e il comportamento di memorizzazione nella cache DNS.

Scalabilità automatica per i deployment personalizzati

kube-dns-autoscaler integrato funziona con il deployment kube-dns predefinito. Se crei un deployment kube-dns personalizzato, il gestore della scalabilità automatica integrato non lo gestisce. Pertanto, devi configurare uno scalatore automatico separato specificamente configurato per monitorare e regolare il conteggio delle repliche del tuo deployment personalizzato. Questo approccio prevede la creazione e il deployment della tua configurazione del gestore della scalabilità automatica nel cluster.

Quando gestisci un deployment personalizzato, sei responsabile di tutti i suoi componenti, ad esempio mantenere aggiornata l'immagine dello scalatore automatico. L'utilizzo di componenti obsoleti può comportare un degrado delle prestazioni o errori DNS.

Per istruzioni dettagliate su come configurare e gestire il tuo deployment kube-dns, consulta Configurazione di un deployment kube-dns personalizzato.

Risoluzione dei problemi

Per informazioni sulla risoluzione dei problemi relativi a kube-dns, consulta le seguenti pagine:

Ottimizzare la risoluzione DNS

Questa sezione descrive i problemi comuni e le best practice per la gestione del DNS in GKE.

Limite dei domini di ricerca dnsConfig di un pod

Kubernetes limita il numero di domini di ricerca DNS a 32. Se tenti di definire più di 32 domini di ricerca nel dnsConfig di un pod, kube-apiserver non creerà il pod e verrà visualizzato un errore simile al seguente:

The Pod "dns-example" is invalid: spec.dnsConfig.searches: Invalid value: []string{"ns1.svc.cluster-domain.example", "my.dns.search.suffix1", "ns2.svc.cluster-domain.example", "my.dns.search.suffix2", "ns3.svc.cluster-domain.example", "my.dns.search.suffix3", "ns4.svc.cluster-domain.example", "my.dns.search.suffix4", "ns5.svc.cluster-domain.example", "my.dns.search.suffix5", "ns6.svc.cluster-domain.example", "my.dns.search.suffix6", "ns7.svc.cluster-domain.example", "my.dns.search.suffix7", "ns8.svc.cluster-domain.example", "my.dns.search.suffix8", "ns9.svc.cluster-domain.example", "my.dns.search.suffix9", "ns10.svc.cluster-domain.example", "my.dns.search.suffix10", "ns11.svc.cluster-domain.example", "my.dns.search.suffix11", "ns12.svc.cluster-domain.example", "my.dns.search.suffix12", "ns13.svc.cluster-domain.example", "my.dns.search.suffix13", "ns14.svc.cluster-domain.example", "my.dns.search.suffix14", "ns15.svc.cluster-domain.example", "my.dns.search.suffix15", "ns16.svc.cluster-domain.example", "my.dns.search.suffix16", "my.dns.search.suffix17"}: must not have more than 32 search paths.

kube-apiserver restituisce questo messaggio di errore in risposta a un tentativo di creazione di un pod. Per risolvere il problema, rimuovi i percorsi di ricerca aggiuntivi dalla configurazione.

Limite upstream nameservers per kube-dns

Le versioni precedenti di kube-dns (versione 1.35 e precedenti) limitano il numero di upstreamNameservers a tre. Se ne definisci più di tre, Cloud Logging mostra un errore simile al seguente:

Invalid configuration: upstreamNameserver cannot have more than three entries (value was &TypeMeta{Kind:,APIVersion:,}), ignoring update

In questo scenario, kube-dns ignora la configurazione upstreamNameservers e continua a utilizzare la configurazione valida precedente. Per risolvere il problema, rimuovi il upstreamNameservers aggiuntivo da kube-dns ConfigMap.

Fai lo scale up di kube-dns

Nei cluster Standard, puoi utilizzare un valore inferiore per nodesPerReplica in modo che vengano creati più pod kube-dns quando i nodi del cluster fanno lo scale up. Ti consigliamo vivamente di impostare un valore esplicito per il campo max per contribuire a garantire che la macchina virtuale (VM) del control plane GKE non sia sovraccarica a causa del numero elevato di pod kube-dns che monitorano l'API Kubernetes.

Puoi impostare il valore del campo max sul numero di nodi nel cluster. Se il cluster ha più di 500 nodi, imposta il valore del campo max su 500.

Puoi modificare il numero di repliche kube-dns modificando kube-dns-autoscaler ConfigMap.

kubectl edit configmap kube-dns-autoscaler --namespace=kube-system

L'output è simile al seguente:

linear: '{"coresPerReplica":256, "nodesPerReplica":16,"preventSinglePointFailure":true}'

Il numero di repliche di kube-dns viene calcolato utilizzando la seguente formula:

replicas = max( ceil( cores * 1/coresPerReplica ) , ceil( nodes * 1/nodesPerReplica ) )

Per fare lo scale up, modifica il valore del campo nodesPerReplica impostandolo su un valore più piccolo e includi un valore per il campo max.

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"preventSinglePointFailure":true}'

Questa configurazione crea un pod kube-dns per ogni otto nodi del cluster. Un cluster di 24 nodi ha tre repliche e un cluster di 40 nodi ne ha cinque. Se il cluster supera i 120 nodi, il numero di repliche di kube-dns non supera 15, ovvero il valore del campo max.

Per garantire un livello di base di disponibilità DNS nel cluster, imposta un conteggio minimo di repliche per il campo kube-dns.

L'output per kube-dns-autoscaler ConfigMap con il campo min configurato è simile al seguente:

linear: '{"coresPerReplica":256, "nodesPerReplica":8,"max": 15,"min": 5,"preventSinglePointFailure":true}'

Migliorare i tempi di ricerca DNS

Diversi fattori possono causare una latenza elevata con le ricerche DNS o errori di risoluzione DNS con il provider kube-dns predefinito. Le applicazioni potrebbero riscontrare questi problemi come errori getaddrinfo EAI_AGAIN, che indicano un errore temporaneo nella risoluzione dei nomi. Le cause includono:

  • Ricerche DNS frequenti all'interno del carico di lavoro.
  • Densità elevata di pod per nodo.
  • Esecuzione di kube-dns su VM spot o VM preemptible, che può comportare eliminazioni impreviste dei nodi.
  • Limiti di connessione:le versioni precedenti di kube-dns (GKE versione 1.35 e precedenti) sono limitate a 200 connessioni TCP simultanee. kube-dns su CoreDNS (GKE versione 1.36 e successive) rimuove questi limiti fissi per le connessioni in entrata e offre una capacità significativamente maggiore per le connessioni in uscita.

Per migliorare i tempi di ricerca DNS:

  • Evita di eseguire componenti di sistema critici come kube-dns su VM spot o VM preemptible. Crea almeno un pool di nodi con VM standard e senza VM spot o VM preemptible. Utilizza taint e tolleranze per assicurarti che i carichi di lavoro critici vengano pianificati su questi nodi affidabili.
  • Abilita NodeLocal DNSCache. NodeLocal DNSCache memorizza nella cache le risposte DNS direttamente su ogni nodo, il che riduce la latenza e il carico sul servizio kube-dns. Se abiliti NodeLocal DNSCache e utilizzi policy di rete con regole di negazione predefinite, aggiungi una policy per consentire ai carichi di lavoro di inviare query DNS ai pod node-local-dns.
  • Fai lo scale up di kube-dns.
  • Assicurati che la tua applicazione utilizzi funzioni basate su dns.resolve* anziché su dns.lookup, perché dns.lookup è sincrono.
  • Utilizza nomi di dominio completi (FQDN), ad esempio https://google.com./ anziché https://google.com/.

Durante gli upgrade del cluster GKE potrebbero verificarsi errori di risoluzione DNS a causa di upgrade simultanei dei componenti del control plane, incluso kube-dns. In genere, questi errori interessano una piccola percentuale di nodi. Testa a fondo gli upgrade del cluster in un ambiente non di produzione prima di applicarli ai cluster di produzione.

Garantire l'individuabilità del servizio

kube-dns crea record DNS solo per i servizi che hanno endpoint. Se un servizio non ha endpoint, kube-dns non crea record DNS per quel servizio.

Gestire le discrepanze TTL DNS

Se kube-dns riceve una risposta DNS da un resolver DNS upstream con un TTL grande o infinito, mantiene questo valore TTL. Questo comportamento può creare una discrepanza tra la voce memorizzata nella cache e l'indirizzo IP effettivo.

GKE risolve questo problema in versioni specifiche del piano di controllo, ad esempio 1.21.14-gke.9100 e successive o 1.22.15-gke.2100 e successive. Queste versioni impostano un valore TTL massimo di 30 secondi per qualsiasi risposta DNS con un TTL superiore. Questo comportamento è simile a NodeLocal DNSCache.

Visualizza le metriche di kube-dns

Puoi recuperare le metriche sulle query DNS direttamente dai pod kube-dns. La modalità di recupero di queste metriche dipende dalla versione di GKE.

GKE 1.36 e versioni successive

Se il tuo cluster esegue GKE versione 1.36 o successive (kube-dns su CoreDNS), puoi monitorare le prestazioni DNS utilizzando dashboard predefinite in Cloud Monitoring o recuperare manualmente le metriche dai pod.

Visualizzare le metriche nella console Google Cloud

  1. Nella console Google Cloud , vai alla pagina Dashboard.
  2. Seleziona la dashboard GKE DNS Observability - Cluster View (Osservabilità DNS GKE - Visualizzazione cluster).

In alternativa, puoi eseguire query su queste metriche direttamente nella console Google Cloud andando a Monitoraggio > Esplora metriche e cercando i nomi delle metriche specifiche.

Recuperare le metriche manualmente

Per recuperare manualmente le metriche dal pod:

  1. Trova i kube-dns Pod.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Inoltra la porta 9153 a uno dei pod.

    kubectl port-forward pod/POD_NAME -n kube-system 9153:9153
    

    Sostituisci POD_NAME con il nome di uno dei pod kube-dns dell'output precedente.

  3. Accedi alle metriche.

    curl http://127.0.0.1:9153/metrics
    

GKE versione 1.35 e precedenti

Questa versione di kube-dns utilizza pod con più container. Per recuperare le metriche:

  1. Trova i pod kube-dns nello spazio dei nomi kube-system.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Esegui il port forwarding alle porte 10055 (per il container kube-dns) e 10054 (per il container dnsmasq):

    #For the kube-dns container
    kubectl port-forward pod/POD_NAME -n kube-system 10055:10055
    #For the dnsmasq container
    kubectl port-forward pod/POD_NAME -n kube-system 10054:10054
    

    Sostituisci POD_NAME con il nome di uno dei pod kube-dns dell'output precedente. Esegui questi comandi di port forwarding in sessioni del terminale separate.

  3. Accedi alle metriche.

    #Metrics from the kube-dns container
    curl http://127.0.0.1:10055/metrics
    
    #Metrics from the dnsmasq container
    curl http://127.0.0.1:10054/metrics
    

Passaggi successivi