mirror of
https://github.com/containerd/containerd.git
synced 2026-11-06 05:17:02 +00:00
Merge pull request #11634 from ningmingxiao/v1.7_fix_event
[release/1.7] cri:fix lost container exit events if they arrive before info is cached
This commit is contained in:
2 files changed
+32
-20
No files matched your search
+16
-10
@@ -150,7 +150,7 @@ func (c *criService) recover(ctx context.Context) error {
|
||||
for _, container := range containers {
|
||||
container := container
|
||||
eg.Go(func() error {
|
||||
cntr, err := c.loadContainer(ctx2, container)
|
||||
cntr, exitCh, pid, err := c.loadContainer(ctx2, container)
|
||||
if err != nil {
|
||||
log.G(ctx2).WithError(err).Errorf("Failed to load container %q", container.ID())
|
||||
return nil
|
||||
@@ -159,6 +159,10 @@ func (c *criService) recover(ctx context.Context) error {
|
||||
if err := c.containerStore.Add(cntr); err != nil {
|
||||
return fmt.Errorf("failed to add container %q to store: %w", container.ID(), err)
|
||||
}
|
||||
if exitCh != nil {
|
||||
// Start the exit monitor. This should run after that container has been added to the container store.
|
||||
c.eventMonitor.startContainerExitMonitor(context.Background(), cntr.ID, pid, exitCh)
|
||||
}
|
||||
if err := c.containerNameIndex.Reserve(cntr.Name, cntr.ID); err != nil {
|
||||
return fmt.Errorf("failed to reserve container name %q: %w", cntr.Name, err)
|
||||
}
|
||||
@@ -228,7 +232,9 @@ func (c *criService) recover(ctx context.Context) error {
|
||||
const loadContainerTimeout = 10 * time.Second
|
||||
|
||||
// loadContainer loads container from containerd and status checkpoint.
|
||||
func (c *criService) loadContainer(ctx context.Context, cntr containerd.Container) (containerstore.Container, error) {
|
||||
func (c *criService) loadContainer(ctx context.Context, cntr containerd.Container) (containerstore.Container, <-chan containerd.ExitStatus, uint32, error) {
|
||||
var exitCh <-chan containerd.ExitStatus
|
||||
var statusPid uint32
|
||||
ctx, cancel := context.WithTimeout(ctx, loadContainerTimeout)
|
||||
defer cancel()
|
||||
id := cntr.ID()
|
||||
@@ -238,15 +244,15 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||
// Load container metadata.
|
||||
exts, err := cntr.Extensions(ctx)
|
||||
if err != nil {
|
||||
return container, fmt.Errorf("failed to get container extensions: %w", err)
|
||||
return container, nil, 0, fmt.Errorf("failed to get container extensions: %w", err)
|
||||
}
|
||||
ext, ok := exts[containerMetadataExtension]
|
||||
if !ok {
|
||||
return container, fmt.Errorf("metadata extension %q not found", containerMetadataExtension)
|
||||
return container, nil, 0, fmt.Errorf("metadata extension %q not found", containerMetadataExtension)
|
||||
}
|
||||
data, err := typeurl.UnmarshalAny(ext)
|
||||
if err != nil {
|
||||
return container, fmt.Errorf("failed to unmarshal metadata extension %q: %w", ext, err)
|
||||
return container, nil, 0, fmt.Errorf("failed to unmarshal metadata extension %q: %w", ext, err)
|
||||
}
|
||||
meta := data.(*containerstore.Metadata)
|
||||
|
||||
@@ -352,11 +358,13 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||
// before status is checkpointed.
|
||||
status.StartedAt = time.Now().UnixNano()
|
||||
status.Pid = t.Pid()
|
||||
statusPid = t.Pid()
|
||||
}
|
||||
// Wait for the task for exit monitor.
|
||||
// wait is a long running background request, no timeout needed.
|
||||
exitCh, err := t.Wait(ctrdutil.NamespacedContext())
|
||||
exitCh, err = t.Wait(ctrdutil.NamespacedContext())
|
||||
if err != nil {
|
||||
exitCh = nil
|
||||
if !errdefs.IsNotFound(err) {
|
||||
return fmt.Errorf("failed to wait for task: %w", err)
|
||||
}
|
||||
@@ -365,9 +373,6 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||
status.FinishedAt = time.Now().UnixNano()
|
||||
status.ExitCode = unknownExitCode
|
||||
status.Reason = unknownExitReason
|
||||
} else {
|
||||
// Start exit monitor.
|
||||
c.eventMonitor.startContainerExitMonitor(context.Background(), id, status.Pid, exitCh)
|
||||
}
|
||||
case containerd.Stopped:
|
||||
// Task is stopped. Update status and delete the task.
|
||||
@@ -396,7 +401,8 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||
if containerIO != nil {
|
||||
opts = append(opts, containerstore.WithContainerIO(containerIO))
|
||||
}
|
||||
return containerstore.NewContainer(*meta, opts...)
|
||||
container, err = containerstore.NewContainer(*meta, opts...)
|
||||
return container, exitCh, statusPid, err
|
||||
}
|
||||
|
||||
// podSandboxRecover is an additional interface implemented by podsandbox/ controller to handle
|
||||
|
||||
+16
-10
@@ -90,7 +90,7 @@ func (c *criService) recover(ctx context.Context) error {
|
||||
for _, container := range containers {
|
||||
container := container
|
||||
eg.Go(func() error {
|
||||
cntr, err := c.loadContainer(ctx2, container)
|
||||
cntr, exitCh, pid, err := c.loadContainer(ctx2, container)
|
||||
if err != nil {
|
||||
log.G(ctx2).WithError(err).Errorf("Failed to load container %q", container.ID())
|
||||
return nil
|
||||
@@ -99,6 +99,10 @@ func (c *criService) recover(ctx context.Context) error {
|
||||
if err := c.containerStore.Add(cntr); err != nil {
|
||||
return fmt.Errorf("failed to add container %q to store: %w", container.ID(), err)
|
||||
}
|
||||
if exitCh != nil {
|
||||
// Start the exit monitor. This should run after that container has been added to the container store.
|
||||
c.eventMonitor.startContainerExitMonitor(context.Background(), cntr.ID, pid, exitCh)
|
||||
}
|
||||
if err := c.containerNameIndex.Reserve(cntr.Name, cntr.ID); err != nil {
|
||||
return fmt.Errorf("failed to reserve container name %q: %w", cntr.Name, err)
|
||||
}
|
||||
@@ -168,7 +172,9 @@ func (c *criService) recover(ctx context.Context) error {
|
||||
const loadContainerTimeout = 10 * time.Second
|
||||
|
||||
// loadContainer loads container from containerd and status checkpoint.
|
||||
func (c *criService) loadContainer(ctx context.Context, cntr containerd.Container) (containerstore.Container, error) {
|
||||
func (c *criService) loadContainer(ctx context.Context, cntr containerd.Container) (containerstore.Container, <-chan containerd.ExitStatus, uint32, error) {
|
||||
var exitCh <-chan containerd.ExitStatus
|
||||
var statusPid uint32
|
||||
ctx, cancel := context.WithTimeout(ctx, loadContainerTimeout)
|
||||
defer cancel()
|
||||
id := cntr.ID()
|
||||
@@ -178,15 +184,15 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||
// Load container metadata.
|
||||
exts, err := cntr.Extensions(ctx)
|
||||
if err != nil {
|
||||
return container, fmt.Errorf("failed to get container extensions: %w", err)
|
||||
return container, nil, 0, fmt.Errorf("failed to get container extensions: %w", err)
|
||||
}
|
||||
ext, ok := exts[containerMetadataExtension]
|
||||
if !ok {
|
||||
return container, fmt.Errorf("metadata extension %q not found", containerMetadataExtension)
|
||||
return container, nil, 0, fmt.Errorf("metadata extension %q not found", containerMetadataExtension)
|
||||
}
|
||||
data, err := typeurl.UnmarshalAny(ext)
|
||||
if err != nil {
|
||||
return container, fmt.Errorf("failed to unmarshal metadata extension %q: %w", ext, err)
|
||||
return container, nil, 0, fmt.Errorf("failed to unmarshal metadata extension %q: %w", ext, err)
|
||||
}
|
||||
meta := data.(*containerstore.Metadata)
|
||||
|
||||
@@ -292,11 +298,13 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||
// before status is checkpointed.
|
||||
status.StartedAt = time.Now().UnixNano()
|
||||
status.Pid = t.Pid()
|
||||
statusPid = t.Pid()
|
||||
}
|
||||
// Wait for the task for exit monitor.
|
||||
// wait is a long running background request, no timeout needed.
|
||||
exitCh, err := t.Wait(ctrdutil.NamespacedContext())
|
||||
exitCh, err = t.Wait(ctrdutil.NamespacedContext())
|
||||
if err != nil {
|
||||
exitCh = nil
|
||||
if !errdefs.IsNotFound(err) {
|
||||
return fmt.Errorf("failed to wait for task: %w", err)
|
||||
}
|
||||
@@ -305,9 +313,6 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||
status.FinishedAt = time.Now().UnixNano()
|
||||
status.ExitCode = unknownExitCode
|
||||
status.Reason = unknownExitReason
|
||||
} else {
|
||||
// Start exit monitor.
|
||||
c.eventMonitor.startContainerExitMonitor(context.Background(), id, status.Pid, exitCh)
|
||||
}
|
||||
case containerd.Stopped:
|
||||
// Task is stopped. Update status and delete the task.
|
||||
@@ -336,7 +341,8 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||
if containerIO != nil {
|
||||
opts = append(opts, containerstore.WithContainerIO(containerIO))
|
||||
}
|
||||
return containerstore.NewContainer(*meta, opts...)
|
||||
container, err = containerstore.NewContainer(*meta, opts...)
|
||||
return container, exitCh, statusPid, err
|
||||
}
|
||||
|
||||
// loadSandbox loads sandbox from containerd.
|
||||
|
||||
Reference in new issue
Block a user