Skip to content

Commit 16baf31

Browse files
authored
Merge pull request #375 from nicklesimba/xagent-rebase-195
Rechecking pending Pods (conflict resolved)
2 parents d9cfa5b + 48c03a5 commit 16baf31

File tree

6 files changed

+87
-11
lines changed

6 files changed

+87
-11
lines changed

doc/crds/daemonset-install.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ rules:
6969
- create
7070
- patch
7171
- update
72+
- get
7273
---
7374
apiVersion: apps/v1
7475
kind: DaemonSet

pkg/reconciler/ip_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,8 @@ var _ = Describe("Whereabouts IP reconciler", func() {
331331
Expect(err).NotTo(HaveOccurred())
332332
})
333333

334-
It("cannot be reconciled", func() {
335-
Expect(reconcileLooper.ReconcileIPPools(context.TODO())).To(BeEmpty())
334+
It("can be reconciled", func() {
335+
Expect(reconcileLooper.ReconcileIPPools(context.TODO())).NotTo(BeEmpty())
336336
})
337337
})
338338
})

pkg/reconciler/iploop.go

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,73 @@ func (rl *ReconcileLooper) findOrphanedIPsPerPool(ipPools []storage.IPPool) erro
103103
func (rl ReconcileLooper) isPodAlive(podRef string, ip string) bool {
104104
for livePodRef, livePod := range rl.liveWhereaboutsPods {
105105
if podRef == livePodRef {
106-
livePodIPs := livePod.ips
107-
logging.Debugf(
108-
"pod reference %s matches allocation; Allocation IP: %s; PodIPs: %s",
109-
livePodRef,
110-
ip,
111-
livePodIPs)
112-
_, isFound := livePodIPs[ip]
113-
return isFound || livePod.phase == v1.PodPending
106+
isFound := isIpOnPod(&livePod, podRef, ip)
107+
if !isFound && (livePod.phase == v1.PodPending) {
108+
/* Sometimes pods are still coming up, and may not yet have Multus
109+
* annotation added to it yet. We don't want to check the IPs yet
110+
* so re-fetch the Pod 5x
111+
*/
112+
podToMatch := &livePod
113+
retries := 0
114+
115+
logging.Debugf("Re-fetching Pending Pod: %s IP-to-match: %s", livePodRef, ip)
116+
117+
for retries < storage.PodRefreshRetries {
118+
retries += 1
119+
podToMatch = rl.refreshPod(livePodRef)
120+
if podToMatch == nil {
121+
logging.Debugf("Cleaning up...")
122+
return false
123+
} else if podToMatch.phase != v1.PodPending {
124+
logging.Debugf("Pending Pod is now in phase: %s", podToMatch.phase)
125+
break
126+
} else {
127+
isFound = isIpOnPod(podToMatch, podRef, ip)
128+
// Short-circuit - Pending Pod may have IP now
129+
if isFound {
130+
logging.Debugf("Pod now has IP annotation while in Pending")
131+
return true
132+
}
133+
time.Sleep(time.Duration(500) * time.Millisecond)
134+
}
135+
}
136+
isFound = isIpOnPod(podToMatch, podRef, ip)
137+
}
138+
139+
return isFound
114140
}
115141
}
116142
return false
117143
}
118144

145+
func (rl ReconcileLooper) refreshPod(podRef string) *podWrapper {
146+
namespace, podName := splitPodRef(podRef)
147+
if namespace == "" || podName == "" {
148+
logging.Errorf("Invalid podRef format: %s", podRef)
149+
return nil
150+
}
151+
152+
pod, err := rl.k8sClient.GetPod(namespace, podName)
153+
if err != nil {
154+
logging.Errorf("Failed to refresh Pod %s: %s\n", podRef, err)
155+
return nil
156+
}
157+
158+
wrappedPod := wrapPod(*pod)
159+
logging.Debugf("Got refreshed pod: %v", wrappedPod)
160+
return wrappedPod
161+
}
162+
163+
func splitPodRef(podRef string) (string, string) {
164+
namespacedName := strings.Split(podRef, "/")
165+
if len(namespacedName) != 2 {
166+
logging.Errorf("Failed to split podRef %s", podRef)
167+
return "", ""
168+
}
169+
170+
return namespacedName[0], namespacedName[1]
171+
}
172+
119173
func composePodRef(pod v1.Pod) string {
120174
return fmt.Sprintf("%s/%s", pod.GetNamespace(), pod.GetName())
121175
}

pkg/reconciler/wrappedPod.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,14 @@ func networkStatusFromPod(pod v1.Pod) string {
8989
}
9090
return networkStatusAnnotationValue
9191
}
92+
93+
func isIpOnPod(livePod *podWrapper, podRef, ip string) bool {
94+
livePodIPs := livePod.ips
95+
logging.Debugf(
96+
"pod reference %s matches allocation; Allocation IP: %s; PodIPs: %s",
97+
podRef,
98+
ip,
99+
livePodIPs)
100+
_, isFound := livePodIPs[ip]
101+
return isFound
102+
}

pkg/storage/kubernetes/client.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ func (i *Client) ListPods(ctx context.Context) ([]v1.Pod, error) {
107107
return podList.Items, nil
108108
}
109109

110+
func (i *Client) GetPod(namespace, name string) (*v1.Pod, error) {
111+
pod, err := i.clientSet.CoreV1().Pods(namespace).Get(context.TODO(), name, metav1.GetOptions{})
112+
if err != nil {
113+
return nil, err
114+
}
115+
116+
return pod, nil
117+
}
118+
110119
func (i *Client) ListOverlappingIPs(ctx context.Context) ([]whereaboutsv1alpha1.OverlappingRangeIPReservation, error) {
111120
ctxWithTimeout, cancel := context.WithTimeout(ctx, storage.RequestTimeout)
112121
defer cancel()

pkg/storage/storage.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ var (
1313
RequestTimeout = 10 * time.Second
1414

1515
// DatastoreRetries defines how many retries are attempted when updating the Pool
16-
DatastoreRetries = 100
16+
DatastoreRetries = 100
17+
PodRefreshRetries = 3
1718
)
1819

1920
// IPPool is the interface that represents an manageable pool of allocated IPs

0 commit comments

Comments
 (0)