kubernetes 集群中的5秒 DNS 延迟

这是个讨论了很久的问题,网上也有很多文章讨论出了结果。因为近期也遇上了这样的问题,将问题解决过程记录下来。

一、问题

一个新搭建的环境,在进行系统各项指标测试时,发现dns解析有延迟:

«https://k8smeetup.github.io/docs/tasks/administer-cluster/dns-debugging-resolution/»

运行命令:

kubectl exec -it busybox-check-dns-bjp -n monitor -- nslookup kubernetes.default 10.190.0.10

可以明显看到解析延迟。

添加 time 命令,可以看到dns解析延迟为5s,10s,15s等规律的延迟。

1572926381234

运行的busybox为 busybox:1.28.4.

二、原因分析

这一块已经有太多雷同的文章,源头应该都是一样的,下面贴几个分析比较好的原因:

https://tencentcloudcontainerteam.github.io/2018/10/26/DNS-5-seconds-delay/

DNS 5秒延时

在pod中(通过nsenter -n tcpdump)抓包,发现是有的DNS请求没有收到响应,超时5秒后,再次发送DNS请求才成功收到响应。

在kube-dns pod抓包,发现是有DNS请求没有到达kube-dns pod, 在中途被丢弃了。

为什么是5秒? man resolv.conf可以看到glibc的resolver的缺省超时时间是5s。

丢包原因

经过搜索发现这是一个普遍问题。 根本原因是内核conntrack模块的bug。

Weave works的工程师Martynas Pumputis对这个问题做了很详细的分析: https://www.weave.works/blog/racy-conntrack-and-dns-lookup-timeouts

相关结论:

  • 只有多个线程或进程,并发从同一个socket发送相同五元组的UDP报文时,才有一定概率会发生
  • glibc, musl(alpine linux的libc库)都使用”parallel query”, 就是并发发出多个查询请求,因此很容易碰到这样的冲突,造成查询请求被丢弃
  • 由于ipvs也使用了conntrack, 使用kube-proxy的ipvs模式,并不能避免这个问题

三、相关解决办法

因为这个涉及系统bug,根本的解决办法是修改内核,然而对大部分人来说不现实。于是产生了以下几种规避方式:

使用TCP发送DNS请求

在容器的resolv.conf中增加options use-vc, 强制glibc使用TCP协议发送DNS query。下面是这个man resolv.conf中关于这个选项的说明:

use-vc (since glibc 2.14)
                     Sets RES_USEVC in _res.options.  This option forces the
                     use of TCP for DNS resolutions.

避免相同五元组DNS请求的并发

resolv.conf:

  • single-request-reopen 发送A类型请求和AAAA类型请求使用不同的源端口。这样两个请求在conntrack表中不占用同一个表项,从而避免冲突。
  • single-request 避免并发,改为串行发送A类型和AAAA类型请求。没有了并发,从而也避免了冲突。

具体容器中的办法参考腾讯云的文章链接。

关于五元组是什么,看到这里的朋友大概率是不知道这个概念的:

1572931550902

四、复盘解决过程

看完相关的文章(一篇文章到处转载内容一毛一样)后,虽然原理和解决办法讲清楚了,实际上还是没有告诉看客们应该如何操作。

半天研究下来,我感觉实际上该问题包含三个方面:

  1. 观察到dns延迟的现象
  2. 系统层面解决dns延迟问题
  3. 再观察是否存在dns延迟现象

这三个方面都很重要,例如第三步,如果观察和再观察选择的工具有问题,你仍会蒙在鼓里。

1、观察到问题

针对第一步,观察到现象,一家成熟的公司,还是尽量不要让客户帮我们发现问题,应当有自己的一套工具,用来验证整个系统处于正常状态。

我们使用 busybox:1.28.4 进行测试,发现了这个问题:

time nslookup kubernetes.default 10.190.0.10

2、尝试解决

修改容器中 resolv.conf 的当然简单,使用 busybox:1.28.4 修改即可:

1572931831600

经过测试发现,虽然解析延迟的概率降低了,但仍然是有问题的。

1572931940527

同理,我们修改了所有主机的resolv.conf,以期解决问题。

cat /etc/resolv.conf

nameserver 10.10.30.10
nameserver 10.10.10.10
options timeout:1 attempts:2 single-request-reopen

与单独修改 busybox 的结果是一样的,解析延迟的问题大大缓解,但仍然没有达到100%解决。

3、改用 glibc 1.28.4 版本的busybox

经过群友的提醒,改用了该版本 busybox 后,结果达到了 100% 无延迟。

1572932362328

至此,问题得到解决。

参考资料


我收藏的 2019 github awesome

这一篇整理一下今年自己收藏的一些github repo。收录的不是2019 新出的repo,而是我今年新收藏的。 去年的收藏在此——《我收藏的 2018 github repos

这篇也会一直更新知道2019年结束。


梅宏院士:软件定义的未来 ——万物皆可互联,一切均可编程 - CNCC 2017

