热门标签 | 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



推荐阅读
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • 本文详细介绍了如何搭建一个高可用的MongoDB集群,包括环境准备、用户配置、目录创建、MongoDB安装、配置文件设置、集群组件部署等步骤。特别关注分片、读写分离及负载均衡的实现。 ... [详细]
  • 本文详细介绍如何在华为鲲鹏平台上构建和使用适配ARM架构的Redis Docker镜像,解决常见错误并提供优化建议。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • 在使用 Nginx 作为服务器时,发现 Chrome 能正确从缓存中读取 CSS 和 JS 文件,而 Firefox 却无法有效利用缓存,导致加载速度显著变慢。 ... [详细]
  • Irish budget airline Ryanair announced plans to significantly increase its route network from Frankfurt Airport, marking a direct challenge to Lufthansa, Germany's leading carrier. ... [详细]
  • 调试利器SSH隧道
    在开发微信公众号或小程序的时候,由于微信平台规则的限制,部分接口需要通过线上域名才能正常访问。但我们一般都会在本地开发,因为这能快速的看到 ... [详细]
  • CentOS下ProFTPD的安装与配置指南
    本文详细介绍在CentOS操作系统上安装和配置ProFTPD服务的方法,包括基本配置、安全设置及高级功能的启用。 ... [详细]
  • 从CodeIgniter中提取图像处理组件
    本指南旨在帮助开发者在未使用CodeIgniter框架的情况下,如何独立使用其强大的图像处理功能,包括图像尺寸调整、创建缩略图、裁剪、旋转及添加水印等。 ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
  • 在尝试加载支持推送通知的iOS应用程序的Ad Hoc构建时,遇到了‘no valid aps-environment entitlement found for application’的错误提示。本文将探讨此错误的原因及多种可能的解决方案。 ... [详细]
  • 本文详细介绍了Oracle 11g中的创建表空间的方法,以及如何设置客户端和服务端的基本配置,包括用户管理、环境变量配置等。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • 本文探讨了如何将个人经历,特别是非传统的职业路径,转化为职业生涯中的优势。通过作者的亲身经历,展示了舞蹈生涯对商业思维的影响。 ... [详细]
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社区 版权所有