golang容器内DNS解析问题排查
先写一个一个测试案例package mainimport ("fmt""net""os")func main() {if len(os.Args) != 2 {fmt.Fprintf(os.Stderr, "Usage: %s hostname\n", os.Args[0])fmt.Println("Usage:
·
先写一个一个测试案例
package main
import (
"fmt"
"net"
"os"
)
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, "Usage: %s hostname\n", os.Args[0])
fmt.Println("Usage: ", os.Args[0], "hostname")
os.Exit(1)
}
name := os.Args[1]
addr, err := net.ResolveIPAddr("ip", name)
if err != nil {
fmt.Println("Resolution error", err.Error())
os.Exit(1) }
fmt.Println("Resolved address is ", addr.String())
os.Exit(0)
}
如果一个主机有多个网卡,可能对应多个IP地址,或者互联网高可用也会使用一个域名对应多个IP
addrs, err := net.LookupHost(name)
解析出多个主机地址
如果自己通过/etc/hosts注入的域名的,在主机上面执行没有任何问题,但放到容器内运行则会出现无法解析域名的问题,通过golang 1.8.3的源码可以看到,golang解析的dns的过程net/lookup_unix.go
func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
order := systemConf().hostLookupOrder(host)
if !r.PreferGo && order == hostLookupCgo {
if addrs, err, ok := cgoLookupHost(ctx, host); ok {
return addrs, err
}
// cgo not available (or netgo); fall back to Go's DNS resolver
order = hostLookupFilesDNS
}
return goLookupHostOrder(ctx, host, order)
}
通过hostLookupOrder确定解析的顺序
nss := c.nss
srcs := nss.sources["hosts"]
// If /etc/nsswitch.conf doesn't exist or doesn't specify any
// sources for "hosts", assume Go's DNS will work fine.
if os.IsNotExist(nss.err) || (nss.err == nil && len(srcs) == 0) {
if c.goos == "solaris" {
// illumos defaults to "nis [NOTFOUND=return] files"
return fallbackOrder
}
if c.goos == "linux" {
// glibc says the default is "dns [!UNAVAIL=return] files"
// http://www.gnu.org/software/libc/manual/html_node/Notes-on-NSS-Configuration-File.html.
return hostLookupDNSFiles
}
return hostLookupFilesDNS
}
if nss.err != nil {
// We failed to parse or open nsswitch.conf, so
// conservatively assume we should use cgo if it's
// available.
return fallbackOrder
}
上面的nss就是/etc/nsswitch.conf这个文件,如果这个文件不存在则会通过hostLookupDNSFiles去解析,就是dns优先的顺序去解析
这里有个地方需要注意,就是容器内运行的话,经常是没有/etc/nsswitch.conf这个文件的
而golang的解析又是需要读取这个文件,得到解析顺序的,所以需要在容器内创建这个文件
并且加入
hosts: files dns
就是先读取files 然后走dns解析,这样就ok了
当然你也可以设置cgo的方式,走传统的c库,也能解决
更多推荐
已为社区贡献19条内容
所有评论(0)