热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

dnsdocker_使用DNS缓存修复Docker中的DNS超时[教程]

dnsdocker在CI中进行不稳定的测试是一场噩梦。您无法确定您的新代码是否损坏了某些东西,或者仅仅是那些测试再次变得不稳定。因此,每当我们看到开源项

dns docker

在CI中进行不稳定的测试是一场噩梦。 您无法确定您的新代码是否损坏了某些东西,或者仅仅是那些测试再次变得不稳定。 因此,每当我们看到开源项目Adapt的CI出现奇怪的随机故障时,我们都将尽快找出问题的根源。 这是关于我们如何发现(偶然)用流量泛滥DNS服务器以及如何在Docker中使用DNS缓存来解决问题的故事。

背景

AdaptJS是我从事的一个开源项目,可以将应用程序部署到多种云和技术中,因此,使用Docker,Kubernetes,AWS,Google Cloud和其他类似技术进行了大量的系统测试和端到端测试。

我们在测试中大量使用了Docker,因此最终创建了许多短期容器,这些容器会启动,完成一些工作,例如构建或安装应用程序,然后被删除。 随着我们添加越来越多的这些测试,我们开始看到以前稳定的系统测试在CI中随机失败。

症状:测试超时

我们看到的第一个症状是测试超时。 我们的许多端到端测试的超时时间都很短,因此我们可以检测到新代码是否突然使最终用户花费了更长的时间。 但是现在,通常需要半秒的测试有时会花费5.5秒。

额外的5秒是一个很好的线索-听起来像-5秒可能是某种超时。 怀着这种直觉,我们回顾了所有看似随机的测试失败并找到了共同的线索:它们都是引发网络请求的测试。 我们还注意到一些测试花费了更长的时间才失败……总是以5秒为增量。

这里没有太多的网络协议可以使用,因此快速搜索可以为我们指明正确的方向。 在Linux上,DNS服务器查询的默认超时仅为5秒 。

为了了解DNS的运行情况,我们找到了在Linux上调试网络问题的最重要的工具: tcpdump 。 (或者,如果您更喜欢GUI版本, wireshark也很棒。)我们在主机系统(Amazon Workspaces Linux实例)上运行tcpdump并使用过滤器查看DNS流量:

$ tcpdump -n -i eth1 port 53
11:35:59.474735 IP 172.16.0.131.54264 > 172.16.0.119.domain: 64859+ AAAA? registry-1.docker.io. (38)
11:35:59.474854 IP 172.16.0.131.49631 > 172.16.0.119.domain: 43524+ A? registry-1.docker.io. (38)
11:35:59.476871 IP 172.16.0.119.domain > 172.16.0.131.49631: 43524 8/0/1 A 34.197.189.129, A 34.199.40.84, A 34.199.77.19, A 34.201.196.144, A 34.228.211.243, A 34.232.31.24, A 52.2.186.244, A 52.55.198.220 (177)
11:35:59.476957 IP 172.16.0.119.domain > 172.16.0.131.54264: 64859 0/1/1 (133)

我们注意到的第一件事是,我们向VPC的AWS默认DNS服务器生成了大量DNS查询。 看起来由于各种原因,所有那些短命的容器在启动时都倾向于进行一堆DNS查找。 接下来,我们注意到其中一些DNS查询没有得到答复。

共享DNS服务器实施速率限制是很常见的,这样一个用户就不会降低其他用户的性能。 在这里,我们怀疑AWS DNS服务器正是在这样做。 我们无法找到一种方法来确认我们是否确实达到了AWS速率限制,但是对于我们来说,不要对我们的DNS服务器进行DoS似乎是明智的。

解决方案:使用dnsmasq的Docker DNS缓存

为了隔离主机中的DNS流量,我们需要一个本地DNS服务器充当缓存。 dnsmasq是此类缓存的绝佳选择。 它可靠,使用广泛且设置超级简单。 并且由于我们所有的测试都在Docker容器中运行,因此也可以在Docker中运行DNS服务器。

基本想法非常简单:在Docker主机网络上运行dnsmasq容器作为DNS缓存,然后使用--dns选项指向缓存容器的IP地址运行测试容器。

这是启动DNS缓存容器的dns_cache脚本:

