前段时间在容器化golang应用的时候遇到一个问题,同样编译的程序,把程序放到centos镜像里,在程序发送请求时,会以/etc/hosts配置对dns为准,一旦把程序放到alpine镜像,/etc/hosts文件却不生效。最终通过一番google后,找到了解决方法 echo "hosts: files dns" > /etc/nsswitch.conf,但其中的原因却一直拖着没去研究,直到最近两天。
解决方法来源于 https://github.com/golang/go/issues/22846。其中有一个回答是通过go的源码注释来说明的。根据提示,找到了对应的源码文件$GOROOT/src/net/conf.go
194 nss:= c.nss
195 srcs:= nss.sources["hosts"]
196 // If /etc/nsswitch.conf doesn't exist or doesn't specify any
197 // sources for "hosts", assume Go's DNS will work fine.
198 if os.IsNotExist(nss.err) || (nss.err == nil && len(srcs) == 0) {
199 if c.goos == "solaris"{
200 // illumos defaults to "nis [NOTFOUND=return] files"
201 return fallbackOrder
202 }
203 if c.goos == "linux" {
204 // glibc says the default is "dns [!UNAVAIL=return] files"
205 // http://www.gnu.org/software/libc/manual/html_node/Notes-on-NSS-Configuration-File.html.
206 return hostLookupDNSFiles
207 }
208 return hostLookupFilesDNS
209 }
大概的意思就是在/etc/nsswitch.conf文件不存在或者hosts的source未指定的情况下,如果操作系统是linux,return hostLookupDNSFiles。然后再查看hostLookupDNSFiles变量的定义/usr/local/go/src/net/dnsclient_unix.go,
405 const (
406 // hostLookupCgo means defer to cgo.
407 hostLookupCgo hostLookupOrder= iota
408 hostLookupFilesDNS // files first
409 hostLookupDNSFiles // dns first
410 hostLookupFiles // only files
411 hostLookupDNS // only DNS
412 )
发现其实是常量,看注释的意思hostLookupDNSFiles的意思就是先通过dns服务器来解析域名,然后再是文件解析。
在大概了解原因后,通过万能的打印调试法,在conf.go文件中添加了两行输出的代码来印证是否正确。在重新编译源码后,把centos的/etc/nsswitch.conf mv走后,执行程序会打印hostLookupDNSFiles,并且所配的/etc/hosts文件不生效。
参考: https://github.com/golang/go/issues/22848
https://www.cnblogs.com/majianguo/p/7258975.html
有疑问加站长微信联系(非本文作者)