Skip to content

Commit 7feb1f3

Browse files
author
Maksym Pavlenko
authored
Merge pull request containerd#9853 from abel-von/make-shim-independent
sandbox: make an independent shim plugin
2 parents b3dd6e3 + a12aced commit 7feb1f3

File tree

6 files changed

+388
-301
lines changed

6 files changed

+388
-301
lines changed

core/runtime/v2/shim_load.go

Lines changed: 88 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,23 @@ package v2
1919
import (
2020
"context"
2121
"errors"
22+
"fmt"
2223
"os"
2324
"path/filepath"
2425

26+
"github.com/containerd/errdefs"
27+
"github.com/containerd/log"
28+
2529
"github.com/containerd/containerd/v2/core/mount"
2630
"github.com/containerd/containerd/v2/internal/cleanup"
2731
"github.com/containerd/containerd/v2/pkg/namespaces"
2832
"github.com/containerd/containerd/v2/pkg/timeout"
29-
"github.com/containerd/errdefs"
30-
"github.com/containerd/log"
3133
)
3234

33-
func (m *ShimManager) loadExistingTasks(ctx context.Context) error {
34-
nsDirs, err := os.ReadDir(m.state)
35+
// LoadExistingShims loads existing shims from the path specified by stateDir
36+
// rootDir is for cleaning up the unused paths of removed shims.
37+
func (m *ShimManager) LoadExistingShims(ctx context.Context, stateDir string, rootDir string) error {
38+
nsDirs, err := os.ReadDir(stateDir)
3539
if err != nil {
3640
return err
3741
}
@@ -45,26 +49,26 @@ func (m *ShimManager) loadExistingTasks(ctx context.Context) error {
4549
continue
4650
}
4751
log.G(ctx).WithField("namespace", ns).Debug("loading tasks in namespace")
48-
if err := m.loadShims(namespaces.WithNamespace(ctx, ns)); err != nil {
52+
if err := m.loadShims(namespaces.WithNamespace(ctx, ns), stateDir); err != nil {
4953
log.G(ctx).WithField("namespace", ns).WithError(err).Error("loading tasks in namespace")
5054
continue
5155
}
52-
if err := m.cleanupWorkDirs(namespaces.WithNamespace(ctx, ns)); err != nil {
56+
if err := m.cleanupWorkDirs(namespaces.WithNamespace(ctx, ns), rootDir); err != nil {
5357
log.G(ctx).WithField("namespace", ns).WithError(err).Error("cleanup working directory in namespace")
5458
continue
5559
}
5660
}
5761
return nil
5862
}
5963

60-
func (m *ShimManager) loadShims(ctx context.Context) error {
64+
func (m *ShimManager) loadShims(ctx context.Context, stateDir string) error {
6165
ns, err := namespaces.NamespaceRequired(ctx)
6266
if err != nil {
6367
return err
6468
}
6569
ctx = log.WithLogger(ctx, log.G(ctx).WithField("namespace", ns))
6670

67-
shimDirs, err := os.ReadDir(filepath.Join(m.state, ns))
71+
shimDirs, err := os.ReadDir(filepath.Join(stateDir, ns))
6872
if err != nil {
6973
return err
7074
}
@@ -77,7 +81,7 @@ func (m *ShimManager) loadShims(ctx context.Context) error {
7781
if len(id) > 0 && id[0] == '.' {
7882
continue
7983
}
80-
bundle, err := LoadBundle(ctx, m.state, id)
84+
bundle, err := LoadBundle(ctx, stateDir, id)
8185
if err != nil {
8286
// fine to return error here, it is a programmer error if the context
8387
// does not have a namespace
@@ -102,78 +106,87 @@ func (m *ShimManager) loadShims(ctx context.Context) error {
102106
bundle.Delete()
103107
continue
104108
}
109+
if err := m.loadShim(ctx, bundle); err != nil {
110+
log.G(ctx).WithError(err).Errorf("failed to load shim %s", bundle.Path)
111+
bundle.Delete()
112+
continue
113+
}
105114

106-
var (
107-
runtime string
108-
)
115+
}
116+
return nil
117+
}
109118

110-
// If we're on 1.6+ and specified custom path to the runtime binary, path will be saved in 'shim-binary-path' file.
111-
if data, err := os.ReadFile(filepath.Join(bundle.Path, "shim-binary-path")); err == nil {
112-
runtime = string(data)
113-
} else if err != nil && !os.IsNotExist(err) {
114-
log.G(ctx).WithError(err).Error("failed to read `runtime` path from bundle")
115-
}
119+
func (m *ShimManager) loadShim(ctx context.Context, bundle *Bundle) error {
120+
var (
121+
runtime string
122+
id = bundle.ID
123+
)
124+
125+
// If we're on 1.6+ and specified custom path to the runtime binary, path will be saved in 'shim-binary-path' file.
126+
if data, err := os.ReadFile(filepath.Join(bundle.Path, "shim-binary-path")); err == nil {
127+
runtime = string(data)
128+
} else if err != nil && !os.IsNotExist(err) {
129+
log.G(ctx).WithError(err).Error("failed to read `runtime` path from bundle")
130+
}
116131

117-
// Query runtime name from metadata store
118-
if runtime == "" {
119-
container, err := m.containers.Get(ctx, id)
120-
if err != nil {
121-
log.G(ctx).WithError(err).Errorf("loading container %s", id)
122-
if err := mount.UnmountRecursive(filepath.Join(bundle.Path, "rootfs"), 0); err != nil {
123-
log.G(ctx).WithError(err).Errorf("failed to unmount of rootfs %s", id)
124-
}
125-
bundle.Delete()
126-
continue
132+
// Query runtime name from metadata store
133+
if runtime == "" {
134+
container, err := m.containers.Get(ctx, id)
135+
if err != nil {
136+
log.G(ctx).WithError(err).Errorf("loading container %s", id)
137+
if err := mount.UnmountRecursive(filepath.Join(bundle.Path, "rootfs"), 0); err != nil {
138+
log.G(ctx).WithError(err).Errorf("failed to unmount of rootfs %s", id)
127139
}
128-
runtime = container.Runtime.Name
140+
return err
129141
}
142+
runtime = container.Runtime.Name
143+
}
130144

131-
runtime, err = m.resolveRuntimePath(runtime)
132-
if err != nil {
133-
bundle.Delete()
134-
log.G(ctx).WithError(err).Error("failed to resolve runtime path")
135-
continue
136-
}
145+
runtime, err := m.resolveRuntimePath(runtime)
146+
if err != nil {
147+
bundle.Delete()
148+
149+
return fmt.Errorf("failed to resolve runtime path: %w", err)
150+
}
137151

138-
binaryCall := shimBinary(bundle,
139-
shimBinaryConfig{
140-
runtime: runtime,
141-
address: m.containerdAddress,
142-
ttrpcAddress: m.containerdTTRPCAddress,
143-
schedCore: m.schedCore,
144-
})
145-
shim, err := loadShimTask(ctx, bundle, func() {
146-
log.G(ctx).WithField("id", id).Info("shim disconnected")
147-
148-
cleanupAfterDeadShim(cleanup.Background(ctx), id, m.shims, m.events, binaryCall)
149-
// Remove self from the runtime task list.
150-
m.shims.Delete(ctx, id)
152+
binaryCall := shimBinary(bundle,
153+
shimBinaryConfig{
154+
runtime: runtime,
155+
address: m.containerdAddress,
156+
ttrpcAddress: m.containerdTTRPCAddress,
157+
schedCore: m.schedCore,
151158
})
152-
if err != nil {
153-
log.G(ctx).WithError(err).Errorf("unable to load shim %q", id)
154-
cleanupAfterDeadShim(ctx, id, m.shims, m.events, binaryCall)
155-
continue
156-
}
159+
// TODO: It seems we can only call loadShim here if it is a sandbox shim?
160+
shim, err := loadShimTask(ctx, bundle, func() {
161+
log.G(ctx).WithField("id", id).Info("shim disconnected")
162+
163+
cleanupAfterDeadShim(cleanup.Background(ctx), id, m.shims, m.events, binaryCall)
164+
// Remove self from the runtime task list.
165+
m.shims.Delete(ctx, id)
166+
})
167+
if err != nil {
168+
cleanupAfterDeadShim(ctx, id, m.shims, m.events, binaryCall)
169+
return fmt.Errorf("unable to load shim %q: %w", id, err)
170+
}
157171

158-
// There are 3 possibilities for the loaded shim here:
159-
// 1. It could be a shim that is running a task.
160-
// 2. It could be a sandbox shim.
161-
// 3. Or it could be a shim that was created for running a task but
162-
// something happened (probably a containerd crash) and the task was never
163-
// created. This shim process should be cleaned up here. Look at
164-
// containerd/containerd#6860 for further details.
165-
166-
_, sgetErr := m.sandboxStore.Get(ctx, id)
167-
pInfo, pidErr := shim.Pids(ctx)
168-
if sgetErr != nil && errors.Is(sgetErr, errdefs.ErrNotFound) && (len(pInfo) == 0 || errors.Is(pidErr, errdefs.ErrNotFound)) {
169-
log.G(ctx).WithField("id", id).Info("cleaning leaked shim process")
170-
// We are unable to get Pids from the shim and it's not a sandbox
171-
// shim. We should clean it up her.
172-
// No need to do anything for removeTask since we never added this shim.
173-
shim.delete(ctx, false, func(ctx context.Context, id string) {})
174-
} else {
175-
m.shims.Add(ctx, shim.ShimInstance)
176-
}
172+
// There are 3 possibilities for the loaded shim here:
173+
// 1. It could be a shim that is running a task.
174+
// 2. It could be a sandbox shim.
175+
// 3. Or it could be a shim that was created for running a task but
176+
// something happened (probably a containerd crash) and the task was never
177+
// created. This shim process should be cleaned up here. Look at
178+
// containerd/containerd#6860 for further details.
179+
180+
_, sgetErr := m.sandboxStore.Get(ctx, id)
181+
pInfo, pidErr := shim.Pids(ctx)
182+
if sgetErr != nil && errors.Is(sgetErr, errdefs.ErrNotFound) && (len(pInfo) == 0 || errors.Is(pidErr, errdefs.ErrNotFound)) {
183+
log.G(ctx).WithField("id", id).Info("cleaning leaked shim process")
184+
// We are unable to get Pids from the shim and it's not a sandbox
185+
// shim. We should clean it up her.
186+
// No need to do anything for removeTask since we never added this shim.
187+
shim.delete(ctx, false, func(ctx context.Context, id string) {})
188+
} else {
189+
m.shims.Add(ctx, shim.ShimInstance)
177190
}
178191
return nil
179192
}
@@ -198,13 +211,13 @@ func loadShimTask(ctx context.Context, bundle *Bundle, onClose func()) (_ *shimT
198211
return s, nil
199212
}
200213

201-
func (m *ShimManager) cleanupWorkDirs(ctx context.Context) error {
214+
func (m *ShimManager) cleanupWorkDirs(ctx context.Context, rootDir string) error {
202215
ns, err := namespaces.NamespaceRequired(ctx)
203216
if err != nil {
204217
return err
205218
}
206219

207-
f, err := os.Open(filepath.Join(m.root, ns))
220+
f, err := os.Open(filepath.Join(rootDir, ns))
208221
if err != nil {
209222
return err
210223
}
@@ -220,7 +233,7 @@ func (m *ShimManager) cleanupWorkDirs(ctx context.Context) error {
220233
// this can happen on a reboot where /run for the bundle state is cleaned up
221234
// but that persistent working dir is left
222235
if _, err := m.shims.Get(ctx, dir); err != nil {
223-
path := filepath.Join(m.root, ns, dir)
236+
path := filepath.Join(rootDir, ns, dir)
224237
if err := os.RemoveAll(path); err != nil {
225238
log.G(ctx).WithError(err).Errorf("cleanup working dir %s", path)
226239
}

0 commit comments

Comments
 (0)