mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-05 09:06:58 +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.
|
||||
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 TTL record can be set with the `external-dns.alpha.kubernetes.io/ttl` node annotation.
|
||||
The node source adds an `A` record per each node `externalIP` (if not found, any IPv4 `internalIP` is used instead).
|
||||
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)
|
||||
|
||||
|
@ -157,11 +157,13 @@ func legacyEndpointsFromDNSControllerNodePortService(svc *v1.Service, sc *servic
|
||||
continue
|
||||
}
|
||||
for _, address := range node.Status.Addresses {
|
||||
if address.Type == v1.NodeExternalIP && isExternal {
|
||||
endpoints = append(endpoints, endpoint.NewEndpoint(hostname, endpoint.RecordTypeA, address.Address))
|
||||
recordType := suitableType(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 {
|
||||
endpoints = append(endpoints, endpoint.NewEndpoint(hostname, endpoint.RecordTypeA, address.Address))
|
||||
if isInternal && address.Type == v1.NodeInternalIP {
|
||||
endpoints = append(endpoints, endpoint.NewEndpoint(hostname, recordType, address.Address))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +76,11 @@ func NewNodeSource(ctx context.Context, kubeClient kubernetes.Interface, annotat
|
||||
}, nil
|
||||
}
|
||||
|
||||
type endpointsKey struct {
|
||||
dnsName string
|
||||
recordType string
|
||||
}
|
||||
|
||||
// Endpoints returns endpoint objects for each service that should be processed.
|
||||
func (ns *nodeSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||
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
|
||||
}
|
||||
|
||||
endpoints := map[string]*endpoint.Endpoint{}
|
||||
endpoints := map[endpointsKey]*endpoint.Endpoint{}
|
||||
|
||||
// create endpoints for all 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
|
||||
ep := &endpoint.Endpoint{
|
||||
RecordType: "A", // hardcoded DNS record type
|
||||
RecordTTL: ttl,
|
||||
RecordTTL: ttl,
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
ep.Targets = endpoint.Targets(addrs)
|
||||
ep.Labels = endpoint.NewLabels()
|
||||
|
||||
log.Debugf("adding endpoint %s", ep)
|
||||
if _, ok := endpoints[ep.DNSName]; ok {
|
||||
endpoints[ep.DNSName].Targets = append(endpoints[ep.DNSName].Targets, ep.Targets...)
|
||||
} else {
|
||||
endpoints[ep.DNSName] = ep
|
||||
for _, addr := range addrs {
|
||||
log.Debugf("adding endpoint %s target %s", ep, addr)
|
||||
key := endpointsKey{
|
||||
dnsName: ep.DNSName,
|
||||
recordType: suitableType(addr),
|
||||
}
|
||||
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.NodeInternalIP: {},
|
||||
}
|
||||
var ipv6Addresses []string
|
||||
|
||||
for _, addr := range node.Status.Addresses {
|
||||
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 {
|
||||
return addresses[v1.NodeExternalIP], nil
|
||||
return append(addresses[v1.NodeExternalIP], ipv6Addresses...), nil
|
||||
}
|
||||
|
||||
if len(addresses[v1.NodeInternalIP]) > 0 {
|
||||
|
@ -127,6 +127,19 @@ func testNodeSourceEndpoints(t *testing.T) {
|
||||
},
|
||||
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",
|
||||
"",
|
||||
@ -166,6 +179,20 @@ func testNodeSourceEndpoints(t *testing.T) {
|
||||
},
|
||||
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",
|
||||
"",
|
||||
@ -179,6 +206,20 @@ func testNodeSourceEndpoints(t *testing.T) {
|
||||
},
|
||||
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",
|
||||
"",
|
||||
@ -192,6 +233,20 @@ func testNodeSourceEndpoints(t *testing.T) {
|
||||
},
|
||||
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",
|
||||
"",
|
||||
@ -318,7 +373,7 @@ func testNodeSourceEndpoints(t *testing.T) {
|
||||
false,
|
||||
},
|
||||
{
|
||||
"node with nil Lables returns valid endpoint",
|
||||
"node with nil Labels returns valid endpoint",
|
||||
"",
|
||||
"",
|
||||
"node1",
|
||||
|
@ -76,13 +76,18 @@ func NewPodSource(ctx context.Context, kubeClient kubernetes.Interface, namespac
|
||||
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) {
|
||||
pods, err := ps.podInformer.Lister().Pods(ps.namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
domains := make(map[string][]string)
|
||||
endpointMap := make(map[endpointKey][]string)
|
||||
for _, pod := range pods {
|
||||
if !pod.Spec.HostNetwork {
|
||||
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 _, ok := domains[domain]; !ok {
|
||||
domains[domain] = []string{}
|
||||
}
|
||||
domains[domain] = append(domains[domain], pod.Status.PodIP)
|
||||
addToEndpointMap(endpointMap, domain, suitableType(pod.Status.PodIP), pod.Status.PodIP)
|
||||
}
|
||||
|
||||
if domain, ok := pod.Annotations[hostnameAnnotationKey]; ok {
|
||||
if _, ok := domains[domain]; !ok {
|
||||
domains[domain] = []string{}
|
||||
}
|
||||
|
||||
node, _ := ps.nodeInformer.Lister().Get(pod.Spec.NodeName)
|
||||
for _, address := range node.Status.Addresses {
|
||||
if address.Type == corev1.NodeExternalIP {
|
||||
domains[domain] = append(domains[domain], address.Address)
|
||||
recordType := suitableType(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 domain, ok := pod.Annotations[kopsDNSControllerInternalHostnameAnnotationKey]; ok {
|
||||
if _, ok := domains[domain]; !ok {
|
||||
domains[domain] = []string{}
|
||||
}
|
||||
domains[domain] = append(domains[domain], pod.Status.PodIP)
|
||||
addToEndpointMap(endpointMap, domain, suitableType(pod.Status.PodIP), pod.Status.PodIP)
|
||||
}
|
||||
|
||||
if domain, ok := pod.Annotations[kopsDNSControllerHostnameAnnotationKey]; ok {
|
||||
if _, ok := domains[domain]; !ok {
|
||||
domains[domain] = []string{}
|
||||
}
|
||||
|
||||
node, _ := ps.nodeInformer.Lister().Get(pod.Spec.NodeName)
|
||||
for _, address := range node.Status.Addresses {
|
||||
if address.Type == corev1.NodeExternalIP {
|
||||
domains[domain] = append(domains[domain], address.Address)
|
||||
recordType := suitableType(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{}
|
||||
for domain, targets := range domains {
|
||||
endpoints = append(endpoints, endpoint.NewEndpoint(domain, endpoint.RecordTypeA, targets...))
|
||||
for key, targets := range endpointMap {
|
||||
endpoints = append(endpoints, endpoint.NewEndpoint(key.domain, key.recordType, targets...))
|
||||
}
|
||||
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
|
||||
}{
|
||||
{
|
||||
"create records based on pod's external and internal IPs",
|
||||
"create IPv4 records based on pod's external and internal IPs",
|
||||
"",
|
||||
"",
|
||||
[]*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",
|
||||
[]*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",
|
||||
"",
|
||||
"",
|
||||
[]*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{"2001:DB8::1"}, RecordType: endpoint.RecordTypeAAAA},
|
||||
{DNSName: "b.foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
|
||||
},
|
||||
false,
|
||||
@ -197,6 +334,7 @@ func TestPodSource(t *testing.T) {
|
||||
Status: corev1.NodeStatus{
|
||||
Addresses: []corev1.NodeAddress{
|
||||
{Type: corev1.NodeExternalIP, Address: "54.10.11.1"},
|
||||
{Type: corev1.NodeInternalIP, Address: "2001:DB8::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
|
||||
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 = append(mergedEndpoints, endpoints[0])
|
||||
@ -308,8 +311,8 @@ func (sc *serviceSource) extractHeadlessEndpoints(svc *v1.Service, hostname stri
|
||||
return endpoints
|
||||
}
|
||||
for _, address := range node.Status.Addresses {
|
||||
if address.Type == v1.NodeExternalIP {
|
||||
targets = endpoint.Targets{address.Address}
|
||||
if address.Type == v1.NodeExternalIP || (address.Type == v1.NodeInternalIP && suitableType(address.Address) == endpoint.RecordTypeAAAA) {
|
||||
targets = append(targets, 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)
|
||||
return endpoints
|
||||
}
|
||||
endpoints = append(endpoints, sc.extractNodePortEndpoints(svc, targets, hostname, ttl)...)
|
||||
endpoints = append(endpoints, sc.extractNodePortEndpoints(svc, hostname, ttl)...)
|
||||
case v1.ServiceTypeExternalName:
|
||||
targets = append(targets, extractServiceExternalName(svc)...)
|
||||
}
|
||||
@ -587,6 +590,7 @@ func (sc *serviceSource) extractNodePortTargets(svc *v1.Service) (endpoint.Targe
|
||||
var (
|
||||
internalIPs endpoint.Targets
|
||||
externalIPs endpoint.Targets
|
||||
ipv6IPs endpoint.Targets
|
||||
nodes []*v1.Node
|
||||
err error
|
||||
)
|
||||
@ -634,24 +638,27 @@ func (sc *serviceSource) extractNodePortTargets(svc *v1.Service) (endpoint.Targe
|
||||
externalIPs = append(externalIPs, address.Address)
|
||||
case v1.NodeInternalIP:
|
||||
internalIPs = append(internalIPs, address.Address)
|
||||
if suitableType(address.Address) == endpoint.RecordTypeAAAA {
|
||||
ipv6IPs = append(ipv6IPs, address.Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
access := getAccessFromAnnotations(svc.Annotations)
|
||||
if access == "public" {
|
||||
return externalIPs, nil
|
||||
return append(externalIPs, ipv6IPs...), nil
|
||||
}
|
||||
if access == "private" {
|
||||
return internalIPs, nil
|
||||
}
|
||||
if len(externalIPs) > 0 {
|
||||
return externalIPs, nil
|
||||
return append(externalIPs, ipv6IPs...), 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
|
||||
|
||||
for _, port := range svc.Spec.Ports {
|
||||
|
@ -1518,6 +1518,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
expected: []*endpoint.Endpoint{
|
||||
{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{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1527,6 +1528,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{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{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1593,6 +1599,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{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{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1627,6 +1636,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Status: v1.NodeStatus{
|
||||
Addresses: []v1.NodeAddress{
|
||||
{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{
|
||||
Addresses: []v1.NodeAddress{
|
||||
{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{
|
||||
{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{"2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1661,6 +1673,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{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{"2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1700,6 +1715,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{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{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1740,6 +1758,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{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{"2001:DB8::1", "2001:DB8::2"}, RecordType: endpoint.RecordTypeAAAA},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1777,6 +1798,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{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.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1"}},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1817,6 +1842,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{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.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1859,6 +1888,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{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.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1", "2001:DB8::2"}},
|
||||
},
|
||||
nodes: []*v1.Node{{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1901,6 +1934,7 @@ func TestServiceSourceNodePortServices(t *testing.T) {
|
||||
Addresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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{
|
||||
{Type: v1.NodeExternalIP, Address: "54.10.11.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.Slice(endpoints, func(i, k int) bool {
|
||||
// Sort by DNSName and Targets
|
||||
// Sort by DNSName, RecordType, and Targets
|
||||
ei, ek := endpoints[i], endpoints[k]
|
||||
if 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.
|
||||
for j, ti := range ei.Targets {
|
||||
if j >= len(ek.Targets) {
|
||||
|
Loading…
Reference in New Issue
Block a user