Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 26 additions & 23 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ GO ?= go
INSTALL ?= install

# Root directory of the project (absolute path).
ROOTDIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
ROOTDIR := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))

# Base path used to install.
# The files will be installed under `$(DESTDIR)/$(PREFIX)`.
Expand Down Expand Up @@ -88,7 +88,7 @@ COMMANDS=ctr containerd containerd-stress
MANPAGES=ctr.8 containerd.8 containerd-config.8 containerd-config.toml.5

ifdef BUILDTAGS
GO_BUILDTAGS = ${BUILDTAGS}
GO_BUILDTAGS = ${BUILDTAGS}
endif
GO_BUILDTAGS ?=
GO_BUILDTAGS += urfave_cli_no_docs
Expand All @@ -111,25 +111,26 @@ GO_LDFLAGS+='
SHIM_GO_LDFLAGS=-ldflags '-X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) -X $(PKG)/version.Package=$(PACKAGE) -extldflags "-static" $(EXTRA_LDFLAGS)'

# Project packages.
PACKAGES=$(shell $(GO) list ${GO_TAGS} ./... | grep -v /vendor/ | grep -v /integration)
API_PACKAGES=$(shell (cd api && $(GO) list ${GO_TAGS} ./... | grep -v /vendor/ | grep -v /integration))
TEST_REQUIRES_ROOT_PACKAGES=$(filter \
${PACKAGES}, \
$(shell \
for f in $$(git grep -l testutil.RequiresRoot | grep -v Makefile); do \
d="$$(dirname $$f)"; \
[ "$$d" = "." ] && echo "${PKG}" && continue; \
echo "${PKG}/$$d"; \
done | sort -u) \
)
PACKAGES := $(shell $(GO) list ${GO_TAGS} ./... | grep -v /integration)
API_PACKAGES := $(shell $(GO) -C api list ${GO_TAGS} ./...)

TEST_REQUIRES_ROOT_PACKAGES := $(filter \
${PACKAGES}, \
$(shell \
for f in $$(git grep -l testutil.RequiresRoot | grep -v Makefile); do \
d="$$(dirname $$f)"; \
[ "$$d" = "." ] && echo "${PKG}" && continue; \
echo "${PKG}/$$d"; \
done | sort -u) \
)

ifdef SKIPTESTS
PACKAGES:=$(filter-out ${SKIPTESTS},${PACKAGES})
TEST_REQUIRES_ROOT_PACKAGES:=$(filter-out ${SKIPTESTS},${TEST_REQUIRES_ROOT_PACKAGES})
PACKAGES := $(filter-out ${SKIPTESTS},${PACKAGES})
TEST_REQUIRES_ROOT_PACKAGES := $(filter-out ${SKIPTESTS},${TEST_REQUIRES_ROOT_PACKAGES})
endif

#Replaces ":" (*nix), ";" (windows) with newline for easy parsing
GOPATHS=$(shell $(GO) env GOPATH | tr ":" "\n" | tr ";" "\n")
# Replaces ":" (*nix), ";" (windows) with newline for easy parsing
GOPATHS := $(shell $(GO) env GOPATH | tr ":" "\n" | tr ";" "\n")

TESTFLAGS_RACE=
GO_BUILD_FLAGS ?=
Expand Down Expand Up @@ -213,7 +214,9 @@ root-test: ## run tests, except integration tests

integration: ## run integration tests
@echo "$(WHALE) $@"
@cd "${ROOTDIR}/integration/client" && $(GO) mod download && $(GOTEST) -v ${TESTFLAGS} -test.root -parallel ${TESTFLAGS_PARALLEL} .
@$(GO) -C "${ROOTDIR}/integration/client" mod download
@cd "${ROOTDIR}/integration/client" && \
$(GOTEST) -v ${TESTFLAGS} -test.root -parallel ${TESTFLAGS_PARALLEL} .

bin/cri-integration.test:
@echo "$(WHALE) $@"
Expand Down Expand Up @@ -487,16 +490,16 @@ vendor: ## ensure all the go.mod/go.sum files are up-to-date including vendor/ d
@$(GO) mod tidy
@$(GO) mod vendor
@$(GO) mod verify
@(cd ${ROOTDIR}/api && ${GO} mod tidy)
@$(GO) -C ${ROOTDIR}/api mod tidy

