Add new plugin: external - resolve k8s ingress and LB address with external names (#2379)
* Add new plugin: external This plugin works in conjunction with the kubernetes plugin and exports ingress and LB addresses as DNS records. It bypasses backend.go and backend_lookup.go flow because it is not needed. README, tests are implemented. The tests only exercise the unit tests, this has not been tested in any ci. Signed-off-by: Miek Gieben <miek@miek.nl> * Rename to k8s_external Signed-off-by: Miek Gieben <miek@miek.nl> * go gen Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
parent
d9880681c3
commit
c1c98924c3
17 changed files with 1156 additions and 1 deletions
92
plugin/kubernetes/external.go
Normal file
92
plugin/kubernetes/external.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/coredns/coredns/plugin/etcd/msg"
|
||||
"github.com/coredns/coredns/plugin/kubernetes/object"
|
||||
"github.com/coredns/coredns/plugin/pkg/dnsutil"
|
||||
"github.com/coredns/coredns/request"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// External implements the ExternalFunc call from the external plugin.
|
||||
// It returns any services matching in the services' ExternalIPs.
|
||||
func (k *Kubernetes) External(state request.Request) ([]msg.Service, int) {
|
||||
base, _ := dnsutil.TrimZone(state.Name(), state.Zone)
|
||||
|
||||
segs := dns.SplitDomainName(base)
|
||||
last := len(segs) - 1
|
||||
if last < 0 {
|
||||
return nil, dns.RcodeServerFailure
|
||||
}
|
||||
// We dealing with a fairly normal domain name here, but; we still need to have the service
|
||||
// and the namespace:
|
||||
// service.namespace.<base>
|
||||
//
|
||||
// for service (and SRV) you can also say _tcp, and port (i.e. _http), we need those be picked
|
||||
// up, unless they are not specified, then we use an internal wildcard.
|
||||
port := "*"
|
||||
protocol := "*"
|
||||
namespace := segs[last]
|
||||
if !k.namespaceExposed(namespace) || !k.namespace(namespace) {
|
||||
return nil, dns.RcodeNameError
|
||||
}
|
||||
|
||||
last--
|
||||
if last < 0 {
|
||||
return nil, dns.RcodeSuccess
|
||||
}
|
||||
|
||||
service := segs[last]
|
||||
last--
|
||||
if last == 1 {
|
||||
protocol = stripUnderscore(segs[last])
|
||||
port = stripUnderscore(segs[last-1])
|
||||
last -= 2
|
||||
}
|
||||
|
||||
if last != -1 {
|
||||
// too long
|
||||
return nil, dns.RcodeNameError
|
||||
}
|
||||
|
||||
idx := object.ServiceKey(service, namespace)
|
||||
serviceList := k.APIConn.SvcIndex(idx)
|
||||
|
||||
services := []msg.Service{}
|
||||
zonePath := msg.Path(state.Zone, coredns)
|
||||
rcode := dns.RcodeNameError
|
||||
|
||||
for _, svc := range serviceList {
|
||||
if namespace != svc.Namespace {
|
||||
continue
|
||||
}
|
||||
if service != svc.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, ip := range svc.ExternalIPs {
|
||||
for _, p := range svc.Ports {
|
||||
if !(match(port, p.Name) && match(protocol, string(p.Protocol))) {
|
||||
continue
|
||||
}
|
||||
rcode = dns.RcodeSuccess
|
||||
s := msg.Service{Host: ip, Port: int(p.Port), TTL: k.ttl}
|
||||
s.Key = strings.Join([]string{zonePath, svc.Namespace, svc.Name}, "/")
|
||||
|
||||
services = append(services, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
return services, rcode
|
||||
}
|
||||
|
||||
// ExternalAddress returns the external service address(es) for the CoreDNS service.
|
||||
func (k *Kubernetes) ExternalAddress(state request.Request) []dns.RR {
|
||||
// This is probably wrong, because of all the fallback behavior of k.nsAddr, i.e. can get
|
||||
// an address that isn't reacheable from outside the cluster.
|
||||
rrs := []dns.RR{k.nsAddr()}
|
||||
return rrs
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue