sandbox: make event monitor in CRI independent
Signed-off-by: Abel Feng <fshb1988@gmail.com>
This commit is contained in:
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/containerd/containerd/v2/core/sandbox"
|
||||
criconfig "github.com/containerd/containerd/v2/internal/cri/config"
|
||||
"github.com/containerd/containerd/v2/internal/cri/constants"
|
||||
"github.com/containerd/containerd/v2/internal/cri/server/events"
|
||||
"github.com/containerd/containerd/v2/internal/cri/server/podsandbox/types"
|
||||
imagestore "github.com/containerd/containerd/v2/internal/cri/store/image"
|
||||
ctrdutil "github.com/containerd/containerd/v2/internal/cri/util"
|
||||
@@ -85,18 +86,19 @@ func init() {
|
||||
imageService: criImagePlugin.(ImageService),
|
||||
store: NewStore(),
|
||||
}
|
||||
|
||||
eventMonitor := events.NewEventMonitor(&podSandboxEventHandler{
|
||||
controller: &c,
|
||||
})
|
||||
eventMonitor.Subscribe(client, []string{`topic="/tasks/exit"`})
|
||||
eventMonitor.Start()
|
||||
c.eventMonitor = eventMonitor
|
||||
|
||||
return &c, nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// CRIService interface contains things required by controller, but not yet refactored from criService.
|
||||
// TODO: this will be removed in subsequent iterations.
|
||||
type CRIService interface {
|
||||
// TODO: we should implement Event backoff in Controller.
|
||||
BackOffEvent(id string, event interface{})
|
||||
}
|
||||
|
||||
// RuntimeService specifies dependencies to CRI runtime service.
|
||||
type RuntimeService interface {
|
||||
Config() criconfig.Config
|
||||
@@ -123,18 +125,13 @@ type Controller struct {
|
||||
imageService ImageService
|
||||
// os is an interface for all required os operations.
|
||||
os osinterface.OS
|
||||
// cri is CRI service that provides missing gaps needed by controller.
|
||||
cri CRIService
|
||||
// eventMonitor is the event monitor for podsandbox controller to handle sandbox task exit event
|
||||
// actually we only use it's backoff mechanism to make sure pause container is cleaned up.
|
||||
eventMonitor *events.EventMonitor
|
||||
|
||||
store *Store
|
||||
}
|
||||
|
||||
func (c *Controller) Init(
|
||||
cri CRIService,
|
||||
) {
|
||||
c.cri = cri
|
||||
}
|
||||
|
||||
var _ sandbox.Controller = (*Controller)(nil)
|
||||
|
||||
func (c *Controller) Platform(_ctx context.Context, _sandboxID string) (platforms.Platform, error) {
|
||||
@@ -172,11 +169,7 @@ func (c *Controller) waitSandboxExit(ctx context.Context, p *types.PodSandbox, e
|
||||
defer dcancel()
|
||||
event := &eventtypes.TaskExit{ExitStatus: exitStatus, ExitedAt: protobuf.ToTimestamp(exitedAt)}
|
||||
if err := handleSandboxTaskExit(dctx, p, event); err != nil {
|
||||
// TODO will backoff the event to the controller's own EventMonitor, but not cri's,
|
||||
// because we should call handleSandboxTaskExit again the next time
|
||||
// eventMonitor handle this event. but now it goes into cri's EventMonitor,
|
||||
// the handleSandboxTaskExit will not be called anymore
|
||||
c.cri.BackOffEvent(p.ID, e)
|
||||
c.eventMonitor.Backoff(p.ID, event)
|
||||
}
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
|
||||
61
internal/cri/server/podsandbox/events.go
Normal file
61
internal/cri/server/podsandbox/events.go
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package podsandbox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/log"
|
||||
|
||||
eventtypes "github.com/containerd/containerd/v2/api/events"
|
||||
ctrdutil "github.com/containerd/containerd/v2/internal/cri/util"
|
||||
)
|
||||
|
||||
const (
|
||||
// handleEventTimeout is the timeout for handling 1 event. Event monitor
|
||||
// handles events in serial, if one event blocks the event monitor, no
|
||||
// other events can be handled.
|
||||
// Add a timeout for each event handling, events that timeout will be requeued and
|
||||
// handled again in the future.
|
||||
handleEventTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
type podSandboxEventHandler struct {
|
||||
controller *Controller
|
||||
}
|
||||
|
||||
func (p *podSandboxEventHandler) HandleEvent(any interface{}) error {
|
||||
switch e := any.(type) {
|
||||
case *eventtypes.TaskExit:
|
||||
log.L.Infof("TaskExit event in podsandbox handler %+v", e)
|
||||
// Use ID instead of ContainerID to rule out TaskExit event for exec.
|
||||
sb := p.controller.store.Get(e.ID)
|
||||
if sb == nil {
|
||||
return nil
|
||||
}
|
||||
ctx := ctrdutil.NamespacedContext()
|
||||
ctx, cancel := context.WithTimeout(ctx, handleEventTimeout)
|
||||
defer cancel()
|
||||
if err := handleSandboxTaskExit(ctx, sb, e); err != nil {
|
||||
return fmt.Errorf("failed to handle container TaskExit event: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/typeurl/v2"
|
||||
@@ -54,10 +53,6 @@ const (
|
||||
unknownExitCode = 255
|
||||
)
|
||||
|
||||
const (
|
||||
handleEventTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
// getSandboxRootDir returns the root directory for managing sandbox files,
|
||||
// e.g. hosts files.
|
||||
func (c *Controller) getSandboxRootDir(id string) string {
|
||||
|
||||
@@ -95,8 +95,8 @@ func (c *Controller) stopSandboxContainer(ctx context.Context, podSandbox *types
|
||||
go func() {
|
||||
defer close(stopCh)
|
||||
err := c.waitSandboxExit(exitCtx, podSandbox, exitCh)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("Failed to wait pod sandbox exit %+v", err)
|
||||
if err != nil && err != context.Canceled && err != context.DeadlineExceeded {
|
||||
log.G(ctx).WithError(err).Errorf("Failed to wait sandbox exit %+v", err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
|
||||
Reference in New Issue
Block a user