Split image config from CRI plugin
Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
@@ -208,7 +208,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
||||
log.G(ctx).Debugf("Container %q spec: %#+v", id, spew.NewFormatter(spec))
|
||||
|
||||
// Grab any platform specific snapshotter opts.
|
||||
sOpts, err := snapshotterOpts(c.config.ContainerdConfig.Snapshotter, config)
|
||||
sOpts, err := snapshotterOpts(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ func appArmorProfileExists(profile string) (bool, error) {
|
||||
}
|
||||
|
||||
// snapshotterOpts returns any Linux specific snapshotter options for the rootfs snapshot
|
||||
func snapshotterOpts(snapshotterName string, config *runtime.ContainerConfig) ([]snapshots.Opt, error) {
|
||||
func snapshotterOpts(config *runtime.ContainerConfig) ([]snapshots.Opt, error) {
|
||||
nsOpts := config.GetLinux().GetSecurityContext().GetNamespaceOptions()
|
||||
return snapshotterRemapOpts(nsOpts)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,6 @@ func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageCon
|
||||
}
|
||||
|
||||
// snapshotterOpts returns snapshotter options for the rootfs snapshot
|
||||
func snapshotterOpts(snapshotterName string, config *runtime.ContainerConfig) ([]snapshots.Opt, error) {
|
||||
func snapshotterOpts(config *runtime.ContainerConfig) ([]snapshots.Opt, error) {
|
||||
return []snapshots.Opt{}, nil
|
||||
}
|
||||
|
||||
@@ -32,18 +32,16 @@ func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageCon
|
||||
}
|
||||
|
||||
// snapshotterOpts returns any Windows specific snapshotter options for the r/w layer
|
||||
func snapshotterOpts(snapshotterName string, config *runtime.ContainerConfig) ([]snapshots.Opt, error) {
|
||||
func snapshotterOpts(config *runtime.ContainerConfig) ([]snapshots.Opt, error) {
|
||||
var opts []snapshots.Opt
|
||||
|
||||
switch snapshotterName {
|
||||
case "windows", "cimfs":
|
||||
rootfsSize := config.GetWindows().GetResources().GetRootfsSizeInBytes()
|
||||
if rootfsSize != 0 {
|
||||
labels := map[string]string{
|
||||
"containerd.io/snapshot/windows/rootfs.sizebytes": strconv.FormatInt(rootfsSize, 10),
|
||||
}
|
||||
opts = append(opts, snapshots.WithLabels(labels))
|
||||
// TODO: Only set for windows and cimfs snapshotter
|
||||
rootfsSize := config.GetWindows().GetResources().GetRootfsSizeInBytes()
|
||||
if rootfsSize != 0 {
|
||||
labels := map[string]string{
|
||||
"containerd.io/snapshot/windows/rootfs.sizebytes": strconv.FormatInt(rootfsSize, 10),
|
||||
}
|
||||
opts = append(opts, snapshots.WithLabels(labels))
|
||||
}
|
||||
|
||||
return opts, nil
|
||||
|
||||
@@ -275,6 +275,8 @@ func (s *fakeImageService) RuntimeSnapshotter(ctx context.Context, ociRuntime cr
|
||||
|
||||
func (s *fakeImageService) UpdateImage(ctx context.Context, r string) error { return nil }
|
||||
|
||||
func (s *fakeImageService) CheckImages(ctx context.Context) error { return nil }
|
||||
|
||||
func (s *fakeImageService) GetImage(id string) (imagestore.Image, error) { return s.imageStore.Get(id) }
|
||||
|
||||
func (s *fakeImageService) GetSnapshot(key, snapshotter string) (snapshotstore.Snapshot, error) {
|
||||
|
||||
@@ -362,6 +362,7 @@ func (em *eventMonitor) handleEvent(any interface{}) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update container status for TaskOOM event: %w", err)
|
||||
}
|
||||
// TODO: ImageService should handle these events directly
|
||||
case *eventtypes.ImageCreate:
|
||||
log.L.Infof("ImageCreate event %+v", e)
|
||||
return em.c.UpdateImage(ctx, e.Name)
|
||||
|
||||
77
pkg/cri/server/images/check.go
Normal file
77
pkg/cri/server/images/check.go
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
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 images
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/v2/images"
|
||||
"github.com/containerd/containerd/v2/platforms"
|
||||
"github.com/containerd/log"
|
||||
)
|
||||
|
||||
// LoadImages checks all existing images to ensure they are ready to
|
||||
// be used for CRI. It may try to recover images which are not ready
|
||||
// but will only log errors, not return any.
|
||||
func (c *CRIImageService) CheckImages(ctx context.Context) error {
|
||||
// TODO: Move way from `client.ListImages` to directly using image store
|
||||
cImages, err := c.client.ListImages(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list images: %w", err)
|
||||
}
|
||||
|
||||
// TODO: Support all snapshotter
|
||||
snapshotter := c.config.Snapshotter
|
||||
var wg sync.WaitGroup
|
||||
for _, i := range cImages {
|
||||
wg.Add(1)
|
||||
i := i
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
// TODO: Check platform/snapshot combination. Snapshot check should come first
|
||||
ok, _, _, _, err := images.Check(ctx, i.ContentStore(), i.Target(), platforms.Default())
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("Failed to check image content readiness for %q", i.Name())
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
log.G(ctx).Warnf("The image content readiness for %q is not ok", i.Name())
|
||||
return
|
||||
}
|
||||
// Checking existence of top-level snapshot for each image being recovered.
|
||||
// TODO: This logic should be done elsewhere and owned by the image service
|
||||
unpacked, err := i.IsUnpacked(ctx, snapshotter)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("Failed to check whether image is unpacked for image %s", i.Name())
|
||||
return
|
||||
}
|
||||
if !unpacked {
|
||||
log.G(ctx).Warnf("The image %s is not unpacked.", i.Name())
|
||||
// TODO(random-liu): Consider whether we should try unpack here.
|
||||
}
|
||||
if err := c.UpdateImage(ctx, i.Name()); err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("Failed to update reference for image %q", i.Name())
|
||||
return
|
||||
}
|
||||
log.G(ctx).Debugf("Loaded image %q", i.Name())
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
@@ -194,12 +194,12 @@ func (c *CRIImageService) PullImage(ctx context.Context, name string, credential
|
||||
|
||||
// Temporarily removed for v2 upgrade
|
||||
//pullOpts = append(pullOpts, c.encryptedImagesPullOpts()...)
|
||||
if !c.config.ContainerdConfig.DisableSnapshotAnnotations {
|
||||
if !c.config.DisableSnapshotAnnotations {
|
||||
pullOpts = append(pullOpts,
|
||||
containerd.WithImageHandlerWrapper(snpkg.AppendInfoHandlerWrapper(ref)))
|
||||
}
|
||||
|
||||
if c.config.ContainerdConfig.DiscardUnpackedLayers {
|
||||
if c.config.DiscardUnpackedLayers {
|
||||
// Allows GC to clean layers up from the content store after unpacking
|
||||
pullOpts = append(pullOpts,
|
||||
containerd.WithChildLabelMap(containerdimages.ChildGCLabelsFilterLayers))
|
||||
@@ -333,7 +333,8 @@ func (c *CRIImageService) createImageReference(ctx context.Context, name string,
|
||||
// getLabels get image labels to be added on CRI image
|
||||
func (c *CRIImageService) getLabels(ctx context.Context, name string) map[string]string {
|
||||
labels := map[string]string{crilabels.ImageLabelKey: crilabels.ImageLabelValue}
|
||||
configSandboxImage := c.config.SandboxImage
|
||||
// TODO: Separate config here to generalize pinned image list
|
||||
configSandboxImage := "" //c.config.SandboxImage
|
||||
// parse sandbox image
|
||||
sandboxNamedRef, err := distribution.ParseDockerRef(configSandboxImage)
|
||||
if err != nil {
|
||||
@@ -756,7 +757,7 @@ func (rt *pullRequestReporterRoundTripper) RoundTrip(req *http.Request) (*http.R
|
||||
// See https://github.com/containerd/containerd/issues/6657
|
||||
func (c *CRIImageService) snapshotterFromPodSandboxConfig(ctx context.Context, imageRef string,
|
||||
s *runtime.PodSandboxConfig) (string, error) {
|
||||
snapshotter := c.config.ContainerdConfig.Snapshotter
|
||||
snapshotter := c.config.Snapshotter
|
||||
if s == nil || s.Annotations == nil {
|
||||
return snapshotter, nil
|
||||
}
|
||||
@@ -766,13 +767,10 @@ func (c *CRIImageService) snapshotterFromPodSandboxConfig(ctx context.Context, i
|
||||
return snapshotter, nil
|
||||
}
|
||||
|
||||
// TODO: Find other way to retrieve sandbox runtime, this must belong to the Runtime part of the CRI.
|
||||
ociRuntime, err := c.config.GetSandboxRuntime(s, runtimeHandler)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("experimental: failed to get sandbox runtime for %s: %w", runtimeHandler, err)
|
||||
if p, ok := c.runtimePlatforms[runtimeHandler]; ok && p.Snapshotter != snapshotter {
|
||||
snapshotter = p.Snapshotter
|
||||
log.G(ctx).Infof("experimental: PullImage %q for runtime %s, using snapshotter %s", imageRef, runtimeHandler, snapshotter)
|
||||
}
|
||||
|
||||
snapshotter = c.RuntimeSnapshotter(ctx, ociRuntime)
|
||||
log.G(ctx).Infof("experimental: PullImage %q for runtime %s, using snapshotter %s", imageRef, runtimeHandler, snapshotter)
|
||||
return snapshotter, nil
|
||||
}
|
||||
|
||||
@@ -425,11 +425,13 @@ func TestSnapshotterFromPodSandboxConfig(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
cri, _ := newTestCRIService()
|
||||
cri.config.ContainerdConfig.Snapshotter = defaultSnashotter
|
||||
cri.config.ContainerdConfig.Runtimes = make(map[string]criconfig.Runtime)
|
||||
cri.config.ContainerdConfig.Runtimes["exiting-runtime"] = criconfig.Runtime{
|
||||
Snapshotter: runtimeSnapshotter,
|
||||
}
|
||||
cri.config.Snapshotter = defaultSnashotter
|
||||
/*
|
||||
cri.config.ContainerdConfig.Runtimes = make(map[string]criconfig.Runtime)
|
||||
cri.config.ContainerdConfig.Runtimes["exiting-runtime"] = criconfig.Runtime{
|
||||
Snapshotter: runtimeSnapshotter,
|
||||
}
|
||||
*/
|
||||
snapshotter, err := cri.snapshotterFromPodSandboxConfig(context.Background(), "test-image", tt.podSandboxConfig)
|
||||
assert.Equal(t, tt.expectSnapshotter, snapshotter)
|
||||
if tt.expectErr {
|
||||
@@ -531,7 +533,8 @@ func TestImageGetLabels(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
criService.config.SandboxImage = tt.configSandboxImage
|
||||
// Change this config name
|
||||
//criService.config.SandboxImage = tt.configSandboxImage
|
||||
labels := criService.getLabels(context.Background(), tt.pullImageName)
|
||||
assert.Equal(t, tt.expectedLabel, labels)
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"github.com/containerd/containerd/v2/pkg/cri/server/base"
|
||||
imagestore "github.com/containerd/containerd/v2/pkg/cri/store/image"
|
||||
snapshotstore "github.com/containerd/containerd/v2/pkg/cri/store/snapshot"
|
||||
ctrdutil "github.com/containerd/containerd/v2/pkg/cri/util"
|
||||
"github.com/containerd/containerd/v2/pkg/kmutex"
|
||||
"github.com/containerd/containerd/v2/platforms"
|
||||
"github.com/containerd/containerd/v2/plugins"
|
||||
@@ -71,22 +70,28 @@ func init() {
|
||||
return nil, fmt.Errorf("unable to init client for cri image service: %w", err)
|
||||
}
|
||||
|
||||
snapshotterOverrides := map[string]RuntimePlatform{}
|
||||
imageFSPaths := map[string]string{}
|
||||
// TODO: Figure out a way to break this plugin's dependency on a shared runtime config
|
||||
for _, ociRuntime := range c.ContainerdConfig.Runtimes {
|
||||
for runtimeName, ociRuntime := range c.ContainerdConfig.Runtimes {
|
||||
// Can not use `c.RuntimeSnapshotter() yet, so hard-coding here.`
|
||||
snapshotter := ociRuntime.Snapshotter
|
||||
if snapshotter != "" {
|
||||
snapshotterOverrides[runtimeName] = RuntimePlatform{
|
||||
Snapshotter: snapshotter,
|
||||
// TODO: This must be provided by runtime
|
||||
Platform: platforms.DefaultSpec(),
|
||||
}
|
||||
imageFSPaths[snapshotter] = filepath.Join(c.ContainerdRootDir, plugins.SnapshotPlugin.String()+"."+snapshotter)
|
||||
log.L.Infof("Get image filesystem path %q for snapshotter %q", imageFSPaths[snapshotter], snapshotter)
|
||||
}
|
||||
}
|
||||
snapshotter := c.ContainerdConfig.Snapshotter
|
||||
snapshotter := c.ImageConfig.Snapshotter
|
||||
imageFSPaths[snapshotter] = filepath.Join(c.ContainerdRootDir, plugins.SnapshotPlugin.String()+"."+snapshotter)
|
||||
log.L.Infof("Get image filesystem path %q for snapshotter %q", imageFSPaths[snapshotter], snapshotter)
|
||||
|
||||
// TODO: Pull out image specific configs here!
|
||||
service, err := NewService(c, imageFSPaths, client)
|
||||
service, err := NewService(c.ImageConfig, imageFSPaths, snapshotterOverrides, client)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create image service: %w", err)
|
||||
}
|
||||
@@ -96,6 +101,11 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
type RuntimePlatform struct {
|
||||
Snapshotter string
|
||||
Platform platforms.Platform
|
||||
}
|
||||
|
||||
type CRIImageService struct {
|
||||
// config contains all configurations.
|
||||
// TODO: Migrate configs from cri type once moved to its own plugin
|
||||
@@ -110,12 +120,14 @@ type CRIImageService struct {
|
||||
// - image decryption (moved to transfer service)
|
||||
// - default runtime
|
||||
// - stats collection interval (only used to startup snapshot sync)
|
||||
config criconfig.Config
|
||||
config criconfig.ImageConfig
|
||||
// client is an instance of the containerd client
|
||||
// TODO: Remove this in favor of using plugins directly
|
||||
client *containerd.Client
|
||||
// imageFSPaths contains path to image filesystem for snapshotters.
|
||||
imageFSPaths map[string]string
|
||||
// runtimePlatforms are the platforms configured for a runtime.
|
||||
runtimePlatforms map[string]RuntimePlatform
|
||||
// imageStore stores all resources associated with images.
|
||||
imageStore *imagestore.Store
|
||||
// snapshotStore stores information of all snapshots.
|
||||
@@ -140,31 +152,29 @@ type GRPCCRIImageService struct {
|
||||
// - Image Service (from metadata)
|
||||
// - Content store (from metadata)
|
||||
// 3. Separate image cache and snapshot cache to first class plugins, make the snapshot cache much more efficient and intelligent
|
||||
func NewService(config criconfig.Config, imageFSPaths map[string]string, client *containerd.Client) (*CRIImageService, error) {
|
||||
func NewService(config criconfig.ImageConfig, imageFSPaths map[string]string, runtimePlatforms map[string]RuntimePlatform, client *containerd.Client) (*CRIImageService, error) {
|
||||
svc := CRIImageService{
|
||||
config: config,
|
||||
client: client,
|
||||
imageStore: imagestore.NewStore(client.ImageService(), client.ContentStore(), platforms.Default()),
|
||||
imageFSPaths: imageFSPaths,
|
||||
runtimePlatforms: runtimePlatforms,
|
||||
snapshotStore: snapshotstore.NewStore(),
|
||||
unpackDuplicationSuppressor: kmutex.New(),
|
||||
}
|
||||
|
||||
snapshotters := map[string]snapshot.Snapshotter{}
|
||||
ctx := ctrdutil.NamespacedContext()
|
||||
|
||||
// Add runtime specific snapshotters
|
||||
for _, runtime := range config.ContainerdConfig.Runtimes {
|
||||
snapshotterName := svc.RuntimeSnapshotter(ctx, runtime)
|
||||
if snapshotter := svc.client.SnapshotService(snapshotterName); snapshotter != nil {
|
||||
snapshotters[snapshotterName] = snapshotter
|
||||
for _, rp := range runtimePlatforms {
|
||||
if snapshotter := svc.client.SnapshotService(rp.Snapshotter); snapshotter != nil {
|
||||
snapshotters[rp.Snapshotter] = snapshotter
|
||||
} else {
|
||||
return nil, fmt.Errorf("failed to find snapshotter %q", snapshotterName)
|
||||
return nil, fmt.Errorf("failed to find snapshotter %q", rp.Snapshotter)
|
||||
}
|
||||
}
|
||||
|
||||
// Add default snapshotter
|
||||
snapshotterName := svc.config.ContainerdConfig.Snapshotter
|
||||
snapshotterName := svc.config.Snapshotter
|
||||
if snapshotter := svc.client.SnapshotService(snapshotterName); snapshotter != nil {
|
||||
snapshotters[snapshotterName] = snapshotter
|
||||
} else {
|
||||
@@ -220,9 +230,10 @@ func (c *CRIImageService) LocalResolve(refOrID string) (imagestore.Image, error)
|
||||
|
||||
// RuntimeSnapshotter overrides the default snapshotter if Snapshotter is set for this runtime.
|
||||
// See https://github.com/containerd/containerd/issues/6657
|
||||
// TODO: Pass in name and get back runtime platform
|
||||
func (c *CRIImageService) RuntimeSnapshotter(ctx context.Context, ociRuntime criconfig.Runtime) string {
|
||||
if ociRuntime.Snapshotter == "" {
|
||||
return c.config.ContainerdConfig.Snapshotter
|
||||
return c.config.Snapshotter
|
||||
}
|
||||
|
||||
log.G(ctx).Debugf("Set snapshotter for runtime %s to %s", ociRuntime.Type, ociRuntime.Snapshotter)
|
||||
|
||||
@@ -41,7 +41,7 @@ const (
|
||||
// newTestCRIService creates a fake criService for test.
|
||||
func newTestCRIService() (*CRIImageService, *GRPCCRIImageService) {
|
||||
service := &CRIImageService{
|
||||
config: testConfig,
|
||||
config: testConfig.ImageConfig,
|
||||
imageFSPaths: map[string]string{"overlayfs": testImageFSPath},
|
||||
imageStore: imagestore.NewStore(nil, nil, platforms.Default()),
|
||||
snapshotStore: snapshotstore.NewStore(),
|
||||
@@ -125,9 +125,7 @@ func TestRuntimeSnapshotter(t *testing.T) {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
cri, _ := newTestCRIService()
|
||||
cri.config = criconfig.Config{
|
||||
PluginConfig: criconfig.DefaultConfig(),
|
||||
}
|
||||
cri.config = criconfig.DefaultConfig().ImageConfig
|
||||
assert.Equal(t, test.expectSnapshotter, cri.RuntimeSnapshotter(context.Background(), test.runtime))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ type ImageService interface {
|
||||
LocalResolve(refOrID string) (imagestore.Image, error)
|
||||
GetImage(id string) (imagestore.Image, error)
|
||||
PullImage(ctx context.Context, name string, creds func(string) (string, string, error), sc *runtime.PodSandboxConfig) (string, error)
|
||||
RuntimeSnapshotter(ctx context.Context, ociRuntime criconfig.Runtime) string
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
|
||||
@@ -33,7 +33,6 @@ import (
|
||||
"github.com/containerd/containerd/v2/containers"
|
||||
clabels "github.com/containerd/containerd/v2/labels"
|
||||
"github.com/containerd/containerd/v2/oci"
|
||||
criconfig "github.com/containerd/containerd/v2/pkg/cri/config"
|
||||
crilabels "github.com/containerd/containerd/v2/pkg/cri/labels"
|
||||
imagestore "github.com/containerd/containerd/v2/pkg/cri/store/image"
|
||||
sandboxstore "github.com/containerd/containerd/v2/pkg/cri/store/sandbox"
|
||||
@@ -188,17 +187,6 @@ func (c *Controller) runtimeSpec(id string, baseSpecFile string, opts ...oci.Spe
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
// Overrides the default snapshotter if Snapshotter is set for this runtime.
|
||||
// See https://github.com/containerd/containerd/issues/6657
|
||||
func (c *Controller) runtimeSnapshotter(ctx context.Context, ociRuntime criconfig.Runtime) string {
|
||||
if ociRuntime.Snapshotter == "" {
|
||||
return c.config.ContainerdConfig.Snapshotter
|
||||
}
|
||||
|
||||
log.G(ctx).Debugf("Set snapshotter for runtime %s to %s", ociRuntime.Type, ociRuntime.Snapshotter)
|
||||
return ociRuntime.Snapshotter
|
||||
}
|
||||
|
||||
func getMetadata(ctx context.Context, container containerd.Container) (*sandboxstore.Metadata, error) {
|
||||
// Load sandbox metadata.
|
||||
exts, err := container.Extensions(ctx)
|
||||
|
||||
@@ -138,7 +138,7 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll
|
||||
snapshotterOpt = append(snapshotterOpt, extraSOpts...)
|
||||
|
||||
opts := []containerd.NewContainerOpts{
|
||||
containerd.WithSnapshotter(c.runtimeSnapshotter(ctx, ociRuntime)),
|
||||
containerd.WithSnapshotter(c.imageService.RuntimeSnapshotter(ctx, ociRuntime)),
|
||||
customopts.WithNewSnapshot(id, containerdImage, snapshotterOpt...),
|
||||
containerd.WithSpec(spec, specOpts...),
|
||||
containerd.WithContainerLabels(sandboxLabels),
|
||||
|
||||
@@ -21,18 +21,15 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
containerdio "github.com/containerd/containerd/v2/cio"
|
||||
containerd "github.com/containerd/containerd/v2/client"
|
||||
"github.com/containerd/containerd/v2/errdefs"
|
||||
containerdimages "github.com/containerd/containerd/v2/images"
|
||||
criconfig "github.com/containerd/containerd/v2/pkg/cri/config"
|
||||
crilabels "github.com/containerd/containerd/v2/pkg/cri/labels"
|
||||
"github.com/containerd/containerd/v2/pkg/cri/server/podsandbox"
|
||||
"github.com/containerd/containerd/v2/pkg/netns"
|
||||
"github.com/containerd/containerd/v2/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/typeurl/v2"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -201,11 +198,9 @@ func (c *criService) recover(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Recover all images.
|
||||
cImages, err := c.client.ListImages(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list images: %w", err)
|
||||
if err := c.ImageService.CheckImages(ctx); err != nil {
|
||||
return fmt.Errorf("failed to check images: %w", err)
|
||||
}
|
||||
c.loadImages(ctx, cImages)
|
||||
|
||||
// It's possible that containerd containers are deleted unexpectedly. In that case,
|
||||
// we can't even get metadata, we should cleanup orphaned sandbox/container directories
|
||||
@@ -444,44 +439,6 @@ func getNetNS(meta *sandboxstore.Metadata) *netns.NetNS {
|
||||
return netns.LoadNetNS(meta.NetNSPath)
|
||||
}
|
||||
|
||||
// loadImages loads images from containerd.
|
||||
func (c *criService) loadImages(ctx context.Context, cImages []containerd.Image) {
|
||||
snapshotter := c.config.ContainerdConfig.Snapshotter
|
||||
var wg sync.WaitGroup
|
||||
for _, i := range cImages {
|
||||
wg.Add(1)
|
||||
i := i
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ok, _, _, _, err := containerdimages.Check(ctx, i.ContentStore(), i.Target(), platforms.Default())
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Errorf("Failed to check image content readiness for %q", i.Name())
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
log.G(ctx).Warnf("The image content readiness for %q is not ok", i.Name())
|
||||
return
|
||||
}
|
||||
// Checking existence of top-level snapshot for each image being recovered.
|
||||
unpacked, err := i.IsUnpacked(ctx, snapshotter)
|
||||
if err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("Failed to check whether image is unpacked for image %s", i.Name())
|
||||
return
|
||||
}
|
||||
if !unpacked {
|
||||
log.G(ctx).Warnf("The image %s is not unpacked.", i.Name())
|
||||
// TODO(random-liu): Consider whether we should try unpack here.
|
||||
}
|
||||
if err := c.UpdateImage(ctx, i.Name()); err != nil {
|
||||
log.G(ctx).WithError(err).Warnf("Failed to update reference for image %q", i.Name())
|
||||
return
|
||||
}
|
||||
log.G(ctx).Debugf("Loaded image %q", i.Name())
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func cleanupOrphanedIDDirs(ctx context.Context, cntrs []containerd.Container, base string) error {
|
||||
// Cleanup orphaned id directories.
|
||||
dirs, err := os.ReadDir(base)
|
||||
|
||||
@@ -70,14 +70,14 @@ type ImageService interface {
|
||||
PullImage(ctx context.Context, name string, credentials func(string) (string, string, error), sandboxConfig *runtime.PodSandboxConfig) (string, error)
|
||||
UpdateImage(ctx context.Context, r string) error
|
||||
|
||||
CheckImages(ctx context.Context) error
|
||||
|
||||
GetImage(id string) (imagestore.Image, error)
|
||||
GetSnapshot(key, snapshotter string) (snapshotstore.Snapshot, error)
|
||||
|
||||
LocalResolve(refOrID string) (imagestore.Image, error)
|
||||
|
||||
ImageFSPaths() map[string]string
|
||||
|
||||
//ImageFsInfo(context.Context, *ImageFsInfoRequest) (*ImageFsInfoResponse, error)
|
||||
}
|
||||
|
||||
// criService implements CRIService.
|
||||
|
||||
@@ -33,8 +33,10 @@ var testConfig = criconfig.Config{
|
||||
PluginConfig: criconfig.PluginConfig{
|
||||
SandboxImage: testSandboxImage,
|
||||
TolerateMissingHugetlbController: true,
|
||||
ImageConfig: criconfig.ImageConfig{
|
||||
Snapshotter: "overlayfs",
|
||||
},
|
||||
ContainerdConfig: criconfig.ContainerdConfig{
|
||||
Snapshotter: "overlayfs",
|
||||
DefaultRuntimeName: "runc",
|
||||
Runtimes: map[string]criconfig.Runtime{
|
||||
"runc": {
|
||||
|
||||
Reference in New Issue
Block a user