golang容器内DNS解析問題の調査

4598 ワード

まずテストケースを1つ書きます
package main
import (
    "fmt"
    "net"
    "os"
)
func main() {
    if len(os.Args) != 2 {
        fmt.Fprintf(os.Stderr, "Usage: %s hostname
"
, 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) }

1つのホストに複数のNICがある場合、複数のIPアドレスに対応しているか、インターネットが高可用性である場合、1つのドメイン名を使用して複数の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ライブラリを歩いても解決できます