Skip to content

Commit 457d8b1

Browse files
committed
fix(logservice): persist PodIP before Running and stabilize node deletion
- oblogservicenode UpdateStatus: refresh PodIP/phase unconditionally (not only when Status==Running) so Pod-IP mode bootstrap can read the node connect address. Preserves the B5 guard (empty PodIP does not overwrite last-known IP) and keeps recovery gating on Running. - oblogservicezone: move sortDeleteCandidates to manager.go (no-return func crashes the task_register generator in _task.go); add name tiebreaker for deterministic deletion ordering.
1 parent a57075d commit 457d8b1

3 files changed

Lines changed: 42 additions & 27 deletions

File tree

internal/resource/oblogservicenode/oblogservicenode_manager.go

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -146,26 +146,36 @@ func (m *OBLogServiceNodeManager) UpdateStatus() error {
146146
}
147147
}
148148

149-
if m.Resource.Status.Status == nodestatus.Running {
150-
pod := &corev1.Pod{}
149+
// Refresh PodIP/phase from the current pod whenever it exists, so that
150+
// bootstrap (which needs the node connect address) can read the PodIP even
151+
// before the node reaches Running. This mirrors the unconditional ServiceIP
152+
// refresh above and is required for Pod-IP mode where the connect address
153+
// is the PodIP itself.
154+
pod := &corev1.Pod{}
155+
if m.Resource.Status.PodName != "" {
151156
err := m.Client.Get(m.Ctx, types.NamespacedName{
152157
Namespace: m.Resource.Namespace,
153158
Name: m.Resource.Status.PodName,
154159
}, pod)
155-
if err != nil {
156-
if kubeerrors.IsNotFound(err) {
157-
m.Logger.Info("LogService node pod not found, need recovery", "pod", m.Resource.Status.PodName)
158-
m.setRecoveryStatus()
159-
} else {
160-
return err
161-
}
162-
} else {
160+
if err != nil && !kubeerrors.IsNotFound(err) {
161+
return err
162+
}
163+
if err == nil {
163164
m.Resource.Status.PodPhase = pod.Status.Phase
164165
// A failed/evicted pod may report an empty PodIP; keep the last
165166
// known IP so recovery can pin the recreated pod to it.
166167
if pod.Status.PodIP != "" {
167168
m.Resource.Status.PodIP = pod.Status.PodIP
168169
}
170+
}
171+
}
172+
173+
if m.Resource.Status.Status == nodestatus.Running {
174+
if m.Resource.Status.PodName != "" && pod.Name == "" {
175+
// Pod lookup above returned NotFound; need recovery.
176+
m.Logger.Info("LogService node pod not found, need recovery", "pod", m.Resource.Status.PodName)
177+
m.setRecoveryStatus()
178+
} else if pod.Name != "" {
169179
m.Resource.Status.Ready = pod.Status.Phase == corev1.PodRunning
170180
if pod.Status.Phase == corev1.PodFailed {
171181
m.Logger.Info("LogService node pod in Failed phase, need recovery", "pod", m.Resource.Status.PodName)

internal/resource/oblogservicezone/oblogservicezone_manager.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ package oblogservicezone
1414

1515
import (
1616
"context"
17+
"sort"
1718

1819
"github.com/go-logr/logr"
1920
corev1 "k8s.io/api/core/v1"
@@ -223,3 +224,24 @@ func (m *OBLogServiceZoneManager) listNodes() (*v1alpha1.OBLogServiceNodeList, e
223224
}
224225
return nodeList, nil
225226
}
227+
228+
// sortDeleteCandidates orders nodes for deletion: unrecoverable first, then
229+
// newest first, with node name as a deterministic tiebreaker so two independent
230+
// list+sort calls select the same set even when CreationTimestamps are equal.
231+
// Defined here (not in _task.go) because it has no return value, which the
232+
// task_register generator cannot scan.
233+
func sortDeleteCandidates(nodes []v1alpha1.OBLogServiceNode) {
234+
sort.SliceStable(nodes, func(i, j int) bool {
235+
iUnrecoverable := nodes[i].Status.Status == nodestatus.Unrecoverable
236+
jUnrecoverable := nodes[j].Status.Status == nodestatus.Unrecoverable
237+
if iUnrecoverable != jUnrecoverable {
238+
return iUnrecoverable
239+
}
240+
ti := nodes[i].CreationTimestamp.Time
241+
tj := nodes[j].CreationTimestamp.Time
242+
if !ti.Equal(tj) {
243+
return ti.After(tj)
244+
}
245+
return nodes[i].Name < nodes[j].Name
246+
})
247+
}

internal/resource/oblogservicezone/oblogservicezone_task.go

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ package oblogservicezone
1515

1616
import (
1717
"fmt"
18-
"sort"
1918
"time"
2019

2120
"github.com/pkg/errors"
@@ -489,22 +488,6 @@ func UnregisterAllNodesFromCluster(m *OBLogServiceZoneManager) tasktypes.TaskErr
489488
return nil
490489
}
491490

492-
func sortDeleteCandidates(nodes []v1alpha1.OBLogServiceNode) {
493-
sort.SliceStable(nodes, func(i, j int) bool {
494-
iUnrecoverable := nodes[i].Status.Status == nodestatus.Unrecoverable
495-
jUnrecoverable := nodes[j].Status.Status == nodestatus.Unrecoverable
496-
if iUnrecoverable != jUnrecoverable {
497-
return iUnrecoverable
498-
}
499-
ti := nodes[i].CreationTimestamp.Time
500-
tj := nodes[j].CreationTimestamp.Time
501-
if !ti.Equal(tj) {
502-
return ti.After(tj)
503-
}
504-
return nodes[i].Name < nodes[j].Name
505-
})
506-
}
507-
508491
func (m *OBLogServiceZoneManager) getRunningNodeHttpAddr(excludeNames ...string) (string, error) {
509492
excludeSet := make(map[string]bool, len(excludeNames))
510493
for _, n := range excludeNames {

0 commit comments

Comments
 (0)