#!/usr/bin/env bash: " ${IMAGE:=andyshinn/dnsmasq:2.76} "
: " ${NAME:=dnsmasq} "
: " ${ADAPT_DNS_IP_FILE:=/tmp/adapt_dns_ip} "# Get IP address for an interface, as visible from inside a container
# connected to the host network
interfaceIP () {# Run a container and get ifconfig output from inside# We need the ifconfig that will be visible from inside the dnsmaq# containerdocker run --rm --net=host busybox ifconfig " $1 " 2>/dev/null | \awk '/inet /{print(gensub(/^.*inet (addr:)?([0-9.]+)\s.*$/, "\\2", 1))}'
}if docker inspect -- type container " ${NAME} " >& /dev/null ; thenif [ -f " ${ADAPT_DNS_IP_FILE} " ]; then# dnsmasq is already startedcat " ${ADAPT_DNS_IP_FILE} "exit 0elseecho DNS cache container running but file ${ADAPT_DNS_IP_FILE} does not exist. >&2exit 1fi
fi# We only support attaching to the default (host) bridge named "bridge".
DOCKER_HOST_NETWORK=bridge# Confirm that "bridge" is the default bridge
IS_DEFAULT=$(docker network inspect " ${DOCKER_HOST_NETWORK} " --format '{{(index .Options "com.docker.network.bridge.default_bridge")}}' )
if [ " ${IS_DEFAULT} " != "true" ]; thenecho Cannot start DNS cache. The Docker network named \ " ${DOCKER_HOST_NETWORK} \" does not exist or is not the default bridge. >&2exit 1
fi# Get the Linux interface name for the bridge, typically " docker0 "
INTF_NAME= $(docker network inspect "${DOCKER_HOST_NETWORK}" --format '{{(index .Options "com.docker.network.bridge.name") }}')
if [ -z " ${INTF_NAME} " ]; thenecho Cannot start DNS cache. Unable to determine default bridge interface name. >&2exit 1
fi# Get the IP address of the bridge interface. This is the address that
# dnsmasq will listen on and other containers will send DNS requests to.
IP_ADDR= $(interfaceIP "${INTF_NAME}")
if [ -z " ${IP_ADDR} " ]; thenecho Cannot start DNS cache. Docker bridge interface ${INTF_NAME} does not exist. >&2exit 1
fi# Run the dnsmasq container. The hosts's /etc/resolv.conf configuration will
# be used by dnsmasq to resolve requests.
docker run --rm -d --cap-add=NET_ADMIN --name " ${NAME} " --net=host -v/etc/resolv.conf:/etc/resolv.conf " ${IMAGE} " --bind-interfaces --listen-address=" ${IP_ADDR} " --log-facility=- > /dev/null
if [ $? -ne 0 ]; thenecho Cannot start DNS cache. Docker run failed.exit 1
fi# Remember what IP address to use as DNS server, then output it.
echo ${IP_ADDR} > " ${ADAPT_DNS_IP_FILE} "
echo ${IP_ADDR}

除了启动容器(如果尚未运行)之外,脚本还会输出缓存容器的IP地址。 我们将在我们启动的任何其他容器的命令行上使用它。 该脚本还确保dnsmasq仅侦听Docker内部(在Docker桥接口上)的DNS请求,因此需要做一些额外的工作来确定要侦听的IP地址。

这是一个如何启动DNS缓存,记住变量DNS_IP的IP地址,然后运行另一个将使用该缓存的容器的DNS_IP

$ DNS_IP=$(dns_cache)
$ docker run --dns ${DNS_IP} --rm busybox ping -c1 adaptjs.org

验证缓存工作正常

在我们的测试中开始使用缓存后,主机系统发送到AWS DNS服务器的DNS查询数量就减少了。 我们还通过检查dnsmasq统计信息来确认缓存正常运行。 将SIGUSR1发送到dnsmasq会使其将统计信息打印到其日志中 :

$ docker kill -s USR1 dnsmasq
$ docker logs dnsmasq
dnsmasq[1]: cache size 150, 1085/4664 cache insertions re-used unexpired cache entries.
dnsmasq[1]: queries forwarded 1712, queries answered locally 3940
dnsmasq[1]: queries for authoritative zones 0
dnsmasq[1]: server 172.16.0.119#53: queries sent 1172, retried or failed 0
dnsmasq[1]: server 172.16.1.65#53: queries sent 252, retried or failed 0
dnsmasq[1]: server 172.16.0.2#53: queries sent 608, retried or failed 0

最重要的是,我们看到系统测试超时显着减少,并且CI运行稳定。

这个问题使我们花了一段时间才找到答案。 但是保持CI健康非常重要。 如果您有太多的零星测试失败,则开发人员倾向于忽略CI结果,并推送可能损坏的代码。

因此,尽管查找这些故障很费时,但考虑到修复的简便性,绝对值得投资。

最初发布在 Adapt博客上

翻译自: https://hackernoon.com/fixing-dns-timeouts-in-docker-hbr32ej

dns docker



推荐阅读
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • Firefox火狐浏览器关闭到http://detectportal.firefox.com的流量问题解决办法
    本文介绍了使用Firefox火狐浏览器时出现关闭到http://detectportal.firefox.com的流量问题,并提供了解决办法。问题的本质是因为火狐默认开启了Captive portal技术,当连接需要认证的WiFi时,火狐会跳出认证界面。通过修改about:config中的network.captive-portal-service.en的值为false,可以解决该问题。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • React基础篇一 - JSX语法扩展与使用
    本文介绍了React基础篇一中的JSX语法扩展与使用。JSX是一种JavaScript的语法扩展,用于描述React中的用户界面。文章详细介绍了在JSX中使用表达式的方法,并给出了一个示例代码。最后,提到了JSX在编译后会被转化为普通的JavaScript对象。 ... [详细]
  • 本文介绍了OkHttp3的基本使用和特性,包括支持HTTP/2、连接池、GZIP压缩、缓存等功能。同时还提到了OkHttp3的适用平台和源码阅读计划。文章还介绍了OkHttp3的请求/响应API的设计和使用方式,包括阻塞式的同步请求和带回调的异步请求。 ... [详细]
author-avatar
小燕子20071973
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有