Informazioni su kube-dns per GKE

Se esegui applicazioni nei cluster Standard, kube-dns è il provider DNS predefinito che ti aiuta ad abilitare il Service Discovery e la comunicazione. Questo documento descrive come gestire il DNS con kube-dns, inclusi la sua architettura, la configurazione e le best practice per ottimizzare la risoluzione DNS nel tuo ambiente GKE.

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

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

Informazioni sull'architettura di kube-dns

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

Il seguente diagramma mostra come i pod interagiscono 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:

  • Pod kube-dns: questi pod eseguono il software del server kube-dns. Più repliche di questi pod vengono eseguite nello spazio dei nomi kube-system e forniscono alta affidabilità e ridondanza.
  • Servizio kube-dns: la seguente tabella 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)
    Rilevamento degli endpoint Rileva fino a 1000 endpoint per servizio. Se un servizio ha più di 1000 pod, kube-dns non rileva gli endpoint aggiuntivi. Rileva tutti gli endpoint. Questa versione utilizza EndpointSlice 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 kube-dns in base alle dimensioni del cluster, incluso il numero di nodi e core della CPU. Questo approccio aiuta 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: il kubelet su ogni nodo configura il file /etc/resolv.conf del pod. Questo file utilizza il ClusterIP del servizio kube-dns come server dei nomi.
  2. Query DNS: il pod invia una query DNS al servizio kube-dns.
  3. Risoluzione dei nomi:

    • GKE versione 1.36 o 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 backup, kube-dns non rileva 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 suo ConfigMap file. 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.

Configurare il DNS dei 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. Popola anche 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 predefinita di /etc/resolv.conf:

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 che vengono aggiunti ai nomi non qualificati durante le ricerche DNS.
  • options ndots:5: imposta la soglia per cui 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 dnsPolicy ClusterFirstWithHostNet.

Personalizzare kube-dns

kube-dns fornisce una risoluzione DNS predefinita robusta. Puoi personalizzarne il comportamento per esigenze specifiche, ad esempio migliorare l'efficienza della risoluzione o utilizzare i 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.

Modificare il ConfigMap kube-dns

Per modificare il ConfigMap kube-dns:

  1. Apri il 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 il ConfigMap. kube-dns ricarica automaticamente la configurazione.

Domini stub

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

Includi una sezione stubDomains nel ConfigMap kube-dns.

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, aggiungendo "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 in modo che utilizzi server dei nomi upstream personalizzati per risolvere i nomi di dominio esterni. Questa configurazione indica a kube-dns di inoltrare tutte le richieste DNS, ad eccezione delle richieste 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 server upstream personalizzati. Se abiliti Workload Identity Federation for GKE o hai workload che dipendono da questi domini, aggiungi un dominio stub per internal in the ConfigMap. Utilizza 169.254.169.254, l'indirizzo IP del server di metadati, come resolver per questo dominio stub.

Gestire un deployment kube-dns personalizzato

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 predefinito fornito da GKE.

Motivi per un deployment personalizzato

Prendi in considerazione un deployment kube-dns personalizzato 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, le policy 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, lo strumento di scalabilità automatica integrato non lo gestisce. Pertanto, devi configurare uno strumento di scalabilità automatica separato configurato specificamente per monitorare e regolare il numero di repliche del deployment personalizzato. Questo approccio prevede la creazione e il deployment della tua configurazione di scalabilità automatica nel cluster.

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

Per istruzioni dettagliate su come configurare e gestire il tuo kube-dns deployment, consulta Configurare 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 in 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 del pod. Per risolvere il problema, rimuovi i percorsi di ricerca aggiuntivi dalla configurazione.

Limite di nameservers upstream per kube-dns

Le versioni legacy di kube-dns (versione 1.35 e precedenti) limitano il numero di upstreamNameservers a tre. Se ne definisci più di tre, Cloud Logging visualizza 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 gli upstreamNameservers aggiuntivi dal ConfigMap kube-dns.

Fare lo scale up 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 assicurarti che la macchina virtuale (VM) del piano di controllo GKE non venga sovraccaricata 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 kube-dns repliche modificando il 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 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 con un valore inferiore 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 nel cluster. Un cluster di 24 nodi ha tre repliche e un cluster di 40 nodi ha cinque repliche. Se il cluster supera i 120 nodi, il numero di repliche kube-dns non supera 15, che è il valore del campo max.

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

L'output per il ConfigMap kube-dns-autoscaler 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 workload.
  • 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 legacy 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 fornisce 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 workload critici siano 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 workload di inviare query DNS ai pod node-local-dns.
  • Fare lo scale up di kube-dns.
  • Assicurati che l'applicazione utilizzi funzioni basate su dns.resolve* anziché funzioni basate su dns.lookup, perché dns.lookup è sincrono.
  • Utilizza nomi di dominio completi (FQDN), ad esempio https://google.com./ anziché https://google.com/.

Potrebbero verificarsi errori di risoluzione DNS durante gli upgrade del cluster GKE a causa degli upgrade simultanei dei componenti del control plane, incluso kube-dns. Questi errori in genere interessano una piccola percentuale di nodi. Esegui test approfonditi degli upgrade del cluster in un ambiente non di produzione prima di applicarli ai cluster di produzione.

Garantire la rilevabilità dei servizi

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 del TTL DNS

Se kube-dns riceve una risposta DNS da un resolver DNS upstream con un TTL elevato 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 più elevato. Questo comportamento è simile a NodeLocal DNSCache.

Visualizzare le metriche 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 versione 1.36 e successive

Se il 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 Google Cloud console

  1. Nella Google Cloud console, vai alla pagina Dashboard.
  2. Seleziona la dashboard GKE DNS Observability - Cluster View.

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

Recuperare le metriche manualmente

Per recuperare manualmente le metriche dal pod:

  1. Trova i pod kube-dns.

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    
  2. Esegui il port forwarding della 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 multi-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 di 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