github地址:https://github.com/kubernetes/dns
dnsmasq简介Dnsmasq是一款小巧的DNS配置工具
● 通过kubedns容器获取DNS规则,在集群中提供DNS查询服务
● 提供DNS缓存,提高查询性能
● dnsmasq通过参数—server=127.0.0.1#10053指定upstream为kubedns。
/dnsmasq-nanny
-v=2
-logtostderr
-configDir=/etc/k8s/dns/dnsmasq-nanny
-restartDnsmasq=true -
- -k
--cache-size=1000
--log-facility=-
--server=/cluster.local/127.0.0.1#10053
--server=/in-addr.arpa/127.0.0.1#10053
--server=/ip6.arpa/127.0.0.1#10053
结构和kubernetes的代码结构类似:首先看cmd/dnsmasq-nanny/main.go一 dnsmasq-nanny启动流程
1 main函数
func main() {
parseFlags()
glog.V(0).Infof("opts: %v", opts)
sync := config.NewFileSync(opts.configDir, opts.syncInterval)
dnsmasq.RunNanny(sync, opts.RunNannyOpts)
}
2 RunNanny函数
// RunNanny runs the nanny and handles configuration updates.
func RunNanny(sync config.Sync, opts RunNannyOpts) {
defer glog.Flush()
currentConfig, err := sync.Once()
if err != nil {
glog.Errorf("Error getting initial config, using default: %v", err)
currentConfig = config.NewDefaultConfig()
}
nanny := &Nanny{Exec: opts.DnsmasqExec}
nanny.Configure(opts.DnsmasqArgs, currentConfig)
if err := nanny.Start(); err != nil {
glog.Fatalf("Could not start dnsmasq with initial configuration: %v", err)
}
configChan := sync.Periodic()
for {
select {
case status := <-nanny.ExitChannel:
glog.Flush()
glog.Fatalf("dnsmasq exited: %v", status)
break
case currentConfig = <-configChan:
if opts.RestartOnChange {
glog.V(0).Infof("Restarting dnsmasq with new configuration")
nanny.Kill()
nanny = &Nanny{Exec: opts.DnsmasqExec}
nanny.Configure(opts.DnsmasqArgs, currentConfig)
nanny.Start()
} else {
glog.V(2).Infof("Not restarting dnsmasq (--restartDnsmasq=false)")
}
break
}
}
}
3 Start函数
可以看到简单粗暴执行exec.Command,/usr/sbin/dnsmasq -k --cache-size=1000 --log-facility=- --server=/cluster.local/127.0.0.1#10053 --server=/in-addr.arpa/127.0.0.1#10053 --server=/ip6.arpa/127.0.0.1#10053
// Start the nanny.
func (n *Nanny) Start() error {
n.cmd = exec.Command(n.Exec, n.args...)
stderrReader, err := n.cmd.StderrPipe()
if err != nil {
return err
}
stdoutReader, err := n.cmd.StdoutPipe()
if err != nil {
return err
}
if err := n.cmd.Start(); err != nil {
return err
}
logToGlog := func(stream string, reader io.Reader) {
bufReader := bufio.NewReader(reader)
for {
bytes, err := bufReader.ReadBytes('\n')
if len(bytes) > 0 {
glog.V(1).Infof("%v", string(bytes))
}
if err == io.EOF {
glog.V(1).Infof("%v", string(bytes))
glog.Warningf("Got EOF from %v", stream)
return
} else if err != nil {
glog.V(1).Infof("%v", string(bytes))
glog.Errorf("Error reading from %v: %v", stream, err)
return
}
}
}
go logToGlog("stderr", stderrReader)
go logToGlog("stdout", stdoutReader)
n.ExitChannel = make(chan error)
go func() {
n.ExitChannel <- n.cmd.Wait()
}()
return nil
}
4 Kill函数
// Kill the running Nanny.
func (n *Nanny) Kill() error {
glog.V(0).Infof("Killing dnsmasq")
if n.cmd == nil {
return fmt.Errorf("Process is not running")
}
if err := n.cmd.Process.Kill(); err != nil {
glog.Errorf("Error killing dnsmasq: %v", err)
return err
}
n.cmd = nil
return nil
}