最近大家在内部测试Kubernetes上层服务,Ingress、Open vSwitch乱飞,于是大家需要使用hostname,比如test.172.3.1.100.xip.cloud.com
,要有个dns能将这个地址解析为172.3.1.100
,xip是外部网站,大家总觉得别扭 (test.172.3.1.100.xip.io
),需要在内部也实现一个,于是就直接写起来。
go get github.com/coredns/coredns
得到源代码并编译好。
扫一眼源代码结构,懒得从头自己写external plugin了,plugin.cfg包含了etcd也不会用到,直接把它改成xip的形式吧。etcd会根据dns查询的hostname去使用etcd的client查询数据,我们只要把client那层干掉,直接解析hostname,把ip抓出来,返回就好了。
grep
下etcd client,定位到plugin/etcd/etcd.go
diff --git a/plugin/etcd/etcd.go b/plugin/etcd/etcd.go
index 493764f..f4e8f38 100644
--- a/plugin/etcd/etcd.go
+++ b/plugin/etcd/etcd.go
@@ -3,10 +3,11 @@ package etcd
import (
"context"
- "encoding/json"
+ //"encoding/json"
"errors"
"fmt"
"strings"
+ "strconv"
"time"
"github.com/coredns/coredns/plugin"
@@ -69,92 +70,47 @@ func (e *Etcd) IsNameError(err error) bool {
return err == errKeyNotFound
}
+func check_number(num string) bool {
+ i, err := strconv.Atoi(num)
+ if (err != nil) { return false }
+ if (i < 0 || i > 255) { return false }
+ return true
+}
+
// Records looks up records in etcd. If exact is true, it will lookup just this
// name. This is used when find matches when completing SRV lookups for instance.
func (e *Etcd) Records(state request.Request, exact bool) ([]msg.Service, error) {
name := state.Name()
-
- path, star := msg.PathWithWildcard(name, e.PathPrefix)
- r, err := e.get(path, true)
- if err != nil {
- return nil, err
// e.g. 配置`etcd x.com`,当查询`127.0.0.1.x.com`时返回`127.0.0.1`
+ suffix := ""
+ if (len(e.Zones) > 0) {
+ suffix = "." + e.Zones[0]
+ }
+ if (len(suffix) > len(name)) {
+ return nil, fmt.Errorf("'%s' is longer than '%s'", suffix, name)
+ }
+ prefix := name[0:len(name) - len(suffix)]
// 检查是ip v4的地址
+ t := strings.Split(prefix, ".")
+ n := len(t)
+ if (n < 4) {
+ return nil, fmt.Errorf("'%s' is not valid", name)
+ }
+ t = t[n - 4:n]
+ if (!check_number(t[0]) || !check_number(t[1]) || !check_number(t[2]) || !check_number(t[3])) {
+ return nil, fmt.Errorf("'%s' is not valid", name)
}
- segments := strings.Split(msg.Path(name, e.PathPrefix), "/")
- return e.loopNodes(r.Kvs, segments, star)
+ host := strings.Join(t, ".")
+ fmt.Println("test:", name, host)
+ bx := make([]msg.Service, 0)
+ bx = append(bx, msg.Service{Host: host, Priority: 500, TTL: 32})
+ return bx, nil
}
// remove used code
func (e *Etcd) get(path string, recursive bool) (*etcdcv3.GetResponse, error) {
- ctx, cancel := context.WithTimeout(e.Ctx, etcdTimeout)
- defer cancel()
- if recursive == true {
- if !strings.HasSuffix(path, "/") {
- path = path + "/"
- }
- r, err := e.Client.Get(ctx, path, etcdcv3.WithPrefix())
- if err != nil {
- return nil, err
- }
- if r.Count == 0 {
- path = strings.TrimSuffix(path, "/")
- r, err = e.Client.Get(ctx, path)
- if err != nil {
- return nil, err
- }
- if r.Count == 0 {
- return nil, errKeyNotFound
- }
- }
- return r, nil
- }
-
- r, err := e.Client.Get(ctx, path)
- if err != nil {
- return nil, err
- }
- if r.Count == 0 {
- return nil, errKeyNotFound
- }
- return r, nil
+ return nil, nil
}
func (e *Etcd) loopNodes(kv []*mvccpb.KeyValue, nameParts []string, star bool) (sx []msg.Service, err error) {
- bx := make(map[msg.Service]bool)
-Nodes:
- for _, n := range kv {
- if star {
- s := string(n.Key)
- keyParts := strings.Split(s, "/")
- for i, n := range nameParts {
- if i > len(keyParts)-1 {
- // name is longer than key
- continue Nodes
- }
- if n == "*" || n == "any" {
- continue
- }
- if keyParts[i] != n {
- continue Nodes
- }
- }
- }
- serv := new(msg.Service)
- if err := json.Unmarshal(n.Value, serv); err != nil {
- return nil, fmt.Errorf("%s: %s", n.Key, err.Error())
- }
- b := msg.Service{Host: serv.Host, Port: serv.Port, Priority: serv.Priority, Weight: serv.Weight, Text: serv.Text, Key: string(n.Key)}
- if _, ok := bx[b]; ok {
- continue
- }
- bx[b] = true
-
- serv.Key = string(n.Key)
- serv.TTL = e.TTL(n, serv)
- if serv.Priority == 0 {
- serv.Priority = priority
- }
- sx = append(sx, *serv)
- }
- return sx, nil
+ return nil, nil
}
go build github.com/coredns/coredns
编译,运行,yes,搞定。
然后因为内部dns在*.cloud.com
是定位服务ip的,就是说我们的配置里有file xxx.db cloud.com
;如果再加个配置etcd xip.cloud.com
,在进行nslookup www.127.0.0.1.xip.cloud.com
查询时总会NXDOWN
。发现coredns plugin的chain处理顺序不是按照配置文件里写的顺序,查查官方文档 https://coredns.io/manual/explugins/ 处理顺序是plugin.cfg里的顺序,把etcd移动上去:
diff --git a/plugin.cfg b/plugin.cfg
index 6a8ad0e..dc0c2ed 100644
--- a/plugin.cfg
+++ b/plugin.cfg
@@ -44,10 +44,10 @@ hosts:hosts
route53:route53
federation:federation
kubernetes:kubernetes
+etcd:etcd
file:file
auto:auto
secondary:secondary
-etcd:etcd
loop:loop
forward:forward
proxy:proxy
go generate github.com/coredns/coredns
然后 go build github.com/coredns/coredns
编译,再运行,好了,所有都正常了;这样既可以查询service.cloud.com
,又可以查询*.<ip>.xip.cloud.com
了。结束。