mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +00:00
set secondary address on host-network pods
host-network pods IPs are obtained from the reported kubelet nodeIPs. Historically, host-network podIPs are immutable once set, but when we've added dual-stack support, we didn't consider that the secondary IP address may not be present at the same time that the primary nodeIP. If a secondary IP address is added to a node after the host-network pods IPs are set, we can add the secondary host-network pod IP address maintaining the current behavior of not updating the current podIPs on host-network pods.
This commit is contained in:
parent
e8b177cfc1
commit
a20b2088ac
@ -1520,10 +1520,16 @@ func (kl *Kubelet) generateAPIPodStatus(pod *v1.Pod, podStatus *kubecontainer.Po
|
||||
klog.V(4).InfoS("Cannot get host IPs", "err", err)
|
||||
} else {
|
||||
s.HostIP = hostIPs[0].String()
|
||||
if kubecontainer.IsHostNetworkPod(pod) && s.PodIP == "" {
|
||||
s.PodIP = hostIPs[0].String()
|
||||
s.PodIPs = []v1.PodIP{{IP: s.PodIP}}
|
||||
if len(hostIPs) == 2 {
|
||||
// HostNetwork Pods inherit the node IPs as PodIPs. They are immutable once set,
|
||||
// other than that if the node becomes dual-stack, we add the secondary IP.
|
||||
if kubecontainer.IsHostNetworkPod(pod) {
|
||||
// Primary IP is not set
|
||||
if s.PodIP == "" {
|
||||
s.PodIP = hostIPs[0].String()
|
||||
s.PodIPs = []v1.PodIP{{IP: s.PodIP}}
|
||||
}
|
||||
// Secondary IP is not set #105320
|
||||
if len(hostIPs) == 2 && len(s.PodIPs) == 1 {
|
||||
s.PodIPs = append(s.PodIPs, v1.PodIP{IP: hostIPs[1].String()})
|
||||
}
|
||||
}
|
||||
|
@ -3349,6 +3349,119 @@ func TestGenerateAPIPodStatusHostNetworkPodIPs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeAddressUpdatesGenerateAPIPodStatusHostNetworkPodIPs(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
nodeIPs []string
|
||||
nodeAddresses []v1.NodeAddress
|
||||
expectedPodIPs []v1.PodIP
|
||||
}{
|
||||
|
||||
{
|
||||
name: "Immutable after update node addresses single-stack",
|
||||
nodeIPs: []string{"10.0.0.1"},
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "1.1.1.1"},
|
||||
},
|
||||
expectedPodIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Immutable after update node addresses dual-stack - primary address",
|
||||
nodeIPs: []string{"10.0.0.1", "2001:db8::2"},
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "1.1.1.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "2001:db8::2"},
|
||||
},
|
||||
expectedPodIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
{IP: "2001:db8::2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Immutable after update node addresses dual-stack - secondary address",
|
||||
nodeIPs: []string{"10.0.0.1", "2001:db8::2"},
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "2001:db8:1:2:3::2"},
|
||||
},
|
||||
expectedPodIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
{IP: "2001:db8::2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Immutable after update node addresses dual-stack - primary and secondary address",
|
||||
nodeIPs: []string{"10.0.0.1", "2001:db8::2"},
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "1.1.1.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "2001:db8:1:2:3::2"},
|
||||
},
|
||||
expectedPodIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
{IP: "2001:db8::2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Update secondary after new secondary address dual-stack",
|
||||
nodeIPs: []string{"10.0.0.1"},
|
||||
nodeAddresses: []v1.NodeAddress{
|
||||
{Type: v1.NodeInternalIP, Address: "10.0.0.1"},
|
||||
{Type: v1.NodeInternalIP, Address: "2001:db8::2"},
|
||||
},
|
||||
expectedPodIPs: []v1.PodIP{
|
||||
{IP: "10.0.0.1"},
|
||||
{IP: "2001:db8::2"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
|
||||
defer testKubelet.Cleanup()
|
||||
kl := testKubelet.kubelet
|
||||
for _, ip := range tc.nodeIPs {
|
||||
kl.nodeIPs = append(kl.nodeIPs, netutils.ParseIPSloppy(ip))
|
||||
}
|
||||
kl.nodeLister = testNodeLister{nodes: []*v1.Node{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: string(kl.nodeName)},
|
||||
Status: v1.NodeStatus{
|
||||
Addresses: tc.nodeAddresses,
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
pod := podWithUIDNameNs("12345", "test-pod", "test-namespace")
|
||||
pod.Spec.HostNetwork = true
|
||||
for _, ip := range tc.nodeIPs {
|
||||
pod.Status.PodIPs = append(pod.Status.PodIPs, v1.PodIP{IP: ip})
|
||||
}
|
||||
if len(pod.Status.PodIPs) > 0 {
|
||||
pod.Status.PodIP = pod.Status.PodIPs[0].IP
|
||||
}
|
||||
|
||||
// set old status
|
||||
podStatus := &kubecontainer.PodStatus{
|
||||
ID: pod.UID,
|
||||
Name: pod.Name,
|
||||
Namespace: pod.Namespace,
|
||||
}
|
||||
podStatus.IPs = tc.nodeIPs
|
||||
|
||||
status := kl.generateAPIPodStatus(pod, podStatus)
|
||||
if !reflect.DeepEqual(status.PodIPs, tc.expectedPodIPs) {
|
||||
t.Fatalf("Expected PodIPs %#v, got %#v", tc.expectedPodIPs, status.PodIPs)
|
||||
}
|
||||
if kl.nodeIPs[0].String() != status.PodIPs[0].IP {
|
||||
t.Fatalf("Expected HostIP %q to equal PodIPs[0].IP %q", status.HostIP, status.PodIPs[0].IP)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateAPIPodStatusPodIPs(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
|
Loading…
Reference in New Issue
Block a user