Kubernetes中的长DNS解析

本文重点介绍我们的团队在Kubernetes中遇到的DNS问题。事实证明,有时问题比最初看起来要严重得多。


介绍


总会有片刻的情况,环境会干扰已经调试过的工作,迫使我们进行某些更改。因此,我们的小型团队被迫将所有使用过的应用程序迁移到Kubernetes。有很多原因,客观而并非完全是事实,但事实并非如此。


由于以前没有人积极使用Kubernetes,因此该集群已被重新创建了几次,这就是为什么我们没有时间评估转移的应用程序的质量的原因。因此,在第四次传输之后,当所有主锥都已经装满,所有容器都组装好并编写了所有部署时,您可以分析已完成的工作,最后进行其他任务。


工作日开始11个小时。监视系统缺少来自其中一个应用程序的消息的一部分。


诊断程序


该应用程序最近被转移到一个集群中,由一个简单的工作人员组成,该工作人员每隔几分钟便爬入数据库一次,检查数据库是否有更改,并向总线发送消息(如果有)。在测试开始之前和完成之后,应用程序将消息写入日志。没有并行性,没有多任务处理,只有其中一个容器的唯一壁炉。


仔细检查后,很明显日志已在控制台中,但在Elastic中不再存在。


关于监控系统的一些知识:具有三个节点的Elasticsearch-cluster,部署在同一Kubernetes中,使用Kibana进行显示。日志使用Serilog.Sinks.Elasticsearch软件包进入Elastic,该软件包通过基于Nginx的反向代理发送请求(最初,所有应用程序都是在期望未在Elasticsearch中使用授权的情况下编写的,因此我必须摆脱它)。查看Nginx日志显示,有时根本没有来自应用程序的请求。


在Internet上进行的快速搜索并未在Serilog用户中发现任何类似的问题,但表示Serilog具有用于记录内部错误的自日志。无需三思,我将其连接到Serilog本身:


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

我进行了新的构建,启动了发行版,检查了应用程序日志。在基巴纳


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


图片


, :


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


, :


图片


, – 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在我们的案例中,为了自动化该过程,编写了最简单的变异Webhook,它自动为集群中的所有新Pod设置了此配置部分。不幸的是,我无法提供代码。


All Articles