verify-vendor: ## verify if all the go.mod/go.sum files are up-to-date
@echo "$(WHALE) $@"
$(eval TMPDIR := $(shell mktemp -d))
@cp -R ${ROOTDIR} ${TMPDIR}
@(cd ${TMPDIR}/containerd && ${GO} mod tidy)
@(cd ${TMPDIR}/containerd && ${GO} mod vendor)
@(cd ${TMPDIR}/containerd && ${GO} mod verify)
@(cd ${TMPDIR}/containerd/api && ${GO} mod tidy)
@$(GO) -C ${TMPDIR}/containerd mod tidy
@$(GO) -C ${TMPDIR}/containerd mod vendor
@$(GO) -C ${TMPDIR}/containerd mod verify
@$(GO) -C ${TMPDIR}/containerd/api mod tidy
@diff -r -u -q ${ROOTDIR} ${TMPDIR}/containerd
@rm -rf ${TMPDIR}

Expand Down
8 changes: 8 additions & 0 deletions internal/cri/server/container_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/stretchr/testify/assert"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"

"github.com/containerd/containerd/v2/internal/cri/server/images"
containerstore "github.com/containerd/containerd/v2/internal/cri/store/container"
imagestore "github.com/containerd/containerd/v2/internal/cri/store/image"
)
Expand Down Expand Up @@ -302,10 +303,17 @@ func (s *fakeImageService) LocalResolve(refOrID string) (imagestore.Image, error

func (s *fakeImageService) ImageFSPaths() map[string]string { return make(map[string]string) }

func (s *fakeImageService) Config() criconfig.ImageConfig {
return criconfig.ImageConfig{}
}

func (s *fakeImageService) PullImage(context.Context, string, func(string) (string, string, error), *runtime.PodSandboxConfig, string) (string, error) {
return "", errors.New("not implemented")
}

func (s *fakeImageService) UpdateRuntimeSnapshotter(runtimeName string, imagePlatform images.ImagePlatform) {
}

func patchExceptedWithState(expected *runtime.ContainerStatus, state runtime.ContainerState) {
expected.State = state
switch state {
Expand Down
21 changes: 14 additions & 7 deletions internal/cri/server/images/image_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,16 +299,23 @@ func (c *CRIImageService) pullImageWithTransferService(
transferProgressReporter := newTransferProgressReporter(ref, rcancel, imagePullProgressTimeout)

// Set image store opts
var sopts []transferimage.StoreOpt
sopts = append(sopts, transferimage.WithPlatforms(platforms.DefaultSpec()))
sopts = append(sopts, transferimage.WithUnpack(platforms.DefaultSpec(), snapshotter))
sopts = append(sopts, transferimage.WithImageLabels(labels))
sopts := []transferimage.StoreOpt{
transferimage.WithPlatforms(platforms.DefaultSpec()),
transferimage.WithUnpack(platforms.DefaultSpec(), snapshotter),
transferimage.WithImageLabels(labels),
}

is := transferimage.NewStore(ref, sopts...)

log.G(ctx).Debugf("Getting new CRI credentials")

ch := newCRICredentials(ref, credentials)
opts := []registry.Opt{registry.WithCredentials(ch)}
opts = append(opts, registry.WithHeaders(c.config.Registry.Headers))
opts = append(opts, registry.WithHostDir(c.config.Registry.ConfigPath))
opts := []registry.Opt{
registry.WithCredentials(ch),
registry.WithHeaders(c.config.Registry.Headers),
registry.WithHostDir(c.config.Registry.ConfigPath),
}

reg, err := registry.NewOCIRegistry(ctx, ref, opts...)
if err != nil {
return nil, fmt.Errorf("failed to create OCI registry: %w", err)
Expand Down
16 changes: 16 additions & 0 deletions internal/cri/server/images/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,22 @@ func NewService(config criconfig.ImageConfig, options *CRIImageServiceOptions) (
return &svc, nil
}

// UpdateRuntimeSnapshotter adds or updates the snapshotter mapping for a runtime.
// This is called by the main CRI plugin after both image and runtime plugins are initialized,
// to propagate runtime-specific snapshotters configured in the runtime plugin's config.
func (c *CRIImageService) UpdateRuntimeSnapshotter(runtimeName string, imagePlatform ImagePlatform) {
if c.runtimePlatforms == nil {
c.runtimePlatforms = make(map[string]ImagePlatform)
}
// Don't override if already configured
if _, exists := c.runtimePlatforms[runtimeName]; exists {
log.L.Debugf("Runtime %q already has snapshotter configured, not overriding", runtimeName)
return
}
c.runtimePlatforms[runtimeName] = imagePlatform
log.L.Infof("Registered runtime %q with snapshotter %q", runtimeName, imagePlatform.Snapshotter)
}

// LocalResolve resolves image reference locally and returns corresponding image metadata. It
// returns errdefs.ErrNotFound if the reference doesn't exist.
func (c *CRIImageService) LocalResolve(refOrID string) (imagestore.Image, error) {
Expand Down
12 changes: 0 additions & 12 deletions internal/cri/server/podsandbox/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/containerd/plugin"
"github.com/containerd/plugin/registry"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"

eventtypes "github.com/containerd/containerd/api/events"
containerd "github.com/containerd/containerd/v2/client"
Expand All @@ -34,7 +33,6 @@ import (
"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"
osinterface "github.com/containerd/containerd/v2/pkg/os"
"github.com/containerd/containerd/v2/pkg/protobuf"
Expand Down Expand Up @@ -90,7 +88,6 @@ func init() {
config: criRuntimePlugin.(interface{ Config() criconfig.Config }).Config(),
imageConfig: criImagePlugin.(interface{ Config() criconfig.ImageConfig }).Config(),
os: osinterface.RealOS{},
imageService: criImagePlugin.(ImageService),
warningService: warningPlugin.(warning.Service),
store: NewStore(),
}
Expand All @@ -109,22 +106,13 @@ func init() {
})
}

// ImageService specifies dependencies to CRI image service.
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, runtimeHandler string) (string, error)
}

type Controller struct {
// config contains all configurations.
config criconfig.Config
// imageConfig contains CRI image configuration.
imageConfig criconfig.ImageConfig
// client is an instance of the containerd client
client *containerd.Client
// imageService is a dependency to CRI image service.
imageService ImageService
// warningService is used to emit deprecation warnings.
warningService warning.Service
// os is an interface for all required os operations.
Expand Down
10 changes: 0 additions & 10 deletions internal/cri/server/podsandbox/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/core/containers"
crilabels "github.com/containerd/containerd/v2/internal/cri/labels"
imagestore "github.com/containerd/containerd/v2/internal/cri/store/image"
sandboxstore "github.com/containerd/containerd/v2/internal/cri/store/sandbox"
ctrdutil "github.com/containerd/containerd/v2/internal/cri/util"
"github.com/containerd/containerd/v2/pkg/oci"
Expand Down Expand Up @@ -73,15 +72,6 @@ func (c *Controller) getVolatileSandboxRootDir(id string) string {
return filepath.Join(c.config.StateDir, sandboxesDir, id)
}

// toContainerdImage converts an image object in image store to containerd image handler.
func (c *Controller) toContainerdImage(ctx context.Context, image imagestore.Image) (containerd.Image, error) {
// image should always have at least one reference.
if len(image.References) == 0 {
return nil, fmt.Errorf("invalid image with no reference %q", image.ID)
}
return c.client.GetImage(ctx, image.References[0])
}

// runtimeSpec returns a default runtime spec used in cri-containerd.
func (c *Controller) runtimeSpec(id string, opts ...oci.SpecOpts) (*runtimespec.Spec, error) {
// GenerateSpec needs namespace.
Expand Down
41 changes: 9 additions & 32 deletions internal/cri/server/podsandbox/sandbox_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"github.com/containerd/typeurl/v2"
"github.com/davecgh/go-spew/spew"
"github.com/opencontainers/selinux/go-selinux"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"

containerd "github.com/containerd/containerd/v2/client"
"github.com/containerd/containerd/v2/core/sandbox"
Expand All @@ -38,7 +37,6 @@ import (
crilabels "github.com/containerd/containerd/v2/internal/cri/labels"
customopts "github.com/containerd/containerd/v2/internal/cri/opts"
"github.com/containerd/containerd/v2/internal/cri/server/podsandbox/types"
imagestore "github.com/containerd/containerd/v2/internal/cri/store/image"
sandboxstore "github.com/containerd/containerd/v2/internal/cri/store/sandbox"
ctrdutil "github.com/containerd/containerd/v2/internal/cri/util"
containerdio "github.com/containerd/containerd/v2/pkg/cio"
Expand Down Expand Up @@ -79,15 +77,16 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll
)

sandboxImage := c.getSandboxImageName()
// Ensure sandbox container image snapshot.
image, err := c.ensureImageExists(ctx, sandboxImage, config, metadata.RuntimeHandler)

pauseImage, err := c.client.GetImage(ctx, sandboxImage)
if err != nil {
return cin, fmt.Errorf("failed to get sandbox image %q: %w", sandboxImage, err)
}

containerdImage, err := c.toContainerdImage(ctx, *image)
// Get the image spec from containerd image
imageSpec, err := pauseImage.Spec(ctx)
if err != nil {
return cin, fmt.Errorf("failed to get image from containerd %q: %w", image.ID, err)
return cin, fmt.Errorf("failed to get image spec: %w", err)
}

ociRuntime, err := c.config.GetSandboxRuntime(config, metadata.RuntimeHandler)
Expand Down Expand Up @@ -135,7 +134,7 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll
// NOTE: sandboxContainerSpec SHOULD NOT have side
// effect, e.g. accessing/creating files, so that we can test
// it safely.
spec, err := c.sandboxContainerSpec(id, config, &image.ImageSpec.Config, metadata.NetNSPath, ociRuntime.PodAnnotations)
spec, err := c.sandboxContainerSpec(id, config, &imageSpec.Config, metadata.NetNSPath, ociRuntime.PodAnnotations)
if err != nil {
return cin, fmt.Errorf("failed to generate sandbox container spec: %w", err)
}
Expand Down Expand Up @@ -174,12 +173,12 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll
}

// Generate spec options that will be applied to the spec later.
specOpts, err := c.sandboxContainerSpecOpts(config, &image.ImageSpec.Config)
specOpts, err := c.sandboxContainerSpecOpts(config, &imageSpec.Config)
if err != nil {
return cin, fmt.Errorf("failed to generate sandbox container spec options: %w", err)
}

sandboxLabels := ctrdutil.BuildLabels(config.Labels, image.ImageSpec.Config.Labels, crilabels.ContainerKindSandbox)
sandboxLabels := ctrdutil.BuildLabels(config.Labels, imageSpec.Config.Labels, crilabels.ContainerKindSandbox)

snapshotterOpt := []snapshots.Opt{snapshots.WithLabels(snapshots.FilterInheritedLabels(config.Annotations))}
extraSOpts, err := sandboxSnapshotterOpts(config)
Expand All @@ -195,7 +194,7 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll

opts := []containerd.NewContainerOpts{
containerd.WithSnapshotter(sandboxSnapshotter),
customopts.WithNewSnapshot(id, containerdImage, snapshotterOpt...),
customopts.WithNewSnapshot(id, pauseImage, snapshotterOpt...),
containerd.WithSpec(spec, specOpts...),
containerd.WithContainerLabels(sandboxLabels),
containerd.WithContainerExtension(crilabels.SandboxMetadataExtension, &metadata),
Expand Down Expand Up @@ -341,28 +340,6 @@ func (c *Controller) Create(_ctx context.Context, info sandbox.Sandbox, opts ...
return c.store.Save(podSandbox)
}

func (c *Controller) ensureImageExists(ctx context.Context, ref string, config *runtime.PodSandboxConfig, runtimeHandler string) (*imagestore.Image, error) {
image, err := c.imageService.LocalResolve(ref)
if err != nil && !errdefs.IsNotFound(err) {
return nil, fmt.Errorf("failed to get image %q: %w", ref, err)
}
if err == nil {
return &image, nil
}
// Pull image to ensure the image exists
// TODO: Cleaner interface
imageID, err := c.imageService.PullImage(ctx, ref, nil, config, runtimeHandler)
if err != nil {
return nil, fmt.Errorf("failed to pull image %q: %w", ref, err)
}
newImage, err := c.imageService.GetImage(imageID)
if err != nil {
// It's still possible that someone removed the image right after it is pulled.
return nil, fmt.Errorf("failed to get image %q after pulling: %w", imageID, err)
}
return &newImage, nil
}

func (c *Controller) getSandboxImageName() string {
// returns the name of the sandbox image used to scope pod shared resources used by the pod's containers,
// if empty return the default sandbox image.
Expand Down
Loading
Loading