Skip to content

Commit 0f1d274

Browse files
committed
sandbox: add methods to sandboxService
so that we cri service don't have to get sandbox controller everytime it needs to call sandbox controller api. Signed-off-by: Abel Feng <[email protected]>
1 parent 33e544e commit 0f1d274

File tree

14 files changed

+168
-97
lines changed

14 files changed

+168
-97
lines changed

integration/build_local_containerd_helper_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ func buildLocalContainerdClient(t *testing.T, tmpDir string, tweakInitFn tweakPl
129129
containerd.WithDefaultNamespace(constants.K8sContainerdNamespace),
130130
containerd.WithDefaultPlatform(platforms.Default()),
131131
containerd.WithInMemoryServices(lastInitContext),
132-
containerd.WithInMemorySandboxControllers(lastInitContext),
133132
)
134133
require.NoError(t, err)
135134

internal/cri/server/container_create.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
6363
return nil, fmt.Errorf("failed to find sandbox id %q: %w", r.GetPodSandboxId(), err)
6464
}
6565

66-
controller, err := c.sandboxService.SandboxController(sandbox.Config, sandbox.RuntimeHandler)
67-
if err != nil {
68-
return nil, fmt.Errorf("failed to get sandbox controller: %w", err)
69-
}
70-
71-
cstatus, err := controller.Status(ctx, sandbox.ID, false)
66+
cstatus, err := c.sandboxService.SandboxStatus(ctx, sandbox.Sandboxer, sandbox.ID, false)
7267
if err != nil {
7368
return nil, fmt.Errorf("failed to get controller status: %w", err)
7469
}
@@ -150,7 +145,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
150145
}
151146
}()
152147

153-
platform, err := controller.Platform(ctx, sandboxID)
148+
platform, err := c.sandboxService.SandboxPlatform(ctx, sandbox.Sandboxer, sandboxID)
154149
if err != nil {
155150
return nil, fmt.Errorf("failed to query sandbox platform: %w", err)
156151
}

