mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 01:26:59 +02:00
IPv6 internal node IPs are usable externally
This commit is contained in:
parent
510eb952b7
commit
683663e9c2
@ -3,8 +3,9 @@
|
|||||||
This tutorial describes how to configure ExternalDNS to use the cluster nodes as source.
|
This tutorial describes how to configure ExternalDNS to use the cluster nodes as source.
|
||||||
Using nodes (`--source=node`) as source is possible to synchronize a DNS zone with the nodes of a cluster.
|
Using nodes (`--source=node`) as source is possible to synchronize a DNS zone with the nodes of a cluster.
|
||||||
|
|
||||||
The node source adds an `A` record per each node `externalIP` (if not found, node's `internalIP` is used).
|
The node source adds an `A` record per each node `externalIP` (if not found, any IPv4 `internalIP` is used instead).
|
||||||
The TTL record can be set with the `external-dns.alpha.kubernetes.io/ttl` node annotation.
|
It also adds an `AAAA` record per each node IPv6 `internalIP`.
|
||||||
|
The TTL of the records can be set with the `external-dns.alpha.kubernetes.io/ttl` node annotation.
|
||||||
|
|
||||||
## Manifest (for cluster without RBAC enabled)
|
## Manifest (for cluster without RBAC enabled)
|
||||||
|
|
||||||
|
@ -157,11 +157,13 @@ func legacyEndpointsFromDNSControllerNodePortService(svc *v1.Service, sc *servic
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, address := range node.Status.Addresses {
|
for _, address := range node.Status.Addresses {
|
||||||
if address.Type == v1.NodeExternalIP && isExternal {
|
recordType := suitableType(address.Address)
|
||||||
endpoints = append(endpoints, endpoint.NewEndpoint(hostname, endpoint.RecordTypeA, address.Address))
|
// IPv6 addresses are labeled as NodeInternalIP despite being usable externally as well.
|
||||||
|
if isExternal && (address.Type == v1.NodeExternalIP || (address.Type == v1.NodeInternalIP && recordType == endpoint.RecordTypeAAAA)) {
|
||||||
|
endpoints = append(endpoints, endpoint.NewEndpoint(hostname, recordType, address.Address))
|
||||||
}
|
}
|
||||||
if address.Type == v1.NodeInternalIP && isInternal {
|
if isInternal && address.Type == v1.NodeInternalIP {
|
||||||
endpoints = append(endpoints, endpoint.NewEndpoint(hostname, endpoint.RecordTypeA, address.Address))
|
endpoints = append(endpoints, endpoint.NewEndpoint(hostname, recordType, address.Address))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,11 @@ func NewNodeSource(ctx context.Context, kubeClient kubernetes.Interface, annotat
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type endpointsKey struct {
|
||||||
|
dnsName string
|
||||||
|
recordType string
|
||||||
|
}
|
||||||
|
|
||||||
// Endpoints returns endpoint objects for each service that should be processed.
|
// Endpoints returns endpoint objects for each service that should be processed.
|
||||||
func (ns *nodeSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
func (ns *nodeSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||||
nodes, err := ns.nodeInformer.Lister().List(labels.Everything())
|
nodes, err := ns.nodeInformer.Lister().List(labels.Everything())
|
||||||
@ -88,7 +93,7 @@ func (ns *nodeSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints := map[string]*endpoint.Endpoint{}
|
endpoints := map[endpointsKey]*endpoint.Endpoint{}
|
||||||
|
|
||||||
// create endpoints for all nodes
|
// create endpoints for all nodes
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
@ -109,8 +114,7 @@ func (ns *nodeSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, erro
|
|||||||
|
|
||||||
// create new endpoint with the information we already have
|
// create new endpoint with the information we already have
|
||||||
ep := &endpoint.Endpoint{
|
ep := &endpoint.Endpoint{
|
||||||
RecordType: "A", // hardcoded DNS record type
|
RecordTTL: ttl,
|
||||||
RecordTTL: ttl,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ns.fqdnTemplate != nil {
|
if ns.fqdnTemplate != nil {
|
||||||
@ -134,14 +138,19 @@ func (ns *nodeSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, erro
|
|||||||
return nil, fmt.Errorf("failed to get node address from %s: %s", node.Name, err.Error())
|
return nil, fmt.Errorf("failed to get node address from %s: %s", node.Name, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
ep.Targets = endpoint.Targets(addrs)
|
|
||||||
ep.Labels = endpoint.NewLabels()
|
ep.Labels = endpoint.NewLabels()
|
||||||
|
for _, addr := range addrs {
|
||||||
log.Debugf("adding endpoint %s", ep)
|
log.Debugf("adding endpoint %s target %s", ep, addr)
|
||||||
if _, ok := endpoints[ep.DNSName]; ok {
|
key := endpointsKey{
|
||||||
endpoints[ep.DNSName].Targets = append(endpoints[ep.DNSName].Targets, ep.Targets...)
|
dnsName: ep.DNSName,
|
||||||
} else {
|
recordType: suitableType(addr),
|
||||||
endpoints[ep.DNSName] = ep
|
}
|
||||||
|
if _, ok := endpoints[key]; !ok {
|
||||||
|
epCopy := *ep
|
||||||
|
epCopy.RecordType = key.recordType
|
||||||
|
endpoints[key] = &epCopy
|
||||||
|
}
|
||||||
|
endpoints[key].Targets = append(endpoints[key].Targets, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,13 +172,18 @@ func (ns *nodeSource) nodeAddresses(node *v1.Node) ([]string, error) {
|
|||||||
v1.NodeExternalIP: {},
|
v1.NodeExternalIP: {},
|
||||||
v1.NodeInternalIP: {},
|
v1.NodeInternalIP: {},
|
||||||
}
|
}
|
||||||
|
var ipv6Addresses []string
|
||||||
|
|
||||||
for _, addr := range node.Status.Addresses {
|
for _, addr := range node.Status.Addresses {
|
||||||
addresses[addr.Type] = append(addresses[addr.Type], addr.Address)
|
addresses[addr.Type] = append(addresses[addr.Type], addr.Address)
|
||||||
|
// IPv6 addresses are labeled as NodeInternalIP despite being usable externally as well.
|
||||||
|
if addr.Type == v1.NodeInternalIP && suitableType(addr.Address) == endpoint.RecordTypeAAAA {
|
||||||
|
ipv6Addresses = append(ipv6Addresses, addr.Address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(addresses[v1.NodeExternalIP]) > 0 {
|
if len(addresses[v1.NodeExternalIP]) > 0 {
|
||||||
return addresses[v1.NodeExternalIP], nil
|
return append(addresses[v1.NodeExternalIP], ipv6Addresses...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(addresses[v1.NodeInternalIP]) > 0 {
|
if len(addresses[v1.NodeInternalIP]) > 0 {
|
||||||
|
@ -127,6 +127,19 @@ func testNodeSourceEndpoints(t *testing.T) {
|
|||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ipv6 node with fqdn returns one endpoint",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"node1.example.org",
|
||||||
|
[]v1.NodeAddress{{Type: v1.NodeInternalIP, Address: "2001:DB8::8"}},
|
||||||
|
map[string]string{},
|
||||||
|
map[string]string{},
|
||||||
|
[]*endpoint.Endpoint{
|
||||||
|
{RecordType: "AAAA", DNSName: "node1.example.org", Targets: endpoint.Targets{"2001:DB8::8"}},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"node with fqdn template returns endpoint with expanded hostname",
|
"node with fqdn template returns endpoint with expanded hostname",
|
||||||
"",
|
"",
|
||||||
@ -166,6 +179,20 @@ func testNodeSourceEndpoints(t *testing.T) {
|
|||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"node with fqdn template returns two endpoints with dual-stack IP addresses and expanded hostname",
|
||||||
|
"",
|
||||||
|
"{{.Name}}.example.org",
|
||||||
|
"node1",
|
||||||
|
[]v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "1.2.3.4"}, {Type: v1.NodeInternalIP, Address: "2001:DB8::8"}},
|
||||||
|
map[string]string{},
|
||||||
|
map[string]string{},
|
||||||
|
[]*endpoint.Endpoint{
|
||||||
|
{RecordType: "A", DNSName: "node1.example.org", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||||
|
{RecordType: "AAAA", DNSName: "node1.example.org", Targets: endpoint.Targets{"2001:DB8::8"}},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"node with both external and internal IP returns an endpoint with external IP",
|
"node with both external and internal IP returns an endpoint with external IP",
|
||||||
"",
|
"",
|
||||||
@ -179,6 +206,20 @@ func testNodeSourceEndpoints(t *testing.T) {
|
|||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"node with both external, internal, and IPv6 IP returns endpoints with external IPs",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"node1",
|
||||||
|
[]v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "1.2.3.4"}, {Type: v1.NodeInternalIP, Address: "2.3.4.5"}, {Type: v1.NodeInternalIP, Address: "2001:DB8::8"}},
|
||||||
|
map[string]string{},
|
||||||
|
map[string]string{},
|
||||||
|
[]*endpoint.Endpoint{
|
||||||
|
{RecordType: "A", DNSName: "node1", Targets: endpoint.Targets{"1.2.3.4"}},
|
||||||
|
{RecordType: "AAAA", DNSName: "node1", Targets: endpoint.Targets{"2001:DB8::8"}},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"node with only internal IP returns an endpoint with internal IP",
|
"node with only internal IP returns an endpoint with internal IP",
|
||||||
"",
|
"",
|
||||||
@ -192,6 +233,20 @@ func testNodeSourceEndpoints(t *testing.T) {
|
|||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"node with only internal IPs returns endpoints with internal IPs",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"node1",
|
||||||
|
[]v1.NodeAddress{{Type: v1.NodeInternalIP, Address: "2.3.4.5"}, {Type: v1.NodeInternalIP, Address: "2001:DB8::8"}},
|
||||||
|
map[string]string{},
|
||||||
|
map[string]string{},
|
||||||
|
[]*endpoint.Endpoint{
|
||||||
|
{RecordType: "A", DNSName: "node1", Targets: endpoint.Targets{"2.3.4.5"}},
|
||||||
|
{RecordType: "AAAA", DNSName: "node1", Targets: endpoint.Targets{"2001:DB8::8"}},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"node with neither external nor internal IP returns no endpoints",
|
"node with neither external nor internal IP returns no endpoints",
|
||||||
"",
|
"",
|
||||||
@ -318,7 +373,7 @@ func testNodeSourceEndpoints(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"node with nil Lables returns valid endpoint",
|
"node with nil Labels returns valid endpoint",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"node1",
|
"node1",
|
||||||
|
@ -76,13 +76,18 @@ func NewPodSource(ctx context.Context, kubeClient kubernetes.Interface, namespac
|
|||||||
func (*podSource) AddEventHandler(ctx context.Context, handler func()) {
|
func (*podSource) AddEventHandler(ctx context.Context, handler func()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type endpointKey struct {
|
||||||
|
domain string
|
||||||
|
recordType string
|
||||||
|
}
|
||||||
|
|
||||||
func (ps *podSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
func (ps *podSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||||
pods, err := ps.podInformer.Lister().Pods(ps.namespace).List(labels.Everything())
|
pods, err := ps.podInformer.Lister().Pods(ps.namespace).List(labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
domains := make(map[string][]string)
|
endpointMap := make(map[endpointKey][]string)
|
||||||
for _, pod := range pods {
|
for _, pod := range pods {
|
||||||
if !pod.Spec.HostNetwork {
|
if !pod.Spec.HostNetwork {
|
||||||
log.Debugf("skipping pod %s. hostNetwork=false", pod.Name)
|
log.Debugf("skipping pod %s. hostNetwork=false", pod.Name)
|
||||||
@ -90,50 +95,51 @@ func (ps *podSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
if domain, ok := pod.Annotations[internalHostnameAnnotationKey]; ok {
|
if domain, ok := pod.Annotations[internalHostnameAnnotationKey]; ok {
|
||||||
if _, ok := domains[domain]; !ok {
|
addToEndpointMap(endpointMap, domain, suitableType(pod.Status.PodIP), pod.Status.PodIP)
|
||||||
domains[domain] = []string{}
|
|
||||||
}
|
|
||||||
domains[domain] = append(domains[domain], pod.Status.PodIP)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if domain, ok := pod.Annotations[hostnameAnnotationKey]; ok {
|
if domain, ok := pod.Annotations[hostnameAnnotationKey]; ok {
|
||||||
if _, ok := domains[domain]; !ok {
|
|
||||||
domains[domain] = []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
node, _ := ps.nodeInformer.Lister().Get(pod.Spec.NodeName)
|
node, _ := ps.nodeInformer.Lister().Get(pod.Spec.NodeName)
|
||||||
for _, address := range node.Status.Addresses {
|
for _, address := range node.Status.Addresses {
|
||||||
if address.Type == corev1.NodeExternalIP {
|
recordType := suitableType(address.Address)
|
||||||
domains[domain] = append(domains[domain], address.Address)
|
// IPv6 addresses are labeled as NodeInternalIP despite being usable externally as well.
|
||||||
|
if address.Type == corev1.NodeExternalIP || (address.Type == corev1.NodeInternalIP && recordType == endpoint.RecordTypeAAAA) {
|
||||||
|
addToEndpointMap(endpointMap, domain, recordType, address.Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ps.compatibility == "kops-dns-controller" {
|
if ps.compatibility == "kops-dns-controller" {
|
||||||
if domain, ok := pod.Annotations[kopsDNSControllerInternalHostnameAnnotationKey]; ok {
|
if domain, ok := pod.Annotations[kopsDNSControllerInternalHostnameAnnotationKey]; ok {
|
||||||
if _, ok := domains[domain]; !ok {
|
addToEndpointMap(endpointMap, domain, suitableType(pod.Status.PodIP), pod.Status.PodIP)
|
||||||
domains[domain] = []string{}
|
|
||||||
}
|
|
||||||
domains[domain] = append(domains[domain], pod.Status.PodIP)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if domain, ok := pod.Annotations[kopsDNSControllerHostnameAnnotationKey]; ok {
|
if domain, ok := pod.Annotations[kopsDNSControllerHostnameAnnotationKey]; ok {
|
||||||
if _, ok := domains[domain]; !ok {
|
|
||||||
domains[domain] = []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
node, _ := ps.nodeInformer.Lister().Get(pod.Spec.NodeName)
|
node, _ := ps.nodeInformer.Lister().Get(pod.Spec.NodeName)
|
||||||
for _, address := range node.Status.Addresses {
|
for _, address := range node.Status.Addresses {
|
||||||
if address.Type == corev1.NodeExternalIP {
|
recordType := suitableType(address.Address)
|
||||||
domains[domain] = append(domains[domain], address.Address)
|
// IPv6 addresses are labeled as NodeInternalIP despite being usable externally as well.
|
||||||
|
if address.Type == corev1.NodeExternalIP || (address.Type == corev1.NodeInternalIP && recordType == endpoint.RecordTypeAAAA) {
|
||||||
|
addToEndpointMap(endpointMap, domain, recordType, address.Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endpoints := []*endpoint.Endpoint{}
|
endpoints := []*endpoint.Endpoint{}
|
||||||
for domain, targets := range domains {
|
for key, targets := range endpointMap {
|
||||||
endpoints = append(endpoints, endpoint.NewEndpoint(domain, endpoint.RecordTypeA, targets...))
|
endpoints = append(endpoints, endpoint.NewEndpoint(key.domain, key.recordType, targets...))
|
||||||
}
|
}
|
||||||
return endpoints, nil
|
return endpoints, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addToEndpointMap(endpointMap map[endpointKey][]string, domain string, recordType string, address string) {
|
||||||
|
key := endpointKey{
|
||||||
|
domain: domain,
|
||||||
|
recordType: recordType,
|
||||||
|
}
|
||||||
|
if _, ok := endpointMap[key]; !ok {
|
||||||
|
endpointMap[key] = []string{}
|
||||||
|
}
|
||||||
|
endpointMap[key] = append(endpointMap[key], address)
|
||||||
|
}
|
||||||
|
@ -41,7 +41,7 @@ func TestPodSource(t *testing.T) {
|
|||||||
pods []*corev1.Pod
|
pods []*corev1.Pod
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"create records based on pod's external and internal IPs",
|
"create IPv4 records based on pod's external and internal IPs",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
@ -111,7 +111,7 @@ func TestPodSource(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"create records based on pod's external and internal IPs using DNS Controller annotations",
|
"create IPv4 records based on pod's external and internal IPs using DNS Controller annotations",
|
||||||
"",
|
"",
|
||||||
"kops-dns-controller",
|
"kops-dns-controller",
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
@ -180,12 +180,149 @@ func TestPodSource(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"create IPv6 records based on pod's external and internal IPs",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
[]*endpoint.Endpoint{
|
||||||
|
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
|
{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
[]*corev1.Node{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-node1",
|
||||||
|
},
|
||||||
|
Status: corev1.NodeStatus{
|
||||||
|
Addresses: []corev1.NodeAddress{
|
||||||
|
{Type: corev1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-node2",
|
||||||
|
},
|
||||||
|
Status: corev1.NodeStatus{
|
||||||
|
Addresses: []corev1.NodeAddress{
|
||||||
|
{Type: corev1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]*corev1.Pod{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-pod1",
|
||||||
|
Namespace: "kube-system",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
internalHostnameAnnotationKey: "internal.a.foo.example.org",
|
||||||
|
hostnameAnnotationKey: "a.foo.example.org",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
HostNetwork: true,
|
||||||
|
NodeName: "my-node1",
|
||||||
|
},
|
||||||
|
Status: corev1.PodStatus{
|
||||||
|
PodIP: "2001:DB8::1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-pod2",
|
||||||
|
Namespace: "kube-system",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
internalHostnameAnnotationKey: "internal.a.foo.example.org",
|
||||||
|
hostnameAnnotationKey: "a.foo.example.org",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
HostNetwork: true,
|
||||||
|
NodeName: "my-node2",
|
||||||
|
},
|
||||||
|
Status: corev1.PodStatus{
|
||||||
|
PodIP: "2001:DB8::2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create IPv6 records based on pod's external and internal IPs using DNS Controller annotations",
|
||||||
|
"",
|
||||||
|
"kops-dns-controller",
|
||||||
|
[]*endpoint.Endpoint{
|
||||||
|
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
|
{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
[]*corev1.Node{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-node1",
|
||||||
|
},
|
||||||
|
Status: corev1.NodeStatus{
|
||||||
|
Addresses: []corev1.NodeAddress{
|
||||||
|
{Type: corev1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-node2",
|
||||||
|
},
|
||||||
|
Status: corev1.NodeStatus{
|
||||||
|
Addresses: []corev1.NodeAddress{
|
||||||
|
{Type: corev1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]*corev1.Pod{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-pod1",
|
||||||
|
Namespace: "kube-system",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
kopsDNSControllerInternalHostnameAnnotationKey: "internal.a.foo.example.org",
|
||||||
|
kopsDNSControllerHostnameAnnotationKey: "a.foo.example.org",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
HostNetwork: true,
|
||||||
|
NodeName: "my-node1",
|
||||||
|
},
|
||||||
|
Status: corev1.PodStatus{
|
||||||
|
PodIP: "2001:DB8::1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "my-pod2",
|
||||||
|
Namespace: "kube-system",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
kopsDNSControllerInternalHostnameAnnotationKey: "internal.a.foo.example.org",
|
||||||
|
kopsDNSControllerHostnameAnnotationKey: "a.foo.example.org",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
HostNetwork: true,
|
||||||
|
NodeName: "my-node2",
|
||||||
|
},
|
||||||
|
Status: corev1.PodStatus{
|
||||||
|
PodIP: "2001:DB8::2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"create multiple records",
|
"create multiple records",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA},
|
||||||
|
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"2001:DB8::1"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
{DNSName: "b.foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "b.foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
@ -197,6 +334,7 @@ func TestPodSource(t *testing.T) {
|
|||||||
Status: corev1.NodeStatus{
|
Status: corev1.NodeStatus{
|
||||||
Addresses: []corev1.NodeAddress{
|
Addresses: []corev1.NodeAddress{
|
||||||
{Type: corev1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: corev1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
|
{Type: corev1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
{Type: corev1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: corev1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -216,7 +216,10 @@ func (sc *serviceSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, e
|
|||||||
})
|
})
|
||||||
// Use stable sort to not disrupt the order of services
|
// Use stable sort to not disrupt the order of services
|
||||||
sort.SliceStable(endpoints, func(i, j int) bool {
|
sort.SliceStable(endpoints, func(i, j int) bool {
|
||||||
return endpoints[i].DNSName < endpoints[j].DNSName
|
if endpoints[i].DNSName != endpoints[j].DNSName {
|
||||||
|
return endpoints[i].DNSName < endpoints[j].DNSName
|
||||||
|
}
|
||||||
|
return endpoints[i].RecordType < endpoints[j].RecordType
|
||||||
})
|
})
|
||||||
mergedEndpoints := []*endpoint.Endpoint{}
|
mergedEndpoints := []*endpoint.Endpoint{}
|
||||||
mergedEndpoints = append(mergedEndpoints, endpoints[0])
|
mergedEndpoints = append(mergedEndpoints, endpoints[0])
|
||||||
@ -308,8 +311,8 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri
|
|||||||
return endpoints
|
return endpoints
|
||||||
}
|
}
|
||||||
for _, address := range node.Status.Addresses {
|
for _, address := range node.Status.Addresses {
|
||||||
if address.Type == v1.NodeExternalIP {
|
if address.Type == v1.NodeExternalIP || (address.Type == v1.NodeInternalIP && suitableType(address.Address) == endpoint.RecordTypeAAAA) {
|
||||||
targets = endpoint.Targets{address.Address}
|
targets = append(targets, address.Address)
|
||||||
log.Debugf("Generating matching endpoint %s with NodeExternalIP %s", headlessDomain, address.Address)
|
log.Debugf("Generating matching endpoint %s with NodeExternalIP %s", headlessDomain, address.Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -499,7 +502,7 @@ func (sc *serviceSource) generateEndpoints(svc *v1.Service, hostname string, pro
|
|||||||
log.Errorf("Unable to extract targets from service %s/%s error: %v", svc.Namespace, svc.Name, err)
|
log.Errorf("Unable to extract targets from service %s/%s error: %v", svc.Namespace, svc.Name, err)
|
||||||
return endpoints
|
return endpoints
|
||||||
}
|
}
|
||||||
endpoints = append(endpoints, sc.extractNodePortEndpoints(svc, targets, hostname, ttl)...)
|
endpoints = append(endpoints, sc.extractNodePortEndpoints(svc, hostname, ttl)...)
|
||||||
case v1.ServiceTypeExternalName:
|
case v1.ServiceTypeExternalName:
|
||||||
targets = append(targets, extractServiceExternalName(svc)...)
|
targets = append(targets, extractServiceExternalName(svc)...)
|
||||||
}
|
}
|
||||||
@ -587,6 +590,7 @@ func (sc *serviceSource) extractNodePortTargets(svc *v1.Service) (endpoint.Targe
|
|||||||
var (
|
var (
|
||||||
internalIPs endpoint.Targets
|
internalIPs endpoint.Targets
|
||||||
externalIPs endpoint.Targets
|
externalIPs endpoint.Targets
|
||||||
|
ipv6IPs endpoint.Targets
|
||||||
nodes []*v1.Node
|
nodes []*v1.Node
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
@ -634,24 +638,27 @@ func (sc *serviceSource) extractNodePortTargets(svc *v1.Service) (endpoint.Targe
|
|||||||
externalIPs = append(externalIPs, address.Address)
|
externalIPs = append(externalIPs, address.Address)
|
||||||
case v1.NodeInternalIP:
|
case v1.NodeInternalIP:
|
||||||
internalIPs = append(internalIPs, address.Address)
|
internalIPs = append(internalIPs, address.Address)
|
||||||
|
if suitableType(address.Address) == endpoint.RecordTypeAAAA {
|
||||||
|
ipv6IPs = append(ipv6IPs, address.Address)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
access := getAccessFromAnnotations(svc.Annotations)
|
access := getAccessFromAnnotations(svc.Annotations)
|
||||||
if access == "public" {
|
if access == "public" {
|
||||||
return externalIPs, nil
|
return append(externalIPs, ipv6IPs...), nil
|
||||||
}
|
}
|
||||||
if access == "private" {
|
if access == "private" {
|
||||||
return internalIPs, nil
|
return internalIPs, nil
|
||||||
}
|
}
|
||||||
if len(externalIPs) > 0 {
|
if len(externalIPs) > 0 {
|
||||||
return externalIPs, nil
|
return append(externalIPs, ipv6IPs...), nil
|
||||||
}
|
}
|
||||||
return internalIPs, nil
|
return internalIPs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *serviceSource) extractNodePortEndpoints(svc *v1.Service, nodeTargets endpoint.Targets, hostname string, ttl endpoint.TTL) []*endpoint.Endpoint {
|
func (sc *serviceSource) extractNodePortEndpoints(svc *v1.Service, hostname string, ttl endpoint.TTL) []*endpoint.Endpoint {
|
||||||
var endpoints []*endpoint.Endpoint
|
var endpoints []*endpoint.Endpoint
|
||||||
|
|
||||||
for _, port := range svc.Spec.Ports {
|
for _, port := range svc.Spec.Ports {
|
||||||
|
@ -1518,6 +1518,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
||||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
||||||
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1527,6 +1528,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1537,6 +1539,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1559,6 +1562,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1569,6 +1573,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1584,6 +1589,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "_foo._tcp.foo.bar.example.com", Targets: endpoint.Targets{"0 50 30192 foo.bar.example.com"}, RecordType: endpoint.RecordTypeSRV},
|
{DNSName: "_foo._tcp.foo.bar.example.com", Targets: endpoint.Targets{"0 50 30192 foo.bar.example.com"}, RecordType: endpoint.RecordTypeSRV},
|
||||||
{DNSName: "foo.bar.example.com", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "foo.bar.example.com", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
||||||
|
{DNSName: "foo.bar.example.com", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1593,6 +1599,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1603,6 +1610,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1619,6 +1627,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
||||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
|
||||||
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1627,6 +1636,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Status: v1.NodeStatus{
|
Status: v1.NodeStatus{
|
||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1636,6 +1646,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Status: v1.NodeStatus{
|
Status: v1.NodeStatus{
|
||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1652,6 +1663,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
||||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
||||||
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1661,6 +1673,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1671,6 +1684,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1691,6 +1705,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
||||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
||||||
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1700,6 +1715,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1710,6 +1726,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1731,6 +1748,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
||||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
|
||||||
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1740,6 +1758,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1750,6 +1769,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1768,6 +1788,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
{DNSName: "_foo._tcp.foo.example.org", Targets: endpoint.Targets{"0 50 30192 foo.example.org"}, RecordType: endpoint.RecordTypeSRV},
|
||||||
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
||||||
|
{DNSName: "foo.example.org", Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1777,6 +1798,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1787,6 +1809,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1804,7 +1827,9 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "internal.foo.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.0.1.1"}},
|
{DNSName: "internal.foo.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.0.1.1"}},
|
||||||
|
{DNSName: "internal.foo.example.org", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1"}},
|
||||||
{DNSName: "internal.bar.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.0.1.1"}},
|
{DNSName: "internal.bar.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.0.1.1"}},
|
||||||
|
{DNSName: "internal.bar.example.org", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1"}},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1817,6 +1842,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1830,6 +1856,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1846,7 +1873,9 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "internal.foo.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}},
|
{DNSName: "internal.foo.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}},
|
||||||
|
{DNSName: "internal.foo.example.org", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}},
|
||||||
{DNSName: "internal.bar.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}},
|
{DNSName: "internal.bar.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}},
|
||||||
|
{DNSName: "internal.bar.example.org", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1859,6 +1888,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1872,6 +1902,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1888,7 +1919,9 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
{DNSName: "foo.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}},
|
{DNSName: "foo.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}},
|
||||||
|
{DNSName: "foo.example.org", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}},
|
||||||
{DNSName: "bar.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}},
|
{DNSName: "bar.example.org", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}},
|
||||||
|
{DNSName: "bar.example.org", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}},
|
||||||
},
|
},
|
||||||
nodes: []*v1.Node{{
|
nodes: []*v1.Node{{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -1901,6 +1934,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1914,6 +1948,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -1942,6 +1977,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.1"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.1"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
@ -1955,6 +1991,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
|||||||
Addresses: []v1.NodeAddress{
|
Addresses: []v1.NodeAddress{
|
||||||
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
{Type: v1.NodeExternalIP, Address: "54.10.11.2"},
|
||||||
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
{Type: v1.NodeInternalIP, Address: "10.0.1.2"},
|
||||||
|
{Type: v1.NodeInternalIP, Address: "2001:DB8::2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
|
@ -29,11 +29,14 @@ func sortEndpoints(endpoints []*endpoint.Endpoint) {
|
|||||||
sort.Strings([]string(ep.Targets))
|
sort.Strings([]string(ep.Targets))
|
||||||
}
|
}
|
||||||
sort.Slice(endpoints, func(i, k int) bool {
|
sort.Slice(endpoints, func(i, k int) bool {
|
||||||
// Sort by DNSName and Targets
|
// Sort by DNSName, RecordType, and Targets
|
||||||
ei, ek := endpoints[i], endpoints[k]
|
ei, ek := endpoints[i], endpoints[k]
|
||||||
if ei.DNSName != ek.DNSName {
|
if ei.DNSName != ek.DNSName {
|
||||||
return ei.DNSName < ek.DNSName
|
return ei.DNSName < ek.DNSName
|
||||||
}
|
}
|
||||||
|
if ei.RecordType != ek.RecordType {
|
||||||
|
return ei.RecordType < ek.RecordType
|
||||||
|
}
|
||||||
// Targets are sorted ahead of time.
|
// Targets are sorted ahead of time.
|
||||||
for j, ti := range ei.Targets {
|
for j, ti := range ei.Targets {
|
||||||
if j >= len(ek.Targets) {
|
if j >= len(ek.Targets) {
|
||||||
|
Loading…
Reference in New Issue
Block a user