Skip to content

Commit d99d0b6

Browse files
committed
fix(260513-kru): 增强 GetContainerNetNS 健壮性,修复 worker netns 获取失败
- namespace.go: GetContainerNetNS 增加 5 次重试(每次 300ms), 重试前验证容器 Running 状态,最终失败时嵌入容器 Status/ExitCode - container_proxy_provider.go: configureWorkerEgress 后加 500ms sleep, 给 Docker 时间稳定容器进程状态
1 parent 648b4a9 commit d99d0b6

2 files changed

Lines changed: 33 additions & 6 deletions

File tree

internal/network/container_proxy_provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ func (p *ContainerProxyProvider) PrepareHost(ctx context.Context, spec HostNetwo
105105
return fmt.Errorf("gateway: configure worker routes/DNS: %w", err)
106106
}
107107

108+
time.Sleep(500 * time.Millisecond)
109+
108110
if err := applyWorkerFirewall(ctx, workerName, gwIP, bridgeGW); err != nil {
109111
p.teardownGateway(ctx, hostID)
110112
return fmt.Errorf("gateway: apply worker firewall: %w", err)

internal/network/namespace.go

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"runtime"
1111
"strconv"
1212
"strings"
13+
"time"
1314

1415
"github.com/vishvananda/netlink"
1516
"github.com/vishvananda/netns"
@@ -40,15 +41,39 @@ func GetContainerNetNS(containerName string) (netns.NsHandle, uint32, error) {
4041
}
4142
}
4243

43-
ns, err := netns.GetFromPid(int(pid))
44-
if err != nil {
45-
return 0, 0, &NetworkError{
46-
Type: ErrTunnelSetupFailed,
47-
Message: fmt.Sprintf("get netns from pid %d: %v", pid, err),
44+
const maxRetry = 5
45+
var lastErr error
46+
for attempt := 1; attempt <= maxRetry; attempt++ {
47+
// 每次重试前验证容器是否仍在运行
48+
runningOut, runErr := exec.Command("docker", "inspect", "-f", "{{.State.Running}}", containerName).Output()
49+
if runErr != nil || strings.TrimSpace(string(runningOut)) != "true" {
50+
if attempt < maxRetry {
51+
time.Sleep(300 * time.Millisecond)
52+
continue
53+
}
54+
}
55+
56+
ns, nsErr := netns.GetFromPid(int(pid))
57+
if nsErr == nil {
58+
return ns, uint32(pid), nil
4859
}
60+
lastErr = nsErr
61+
if attempt < maxRetry {
62+
time.Sleep(300 * time.Millisecond)
63+
}
64+
}
65+
66+
// 最后一次失败时,获取容器状态信息嵌入错误
67+
statusOut, _ := exec.Command("docker", "inspect", "-f", "{{.State.Status}}|{{.State.ExitCode}}", containerName).Output()
68+
statusInfo := strings.TrimSpace(string(statusOut))
69+
if statusInfo == "" {
70+
statusInfo = "unknown"
4971
}
5072

51-
return ns, uint32(pid), nil
73+
return 0, 0, &NetworkError{
74+
Type: ErrTunnelSetupFailed,
75+
Message: fmt.Sprintf("get netns from pid %d after %d attempts (container status=%s): %v", pid, maxRetry, statusInfo, lastErr),
76+
}
5277
}
5378

5479
// InjectManagementVeth creates a veth pair between the host and container

0 commit comments

Comments
 (0)