mirror of
https://github.com/coredns/coredns.git
synced 2025-10-28 16:54:15 -04:00
kubernetes: add multicluster support (#7266)
* kubernetes: add multicluster support Add multicluster support via Multi-Cluster Services API (MCS-API) via a new option `multiclusterZones` in the kubernetes plugin. When some multicluster zones are passed to the kubernetes plugin, it will start watching the ServiceImport objects and its associated EndpointSlices. Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr> * kubernetes: implement xfr support for multicluster zones Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr> --------- Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>
This commit is contained in:
committed by
GitHub
parent
76b199f829
commit
5c71bd0b87
@@ -3,6 +3,7 @@ package kubernetes
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/coredns/coredns/plugin"
|
||||
@@ -12,10 +13,11 @@ import (
|
||||
"github.com/miekg/dns"
|
||||
api "k8s.io/api/core/v1"
|
||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
mcs "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
|
||||
)
|
||||
|
||||
func TestEndpointHostname(t *testing.T) {
|
||||
var tests = []struct {
|
||||
tests := []struct {
|
||||
ip string
|
||||
hostname string
|
||||
expected string
|
||||
@@ -46,7 +48,7 @@ func (APIConnServiceTest) PodIndex(string) []*object.Pod { return
|
||||
func (APIConnServiceTest) SvcIndexReverse(string) []*object.Service { return nil }
|
||||
func (APIConnServiceTest) SvcExtIndexReverse(string) []*object.Service { return nil }
|
||||
func (APIConnServiceTest) EpIndexReverse(string) []*object.Endpoints { return nil }
|
||||
func (APIConnServiceTest) Modified(bool) int64 { return 0 }
|
||||
func (APIConnServiceTest) Modified(ModifiedMode) int64 { return 0 }
|
||||
|
||||
func (APIConnServiceTest) SvcIndex(string) []*object.Service {
|
||||
svcs := []*object.Service{
|
||||
@@ -225,6 +227,107 @@ func (APIConnServiceTest) EndpointsList() []*object.Endpoints {
|
||||
return eps
|
||||
}
|
||||
|
||||
func (APIConnServiceTest) SvcImportIndex(string) []*object.ServiceImport {
|
||||
svcs := []*object.ServiceImport{
|
||||
{
|
||||
Name: "svc1",
|
||||
Namespace: "testns",
|
||||
Type: mcs.ClusterSetIP,
|
||||
ClusterIPs: []string{"10.0.0.1"},
|
||||
Ports: []mcs.ServicePort{
|
||||
{Name: "http", Protocol: "tcp", Port: 80},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "svc-dual-stack",
|
||||
Namespace: "testns",
|
||||
Type: mcs.ClusterSetIP,
|
||||
ClusterIPs: []string{"10.0.0.2", "10::2"},
|
||||
Ports: []mcs.ServicePort{
|
||||
{Name: "http", Protocol: "tcp", Port: 80},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "hdls1",
|
||||
Namespace: "testns",
|
||||
Type: mcs.Headless,
|
||||
ClusterIPs: []string{},
|
||||
},
|
||||
}
|
||||
return svcs
|
||||
}
|
||||
|
||||
func (APIConnServiceTest) ServiceImportList() []*object.ServiceImport {
|
||||
svcs := []*object.ServiceImport{
|
||||
{
|
||||
Name: "",
|
||||
Namespace: "testns",
|
||||
Type: mcs.ClusterSetIP,
|
||||
ClusterIPs: []string{"10.0.0.1"},
|
||||
Ports: []mcs.ServicePort{
|
||||
{Name: "http", Protocol: "tcp", Port: 80},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "svc-dual-stack",
|
||||
Namespace: "testns",
|
||||
Type: mcs.ClusterSetIP,
|
||||
ClusterIPs: []string{"10.0.0.2", "10::2"},
|
||||
Ports: []mcs.ServicePort{
|
||||
{Name: "http", Protocol: "tcp", Port: 80},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "hdls1",
|
||||
Namespace: "testns",
|
||||
Type: mcs.Headless,
|
||||
},
|
||||
}
|
||||
return svcs
|
||||
}
|
||||
|
||||
func (APIConnServiceTest) McEpIndex(string) []*object.MultiClusterEndpoints {
|
||||
eps := []*object.MultiClusterEndpoints{
|
||||
{
|
||||
Endpoints: object.Endpoints{
|
||||
Subsets: []object.EndpointSubset{
|
||||
{
|
||||
Addresses: []object.EndpointAddress{
|
||||
{IP: "172.0.0.1", Hostname: "ep1a"},
|
||||
},
|
||||
Ports: []object.EndpointPort{
|
||||
{Port: 80, Protocol: "tcp", Name: "http"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Name: "svc1-slice1",
|
||||
Namespace: "testns",
|
||||
Index: object.EndpointsKey("svc1", "testns"),
|
||||
},
|
||||
ClusterId: "cluster1",
|
||||
},
|
||||
{
|
||||
Endpoints: object.Endpoints{
|
||||
Subsets: []object.EndpointSubset{
|
||||
{
|
||||
Addresses: []object.EndpointAddress{
|
||||
{IP: "172.0.0.2"},
|
||||
},
|
||||
Ports: []object.EndpointPort{
|
||||
{Port: 80, Protocol: "tcp", Name: "http"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Name: "hdls1-slice1",
|
||||
Namespace: "testns",
|
||||
Index: object.EndpointsKey("hdls1", "testns"),
|
||||
},
|
||||
ClusterId: "cluster1",
|
||||
},
|
||||
}
|
||||
return eps
|
||||
}
|
||||
|
||||
func (APIConnServiceTest) GetNodeByName(ctx context.Context, name string) (*api.Node, error) {
|
||||
return &api.Node{
|
||||
ObjectMeta: meta.ObjectMeta{
|
||||
@@ -240,7 +343,8 @@ func (APIConnServiceTest) GetNamespaceByName(name string) (*object.Namespace, er
|
||||
}
|
||||
|
||||
func TestServices(t *testing.T) {
|
||||
k := New([]string{"interwebs.test."})
|
||||
k := New([]string{"interwebs.test.", "clusterset.test."})
|
||||
k.opts.multiclusterZones = []string{"clusterset.test."}
|
||||
k.APIConn = &APIConnServiceTest{}
|
||||
|
||||
type svcAns struct {
|
||||
@@ -273,12 +377,34 @@ func TestServices(t *testing.T) {
|
||||
|
||||
// Headless Services
|
||||
{qname: "hdls1.testns.svc.interwebs.test.", qtype: dns.TypeA, answer: []svcAns{{host: "172.0.0.2", key: "/" + coredns + "/test/interwebs/svc/testns/hdls1/172-0-0-2"}}},
|
||||
|
||||
// ClusterSet MultiCluster IP Services
|
||||
{qname: "svc1.testns.svc.clusterset.test.", qtype: dns.TypeA, answer: []svcAns{{host: "10.0.0.1", key: "/" + coredns + "/test/clusterset/svc/testns/svc1"}}},
|
||||
{qname: "_http._tcp.svc1.testns.svc.clusterset.test.", qtype: dns.TypeSRV, answer: []svcAns{{host: "10.0.0.1", key: "/" + coredns + "/test/clusterset/svc/testns/svc1"}}},
|
||||
{qname: "ep1a.cluster1.svc1.testns.svc.clusterset.test.", qtype: dns.TypeA, answer: []svcAns{{host: "172.0.0.1", key: "/" + coredns + "/test/clusterset/svc/testns/svc1/cluster1/ep1a"}}},
|
||||
|
||||
// Dual-Stack ClusterSet MultiCluster IP Service
|
||||
{
|
||||
qname: "_http._tcp.svc-dual-stack.testns.svc.clusterset.test.",
|
||||
qtype: dns.TypeSRV,
|
||||
answer: []svcAns{
|
||||
{host: "10.0.0.2", key: "/" + coredns + "/test/clusterset/svc/testns/svc-dual-stack"},
|
||||
{host: "10::2", key: "/" + coredns + "/test/clusterset/svc/testns/svc-dual-stack"},
|
||||
},
|
||||
},
|
||||
|
||||
// Headless MultiCluster Services
|
||||
{qname: "hdls1.testns.svc.clusterset.test.", qtype: dns.TypeA, answer: []svcAns{{host: "172.0.0.2", key: "/" + coredns + "/test/clusterset/svc/testns/hdls1/cluster1/172-0-0-2"}}},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
zone := "interwebs.test."
|
||||
if strings.Contains(test.qname, "clusterset.test") {
|
||||
zone = "clusterset.test."
|
||||
}
|
||||
state := request.Request{
|
||||
Req: &dns.Msg{Question: []dns.Question{{Name: test.qname, Qtype: test.qtype}}},
|
||||
Zone: "interwebs.test.", // must match from k.Zones[0]
|
||||
Zone: zone,
|
||||
}
|
||||
svcs, e := k.Services(context.TODO(), state, false, plugin.Options{})
|
||||
if e != nil {
|
||||
|
||||
Reference in New Issue
Block a user