internal/cri/server/container_stats_list.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,12 @@ func (c *criService) getMetricsHandler(ctx context.Context, sandboxID string) (m
6868
if err != nil {
6969
return nil, fmt.Errorf("failed to find sandbox id %q: %w", sandboxID, err)
7070
}
71-
controller, err := c.sandboxService.SandboxController(sandbox.Config, sandbox.RuntimeHandler)
72-
if err != nil {
73-
return nil, fmt.Errorf("failed to get sandbox controller: %w", err)
74-
}
71+
7572
// Grab the platform that this containers sandbox advertises. Reason being, even if
7673
// the host may be {insert platform}, if it virtualizes or emulates a different platform
7774
// it will return stats in that format, and we need to handle the conversion logic based
7875
// off of this info.
79-
p, err := controller.Platform(ctx, sandboxID)
76+
p, err := c.sandboxService.SandboxPlatform(ctx, sandbox.Sandboxer, sandboxID)
8077
if err != nil {
8178
return nil, err
8279
}

internal/cri/server/podsandbox/recover.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@ import (
2222
goruntime "runtime"
2323
"time"
2424

25+
"github.com/containerd/errdefs"
2526
"github.com/containerd/log"
2627
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
2728

2829
containerd "github.com/containerd/containerd/v2/client"
2930
sandbox2 "github.com/containerd/containerd/v2/core/sandbox"
31+
"github.com/containerd/containerd/v2/internal/cri/config"
3032
"github.com/containerd/containerd/v2/internal/cri/server/podsandbox/types"
3133
sandboxstore "github.com/containerd/containerd/v2/internal/cri/store/sandbox"
3234
ctrdutil "github.com/containerd/containerd/v2/internal/cri/util"
3335
"github.com/containerd/containerd/v2/pkg/netns"
34-
"github.com/containerd/errdefs"
3536
)
3637

3738
// loadContainerTimeout is the default timeout for loading a container/sandbox.
@@ -144,6 +145,7 @@ func (c *Controller) RecoverContainer(ctx context.Context, cntr containerd.Conta
144145

145146
sandbox = sandboxstore.NewSandbox(*meta, s)
146147
sandbox.Container = cntr
148+
sandbox.Sandboxer = string(config.ModePodSandbox)
147149

148150
// Load network namespace.
149151
sandbox.NetNS = getNetNS(meta)

internal/cri/server/restart.go

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ func (c *criService) recover(ctx context.Context) error {
5858
return fmt.Errorf("failed to list sandbox containers: %w", err)
5959
}
6060

61-
podSandboxController := c.client.SandboxController(string(criconfig.ModePodSandbox))
62-
61+
podSandboxController, err := c.sandboxService.SandboxController(string(criconfig.ModePodSandbox))
62+
if err != nil {
63+
return fmt.Errorf("failed to get podsanbox controller %v", err)
64+
}
6365
podSandboxLoader, ok := podSandboxController.(podSandboxRecover)
6466
if !ok {
6567
log.G(ctx).Fatal("pod sandbox controller doesn't support recovery")
@@ -134,6 +136,7 @@ func (c *criService) recover(ctx context.Context) error {
134136
}
135137

136138
sb := sandboxstore.NewSandbox(metadata, sandboxstore.Status{State: state})
139+
sb.Sandboxer = sbx.Sandboxer
137140

138141
// Load network namespace.
139142
sb.NetNS = getNetNS(&metadata)
@@ -149,20 +152,11 @@ func (c *criService) recover(ctx context.Context) error {
149152
if status.State == sandboxstore.StateNotReady {
150153
continue
151154
}
152-
controller, err := c.sandboxService.SandboxController(sb.Config, sb.RuntimeHandler)
155+
exitCh, err := c.sandboxService.WaitSandbox(ctrdutil.NamespacedContext(), sb.Sandboxer, sb.ID)
153156
if err != nil {
154-
log.G(ctx).WithError(err).Error("failed to get sandbox controller while waiting sandbox")
157+
log.G(ctx).WithError(err).Error("failed to wait sandbox")
155158
continue
156159
}
157-
exitCh := make(chan containerd.ExitStatus, 1)
158-
go func() {
159-
exit, err := controller.Wait(ctrdutil.NamespacedContext(), sb.ID)
160-
if err != nil {
161-
log.G(ctx).WithError(err).Error("failed to wait for sandbox exit")
162-
exitCh <- *containerd.NewExitStatus(containerd.UnknownExitStatus, time.Time{}, err)
163-
}
164-
exitCh <- *containerd.NewExitStatus(exit.ExitStatus, exit.ExitedAt, nil)
165-
}()
166160
c.eventMonitor.startSandboxExitMonitor(context.Background(), sb.ID, exitCh)
167161
}
168162
// Recover all containers.

internal/cri/server/sandbox_remove.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,7 @@ func (c *criService) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodS
7979
}
8080
}
8181

82-
// Use sandbox controller to delete sandbox
83-
controller, err := c.sandboxService.SandboxController(sandbox.Config, sandbox.RuntimeHandler)
84-
if err != nil {
85-
return nil, fmt.Errorf("failed to get sandbox controller: %w", err)
86-
}
87-
88-
if err := controller.Shutdown(ctx, id); err != nil && !errdefs.IsNotFound(err) {
82+
if err := c.sandboxService.ShutdownSandbox(ctx, sandbox.Sandboxer, id); err != nil && !errdefs.IsNotFound(err) {
8983
return nil, fmt.Errorf("failed to delete sandbox %q: %w", id, err)
9084
}
9185

internal/cri/server/sandbox_run.go

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
"github.com/containerd/typeurl/v2"
3232
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
3333

34-
containerd "github.com/containerd/containerd/v2/client"
3534
sb "github.com/containerd/containerd/v2/core/sandbox"
3635
"github.com/containerd/containerd/v2/internal/cri/annotations"
3736
"github.com/containerd/containerd/v2/internal/cri/bandwidth"
@@ -124,6 +123,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
124123
CreatedAt: time.Now().UTC(),
125124
},
126125
)
126+
sandbox.Sandboxer = ociRuntime.Sandboxer
127127

128128
if _, err := c.client.SandboxStore().Create(ctx, sandboxInfo); err != nil {
129129
return nil, fmt.Errorf("failed to save sandbox metadata: %w", err)
@@ -240,21 +240,16 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
240240
return nil, fmt.Errorf("unable to save sandbox %q to store: %w", id, err)
241241
}
242242

243-
controller, err := c.sandboxService.SandboxController(config, r.GetRuntimeHandler())
244-
if err != nil {
245-
return nil, fmt.Errorf("failed to get sandbox controller: %w", err)
246-
}
247-
248243
// Save sandbox metadata to store
249244
if sandboxInfo, err = c.client.SandboxStore().Update(ctx, sandboxInfo, "extensions"); err != nil {
250245
return nil, fmt.Errorf("unable to update extensions for sandbox %q: %w", id, err)
251246
}
252247

