Golang DNS without CGO on a Kubernetes Cluster

10/3/2016

I got a api written in Golang and deployed in a Kubernetes cluster. Meaning it runs inside a docker container with the scratch image. To compile to a light image like scratch/alpine I need to turn off cgo. But the net package does not work well without cgo. I know there is an issue with the net package because itself uses cgo.

All the services I need to use for this app are on another Kubernetes namespace, so the only way go get to it is using DNS. I am in a corner here.

I build the binaries with something like this

GOOS='linux' CGO_ENABLED=0 GODEBUG=netdns=go+1 go build -a -installsuffix cgo -ldflags -s -o ./dist/prod/api ./src/backend/api.go

Which by itself does not resolve the issue, but as stated here by Brad Fitzpatrick from the go team, there is a hackaround it. Which I finally got it to work like

//Connect is a function that connects to MOngoDB
func Connect() (*mgo.Session, error) {
    var host string
    if os.Getenv("KUBERNETES") == "true" {
        cmd := exec.Command("ping", "-c", "1", viper.GetString("MONGO-HOST"))
        var out bytes.Buffer
        cmd.Stdout = &out
        _ = cmd.Run()
        match := regexp.MustCompile(`\(([^\)]+)\)`).FindStringSubmatch(out.String())
        host = match[1]
    } else {
        host = viper.GetString("MONGO-HOST")
    }

    inf := &mgo.DialInfo{
        Addrs:    []string{host + ":" + viper.GetString("MONGO-PORT")},
        Timeout:  5 * time.Second,
        Database: "admin",
        Username: viper.GetString("MONGO-USER"),
        Password: viper.GetString("MONGO-PASS"),
    }
    return mgo.DialWithInfo(inf)
}

It just cuts the output of a ping command and use the resolved ip instead of the hostname to avoid the issue with dns. But it adds an extra complexity that my app should not be handling. How can I make better?

-- CESCO
cgo
dns
docker
go
kubernetes

0 Answers