Resolución DNS larga en Kubernetes

Este artículo se centra en los problemas de DNS en Kubernetes que nuestro equipo encontró. Al final resultó que, a veces el problema es mucho más profundo de lo que parece inicialmente.


Introducción


Siempre llega un momento en que las circunstancias intervienen en el trabajo ya depurado, lo que nos obliga a cambiar algo. Por lo tanto, nuestro pequeño equipo se vio obligado a migrar todas las aplicaciones usadas a Kubernetes. Hubo muchas razones, objetivas y no muy, pero la historia, de hecho, no se trata de eso.


Como nadie antes usaba Kubernetes activamente, el clúster se recreó varias veces, por lo que no tuvimos tiempo para evaluar la calidad de las aplicaciones transferidas. Y así, después de la cuarta transferencia, cuando todos los conos principales ya están llenos, se ensamblan todos los contenedores y se escriben todas las implementaciones, puede analizar el trabajo realizado y, finalmente, pasar a otras tareas.


11 horas, el comienzo de la jornada laboral. El sistema de monitoreo carece de una parte de los mensajes de una de las aplicaciones.


Diagnósticos


La aplicación se transfirió recientemente a un clúster y consistió en un simple trabajador que ingresó a la base de datos una vez cada pocos minutos, verificó los cambios y, de haberlos, envió un mensaje al autobús. Antes del inicio de la prueba y después de su finalización, la aplicación escribe un mensaje en el registro. Sin paralelismo, sin multitarea, el único hogar con el único contenedor.


Tras una inspección más cercana, quedó claro que los registros están en la consola, pero en Elastic ya no están allí.


: Elasticsearch- , Kubernetes, Kibana. Elastic Serilog.Sinks.Elasticsearch, - Nginx ( , Elasticsearch , ). Nginx , .


Serilog, , Serilog selflog . , Serilog:


Serilog.Debugging.SelfLog.Enable(msg =>
{
  Serilog.Log.Logger.Error($"Serilog self log: {msg}");
});

, , . Kibana.


> Caught exception while preforming bulk operation to Elasticsearch: Elasticsearch.Net.ElasticsearchClientException: Maximum timeout reached while retrying request. Call: Status code unknown from: POST /_bulk

Elasticsearch , Elasticsearch . , HttpClient . , , .


, , . . , API Kubernetes, 5-10 100-150 . HTTP . .


– , , HTTP .


, , bash-, google.com :


while true;
do curl -w "%{time_total}\n" -o /dev/null -s "https://google.com/";
sleep 1;
done

– 5 .


imagen


, :


apiVersion: v1
kind: ConfigMap
metadata:
  name: ubuntu-test-scripts
data:
  loop.sh: |-
    apt-get update;
    apt-get install -y curl;
    while true;
    do echo $(date)'\n';
    curl -w "@/etc/script/curl.txt" -o /dev/null -s "https://google.com/";
    sleep 1;
    done
  curl.txt: |-
    lookup:        %{time_namelookup}\n
    connect:       %{time_connect}\n
    appconnect:    %{time_appconnect}\n
    pretransfer:   %{time_pretransfer}\n
    redirect:      %{time_redirect}\n
    starttransfer: %{time_starttransfer}\n
    total:         %{time_total}\n
---
apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-test
  labels:
      app: ubuntu-test
spec:
  containers:
  - name: test
    image: ubuntu
    args: [/bin/sh, /etc/script/loop.sh]
    volumeMounts:
    - name: config
      mountPath: /etc/script
      readOnly: true
  volumes:
  - name: config
    configMap:
      defaultMode: 0755
      name: ubuntu-test-scripts

– google.com curl. , /dev/null, curl.


, , . – DNS ( – ). Kubernetes 1.14, , , .


, :


imagen


, – DNS-lookup, 99% – 5 . , .



.


, — 5 seconds dns resolve kubernetes.


, :



issue weave.


, :


  1. ( , – 2017 , , , ) .
  2. DNS lookup. , 10-15 .
  3. , DNS- VIP, DNAT.
  4. .

– race conditions conntraking Linux SNAT DNAT. Tobias Klausmann 2009 , Linux 5.0 , .


, Kubernetes DNS, race condition .


glibc ( Ubuntu, Debian . .), :


  1. glibc UDP (A AAAA). UDP connectionless , connect(2) , conntrack .
  2. DNS- Kubernetes VIP DNAT iptables.
  3. DNAT , netfilter :
    a. nf_conntrack_in: conntrack hash object .
    b. nf_nat_ipv4_fn: conntrack.
    c. nf_conntrack_confirm: , .
  4. UDP . , DNS-. , . - insert_failed, .


, workaround:


  1. DNS- nameserver. LocalDNS cache
  2. Weave tc(8) - AAAA DNS
  3. single-request-reopen resolv.conf

, .


Kubernetes 1.9, pod dnsConfig, resolv.conf.


pod, glibc A AAAA , race condition.


spec:
  dnsConfig:
    options:
    - name: single-request-reopen

, — glibc (, alpine, musl), resolv.conf .


PD: En nuestro caso, para automatizar este proceso, se escribió el webhook mutante más simple, que anula automáticamente esta sección de configuración para todos los pods nuevos en el clúster. Lamentablemente, no puedo proporcionar el código.


All Articles