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 Enterprise.

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 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:

  • 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 disponibilità e ridondanza.
  • Servizio kube-dns: questo servizio Kubernetes di tipo ClusterIP raggruppa i pod kube-dns e li espone come un unico endpoint stabile. ClusterIP funge da server DNS per il cluster, che i pod utilizzano per inviare query DNS. kube-dns supporta fino a 1000 endpoint per servizio headless.
  • 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 dei nomi:kube-dns riceve la query. Cerca l'indirizzo IP corrispondente nei suoi record DNS interni e risponde al pod.
  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 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. 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 dell'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 che vengono 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 l'impostazione hostNetwork: true ereditano la configurazione DNS dall'host e non eseguono query direttamente su kube-dns.

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 a:

    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
          "1.1.1.1" # Cloudflare DNS
        ]
    
  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 di metadati, come resolver per questo dominio stub.

Gestire un deployment personalizzato di kube-dns

In GKE 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 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, i criteri di sicurezza e il comportamento di memorizzazione nella cache DNS.

Scalabilità automatica per i deployment personalizzati

kube-dns-autoscaler integrato funziona con l'deployment kube-dns predefinita. 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, vedi 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 di nameservers a monte per kube-dns

kube-dns limita il numero di valori 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 vengono scalati. 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 di 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 aumentare la scalabilità, modifica il valore del campo nodesPerReplica impostandolo su 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 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.
  • Volume elevato di query che supera la capacità dell'istanza dnsmasq all'interno del pod kube-dns. Una singola istanza kube-dns ha un limite di 200 connessioni TCP simultanee in GKE versione 1.31 e successive e un limite di 20 connessioni TCP simultanee in GKE versione 1.30 e precedenti.

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 criteri di rete con regole di negazione predefinite, aggiungi un criterio 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é funzioni basate 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 dei 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 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 control plane, 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 nel cluster direttamente dai pod kube-dns.

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

    kubectl get pods -n kube-system --selector=k8s-app=kube-dns
    

    L'output è simile al seguente:

    NAME                        READY     STATUS    RESTARTS   AGE
    kube-dns-548976df6c-98fkd   4/4       Running   0          48m
    kube-dns-548976df6c-x4xsh   4/4       Running   0          47m
    
  2. Scegli uno dei pod e configura il port forwarding per accedere alle metriche da quel pod:

    • La porta 10055 espone le metriche kube-dns.
    • La porta 10054 espone le metriche dnsmasq.

    Sostituisci POD_NAME con il nome del pod che hai scelto.

    POD_NAME="kube-dns-548976df6c-98fkd" # Replace with your pod name
    kubectl port-forward pod/${POD_NAME} -n kube-system 10055:10055 10054:10054
    

    L'output è simile al seguente:

    Forwarding from 127.0.0.1:10054 -> 10054
    Forwarding from 127.0.0.1:10055 -> 10055
    
  3. In una nuova sessione del terminale, utilizza il comando curl per accedere agli endpoint delle metriche.

    # Get kube-dns metrics
    curl http://127.0.0.1:10055/metrics
    
    # Get dnsmasq metrics
    curl http://127.0.0.1:10054/metrics
    

    L'output sarà simile al seguente:

    kubedns_dnsmasq_errors 0
    kubedns_dnsmasq_evictions 0
    kubedns_dnsmasq_hits 3.67351e+06
    kubedns_dnsmasq_insertions 254114
    kubedns_dnsmasq_max_size 1000
    kubedns_dnsmasq_misses 3.278166e+06
    

Passaggi successivi