From 5e826dd2ea44cd9be211ad9363dbd153ff03409f Mon Sep 17 00:00:00 2001 From: xiejunqiao Date: Tue, 29 Apr 2025 00:51:08 +0800 Subject: [PATCH 1/4] feat:add static domain ip map Signed-off-by: xiejunqiao --- chaos.go | 50 +++++++++++++- go.mod | 2 +- grpc_server.go | 36 +++++++++- handler.go | 8 ++- kubernetes.go | 5 +- pb/dns.pb.go | 184 ++++++++++++++++++++++++++++++++++--------------- pb/dns.proto | 9 ++- 7 files changed, 231 insertions(+), 63 deletions(-) diff --git a/chaos.go b/chaos.go index 5ec422c..3026f1c 100644 --- a/chaos.go +++ b/chaos.go @@ -26,6 +26,8 @@ const ( ActionError = "error" // ActionRandom means return random IP for DNS request ActionRandom = "random" + // ActionChaos means return chaos IP for DNS request + ActionStatic = "static" ) // PodInfo saves some information for pod @@ -39,6 +41,12 @@ type PodInfo struct { LastUpdateTime time.Time } +// DomainIP Domain and ip mapping +type DomainIP struct { + Domain string + IP string +} + // IsOverdue ... func (p *PodInfo) IsOverdue() bool { // if the pod's IP is not updated greater than 10 seconds, will treate it as overdue @@ -55,7 +63,13 @@ func (k Kubernetes) chaosDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M return dns.RcodeServerFailure, fmt.Errorf("dns chaos error") } - // return random IP + //return static IP + if podInfo.Action == ActionStatic { + //return staticIP(ctx, w, r, state, podInfo) + //k.chaosMap + domainAndIPMap := k.domainAndIPMap[podInfo.Namespace][podInfo.Name] + return generateDNSRecords(state, domainAndIPMap, r, w) + } answers := []dns.RR{} qname := state.Name() @@ -166,6 +180,9 @@ func (k Kubernetes) needChaos(podInfo *PodInfo, records []dns.RR, name string) b if podInfo.Scope == ScopeAll { return true } + if podInfo.Action == ActionStatic && k.domainAndIPMap[podInfo.Namespace][podInfo.Name] != nil { + return true + } rules := podInfo.Selector.Match(name, "") if len(rules) == 0 { @@ -188,3 +205,34 @@ func (k Kubernetes) getPodFromCluster(namespace, name string) (*api.Pod, error) } return pods.Get(context.Background(), name, meta.GetOptions{}) } + +func generateDNSRecords(state request.Request, domainAndIpMap map[string]string, r *dns.Msg, w dns.ResponseWriter) (int, error) { + answers := []dns.RR{} + qname := state.Name() + if domainAndIpMap == nil { + return dns.RcodeServerFailure, nil + } + ip, ok := domainAndIpMap[qname] + if !ok { + //如果不存在则 + return dns.RcodeServerFailure, fmt.Errorf("domain %s not found", qname) + } + switch state.QType() { + case dns.TypeA: + ips := []net.IP{net.ParseIP(ip)} + log.Debugf("dns.TypeA %v", ips) + answers = a(qname, 10, ips) + case dns.TypeAAAA: + // TODO: return random IP + ips := []net.IP{net.ParseIP(ip)} + log.Debugf("dns.TypeAAAA %v", ips) + answers = aaaa(qname, 10, ips) + } + m := new(dns.Msg) + m.SetReply(r) + m.Authoritative = true + m.Answer = answers + + w.WriteMsg(m) + return dns.RcodeSuccess, nil +} diff --git a/go.mod b/go.mod index 5deefca..53ef8f6 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/miekg/dns v1.1.43 github.com/pingcap/tidb-tools v6.3.0+incompatible github.com/prometheus/client_golang v1.11.0 - golang.org/x/net v0.0.0-20210614182718-04defd469f4e google.golang.org/grpc v1.41.0 k8s.io/api v0.22.2 k8s.io/apimachinery v0.22.2 @@ -45,6 +44,7 @@ require ( github.com/prometheus/common v0.31.1 // indirect github.com/prometheus/procfs v0.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 // indirect golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect diff --git a/grpc_server.go b/grpc_server.go index 593768c..674f1ed 100644 --- a/grpc_server.go +++ b/grpc_server.go @@ -44,7 +44,6 @@ func (k Kubernetes) SetDNSChaos(ctx context.Context, req *pb.SetDNSChaosRequest) k.Lock() defer k.Unlock() - k.chaosMap[req.Name] = req var scope string @@ -70,6 +69,15 @@ func (k Kubernetes) SetDNSChaos(ctx context.Context, req *pb.SetDNSChaosRequest) } } } + if req.Action == ActionStatic && req.IpDomainMaps != nil { + for _, domainIPMap := range req.IpDomainMaps { + err := selector.Insert(domainIPMap.Domain, "", true, trieselector.Insert) + if err != nil { + log.Errorf("fail to build selector %v", err) + return nil, err + } + } + } for _, pod := range req.Pods { v1Pod, err := k.getPodFromCluster(pod.Namespace, pod.Name) @@ -100,8 +108,15 @@ func (k Kubernetes) SetDNSChaos(ctx context.Context, req *pb.SetDNSChaosRequest) k.podMap[pod.Namespace][pod.Name] = podInfo k.ipPodMap[v1Pod.Status.PodIP] = podInfo - } + domainIPMap := saveDomainAndIp(req.IpDomainMaps) + if domainIPMap != nil { + if _, ok := k.domainAndIPMap[pod.Namespace]; !ok { + k.domainAndIPMap[pod.Namespace] = make(map[string]map[string]string) + } + k.domainAndIPMap[pod.Namespace][pod.Name] = domainIPMap + } + } return &pb.DNSChaosResponse{ Result: true, }, nil @@ -125,6 +140,9 @@ func (k Kubernetes) CancelDNSChaos(ctx context.Context, req *pb.CancelDNSChaosRe delete(k.podMap[pod.Namespace], pod.Name) delete(k.ipPodMap, podInfo.IP) } + if _, ok1 := k.domainAndIPMap[pod.Namespace][pod.Name]; ok1 { + delete(k.domainAndIPMap[pod.Namespace], pod.Name) + } } } @@ -136,6 +154,7 @@ func (k Kubernetes) CancelDNSChaos(ctx context.Context, req *pb.CancelDNSChaosRe } for _, namespace := range shouldDeleteNs { delete(k.podMap, namespace) + delete(k.domainAndIPMap, namespace) } delete(k.chaosMap, req.Name) @@ -144,3 +163,16 @@ func (k Kubernetes) CancelDNSChaos(ctx context.Context, req *pb.CancelDNSChaosRe Result: true, }, nil } + +// save domain and ip +func saveDomainAndIp(domainMapList []*pb.IpDomainMap) map[string]string { + if len(domainMapList) == 0 { + return nil + } + domainIPMap := make(map[string]string) + for _, domainMap := range domainMapList { + key := fmt.Sprintf("%s.", domainMap.Domain) + domainIPMap[key] = domainMap.Ip + } + return domainIPMap +} diff --git a/handler.go b/handler.go index 87169ce..9677e8e 100644 --- a/handler.go +++ b/handler.go @@ -2,7 +2,6 @@ package kubernetes import ( "context" - "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/request" @@ -22,10 +21,13 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M records, extra, zone, err := k.getRecords(ctx, state) log.Debugf("records: %v, err: %v", records, err) - - if k.needChaos(chaosPod, records, state.QName()) { + if k.needChaos(chaosPod, records, state.QName()) && chaosPod.Action != ActionStatic { return k.chaosDNS(ctx, w, r, state, chaosPod) } + if k.needChaos(chaosPod, records, state.QName()) && chaosPod.Action == ActionStatic { + log.Infof("need chaos, but action is static") + return generateDNSRecords(state, k.domainAndIPMap[chaosPod.Namespace][chaosPod.Name], r, w) + } if k.IsNameError(err) { if len(zone) == 0 { diff --git a/kubernetes.go b/kubernetes.go index fa7b706..1755ee6 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -5,13 +5,13 @@ import ( "context" "errors" "fmt" + "github.com/chaos-mesh/k8s_dns_chaos/pb" "math/rand" "net" "strings" "sync" "time" - "github.com/chaos-mesh/k8s_dns_chaos/pb" "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin/etcd/msg" "github.com/coredns/coredns/plugin/kubernetes/object" @@ -68,6 +68,8 @@ type Kubernetes struct { podMap map[string]map[string]*PodInfo ipPodMap map[string]*PodInfo + + domainAndIPMap map[string]map[string]map[string]string } // New returns a initialized Kubernetes. It default interfaceAddrFunc to return 127.0.0.1. All other @@ -81,6 +83,7 @@ func New(zones []string) *Kubernetes { k.chaosMap = make(map[string]*pb.SetDNSChaosRequest) k.podMap = make(map[string]map[string]*PodInfo) k.ipPodMap = make(map[string]*PodInfo) + k.domainAndIPMap = make(map[string]map[string]map[string]string) rand.Seed(time.Now().UnixNano()) return k diff --git a/pb/dns.pb.go b/pb/dns.pb.go index 9a82da1..7b20e2c 100644 --- a/pb/dns.pb.go +++ b/pb/dns.pb.go @@ -4,15 +4,13 @@ package pb import ( + context "context" fmt "fmt" - proto "github.com/golang/protobuf/proto" - - math "math" - - context "golang.org/x/net/context" - grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" ) // Reference imports to suppress errors if they are not otherwise used. @@ -24,41 +22,45 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package type SetDNSChaosRequest struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Pods []*Pod `protobuf:"bytes,2,rep,name=pods,proto3" json:"pods,omitempty"` // action means the chaos action, values can be "random" or "error" - // "random": return random IP for DNS request - // "error": return error for DNS request + // + // "random": return random IP for DNS request + // "error": return error for DNS request Action string `protobuf:"bytes,3,opt,name=action,proto3" json:"action,omitempty"` // scope means the chaos scope, values can be "inner", "outer" or "all": - // "inner": chaos only works on the inner host in Kubernetes cluster - // "outer": chaos only works on the outer host of Kubernetes cluster - // "all": chaos works on all host - Scope string `protobuf:"bytes,4,opt,name=scope,proto3" json:"scope,omitempty"` - Selector string `protobuf:"bytes,5,opt,name=selector,proto3" json:"selector,omitempty"` - Patterns []string `protobuf:"bytes,6,rep,name=patterns,proto3" json:"patterns,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // + // "inner": chaos only works on the inner host in Kubernetes cluster + // "outer": chaos only works on the outer host of Kubernetes cluster + // "all": chaos works on all host + Scope string `protobuf:"bytes,4,opt,name=scope,proto3" json:"scope,omitempty"` + Selector string `protobuf:"bytes,5,opt,name=selector,proto3" json:"selector,omitempty"` + Patterns []string `protobuf:"bytes,6,rep,name=patterns,proto3" json:"patterns,omitempty"` + IpDomainMaps []*IpDomainMap `protobuf:"bytes,7,rep,name=ipDomainMaps,proto3" json:"ipDomainMaps,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *SetDNSChaosRequest) Reset() { *m = SetDNSChaosRequest{} } func (m *SetDNSChaosRequest) String() string { return proto.CompactTextString(m) } func (*SetDNSChaosRequest) ProtoMessage() {} func (*SetDNSChaosRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_dns_ad842bfaa9b8d3cd, []int{0} + return fileDescriptor_638ff8d8aaf3d8ae, []int{0} } + func (m *SetDNSChaosRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SetDNSChaosRequest.Unmarshal(m, b) } func (m *SetDNSChaosRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_SetDNSChaosRequest.Marshal(b, m, deterministic) } -func (dst *SetDNSChaosRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_SetDNSChaosRequest.Merge(dst, src) +func (m *SetDNSChaosRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_SetDNSChaosRequest.Merge(m, src) } func (m *SetDNSChaosRequest) XXX_Size() int { return xxx_messageInfo_SetDNSChaosRequest.Size(m) @@ -111,6 +113,13 @@ func (m *SetDNSChaosRequest) GetPatterns() []string { return nil } +func (m *SetDNSChaosRequest) GetIpDomainMaps() []*IpDomainMap { + if m != nil { + return m.IpDomainMaps + } + return nil +} + type Pod struct { Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` @@ -123,16 +132,17 @@ func (m *Pod) Reset() { *m = Pod{} } func (m *Pod) String() string { return proto.CompactTextString(m) } func (*Pod) ProtoMessage() {} func (*Pod) Descriptor() ([]byte, []int) { - return fileDescriptor_dns_ad842bfaa9b8d3cd, []int{1} + return fileDescriptor_638ff8d8aaf3d8ae, []int{1} } + func (m *Pod) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_Pod.Unmarshal(m, b) } func (m *Pod) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_Pod.Marshal(b, m, deterministic) } -func (dst *Pod) XXX_Merge(src proto.Message) { - xxx_messageInfo_Pod.Merge(dst, src) +func (m *Pod) XXX_Merge(src proto.Message) { + xxx_messageInfo_Pod.Merge(m, src) } func (m *Pod) XXX_Size() int { return xxx_messageInfo_Pod.Size(m) @@ -168,16 +178,17 @@ func (m *CancelDNSChaosRequest) Reset() { *m = CancelDNSChaosRequest{} } func (m *CancelDNSChaosRequest) String() string { return proto.CompactTextString(m) } func (*CancelDNSChaosRequest) ProtoMessage() {} func (*CancelDNSChaosRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_dns_ad842bfaa9b8d3cd, []int{2} + return fileDescriptor_638ff8d8aaf3d8ae, []int{2} } + func (m *CancelDNSChaosRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_CancelDNSChaosRequest.Unmarshal(m, b) } func (m *CancelDNSChaosRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_CancelDNSChaosRequest.Marshal(b, m, deterministic) } -func (dst *CancelDNSChaosRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_CancelDNSChaosRequest.Merge(dst, src) +func (m *CancelDNSChaosRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CancelDNSChaosRequest.Merge(m, src) } func (m *CancelDNSChaosRequest) XXX_Size() int { return xxx_messageInfo_CancelDNSChaosRequest.Size(m) @@ -207,16 +218,17 @@ func (m *DNSChaosResponse) Reset() { *m = DNSChaosResponse{} } func (m *DNSChaosResponse) String() string { return proto.CompactTextString(m) } func (*DNSChaosResponse) ProtoMessage() {} func (*DNSChaosResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_dns_ad842bfaa9b8d3cd, []int{3} + return fileDescriptor_638ff8d8aaf3d8ae, []int{3} } + func (m *DNSChaosResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_DNSChaosResponse.Unmarshal(m, b) } func (m *DNSChaosResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return xxx_messageInfo_DNSChaosResponse.Marshal(b, m, deterministic) } -func (dst *DNSChaosResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_DNSChaosResponse.Merge(dst, src) +func (m *DNSChaosResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_DNSChaosResponse.Merge(m, src) } func (m *DNSChaosResponse) XXX_Size() int { return xxx_messageInfo_DNSChaosResponse.Size(m) @@ -241,11 +253,88 @@ func (m *DNSChaosResponse) GetMsg() string { return "" } +// 定义ip 域名的映射关系 +type IpDomainMap struct { + Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"` + Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *IpDomainMap) Reset() { *m = IpDomainMap{} } +func (m *IpDomainMap) String() string { return proto.CompactTextString(m) } +func (*IpDomainMap) ProtoMessage() {} +func (*IpDomainMap) Descriptor() ([]byte, []int) { + return fileDescriptor_638ff8d8aaf3d8ae, []int{4} +} + +func (m *IpDomainMap) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_IpDomainMap.Unmarshal(m, b) +} +func (m *IpDomainMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_IpDomainMap.Marshal(b, m, deterministic) +} +func (m *IpDomainMap) XXX_Merge(src proto.Message) { + xxx_messageInfo_IpDomainMap.Merge(m, src) +} +func (m *IpDomainMap) XXX_Size() int { + return xxx_messageInfo_IpDomainMap.Size(m) +} +func (m *IpDomainMap) XXX_DiscardUnknown() { + xxx_messageInfo_IpDomainMap.DiscardUnknown(m) +} + +var xxx_messageInfo_IpDomainMap proto.InternalMessageInfo + +func (m *IpDomainMap) GetIp() string { + if m != nil { + return m.Ip + } + return "" +} + +func (m *IpDomainMap) GetDomain() string { + if m != nil { + return m.Domain + } + return "" +} + func init() { proto.RegisterType((*SetDNSChaosRequest)(nil), "pb.SetDNSChaosRequest") proto.RegisterType((*Pod)(nil), "pb.Pod") proto.RegisterType((*CancelDNSChaosRequest)(nil), "pb.CancelDNSChaosRequest") proto.RegisterType((*DNSChaosResponse)(nil), "pb.DNSChaosResponse") + proto.RegisterType((*IpDomainMap)(nil), "pb.IpDomainMap") +} + +func init() { proto.RegisterFile("dns.proto", fileDescriptor_638ff8d8aaf3d8ae) } + +var fileDescriptor_638ff8d8aaf3d8ae = []byte{ + // 340 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x4d, 0x4f, 0xf2, 0x40, + 0x10, 0x7e, 0xfb, 0x41, 0x81, 0xe1, 0x0d, 0x92, 0x09, 0x92, 0x8a, 0x1e, 0x48, 0x4f, 0x24, 0x26, + 0x35, 0x81, 0x18, 0x2f, 0x7a, 0x11, 0x2e, 0x1e, 0x24, 0xa4, 0xdc, 0xbc, 0x6d, 0xdb, 0x8d, 0x36, + 0x81, 0xdd, 0xb5, 0xb3, 0xfc, 0x08, 0xff, 0xa5, 0x3f, 0xc5, 0xec, 0x5a, 0x28, 0xf8, 0x91, 0x78, + 0xdb, 0xe7, 0x63, 0xa6, 0xf3, 0xcc, 0x14, 0xda, 0xb9, 0xa0, 0x58, 0x95, 0x52, 0x4b, 0x74, 0x55, + 0x1a, 0xbd, 0x3b, 0x80, 0x2b, 0xae, 0xe7, 0x8b, 0xd5, 0xec, 0x85, 0x49, 0x4a, 0xf8, 0xeb, 0x96, + 0x93, 0x46, 0x04, 0x5f, 0xb0, 0x0d, 0x0f, 0x9d, 0x91, 0x33, 0x6e, 0x27, 0xf6, 0x8d, 0xe7, 0xe0, + 0x2b, 0x99, 0x53, 0xe8, 0x8e, 0xbc, 0x71, 0x67, 0xd2, 0x8c, 0x55, 0x1a, 0x2f, 0x65, 0x9e, 0x58, + 0x12, 0x07, 0x10, 0xb0, 0x4c, 0x17, 0x52, 0x84, 0x9e, 0x2d, 0xa9, 0x10, 0xf6, 0xa1, 0x41, 0x99, + 0x54, 0x3c, 0xf4, 0x2d, 0xfd, 0x09, 0x70, 0x08, 0x2d, 0xe2, 0x6b, 0x9e, 0x69, 0x59, 0x86, 0x0d, + 0x2b, 0xec, 0xb1, 0xd1, 0x14, 0xd3, 0x9a, 0x97, 0x82, 0xc2, 0x60, 0xe4, 0x19, 0x6d, 0x87, 0x71, + 0x0a, 0xff, 0x0b, 0x35, 0x97, 0x1b, 0x56, 0x88, 0x47, 0xa6, 0x28, 0x6c, 0xda, 0x51, 0x4e, 0xcc, + 0x28, 0x0f, 0x35, 0x9f, 0x1c, 0x99, 0xa2, 0x1b, 0xf0, 0x96, 0x32, 0xc7, 0x0b, 0x68, 0x9b, 0x18, + 0xa4, 0x58, 0xb6, 0xcb, 0x55, 0x13, 0xfb, 0xc0, 0x6e, 0x1d, 0x38, 0xba, 0x84, 0xd3, 0x19, 0x13, + 0x19, 0x5f, 0xff, 0x61, 0x3b, 0xd1, 0x2d, 0xf4, 0x6a, 0x1b, 0x29, 0x29, 0x88, 0x9b, 0xa5, 0x94, + 0x9c, 0xb6, 0x6b, 0x6d, 0x9d, 0xad, 0xa4, 0x42, 0xd8, 0x03, 0x6f, 0x43, 0xcf, 0xd5, 0xb7, 0xcc, + 0x33, 0xba, 0x86, 0xce, 0x41, 0x00, 0xec, 0x82, 0x5b, 0xa8, 0xaa, 0xbd, 0x5b, 0x28, 0xd3, 0x28, + 0xb7, 0x62, 0x55, 0x53, 0xa1, 0xc9, 0x9b, 0x03, 0xde, 0x7c, 0xb1, 0xc2, 0x3b, 0xe8, 0x1c, 0x1c, + 0x11, 0x07, 0x66, 0x21, 0xdf, 0xaf, 0x3a, 0xec, 0x1b, 0xfe, 0xeb, 0x94, 0xd1, 0x3f, 0x9c, 0x41, + 0xf7, 0x38, 0x28, 0x9e, 0x19, 0xe7, 0x8f, 0xe1, 0x7f, 0x6b, 0x72, 0x1f, 0x3c, 0xf9, 0xf1, 0x95, + 0x4a, 0xd3, 0xc0, 0xfe, 0x5c, 0xd3, 0x8f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdd, 0x7e, 0x99, 0x58, + 0x69, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -296,6 +385,17 @@ type DNSServer interface { CancelDNSChaos(context.Context, *CancelDNSChaosRequest) (*DNSChaosResponse, error) } +// UnimplementedDNSServer can be embedded to have forward compatible implementations. +type UnimplementedDNSServer struct { +} + +func (*UnimplementedDNSServer) SetDNSChaos(ctx context.Context, req *SetDNSChaosRequest) (*DNSChaosResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetDNSChaos not implemented") +} +func (*UnimplementedDNSServer) CancelDNSChaos(ctx context.Context, req *CancelDNSChaosRequest) (*DNSChaosResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CancelDNSChaos not implemented") +} + func RegisterDNSServer(s *grpc.Server, srv DNSServer) { s.RegisterService(&_DNS_serviceDesc, srv) } @@ -352,27 +452,3 @@ var _DNS_serviceDesc = grpc.ServiceDesc{ Streams: []grpc.StreamDesc{}, Metadata: "dns.proto", } - -func init() { proto.RegisterFile("dns.proto", fileDescriptor_dns_ad842bfaa9b8d3cd) } - -var fileDescriptor_dns_ad842bfaa9b8d3cd = []byte{ - // 285 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x51, 0xcd, 0x4e, 0xf3, 0x30, - 0x10, 0xfc, 0x52, 0xa7, 0xf9, 0x9a, 0xad, 0x84, 0xaa, 0x55, 0xa9, 0x4c, 0xe1, 0x10, 0xe5, 0x54, - 0x09, 0x29, 0x87, 0x72, 0xe0, 0x02, 0xa7, 0xf4, 0x5c, 0x55, 0xc9, 0x13, 0x38, 0x89, 0x05, 0x48, - 0xa9, 0x6d, 0xb2, 0xee, 0x43, 0xf0, 0x2c, 0xbc, 0x24, 0xb2, 0x49, 0x1b, 0x7e, 0x25, 0x6e, 0x3b, - 0xb3, 0x93, 0xec, 0xcc, 0x18, 0xe2, 0x46, 0x51, 0x66, 0x3a, 0x6d, 0x35, 0x8e, 0x4c, 0x95, 0xbe, - 0x06, 0x80, 0xa5, 0xb4, 0x9b, 0x6d, 0x99, 0x3f, 0x0a, 0x4d, 0x85, 0x7c, 0x3e, 0x48, 0xb2, 0x88, - 0x10, 0x2a, 0xb1, 0x97, 0x3c, 0x48, 0x82, 0x55, 0x5c, 0xf8, 0x19, 0x2f, 0x21, 0x34, 0xba, 0x21, - 0x3e, 0x4a, 0xd8, 0x6a, 0xba, 0xfe, 0x9f, 0x99, 0x2a, 0xdb, 0xe9, 0xa6, 0xf0, 0x24, 0x2e, 0x20, - 0x12, 0xb5, 0x7d, 0xd2, 0x8a, 0x33, 0xff, 0x49, 0x8f, 0x70, 0x0e, 0x63, 0xaa, 0xb5, 0x91, 0x3c, - 0xf4, 0xf4, 0x3b, 0xc0, 0x25, 0x4c, 0x48, 0xb6, 0xb2, 0xb6, 0xba, 0xe3, 0x63, 0xbf, 0x38, 0x61, - 0xb7, 0x33, 0xc2, 0x5a, 0xd9, 0x29, 0xe2, 0x51, 0xc2, 0xdc, 0xee, 0x88, 0xd3, 0x5b, 0x60, 0x3b, - 0xdd, 0xe0, 0x15, 0xc4, 0xce, 0x11, 0x19, 0x51, 0x1f, 0x2d, 0x0e, 0xc4, 0xc9, 0xfb, 0x68, 0xf0, - 0x9e, 0x5e, 0xc3, 0x79, 0x2e, 0x54, 0x2d, 0xdb, 0x3f, 0x04, 0x4d, 0xef, 0x60, 0x36, 0xc8, 0xc8, - 0x68, 0x45, 0xd2, 0xe5, 0xeb, 0x24, 0x1d, 0x5a, 0xeb, 0x95, 0x93, 0xa2, 0x47, 0x38, 0x03, 0xb6, - 0xa7, 0x87, 0xfe, 0x96, 0x1b, 0xd7, 0x2f, 0x01, 0xb0, 0xcd, 0xb6, 0xc4, 0x7b, 0x98, 0x7e, 0x28, - 0x16, 0x17, 0xae, 0xaf, 0xef, 0x4d, 0x2f, 0xe7, 0x8e, 0xff, 0x7a, 0x2e, 0xfd, 0x87, 0x39, 0x9c, - 0x7d, 0x76, 0x8c, 0x17, 0x4e, 0xf9, 0x63, 0x8a, 0xdf, 0x7e, 0x52, 0x45, 0xfe, 0xa1, 0x6f, 0xde, - 0x02, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x16, 0x0c, 0xd6, 0xf5, 0x01, 0x00, 0x00, -} diff --git a/pb/dns.proto b/pb/dns.proto index 509e516..f224c6b 100644 --- a/pb/dns.proto +++ b/pb/dns.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package pb; - +option go_package = "./pb"; service DNS { rpc SetDNSChaos(SetDNSChaosRequest) returns (DNSChaosResponse) {} rpc CancelDNSChaos(CancelDNSChaosRequest) returns (DNSChaosResponse) {} @@ -23,6 +23,7 @@ message SetDNSChaosRequest { string scope = 4; string selector = 5; repeated string patterns = 6; + repeated IpDomainMap ipDomainMaps = 7; } message Pod { @@ -37,4 +38,10 @@ message CancelDNSChaosRequest { message DNSChaosResponse { bool result = 1; string msg = 2; +} + +//定义ip 域名的映射关系 +message IpDomainMap { + string ip = 1; + string domain = 2; } \ No newline at end of file From 861c98032bed6405bff823fc6fcf97722f4c695f Mon Sep 17 00:00:00 2001 From: xiejunqiao Date: Thu, 1 May 2025 00:49:17 +0800 Subject: [PATCH 2/4] feat:Complete the domain name resolution of the static type Signed-off-by: xiejunqiao --- chaos.go | 41 ++++++++++++++++++++++------------------- handler.go | 14 ++++++++++++-- setup.go | 5 ++--- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/chaos.go b/chaos.go index 3026f1c..ea2f03d 100644 --- a/chaos.go +++ b/chaos.go @@ -63,14 +63,6 @@ func (k Kubernetes) chaosDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M return dns.RcodeServerFailure, fmt.Errorf("dns chaos error") } - //return static IP - if podInfo.Action == ActionStatic { - //return staticIP(ctx, w, r, state, podInfo) - //k.chaosMap - domainAndIPMap := k.domainAndIPMap[podInfo.Namespace][podInfo.Name] - return generateDNSRecords(state, domainAndIPMap, r, w) - } - answers := []dns.RR{} qname := state.Name() @@ -180,8 +172,14 @@ func (k Kubernetes) needChaos(podInfo *PodInfo, records []dns.RR, name string) b if podInfo.Scope == ScopeAll { return true } - if podInfo.Action == ActionStatic && k.domainAndIPMap[podInfo.Namespace][podInfo.Name] != nil { - return true + if podInfo.Action == ActionStatic { + domainMap := k.domainAndIPMap[podInfo.Namespace][podInfo.Name] + if domainMap != nil { + if _, ok := domainMap[name]; ok { + return true + } + } + return false } rules := podInfo.Selector.Match(name, "") @@ -212,21 +210,26 @@ func generateDNSRecords(state request.Request, domainAndIpMap map[string]string, if domainAndIpMap == nil { return dns.RcodeServerFailure, nil } - ip, ok := domainAndIpMap[qname] + ipStr, ok := domainAndIpMap[qname] if !ok { - //如果不存在则 return dns.RcodeServerFailure, fmt.Errorf("domain %s not found", qname) } + ip := net.ParseIP(ipStr) switch state.QType() { case dns.TypeA: - ips := []net.IP{net.ParseIP(ip)} - log.Debugf("dns.TypeA %v", ips) - answers = a(qname, 10, ips) + ipv4 := ip.To4() + if ipv4 == nil { + return dns.RcodeServerFailure, fmt.Errorf("not a valid IPv4 address: %s", ipStr) + } + answers = a(qname, 10, []net.IP{ipv4}) + log.Debugf("dns.TypeA %v", ipv4) case dns.TypeAAAA: - // TODO: return random IP - ips := []net.IP{net.ParseIP(ip)} - log.Debugf("dns.TypeAAAA %v", ips) - answers = aaaa(qname, 10, ips) + ipv6 := ip.To16() + if ip.To4() != nil { + return dns.RcodeServerFailure, fmt.Errorf("not a valid IPv6 address: %s", ipStr) + } + log.Debugf("dns.TypeAAAA %v", ipv6) + answers = aaaa(qname, 10, []net.IP{ipv6}) } m := new(dns.Msg) m.SetReply(r) diff --git a/handler.go b/handler.go index 9677e8e..36637a2 100644 --- a/handler.go +++ b/handler.go @@ -24,9 +24,19 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M if k.needChaos(chaosPod, records, state.QName()) && chaosPod.Action != ActionStatic { return k.chaosDNS(ctx, w, r, state, chaosPod) } + // Check if chaos testing is needed and the action type is static IP. if k.needChaos(chaosPod, records, state.QName()) && chaosPod.Action == ActionStatic { - log.Infof("need chaos, but action is static") - return generateDNSRecords(state, k.domainAndIPMap[chaosPod.Namespace][chaosPod.Name], r, w) + log.Debugf("need chaos, but action is static") + // Get the domain-IP mapping for the specific namespace and pod name. + domainMap := k.domainAndIPMap[chaosPod.Namespace][chaosPod.Name] + // Check if the domain-IP mapping exists. + if domainMap != nil { + // Check if the requested domain exists in the mapping. + if _, ok := domainMap[state.Name()]; ok { + // Generate DNS records using the domain-IP mapping and return the result. + return generateDNSRecords(state, domainMap, r, w) + } + } } if k.IsNameError(err) { diff --git a/setup.go b/setup.go index 59daf21..2b86aca 100644 --- a/setup.go +++ b/setup.go @@ -19,9 +19,8 @@ import ( "github.com/caddyserver/caddy" "github.com/miekg/dns" meta "k8s.io/apimachinery/pkg/apis/meta/v1" - _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // pull this in here, because we want it excluded if plugin.cfg doesn't have k8s - _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" // pull this in here, because we want it excluded if plugin.cfg doesn't have k8s - _ "k8s.io/client-go/plugin/pkg/client/auth/openstack" // pull this in here, because we want it excluded if plugin.cfg doesn't have k8s + _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // pull this in here, because we want it excluded if plugin.cfg doesn't have k8s + _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" // pull this in here, because we want it excluded if plugin.cfg doesn't have k8s "k8s.io/client-go/tools/clientcmd" "k8s.io/klog" ) From f8763d9ced09ac58224de72b40fca41e49e2a82c Mon Sep 17 00:00:00 2001 From: xiejunqiao Date: Fri, 6 Jun 2025 19:30:37 +0800 Subject: [PATCH 3/4] Refactor: apply review suggestions - Removed unused IpDomainMap type - Replaced Chinese comment with English in IpDomainMap - Renamed domainAndIPMap to domainIPMapByNamespacedName for better clarity Signed-off-by: xiejunqiao --- chaos.go | 14 ++++---------- grpc_server.go | 12 ++++++------ handler.go | 2 +- kubernetes.go | 4 ++-- pb/dns.proto | 3 ++- 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/chaos.go b/chaos.go index ea2f03d..a779b52 100644 --- a/chaos.go +++ b/chaos.go @@ -41,12 +41,6 @@ type PodInfo struct { LastUpdateTime time.Time } -// DomainIP Domain and ip mapping -type DomainIP struct { - Domain string - IP string -} - // IsOverdue ... func (p *PodInfo) IsOverdue() bool { // if the pod's IP is not updated greater than 10 seconds, will treate it as overdue @@ -173,7 +167,7 @@ func (k Kubernetes) needChaos(podInfo *PodInfo, records []dns.RR, name string) b return true } if podInfo.Action == ActionStatic { - domainMap := k.domainAndIPMap[podInfo.Namespace][podInfo.Name] + domainMap := k.domainIPMapByNamespacedName[podInfo.Namespace][podInfo.Name] if domainMap != nil { if _, ok := domainMap[name]; ok { return true @@ -204,13 +198,13 @@ func (k Kubernetes) getPodFromCluster(namespace, name string) (*api.Pod, error) return pods.Get(context.Background(), name, meta.GetOptions{}) } -func generateDNSRecords(state request.Request, domainAndIpMap map[string]string, r *dns.Msg, w dns.ResponseWriter) (int, error) { +func generateDNSRecords(state request.Request, domainIPMapByNamespacedName map[string]string, r *dns.Msg, w dns.ResponseWriter) (int, error) { answers := []dns.RR{} qname := state.Name() - if domainAndIpMap == nil { + if domainIPMapByNamespacedName == nil { return dns.RcodeServerFailure, nil } - ipStr, ok := domainAndIpMap[qname] + ipStr, ok := domainIPMapByNamespacedName[qname] if !ok { return dns.RcodeServerFailure, fmt.Errorf("domain %s not found", qname) } diff --git a/grpc_server.go b/grpc_server.go index 674f1ed..cfa99dc 100644 --- a/grpc_server.go +++ b/grpc_server.go @@ -110,10 +110,10 @@ func (k Kubernetes) SetDNSChaos(ctx context.Context, req *pb.SetDNSChaosRequest) k.ipPodMap[v1Pod.Status.PodIP] = podInfo domainIPMap := saveDomainAndIp(req.IpDomainMaps) if domainIPMap != nil { - if _, ok := k.domainAndIPMap[pod.Namespace]; !ok { - k.domainAndIPMap[pod.Namespace] = make(map[string]map[string]string) + if _, ok := k.domainIPMapByNamespacedName[pod.Namespace]; !ok { + k.domainIPMapByNamespacedName[pod.Namespace] = make(map[string]map[string]string) } - k.domainAndIPMap[pod.Namespace][pod.Name] = domainIPMap + k.domainIPMapByNamespacedName[pod.Namespace][pod.Name] = domainIPMap } } @@ -140,8 +140,8 @@ func (k Kubernetes) CancelDNSChaos(ctx context.Context, req *pb.CancelDNSChaosRe delete(k.podMap[pod.Namespace], pod.Name) delete(k.ipPodMap, podInfo.IP) } - if _, ok1 := k.domainAndIPMap[pod.Namespace][pod.Name]; ok1 { - delete(k.domainAndIPMap[pod.Namespace], pod.Name) + if _, ok1 := k.domainIPMapByNamespacedName[pod.Namespace][pod.Name]; ok1 { + delete(k.domainIPMapByNamespacedName[pod.Namespace], pod.Name) } } } @@ -154,7 +154,7 @@ func (k Kubernetes) CancelDNSChaos(ctx context.Context, req *pb.CancelDNSChaosRe } for _, namespace := range shouldDeleteNs { delete(k.podMap, namespace) - delete(k.domainAndIPMap, namespace) + delete(k.domainIPMapByNamespacedName, namespace) } delete(k.chaosMap, req.Name) diff --git a/handler.go b/handler.go index 36637a2..4d4d7ab 100644 --- a/handler.go +++ b/handler.go @@ -28,7 +28,7 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M if k.needChaos(chaosPod, records, state.QName()) && chaosPod.Action == ActionStatic { log.Debugf("need chaos, but action is static") // Get the domain-IP mapping for the specific namespace and pod name. - domainMap := k.domainAndIPMap[chaosPod.Namespace][chaosPod.Name] + domainMap := k.domainIPMapByNamespacedName[chaosPod.Namespace][chaosPod.Name] // Check if the domain-IP mapping exists. if domainMap != nil { // Check if the requested domain exists in the mapping. diff --git a/kubernetes.go b/kubernetes.go index 1755ee6..d5eb20c 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -69,7 +69,7 @@ type Kubernetes struct { ipPodMap map[string]*PodInfo - domainAndIPMap map[string]map[string]map[string]string + domainIPMapByNamespacedName map[string]map[string]map[string]string } // New returns a initialized Kubernetes. It default interfaceAddrFunc to return 127.0.0.1. All other @@ -83,7 +83,7 @@ func New(zones []string) *Kubernetes { k.chaosMap = make(map[string]*pb.SetDNSChaosRequest) k.podMap = make(map[string]map[string]*PodInfo) k.ipPodMap = make(map[string]*PodInfo) - k.domainAndIPMap = make(map[string]map[string]map[string]string) + k.domainIPMapByNamespacedName = make(map[string]map[string]map[string]string) rand.Seed(time.Now().UnixNano()) return k diff --git a/pb/dns.proto b/pb/dns.proto index f224c6b..9abd33e 100644 --- a/pb/dns.proto +++ b/pb/dns.proto @@ -40,7 +40,8 @@ message DNSChaosResponse { string msg = 2; } -//定义ip 域名的映射关系 +// Defines the mapping relationship between an IP address and a domain name. +// This structure represents a single IP-to-domain pair. message IpDomainMap { string ip = 1; string domain = 2; From b34cd7a08a695046f6015f20d854d9be0451f9c1 Mon Sep 17 00:00:00 2001 From: Yue Yang Date: Mon, 9 Jun 2025 21:33:41 +0800 Subject: [PATCH 4/4] fix: add a fmt target Signed-off-by: Yue Yang --- Makefile | 3 +++ handler.go | 1 + handler_test.go | 26 +++++++++++++------------- kubernetes.go | 3 ++- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 722b8ae..72c600a 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,9 @@ protoc: ## Generate the protobuf code go install google.golang.org/protobuf/cmd/protoc-gen-go@latest protoc --proto_path=pb --go_out=pb --go_opt=paths=source_relative ./pb/dns.proto +fmt: + find . -type f -name '*.go' -not -path './pb/**' -exec goimports -w -l {} + + # The help will print out all targets with their descriptions organized bellow their categories. The categories are represented by `##@` and the target descriptions by `##`. # The awk commands is responsible to read the entire set of makefiles included in this invocation, looking for lines of the file as xyz: ## something, and then pretty-format the target and help. Then, if there's a line with ##@ something, that gets pretty-printed as a category. # More info over the usage of ANSI control characters for terminal formatting: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters diff --git a/handler.go b/handler.go index 4d4d7ab..1daf253 100644 --- a/handler.go +++ b/handler.go @@ -2,6 +2,7 @@ package kubernetes import ( "context" + "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/request" diff --git a/handler_test.go b/handler_test.go index 3021368..2b4fdb1 100644 --- a/handler_test.go +++ b/handler_test.go @@ -41,41 +41,41 @@ var dnsTestCases = []test.Case{ }, { Qname: "svc1.testns.svc.cluster.local.", Qtype: dns.TypeSRV, - Rcode: dns.RcodeSuccess, + Rcode: dns.RcodeSuccess, Answer: []dns.RR{test.SRV("svc1.testns.svc.cluster.local. 5 IN SRV 0 100 80 svc1.testns.svc.cluster.local.")}, - Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, + Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, }, { Qname: "svcempty.testns.svc.cluster.local.", Qtype: dns.TypeSRV, - Rcode: dns.RcodeSuccess, + Rcode: dns.RcodeSuccess, Answer: []dns.RR{test.SRV("svcempty.testns.svc.cluster.local. 5 IN SRV 0 100 80 svcempty.testns.svc.cluster.local.")}, - Extra: []dns.RR{test.A("svcempty.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, + Extra: []dns.RR{test.A("svcempty.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, }, { Qname: "svc6.testns.svc.cluster.local.", Qtype: dns.TypeSRV, - Rcode: dns.RcodeSuccess, + Rcode: dns.RcodeSuccess, Answer: []dns.RR{test.SRV("svc6.testns.svc.cluster.local. 5 IN SRV 0 100 80 svc6.testns.svc.cluster.local.")}, - Extra: []dns.RR{test.AAAA("svc6.testns.svc.cluster.local. 5 IN AAAA 1234:abcd::1")}, + Extra: []dns.RR{test.AAAA("svc6.testns.svc.cluster.local. 5 IN AAAA 1234:abcd::1")}, }, // SRV Service (wildcard) { Qname: "svc1.*.svc.cluster.local.", Qtype: dns.TypeSRV, - Rcode: dns.RcodeSuccess, + Rcode: dns.RcodeSuccess, Answer: []dns.RR{test.SRV("svc1.*.svc.cluster.local. 5 IN SRV 0 100 80 svc1.testns.svc.cluster.local.")}, - Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, + Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, }, { Qname: "svcempty.*.svc.cluster.local.", Qtype: dns.TypeSRV, - Rcode: dns.RcodeSuccess, + Rcode: dns.RcodeSuccess, Answer: []dns.RR{test.SRV("svcempty.*.svc.cluster.local. 5 IN SRV 0 100 80 svcempty.testns.svc.cluster.local.")}, - Extra: []dns.RR{test.A("svcempty.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, + Extra: []dns.RR{test.A("svcempty.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, }, // SRV Service (wildcards) { Qname: "*.any.svc1.*.svc.cluster.local.", Qtype: dns.TypeSRV, - Rcode: dns.RcodeSuccess, + Rcode: dns.RcodeSuccess, Answer: []dns.RR{test.SRV("*.any.svc1.*.svc.cluster.local. 5 IN SRV 0 100 80 svc1.testns.svc.cluster.local.")}, - Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, + Extra: []dns.RR{test.A("svc1.testns.svc.cluster.local. 5 IN A 10.0.0.1")}, }, // A Service (wildcards) { @@ -207,7 +207,7 @@ var dnsTestCases = []test.Case{ // AAAA { Qname: "5678-abcd--2.hdls1.testns.svc.cluster.local", Qtype: dns.TypeAAAA, - Rcode: dns.RcodeSuccess, + Rcode: dns.RcodeSuccess, Answer: []dns.RR{test.AAAA("5678-abcd--2.hdls1.testns.svc.cluster.local. 5 IN AAAA 5678:abcd::2")}, }, // CNAME External diff --git a/kubernetes.go b/kubernetes.go index d5eb20c..27ddb57 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -5,13 +5,14 @@ import ( "context" "errors" "fmt" - "github.com/chaos-mesh/k8s_dns_chaos/pb" "math/rand" "net" "strings" "sync" "time" + "github.com/chaos-mesh/k8s_dns_chaos/pb" + "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin/etcd/msg" "github.com/coredns/coredns/plugin/kubernetes/object"