go程序在容器中域名解析的困惑

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: #我修复的印象最深的一个bug

在容器中碰到一个怪的现象,一个域名配置了host解析,但是程序调用中,tcp连接成了其它IP


看如下操作: 通过nslookup解析域名 test.datakit.com 返回的IP不是hosts文件中配置的IP

# nslookup test.datakit.comServer:   127.0.0.11
Address:  127.0.0.11:53
Non-authoritative answer:
test.datakit.com  canonical name = server.datakit.com
Non-authoritative answer:
test.datakit.com  canonical name = server.datakit.com
Name: server.datakit.com
Address: 46.105.51.17
# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.16.5.9  test.datakit.com
172.26.0.14 7707e6a4e86f



通过docker logs 获取容器中应用的日志,发现请求该域名,最后连接的IP也不是hosts文件中的IP,而是DNS解析的IP

Datadog Tracer v1.29.0 ERROR: lost 1 traces: Post "http://test.datakit.com:9529/v0.4/traces": dial tcp 46.105.51.17:9529: i/o timeout (occurred: 29 Mar 21 02:32 UTC)
Datadog Tracer v1.29.0 ERROR: lost 1 traces: Post "http://test.datakit.com:9529/v0.4/traces": dial tcp 46.105.51.17:9529: i/o timeout (occurred: 29 Mar 21 02:33 UTC)


遇到的问题:

问题1: 为什么host配置了解析,不使用,这个不是优先使用吗


是因为这个容器镜像bash:4.4,没有/etc/nsswitch.conf 解析顺序文件,导致没有优先使用host解析,而使用了dns


问题2: 解析test.datakit.com,为什么返回个server.datakit.com的IP

dnslookup返回了非权威的应答,是一个缓存中的结果,所以自己随便定义域名,也不能和其它能解析的域名相关联,例如: datakit.com 顶级域名,你随便查看其它的a.datakit.com,b.datakit.com 也是这样的结果



解决此问题:

方法一:增加/etc/nsswitch.conf解析顺序文件,从其它系统拷贝到容器中/etc/目录下面

docker cp /etc/nsswitch.conf b753da9b566e:/etc/

方法二:更换域名绑定,如果dns解析失败,那么就会走host解析

# nslookup test.jiangyd.com
Server:   127.0.0.11
Address:  127.0.0.11:53
** server can't find test.jiangyd.com: NXDOMAIN
** server can't find test.jiangyd.com: NXDOMAIN
# cat /etc/hosts |grep test
172.16.5.9  test.jiangyd.com



问题到这里就结束了吗,以上的问题虽然是解决,但其实还有2个疑惑不能答疑?

在使用ping命令过程中,是正确的,能匹配到/etc/hosts的配置

# ping test.datakit.com
PING test.datakit.com (172.16.5.9): 56 data bytes
64 bytes from 172.16.5.9: seq=0 ttl=64 time=0.095 ms
64 bytes from 172.16.5.9: seq=1 ttl=64 time=0.076 ms

在使用curl调用过程中,是正确的,能匹配到/etc/hosts的配置