253-
if err := controller.Create(ctx, sandboxInfo, sb.WithOptions(config), sb.WithNetNSPath(sandbox.NetNSPath)); err != nil {
248+
if err := c.sandboxService.CreateSandbox(ctx, sandboxInfo, sb.WithOptions(config), sb.WithNetNSPath(sandbox.NetNSPath)); err != nil {
254249
return nil, fmt.Errorf("failed to create sandbox %q: %w", id, err)
255250
}
256251

257-
ctrl, err := controller.Start(ctx, id)
252+
ctrl, err := c.sandboxService.StartSandbox(ctx, sandbox.Sandboxer, id)
258253
if err != nil {
259254
var cerr podsandbox.CleanupErr
260255
if errors.As(err, &cerr) {
@@ -401,21 +396,10 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
401396
// SandboxStatus from the store and include it in the event.
402397
c.generateAndSendContainerEvent(ctx, id, id, runtime.ContainerEventType_CONTAINER_CREATED_EVENT)
403398

404-
// TODO: Use sandbox client instead
405-
exitCh := make(chan containerd.ExitStatus, 1)
406-
go func() {
407-
defer close(exitCh)
408-
409-
ctx := util.NamespacedContext()
410-
resp, err := controller.Wait(ctx, id)
411-
if err != nil {
412-
log.G(ctx).WithError(err).Error("failed to wait for sandbox exit")
413-
exitCh <- *containerd.NewExitStatus(containerd.UnknownExitStatus, time.Time{}, err)
414-
return
415-
}
416-
417-
exitCh <- *containerd.NewExitStatus(resp.ExitStatus, resp.ExitedAt, nil)
418-
}()
399+
exitCh, err := c.sandboxService.WaitSandbox(util.NamespacedContext(), sandbox.Sandboxer, id)
400+
if err != nil {
401+
return nil, fmt.Errorf("failed to wait sandbox %s: %v", id, err)
402+
}
419403

420404
// start the monitor after adding sandbox into the store, this ensures
421405
// that sandbox is in the store, when event monitor receives the TaskExit event.

internal/cri/server/sandbox_service.go

Lines changed: 82 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,103 @@
1717
package server
1818

1919
import (
20+
"context"
2021
"fmt"
22+
"time"
2123

22-
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
24+
"github.com/containerd/platforms"
2325

2426
"github.com/containerd/containerd/v2/client"
2527
"github.com/containerd/containerd/v2/core/sandbox"
2628
criconfig "github.com/containerd/containerd/v2/internal/cri/config"
2729
)
2830

2931
type criSandboxService struct {
30-
cli *client.Client
31-
config *criconfig.Config
32+
sandboxControllers map[string]sandbox.Controller
33+
config *criconfig.Config
3234
}
3335

34-
func newCriSandboxService(config *criconfig.Config, c *client.Client) *criSandboxService {
36+
func newCriSandboxService(config *criconfig.Config, sandboxers map[string]sandbox.Controller) *criSandboxService {
3537
return &criSandboxService{
36-
cli: c,
37-
config: config,
38+
sandboxControllers: sandboxers,
39+
config: config,
3840
}
3941
}
4042

41-
func (c *criSandboxService) SandboxController(config *runtime.PodSandboxConfig, runtimeHandler string) (sandbox.Controller, error) {
42-
ociRuntime, err := c.config.GetSandboxRuntime(config, runtimeHandler)
43+
func (c *criSandboxService) SandboxController(sandboxer string) (sandbox.Controller, error) {
44+
sbController, ok := c.sandboxControllers[sandboxer]
45+
if !ok {
46+
return nil, fmt.Errorf("failed to get sandbox controller by %s", sandboxer)
47+
}
48+
return sbController, nil
49+
}
50+
51+
func (c *criSandboxService) CreateSandbox(ctx context.Context, info sandbox.Sandbox, opts ...sandbox.CreateOpt) error {
52+
ctrl, err := c.SandboxController(info.Sandboxer)
53+
if err != nil {
54+
return err
55+
}
56+
return ctrl.Create(ctx, info, opts...)
57+
}
58+
59+
func (c *criSandboxService) StartSandbox(ctx context.Context, sandboxer string, sandboxID string) (sandbox.ControllerInstance, error) {
60+
ctrl, err := c.SandboxController(sandboxer)
61+
if err != nil {
62+
return sandbox.ControllerInstance{}, err
63+
}
64+
return ctrl.Start(ctx, sandboxID)
65+
}
66+
67+
func (c *criSandboxService) WaitSandbox(ctx context.Context, sandboxer string, sandboxID string) (<-chan client.ExitStatus, error) {
68+
ctrl, err := c.SandboxController(sandboxer)
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
ch := make(chan client.ExitStatus, 1)
74+
go func() {
75+
defer close(ch)
76+
77+
exitStatus, err := ctrl.Wait(ctx, sandboxID)
78+
if err != nil {
79+
ch <- *client.NewExitStatus(client.UnknownExitStatus, time.Time{}, err)
80+
return
81+
}
82+
83+
ch <- *client.NewExitStatus(exitStatus.ExitStatus, exitStatus.ExitedAt, nil)
84+
}()
85+
86+
return ch, nil
87+
}
88+
89+
func (c *criSandboxService) SandboxStatus(ctx context.Context, sandboxer string, sandboxID string, verbose bool) (sandbox.ControllerStatus, error) {
90+
ctrl, err := c.SandboxController(sandboxer)
91+
if err != nil {
92+
return sandbox.ControllerStatus{}, err
93+
}
94+
return ctrl.Status(ctx, sandboxID, verbose)
95+
}
96+
97+
func (c *criSandboxService) SandboxPlatform(ctx context.Context, sandboxer string, sandboxID string) (platforms.Platform, error) {
98+
ctrl, err := c.SandboxController(sandboxer)
99+
if err != nil {
100+
return platforms.Platform{}, err
101+
}
102+
return ctrl.Platform(ctx, sandboxID)
103+
}
104+
105+
func (c *criSandboxService) ShutdownSandbox(ctx context.Context, sandboxer string, sandboxID string) error {
106+
ctrl, err := c.SandboxController(sandboxer)
107+
if err != nil {
108+
return err
109+
}
110+
return ctrl.Shutdown(ctx, sandboxID)
111+
}
112+
113+
func (c *criSandboxService) StopSandbox(ctx context.Context, sandboxer, sandboxID string, opts ...sandbox.StopOpt) error {
114+
ctrl, err := c.SandboxController(sandboxer)
43115
if err != nil {
44-
return nil, fmt.Errorf("failed to get sandbox runtime: %w", err)
116+
return err
45117
}
46-
return c.cli.SandboxController(ociRuntime.Sandboxer), nil
118+
return ctrl.Stop(ctx, sandboxID, opts...)
47119
}

internal/cri/server/sandbox_status.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,12 @@ func (c *criService) PodSandboxStatus(ctx context.Context, r *runtime.PodSandbox
4141
return nil, fmt.Errorf("failed to get sandbox ip: %w", err)
4242
}
4343

44-
controller, err := c.sandboxService.SandboxController(sandbox.Config, sandbox.RuntimeHandler)
45-
if err != nil {
46-
return nil, fmt.Errorf("failed to get sandbox controller: %w", err)
47-
}
48-
4944
var (
5045
createdAt time.Time
5146
state string
5247
info map[string]string
5348
)
54-
cstatus, err := controller.Status(ctx, sandbox.ID, r.GetVerbose())
49+
cstatus, err := c.sandboxService.SandboxStatus(ctx, sandbox.Sandboxer, sandbox.ID, r.GetVerbose())
5550
if err != nil {
5651
// If the shim died unexpectedly (segfault etc.) let's set the state as
5752
// NOTREADY and not just error out to make k8s and clients like crictl

internal/cri/server/sandbox_stop.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,7 @@ func (c *criService) stopPodSandbox(ctx context.Context, sandbox sandboxstore.Sa
6868
// Only stop sandbox container when it's running or unknown.
6969
state := sandbox.Status.Get().State
7070
if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown {
71-
// Use sandbox controller to stop sandbox
72-
controller, err := c.sandboxService.SandboxController(sandbox.Config, sandbox.RuntimeHandler)
73-
if err != nil {
74-
return fmt.Errorf("failed to get sandbox controller: %w", err)
75-
}
76-
77-
if err := controller.Stop(ctx, id); err != nil {
71+
if err := c.sandboxService.StopSandbox(ctx, sandbox.Sandboxer, id); err != nil {
7872
// Log and ignore the error if controller already removed the sandbox
7973
if errdefs.IsNotFound(err) {
8074
log.G(ctx).Warnf("sandbox %q is not found when stopping it", id)

0 commit comments

Comments
 (0)