Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 37 additions & 17 deletions dns-controller/pkg/watchers/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,25 @@ func (c *PodController) runWatcher(stopCh <-chan struct{}) {
}
}

// podIPsMatchingNodeInternalIP checks which pod IPs match a NodeInternalIP address on the specified node
func (c *PodController) podIPsMatchingNodeInternalIP(pod *v1.Pod) []string {
ctx := context.TODO()
var internalIPs []string
node, err := c.client.CoreV1().Nodes().Get(ctx, pod.Spec.NodeName, metav1.GetOptions{})
if err != nil {
klog.Warningf("Failed to get node %q: %v", pod.Spec.NodeName, err)
return []string{}
}
for _, podIP := range pod.Status.PodIPs {
for _, addr := range node.Status.Addresses {
if addr.Type == v1.NodeInternalIP && addr.Address == podIP.IP {
internalIPs = append(internalIPs, addr.Address)
}
}
}
return internalIPs
}

// updatePodRecords will apply the records for the specified pod. It returns the key that was set.
func (c *PodController) updatePodRecords(pod *v1.Pod) string {
var records []dns.Record
Expand Down Expand Up @@ -176,27 +195,28 @@ func (c *PodController) updatePodRecords(pod *v1.Pod) string {

specInternal := pod.Annotations[AnnotationNameDNSInternal]
if specInternal != "" {
var aliases []string
if pod.Spec.HostNetwork {
if pod.Spec.NodeName != "" {
aliases = append(aliases, "node/"+pod.Spec.NodeName+"/internal")
}
} else {
klog.V(4).Infof("Pod %q had %s=%s, but was not HostNetwork", pod.Name, AnnotationNameDNSInternal, specInternal)
}

tokens := strings.Split(specInternal, ",")
for _, token := range tokens {
token = strings.TrimSpace(token)

fqdn := dns.EnsureDotSuffix(token)
for _, alias := range aliases {
records = append(records, dns.Record{
RecordType: dns.RecordTypeAlias,
FQDN: fqdn,
Value: alias,
})
if pod.Spec.NodeName != "" && pod.Spec.HostNetwork {
podInternalIPs := c.podIPsMatchingNodeInternalIP(pod)
if len(podInternalIPs) == 0 {
klog.V(4).Infof("Pod %q IPs do not match any NodeInternalIP on node %q", pod.Name, pod.Spec.NodeName)
} else {
for _, token := range tokens {
token = strings.TrimSpace(token)
fqdn := dns.EnsureDotSuffix(token)
for _, podIP := range podInternalIPs {
records = append(records, dns.Record{
RecordType: dns.RecordTypeA,
FQDN: fqdn,
Value: podIP,
})
}
}
}
} else {
klog.V(4).Infof("Pod %q had %s=%s, but was not HostNetwork or NodeName not set", pod.Name, AnnotationNameDNSInternal, specInternal)
}
} else {
klog.V(4).Infof("Pod %q did not have %s label", pod.Name, AnnotationNameDNSInternal)
Expand Down
39 changes: 35 additions & 4 deletions dns-controller/pkg/watchers/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,32 @@ import (

func TestPodController(t *testing.T) {
ctx := context.Background()

nspec := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "my-node",
},
Status: corev1.NodeStatus{
Addresses: []corev1.NodeAddress{
// Internal IPs allocated to the Pod
{Type: corev1.NodeInternalIP, Address: "10.0.0.1"},
{Type: corev1.NodeInternalIP, Address: "10.0.0.2"},
// The following 2 addresses should be ignored, as they are not associated allocated to the Pod
{Type: corev1.NodeInternalIP, Address: "10.0.0.3"},
{Type: corev1.NodeInternalIP, Address: "10.0.0.4"},
// External IPs
{Type: corev1.NodeExternalIP, Address: "2001:db8:0:0:0:ff00:42:8329"},
{Type: corev1.NodeExternalIP, Address: "54.100.0.1"},
},
},
}

pspec := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "somepod",
Namespace: "kube-system",
Annotations: map[string]string{
"dns.alpha.kubernetes.io/internal": "internal.a.foo.com",
"dns.alpha.kubernetes.io/internal": "internal.a.foo.com,internal.b.foo.com",
"dns.alpha.kubernetes.io/external": "a.foo.com",
},
},
Expand All @@ -47,15 +67,23 @@ func TestPodController(t *testing.T) {
PodIP: "10.0.0.1",
PodIPs: []corev1.PodIP{
{IP: "10.0.0.1"},
{IP: "10.0.0.2"},
{IP: "2001:db8:0:0:0:ff00:42:8329"},
{IP: "54.100.0.1"},
},
},
}

client := fake.NewClientset()
pods := client.CoreV1().Pods("kube-system")

_, err := pods.Create(ctx, pspec, metav1.CreateOptions{})
nodes := client.CoreV1().Nodes()
_, err := nodes.Create(ctx, nspec, metav1.CreateOptions{})
if err != nil {
t.Fatalf("unexpected error creating node: %v", err)
}

pods := client.CoreV1().Pods("kube-system")
_, err = pods.Create(ctx, pspec, metav1.CreateOptions{})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand Down Expand Up @@ -88,7 +116,10 @@ func TestPodController(t *testing.T) {
want := map[string][]dns.Record{
"kube-system/somepod": {
{RecordType: "_alias", FQDN: "a.foo.com.", Value: "node/my-node/external"},
{RecordType: "_alias", FQDN: "internal.a.foo.com.", Value: "node/my-node/internal"},
{RecordType: "A", FQDN: "internal.a.foo.com.", Value: "10.0.0.1"},
{RecordType: "A", FQDN: "internal.a.foo.com.", Value: "10.0.0.2"},
{RecordType: "A", FQDN: "internal.b.foo.com.", Value: "10.0.0.1"},
{RecordType: "A", FQDN: "internal.b.foo.com.", Value: "10.0.0.2"},
},
}
if diff := cmp.Diff(scope.records, want); diff != "" {
Expand Down
Loading