# curl http://test.datakit.com:9529/stats
{
    "inputs_status": [
        {
            "name": "aliyunobject",
            "category": "/v1/write/object",
            "frequency": "20.23/min",
            ...


难道我还是没理解?,不同的程序使用解析还不一样,ping ,curl,自己写的程序(go二进制)

怎么办,这就要放弃?,好吧,再尝试下使用tcpdump抓包看看吧


ping命令抓的包,直接就是IP了,IP是在/etc/hosts中配置的

image.png

curl 抓的包,直接就是IP了,IP是在/etc/hosts中配置的

image.png

程序(程序部署在容器中,映射出端口18090,容器内部端口18080,在宿主机上访问程序 http://ip:18090,然后程序调用test.datakit.com

看抓包该IP不是hosts解析配置的,而是通过DNS解析的(非权威应答)

image.png


我怀疑程序是不是有问题,因为程序使用了第三方的包,我来个最简单的demo看看

packagemainimport (
"fmt""io/ioutil""net/http")
funcmain()  {
c:=http.Client{}
req,err:=http.NewRequest("GET","http://test.datakit.com:9529/stats",nil)
iferr!=nil{
fmt.Println(err)
   }
resp,err:=c.Do(req)
iferr!=nil{
fmt.Println(err)
   }
data,_:=ioutil.ReadAll(resp.Body)
fmt.Println(string(data))
}

编译后执行,同样的是,tcp连接的IP不是我hosts配置文件中的,那么显然问题与这个程序有关系了

image.png

抓包中显示,query 查了A记录,显示经过了DNS,这下搞懂了原因了,只是不明白为啥go程序会先查询下DNS

image.png


最后在网上找到了答案,go默认使用纯go的域名解析,还有一种cgo的方式

可以临时设置下环境变量尝试一下执行

bash-4.4# export GODEBUG=netdns=cgobash-4.4# ./demo{
"inputs_status": [
        {
            ...


为什么go程序默认使用纯go的域名解析呢,因为当DNS解析阻塞时,内置Go解析器只是阻塞了一个goroutine,而cgo的解析器则是阻塞了一个操作系统级别的线程.


这也是巧合,把程序运行在容器镜像bash4.4(没有/etc/nsswitch.conf),如果运行在其它地方还不一定能知道此问题,所以说失败乃是成功之母,只要踩过坑,并认真找原因,解决问题,我相信你一定能有收货

目录
相关文章
|
2月前
|
Linux iOS开发 Docker
Docker:容器化技术的领航者 —— 从基础到实践的全面解析
在云计算与微服务架构日益盛行的今天,Docker作为容器化技术的佼佼者,正引领着一场软件开发与部署的革命。它不仅极大地提升了应用部署的灵活性与效率,还为持续集成/持续部署(CI/CD)提供了强有力的支撑。
242 69
|
24天前
|
缓存 前端开发 JavaScript
前端的全栈之路Meteor篇(二):容器化开发环境下的meteor工程架构解析
本文详细介绍了使用Docker创建Meteor项目的准备工作与步骤,解析了容器化Meteor项目的目录结构,包括工程准备、环境配置、容器启动及项目架构分析。提供了最佳实践建议,适合初学者参考学习。项目代码已托管至GitCode,方便读者实践与交流。
|
28天前
|
存储 应用服务中间件 云计算
深入解析:云计算中的容器化技术——Docker实战指南
【10月更文挑战第14天】深入解析:云计算中的容器化技术——Docker实战指南
52 1
|
10天前
|
安全 测试技术 Go
Go语言中的并发编程模型解析####
在当今的软件开发领域,高效的并发处理能力是提升系统性能的关键。本文深入探讨了Go语言独特的并发编程模型——goroutines和channels,通过实例解析其工作原理、优势及最佳实践,旨在为开发者提供实用的Go语言并发编程指南。 ####
|
15天前
|
Go
|
1月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
53 2
|
2月前
|
Kubernetes Go 持续交付
一个基于Go程序的持续集成/持续部署(CI/CD)
本教程通过一个简单的Go程序示例,展示了如何使用GitHub Actions实现从代码提交到Kubernetes部署的CI/CD流程。首先创建并版本控制Go项目,接着编写Dockerfile构建镜像,再配置CI/CD流程自动化构建、推送Docker镜像及部署应用。此流程基于GitHub仓库,适用于快速迭代开发。
49 3
|
2月前
|
Kubernetes 持续交付 Go
创建一个基于Go程序的持续集成/持续部署(CI/CD)流水线
创建一个基于Go程序的持续集成/持续部署(CI/CD)流水线
|
30天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
65 0
|
1月前
|
云计算 开发者 Docker
揭秘云计算中的容器化技术——Docker的深度解析
【10月更文挑战第6天】揭秘云计算中的容器化技术——Docker的深度解析

推荐镜像

更多