感谢大会给的这个机会!近几年中,我在不同的场合也做了很多不同的报告,但是这几年都是被动地被拉去讲大数据,后来想想,差点把自己的主业忘了。现在软件很重要,我们每天的生活都离不开软件,可能大多数人每天早上起床的第一件事儿就是打开某个APP。所以我今年给自己订了一个小目标,但凡有机会做报告,我就只讲软件,也是为本行业的人呼吁一下,所以我今天讲的题目很大,软件定义一切。

无处不在的软件

“软件定义一切”并不是我说的,我要是这么说可能把咱们今天在座的很多同行都给得罪了。我是想借这个题目讲一讲软件的三个阶段。第一个题目我想大家都认可,软件已经无处不在,第二个题目是软件定义的时代。我们正在进入一个新的时代,刚刚过去的十九大讲是中华民族复兴的时代,我是从信息技术对人类社会的改造这个角度来谈这个新时代,不同的人从不同的角度也给了这个时代不同的赋名。从基础设施视角来看,这是一个互联网+时代;从计算模式视角来看,这是一个云计算时代;从信息资源视角来看,这是一个大数据时代;从信息应用视角来看,这是智能化时代。我想说在这些里面有一项很重要的技术,那就是软件。某种意义上来说,我们这个时代就是一个软件定义的时代。

梅宏院士:软件定义的未来——万物皆可互联,一切均可编程

软件产业呈持续增长态势。从国内来看,国家工信部公布的2012年到2016年的五年数据中,软件和信息技术服务业始终保持高增长,在电子信息行业的比重也在不断上升。2008年金融危机开始以后,很多行业都在下滑,而信息技术行业还在保持增长,而软件行业的增长又是远远高于信息技术其他的比重。从国际上来看,全球有19个国家软件支出占国内生产总值的比重超过0.5%,其中美国已经超过1%。这个产业规模一直在保持增长。第二个软件从业的人数,2014年全球ICT技术工人约为2900万人,其中专业软件开发人员约1100万人。国家工信部给出的近五年数据中,软件从业人数也在逐年增长,2016年达到576万人。但如果换一个视角,从开源社区来看,比如程序员经常去的一个软件问答网站stack overflow,注册3200万人,其中超过2500万人是多次访问。再比如CSDN,注册用户达2500万,活跃用户超过800万。它们普遍都要比工信部公布的数据高,这说明和软件相关的从业人数有很多。

回顾过去计算机软件发展,我认为大概可以分为三个阶段。第一个是1946到1975中期,是软硬一体化阶段。第二个是1975年以后,软件产品化、产业化阶段;第三个是1995年以后,软件的网络化、服务化阶段。


数据可视化的方法、工具和应用 - 林骥

1. 数据可视化简介

数据可视化,是指用图形的方式来展现数据,从而更加清晰有效地传递信息,主要方法包括图表类型的选择和图表设计的准则。随着互联网的广泛应用,我们的工作和生活等各个方面,每时每刻都在产生大量的数据,也就是所谓的「大数据时代」,发展的趋势是人们越来越喜欢用数据说话。


为 Centos 7 设置静态IP

  1. 编辑 ifcfg-eth0

    vi /etc/sysconfig/network-scripts/ifcfg-eth0
    
  2. 增加/修改设置

    BOOTPROTO="static" # dhcp改为static 
    ONBOOT="yes" # 开机启用本配置
    IPADDR=192.168.7.106 # 静态IP
    GATEWAY=192.168.7.1 # 默认网关
    NETMASK=255.255.255.0 # 子网掩码
    DNS1=192.168.7.1 # DNS 配置
    
  3. 重启网络

    service network restart
    

kubernetes 限制磁盘IO

磁盘 IO 限制 在 IaaS 层是一个基本功能,在 docker 中也有实现。

参考这篇文章: 《限制容器的_Block_IO_每天5分钟玩转_Docker_容器技术 - IBM developerworks》

Block IO 指的是磁盘的读写,实际上 docker 是通过 cgroups 做了限制,通过设置权重、限制 bps 和 iops 的方式控制容器读写磁盘的带宽。 --device-read-bps,限制读某个设备的 bps。 --device-write-bps,限制写某个设备的 bps。 --device-read-iops,限制读某个设备的 iops。 --device-write-iops,限制写某个设备的 iops。

docker run -it --device-write-bps /dev/sda:30MB ubuntu /bin/bash

time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct

不清楚是什么原因,kubernetes 一直未把 io 限速加入到系统功能中。社区中相关的 issue 和 pull request 已经多到不行了,例如:

然而一直未合并至主分支。

由于我使用的为 1.10 某版本的kubernetes,参考了这位朋友的提交,完成了对 block io 的支持 honglei24/kubernetes

修改完成代码之后根据之前 《kubernetes 的编译、打包和发布(v1.10)》,编译完成。

使用时按照代码也可以猜出来用法了:

以下注释表示限制磁盘写的速度为30M:

annotations: 
  BlkioDeviceWriteBps: '/dev/sda:31457280'

1 2 3 4 5 6 90 91 92 93 94