Lange DNS-Auflösung in Kubernetes

Dieser Artikel konzentriert sich auf die DNS-Probleme in Kubernetes, auf die unser Team gestoßen ist. Wie sich herausstellte, liegt das Problem manchmal viel tiefer als es zunächst scheint.


Einführung


Es kommt immer ein Moment, in dem die Umstände in die bereits debuggte Arbeit eingreifen und uns zwingen, etwas zu ändern. Daher musste unser kleines Team alle verwendeten Anwendungen auf Kubernetes migrieren. Es gab viele Gründe, objektiv und nicht sehr, aber in der Geschichte geht es tatsächlich nicht darum.


Da zuvor niemand Kubernetes aktiv genutzt hat, wurde der Cluster mehrmals neu erstellt, weshalb wir keine Zeit hatten, die Qualität der übertragenen Anwendungen zu bewerten. Nach der vierten Übertragung, wenn alle Hauptkegel bereits voll sind, alle Container zusammengesetzt und alle Bereitstellungen geschrieben sind, können Sie die geleistete Arbeit analysieren und schließlich mit anderen Aufgaben fortfahren.


11 Stunden, Beginn des Arbeitstages. Dem Überwachungssystem fehlt ein Teil der Nachrichten von einer der Anwendungen.


Diagnose


Die Anwendung wurde kürzlich in einen Cluster übertragen und bestand aus einem einfachen Mitarbeiter, der alle paar Minuten in die Datenbank kletterte, sie auf Änderungen überprüfte und gegebenenfalls eine Nachricht an den Bus sendete. Vor dem Start des Tests und nach dessen Abschluss schreibt die Anwendung eine Nachricht in das Protokoll. Keine Parallelität, kein Multitasking, der einzige Herd mit dem einzigen Behälter darin.


Bei näherer Betrachtung wurde klar, dass sich die Protokolle in der Konsole befinden, in Elastic jedoch nicht mehr.


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


Bild


, :


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


, :


Bild


, – 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 .


PS In unserem Fall wurde zur Automatisierung dieses Prozesses der einfachste mutierende Webhook geschrieben, der diesen Konfigurationsabschnitt automatisch für alle neuen Pods im Cluster ablegt. Leider kann ich den Code nicht bereitstellen.


All Articles