Split image config from CRI plugin
Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
parent
d23ac1122e
commit
02a9a456e1
@ -44,7 +44,7 @@ func FuzzCRIServer(data []byte) int {
|
|||||||
|
|
||||||
config := criconfig.Config{}
|
config := criconfig.Config{}
|
||||||
|
|
||||||
imageService, err := images.NewService(config, map[string]string{}, client)
|
imageService, err := images.NewService(config.ImageConfig, map[string]string{}, map[string]images.RuntimePlatform{}, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -478,17 +478,17 @@ func initLocalCRIPlugin(client *containerd.Client, tmpDir string, registryCfg cr
|
|||||||
|
|
||||||
cfg := criconfig.Config{
|
cfg := criconfig.Config{
|
||||||
PluginConfig: criconfig.PluginConfig{
|
PluginConfig: criconfig.PluginConfig{
|
||||||
ContainerdConfig: criconfig.ContainerdConfig{
|
ImageConfig: criconfig.ImageConfig{
|
||||||
Snapshotter: containerd.DefaultSnapshotter,
|
Snapshotter: containerd.DefaultSnapshotter,
|
||||||
|
Registry: registryCfg,
|
||||||
|
ImagePullProgressTimeout: defaultImagePullProgressTimeout.String(),
|
||||||
|
StatsCollectPeriod: 10,
|
||||||
},
|
},
|
||||||
Registry: registryCfg,
|
|
||||||
ImagePullProgressTimeout: defaultImagePullProgressTimeout.String(),
|
|
||||||
StatsCollectPeriod: 10,
|
|
||||||
},
|
},
|
||||||
ContainerdRootDir: containerdRootDir,
|
ContainerdRootDir: containerdRootDir,
|
||||||
RootDir: filepath.Join(criWorkDir, "root"),
|
RootDir: filepath.Join(criWorkDir, "root"),
|
||||||
StateDir: filepath.Join(criWorkDir, "state"),
|
StateDir: filepath.Join(criWorkDir, "state"),
|
||||||
}
|
}
|
||||||
|
|
||||||
return images.NewService(cfg, map[string]string{}, client)
|
return images.NewService(cfg.ImageConfig, map[string]string{}, map[string]images.RuntimePlatform{}, client)
|
||||||
}
|
}
|
||||||
|
@ -116,8 +116,6 @@ type Runtime struct {
|
|||||||
|
|
||||||
// ContainerdConfig contains toml config related to containerd
|
// ContainerdConfig contains toml config related to containerd
|
||||||
type ContainerdConfig struct {
|
type ContainerdConfig struct {
|
||||||
// Snapshotter is the snapshotter used by containerd.
|
|
||||||
Snapshotter string `toml:"snapshotter" json:"snapshotter"`
|
|
||||||
// DefaultRuntimeName is the default runtime name to use from the runtimes table.
|
// DefaultRuntimeName is the default runtime name to use from the runtimes table.
|
||||||
DefaultRuntimeName string `toml:"default_runtime_name" json:"defaultRuntimeName"`
|
DefaultRuntimeName string `toml:"default_runtime_name" json:"defaultRuntimeName"`
|
||||||
|
|
||||||
@ -125,16 +123,6 @@ type ContainerdConfig struct {
|
|||||||
// configurations, to the matching configurations.
|
// configurations, to the matching configurations.
|
||||||
Runtimes map[string]Runtime `toml:"runtimes" json:"runtimes"`
|
Runtimes map[string]Runtime `toml:"runtimes" json:"runtimes"`
|
||||||
|
|
||||||
// DisableSnapshotAnnotations disables to pass additional annotations (image
|
|
||||||
// related information) to snapshotters. These annotations are required by
|
|
||||||
// stargz snapshotter (https://github.com/containerd/stargz-snapshotter).
|
|
||||||
DisableSnapshotAnnotations bool `toml:"disable_snapshot_annotations" json:"disableSnapshotAnnotations"`
|
|
||||||
|
|
||||||
// DiscardUnpackedLayers is a boolean flag to specify whether to allow GC to
|
|
||||||
// remove layers from the content store after successfully unpacking these
|
|
||||||
// layers to the snapshotter.
|
|
||||||
DiscardUnpackedLayers bool `toml:"discard_unpacked_layers" json:"discardUnpackedLayers"`
|
|
||||||
|
|
||||||
// IgnoreBlockIONotEnabledErrors is a boolean flag to ignore
|
// IgnoreBlockIONotEnabledErrors is a boolean flag to ignore
|
||||||
// blockio related errors when blockio support has not been
|
// blockio related errors when blockio support has not been
|
||||||
// enabled.
|
// enabled.
|
||||||
@ -249,17 +237,57 @@ type ImageDecryption struct {
|
|||||||
KeyModel string `toml:"key_model" json:"keyModel"`
|
KeyModel string `toml:"key_model" json:"keyModel"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ImageConfig struct {
|
||||||
|
// Snapshotter is the snapshotter used by containerd.
|
||||||
|
Snapshotter string `toml:"snapshotter" json:"snapshotter"`
|
||||||
|
|
||||||
|
// DisableSnapshotAnnotations disables to pass additional annotations (image
|
||||||
|
// related information) to snapshotters. These annotations are required by
|
||||||
|
// stargz snapshotter (https://github.com/containerd/stargz-snapshotter).
|
||||||
|
DisableSnapshotAnnotations bool `toml:"disable_snapshot_annotations" json:"disableSnapshotAnnotations"`
|
||||||
|
|
||||||
|
// DiscardUnpackedLayers is a boolean flag to specify whether to allow GC to
|
||||||
|
// remove layers from the content store after successfully unpacking these
|
||||||
|
// layers to the snapshotter.
|
||||||
|
DiscardUnpackedLayers bool `toml:"discard_unpacked_layers" json:"discardUnpackedLayers"`
|
||||||
|
|
||||||
|
// Registry contains config related to the registry
|
||||||
|
Registry Registry `toml:"registry" json:"registry"`
|
||||||
|
|
||||||
|
// ImageDecryption contains config related to handling decryption of encrypted container images
|
||||||
|
ImageDecryption `toml:"image_decryption" json:"imageDecryption"`
|
||||||
|
|
||||||
|
// MaxConcurrentDownloads restricts the number of concurrent downloads for each image.
|
||||||
|
// TODO: Migrate to transfer service
|
||||||
|
MaxConcurrentDownloads int `toml:"max_concurrent_downloads" json:"maxConcurrentDownloads"`
|
||||||
|
|
||||||
|
// ImagePullProgressTimeout is the maximum duration that there is no
|
||||||
|
// image data read from image registry in the open connection. It will
|
||||||
|
// be reset whatever a new byte has been read. If timeout, the image
|
||||||
|
// pulling will be cancelled. A zero value means there is no timeout.
|
||||||
|
//
|
||||||
|
// The string is in the golang duration format, see:
|
||||||
|
// https://golang.org/pkg/time/#ParseDuration
|
||||||
|
ImagePullProgressTimeout string `toml:"image_pull_progress_timeout" json:"imagePullProgressTimeout"`
|
||||||
|
|
||||||
|
// ImagePullWithSyncFs is an experimental setting. It's to force sync
|
||||||
|
// filesystem during unpacking to ensure that data integrity.
|
||||||
|
// TODO: Migrate to transfer service
|
||||||
|
ImagePullWithSyncFs bool `toml:"image_pull_with_sync_fs" json:"imagePullWithSyncFs"`
|
||||||
|
|
||||||
|
// StatsCollectPeriod is the period (in seconds) of snapshots stats collection.
|
||||||
|
StatsCollectPeriod int `toml:"stats_collect_period" json:"statsCollectPeriod"`
|
||||||
|
}
|
||||||
|
|
||||||
// PluginConfig contains toml config related to CRI plugin,
|
// PluginConfig contains toml config related to CRI plugin,
|
||||||
// it is a subset of Config.
|
// it is a subset of Config.
|
||||||
type PluginConfig struct {
|
type PluginConfig struct {
|
||||||
|
// ImageConfig is the image service configuration
|
||||||
|
ImageConfig
|
||||||
// ContainerdConfig contains config related to containerd
|
// ContainerdConfig contains config related to containerd
|
||||||
ContainerdConfig `toml:"containerd" json:"containerd"`
|
ContainerdConfig `toml:"containerd" json:"containerd"`
|
||||||
// CniConfig contains config related to cni
|
// CniConfig contains config related to cni
|
||||||
CniConfig `toml:"cni" json:"cni"`
|
CniConfig `toml:"cni" json:"cni"`
|
||||||
// Registry contains config related to the registry
|
|
||||||
Registry Registry `toml:"registry" json:"registry"`
|
|
||||||
// ImageDecryption contains config related to handling decryption of encrypted container images
|
|
||||||
ImageDecryption `toml:"image_decryption" json:"imageDecryption"`
|
|
||||||
// DisableTCPService disables serving CRI on the TCP server.
|
// DisableTCPService disables serving CRI on the TCP server.
|
||||||
DisableTCPService bool `toml:"disable_tcp_service" json:"disableTCPService"`
|
DisableTCPService bool `toml:"disable_tcp_service" json:"disableTCPService"`
|
||||||
// StreamServerAddress is the ip address streaming server is listening on.
|
// StreamServerAddress is the ip address streaming server is listening on.
|
||||||
@ -278,8 +306,6 @@ type PluginConfig struct {
|
|||||||
SelinuxCategoryRange int `toml:"selinux_category_range" json:"selinuxCategoryRange"`
|
SelinuxCategoryRange int `toml:"selinux_category_range" json:"selinuxCategoryRange"`
|
||||||
// SandboxImage is the image used by sandbox container.
|
// SandboxImage is the image used by sandbox container.
|
||||||
SandboxImage string `toml:"sandbox_image" json:"sandboxImage"`
|
SandboxImage string `toml:"sandbox_image" json:"sandboxImage"`
|
||||||
// StatsCollectPeriod is the period (in seconds) of snapshots stats collection.
|
|
||||||
StatsCollectPeriod int `toml:"stats_collect_period" json:"statsCollectPeriod"`
|
|
||||||
// EnableTLSStreaming indicates to enable the TLS streaming support.
|
// EnableTLSStreaming indicates to enable the TLS streaming support.
|
||||||
EnableTLSStreaming bool `toml:"enable_tls_streaming" json:"enableTLSStreaming"`
|
EnableTLSStreaming bool `toml:"enable_tls_streaming" json:"enableTLSStreaming"`
|
||||||
// X509KeyPairStreaming is a x509 key pair used for TLS streaming
|
// X509KeyPairStreaming is a x509 key pair used for TLS streaming
|
||||||
@ -298,8 +324,6 @@ type PluginConfig struct {
|
|||||||
// current OOMScoreADj.
|
// current OOMScoreADj.
|
||||||
// This is useful when the containerd does not have permission to decrease OOMScoreAdj.
|
// This is useful when the containerd does not have permission to decrease OOMScoreAdj.
|
||||||
RestrictOOMScoreAdj bool `toml:"restrict_oom_score_adj" json:"restrictOOMScoreAdj"`
|
RestrictOOMScoreAdj bool `toml:"restrict_oom_score_adj" json:"restrictOOMScoreAdj"`
|
||||||
// MaxConcurrentDownloads restricts the number of concurrent downloads for each image.
|
|
||||||
MaxConcurrentDownloads int `toml:"max_concurrent_downloads" json:"maxConcurrentDownloads"`
|
|
||||||
// DisableProcMount disables Kubernetes ProcMount support. This MUST be set to `true`
|
// DisableProcMount disables Kubernetes ProcMount support. This MUST be set to `true`
|
||||||
// when using containerd with Kubernetes <=1.11.
|
// when using containerd with Kubernetes <=1.11.
|
||||||
DisableProcMount bool `toml:"disable_proc_mount" json:"disableProcMount"`
|
DisableProcMount bool `toml:"disable_proc_mount" json:"disableProcMount"`
|
||||||
@ -345,14 +369,7 @@ type PluginConfig struct {
|
|||||||
// For more details about CDI configuration please refer to
|
// For more details about CDI configuration please refer to
|
||||||
// https://github.com/container-orchestrated-devices/container-device-interface#containerd-configuration
|
// https://github.com/container-orchestrated-devices/container-device-interface#containerd-configuration
|
||||||
CDISpecDirs []string `toml:"cdi_spec_dirs" json:"cdiSpecDirs"`
|
CDISpecDirs []string `toml:"cdi_spec_dirs" json:"cdiSpecDirs"`
|
||||||
// ImagePullProgressTimeout is the maximum duration that there is no
|
|
||||||
// image data read from image registry in the open connection. It will
|
|
||||||
// be reset whatever a new byte has been read. If timeout, the image
|
|
||||||
// pulling will be cancelled. A zero value means there is no timeout.
|
|
||||||
//
|
|
||||||
// The string is in the golang duration format, see:
|
|
||||||
// https://golang.org/pkg/time/#ParseDuration
|
|
||||||
ImagePullProgressTimeout string `toml:"image_pull_progress_timeout" json:"imagePullProgressTimeout"`
|
|
||||||
// DrainExecSyncIOTimeout is the maximum duration to wait for ExecSync
|
// DrainExecSyncIOTimeout is the maximum duration to wait for ExecSync
|
||||||
// API' IO EOF event after exec init process exits. A zero value means
|
// API' IO EOF event after exec init process exits. A zero value means
|
||||||
// there is no timeout.
|
// there is no timeout.
|
||||||
@ -362,9 +379,6 @@ type PluginConfig struct {
|
|||||||
//
|
//
|
||||||
// For example, the value can be '5h', '2h30m', '10s'.
|
// For example, the value can be '5h', '2h30m', '10s'.
|
||||||
DrainExecSyncIOTimeout string `toml:"drain_exec_sync_io_timeout" json:"drainExecSyncIOTimeout"`
|
DrainExecSyncIOTimeout string `toml:"drain_exec_sync_io_timeout" json:"drainExecSyncIOTimeout"`
|
||||||
// ImagePullWithSyncFs is an experimental setting. It's to force sync
|
|
||||||
// filesystem during unpacking to ensure that data integrity.
|
|
||||||
ImagePullWithSyncFs bool `toml:"image_pull_with_sync_fs" json:"imagePullWithSyncFs"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// X509KeyPairStreaming contains the x509 configuration for streaming
|
// X509KeyPairStreaming contains the x509 configuration for streaming
|
||||||
|
@ -54,9 +54,11 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
RuntimeDefault: {},
|
RuntimeDefault: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Registry: Registry{
|
ImageConfig: ImageConfig{
|
||||||
Auths: map[string]AuthConfig{
|
Registry: Registry{
|
||||||
"https://gcr.io": {Username: "test"},
|
Auths: map[string]AuthConfig{
|
||||||
|
"https://gcr.io": {Username: "test"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -69,16 +71,18 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Registry: Registry{
|
ImageConfig: ImageConfig{
|
||||||
Configs: map[string]RegistryConfig{
|
Registry: Registry{
|
||||||
"gcr.io": {
|
Configs: map[string]RegistryConfig{
|
||||||
Auth: &AuthConfig{
|
"gcr.io": {
|
||||||
Username: "test",
|
Auth: &AuthConfig{
|
||||||
|
Username: "test",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
Auths: map[string]AuthConfig{
|
||||||
Auths: map[string]AuthConfig{
|
"https://gcr.io": {Username: "test"},
|
||||||
"https://gcr.io": {Username: "test"},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -108,10 +112,12 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Registry: Registry{
|
ImageConfig: ImageConfig{
|
||||||
ConfigPath: "/etc/containerd/conf.d",
|
Registry: Registry{
|
||||||
Mirrors: map[string]Mirror{
|
ConfigPath: "/etc/containerd/conf.d",
|
||||||
"something.io": {},
|
Mirrors: map[string]Mirror{
|
||||||
|
"something.io": {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -125,9 +131,11 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
RuntimeDefault: {},
|
RuntimeDefault: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Registry: Registry{
|
ImageConfig: ImageConfig{
|
||||||
Mirrors: map[string]Mirror{
|
Registry: Registry{
|
||||||
"example.com": {},
|
Mirrors: map[string]Mirror{
|
||||||
|
"example.com": {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -140,9 +148,11 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Registry: Registry{
|
ImageConfig: ImageConfig{
|
||||||
Mirrors: map[string]Mirror{
|
Registry: Registry{
|
||||||
"example.com": {},
|
Mirrors: map[string]Mirror{
|
||||||
|
"example.com": {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -156,11 +166,13 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
RuntimeDefault: {},
|
RuntimeDefault: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Registry: Registry{
|
ImageConfig: ImageConfig{
|
||||||
Configs: map[string]RegistryConfig{
|
Registry: Registry{
|
||||||
"gcr.io": {
|
Configs: map[string]RegistryConfig{
|
||||||
Auth: &AuthConfig{
|
"gcr.io": {
|
||||||
Username: "test",
|
Auth: &AuthConfig{
|
||||||
|
Username: "test",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -175,11 +187,13 @@ func TestValidateConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Registry: Registry{
|
ImageConfig: ImageConfig{
|
||||||
Configs: map[string]RegistryConfig{
|
Registry: Registry{
|
||||||
"gcr.io": {
|
Configs: map[string]RegistryConfig{
|
||||||
Auth: &AuthConfig{
|
"gcr.io": {
|
||||||
Username: "test",
|
Auth: &AuthConfig{
|
||||||
|
Username: "test",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -62,8 +62,18 @@ func DefaultConfig() PluginConfig {
|
|||||||
NetworkPluginSetupSerially: false,
|
NetworkPluginSetupSerially: false,
|
||||||
NetworkPluginConfTemplate: "",
|
NetworkPluginConfTemplate: "",
|
||||||
},
|
},
|
||||||
|
ImageConfig: ImageConfig{
|
||||||
|
Snapshotter: containerd.DefaultSnapshotter,
|
||||||
|
DisableSnapshotAnnotations: true,
|
||||||
|
MaxConcurrentDownloads: 3,
|
||||||
|
ImageDecryption: ImageDecryption{
|
||||||
|
KeyModel: KeyModelNode,
|
||||||
|
},
|
||||||
|
ImagePullProgressTimeout: defaultImagePullProgressTimeoutDuration.String(),
|
||||||
|
ImagePullWithSyncFs: false,
|
||||||
|
StatsCollectPeriod: 10,
|
||||||
|
},
|
||||||
ContainerdConfig: ContainerdConfig{
|
ContainerdConfig: ContainerdConfig{
|
||||||
Snapshotter: containerd.DefaultSnapshotter,
|
|
||||||
DefaultRuntimeName: "runc",
|
DefaultRuntimeName: "runc",
|
||||||
Runtimes: map[string]Runtime{
|
Runtimes: map[string]Runtime{
|
||||||
"runc": {
|
"runc": {
|
||||||
@ -72,7 +82,6 @@ func DefaultConfig() PluginConfig {
|
|||||||
Sandboxer: string(ModePodSandbox),
|
Sandboxer: string(ModePodSandbox),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
DisableSnapshotAnnotations: true,
|
|
||||||
},
|
},
|
||||||
DisableTCPService: true,
|
DisableTCPService: true,
|
||||||
StreamServerAddress: "127.0.0.1",
|
StreamServerAddress: "127.0.0.1",
|
||||||
@ -86,22 +95,15 @@ func DefaultConfig() PluginConfig {
|
|||||||
TLSCertFile: "",
|
TLSCertFile: "",
|
||||||
},
|
},
|
||||||
SandboxImage: "registry.k8s.io/pause:3.9",
|
SandboxImage: "registry.k8s.io/pause:3.9",
|
||||||
StatsCollectPeriod: 10,
|
|
||||||
MaxContainerLogLineSize: 16 * 1024,
|
MaxContainerLogLineSize: 16 * 1024,
|
||||||
MaxConcurrentDownloads: 3,
|
|
||||||
DisableProcMount: false,
|
DisableProcMount: false,
|
||||||
TolerateMissingHugetlbController: true,
|
TolerateMissingHugetlbController: true,
|
||||||
DisableHugetlbController: true,
|
DisableHugetlbController: true,
|
||||||
IgnoreImageDefinedVolumes: false,
|
IgnoreImageDefinedVolumes: false,
|
||||||
ImageDecryption: ImageDecryption{
|
EnableCDI: false,
|
||||||
KeyModel: KeyModelNode,
|
CDISpecDirs: []string{"/etc/cdi", "/var/run/cdi"},
|
||||||
},
|
DrainExecSyncIOTimeout: "0s",
|
||||||
EnableCDI: false,
|
EnableUnprivilegedPorts: true,
|
||||||
CDISpecDirs: []string{"/etc/cdi", "/var/run/cdi"},
|
EnableUnprivilegedICMP: true,
|
||||||
ImagePullProgressTimeout: defaultImagePullProgressTimeoutDuration.String(),
|
|
||||||
DrainExecSyncIOTimeout: "0s",
|
|
||||||
ImagePullWithSyncFs: false,
|
|
||||||
EnableUnprivilegedPorts: true,
|
|
||||||
EnableUnprivilegedICMP: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,16 @@ func DefaultConfig() PluginConfig {
|
|||||||
NetworkPluginSetupSerially: false,
|
NetworkPluginSetupSerially: false,
|
||||||
NetworkPluginConfTemplate: "",
|
NetworkPluginConfTemplate: "",
|
||||||
},
|
},
|
||||||
|
ImageConfig: ImageConfig{
|
||||||
|
Snapshotter: containerd.DefaultSnapshotter,
|
||||||
|
StatsCollectPeriod: 10,
|
||||||
|
MaxConcurrentDownloads: 3,
|
||||||
|
ImageDecryption: ImageDecryption{
|
||||||
|
KeyModel: KeyModelNode,
|
||||||
|
},
|
||||||
|
ImagePullProgressTimeout: defaultImagePullProgressTimeoutDuration.String(),
|
||||||
|
},
|
||||||
ContainerdConfig: ContainerdConfig{
|
ContainerdConfig: ContainerdConfig{
|
||||||
Snapshotter: containerd.DefaultSnapshotter,
|
|
||||||
DefaultRuntimeName: "runhcs-wcow-process",
|
DefaultRuntimeName: "runhcs-wcow-process",
|
||||||
Runtimes: map[string]Runtime{
|
Runtimes: map[string]Runtime{
|
||||||
"runhcs-wcow-process": {
|
"runhcs-wcow-process": {
|
||||||
@ -74,16 +82,10 @@ func DefaultConfig() PluginConfig {
|
|||||||
TLSCertFile: "",
|
TLSCertFile: "",
|
||||||
},
|
},
|
||||||
SandboxImage: "registry.k8s.io/pause:3.9",
|
SandboxImage: "registry.k8s.io/pause:3.9",
|
||||||
StatsCollectPeriod: 10,
|
|
||||||
MaxContainerLogLineSize: 16 * 1024,
|
MaxContainerLogLineSize: 16 * 1024,
|
||||||
MaxConcurrentDownloads: 3,
|
|
||||||
IgnoreImageDefinedVolumes: false,
|
IgnoreImageDefinedVolumes: false,
|
||||||
// TODO(windows): Add platform specific config, so that most common defaults can be shared.
|
// TODO(windows): Add platform specific config, so that most common defaults can be shared.
|
||||||
|
|
||||||
ImageDecryption: ImageDecryption{
|
DrainExecSyncIOTimeout: "0s",
|
||||||
KeyModel: KeyModelNode,
|
|
||||||
},
|
|
||||||
ImagePullProgressTimeout: defaultImagePullProgressTimeoutDuration.String(),
|
|
||||||
DrainExecSyncIOTimeout: "0s",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,8 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Update this logic to use runtime snapshotter
|
// TODO: Update this logic to use runtime snapshotter
|
||||||
if client.SnapshotService(c.ContainerdConfig.Snapshotter) == nil {
|
if client.SnapshotService(c.ImageConfig.Snapshotter) == nil {
|
||||||
return nil, fmt.Errorf("failed to find snapshotter %q", c.ContainerdConfig.Snapshotter)
|
return nil, fmt.Errorf("failed to find snapshotter %q", c.ImageConfig.Snapshotter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dmcgowan): Get the full list directly from configured plugins
|
// TODO(dmcgowan): Get the full list directly from configured plugins
|
||||||
|
@ -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))
|
log.G(ctx).Debugf("Container %q spec: %#+v", id, spew.NewFormatter(spec))
|
||||||
|
|
||||||
// Grab any platform specific snapshotter opts.
|
// Grab any platform specific snapshotter opts.
|
||||||
sOpts, err := snapshotterOpts(c.config.ContainerdConfig.Snapshotter, config)
|
sOpts, err := snapshotterOpts(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -264,7 +264,7 @@ func appArmorProfileExists(profile string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// snapshotterOpts returns any Linux specific snapshotter options for the rootfs snapshot
|
// 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()
|
nsOpts := config.GetLinux().GetSecurityContext().GetNamespaceOptions()
|
||||||
return snapshotterRemapOpts(nsOpts)
|
return snapshotterRemapOpts(nsOpts)
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,6 @@ func (c *criService) containerSpecOpts(config *runtime.ContainerConfig, imageCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// snapshotterOpts returns snapshotter options for the rootfs snapshot
|
// 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
|
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
|
// 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
|
var opts []snapshots.Opt
|
||||||
|
|
||||||
switch snapshotterName {
|
// TODO: Only set for windows and cimfs snapshotter
|
||||||
case "windows", "cimfs":
|
rootfsSize := config.GetWindows().GetResources().GetRootfsSizeInBytes()
|
||||||
rootfsSize := config.GetWindows().GetResources().GetRootfsSizeInBytes()
|
if rootfsSize != 0 {
|
||||||
if rootfsSize != 0 {
|
labels := map[string]string{
|
||||||
labels := map[string]string{
|
"containerd.io/snapshot/windows/rootfs.sizebytes": strconv.FormatInt(rootfsSize, 10),
|
||||||
"containerd.io/snapshot/windows/rootfs.sizebytes": strconv.FormatInt(rootfsSize, 10),
|
|
||||||
}
|
|
||||||
opts = append(opts, snapshots.WithLabels(labels))
|
|
||||||
}
|
}
|
||||||
|
opts = append(opts, snapshots.WithLabels(labels))
|
||||||
}
|
}
|
||||||
|
|
||||||
return opts, nil
|
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) 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) GetImage(id string) (imagestore.Image, error) { return s.imageStore.Get(id) }
|
||||||
|
|
||||||
func (s *fakeImageService) GetSnapshot(key, snapshotter string) (snapshotstore.Snapshot, error) {
|
func (s *fakeImageService) GetSnapshot(key, snapshotter string) (snapshotstore.Snapshot, error) {
|
||||||
|
@ -362,6 +362,7 @@ func (em *eventMonitor) handleEvent(any interface{}) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update container status for TaskOOM event: %w", err)
|
return fmt.Errorf("failed to update container status for TaskOOM event: %w", err)
|
||||||
}
|
}
|
||||||
|
// TODO: ImageService should handle these events directly
|
||||||
case *eventtypes.ImageCreate:
|
case *eventtypes.ImageCreate:
|
||||||
log.L.Infof("ImageCreate event %+v", e)
|
log.L.Infof("ImageCreate event %+v", e)
|
||||||
return em.c.UpdateImage(ctx, e.Name)
|
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
|
// Temporarily removed for v2 upgrade
|
||||||
//pullOpts = append(pullOpts, c.encryptedImagesPullOpts()...)
|
//pullOpts = append(pullOpts, c.encryptedImagesPullOpts()...)
|
||||||
if !c.config.ContainerdConfig.DisableSnapshotAnnotations {
|
if !c.config.DisableSnapshotAnnotations {
|
||||||
pullOpts = append(pullOpts,
|
pullOpts = append(pullOpts,
|
||||||
containerd.WithImageHandlerWrapper(snpkg.AppendInfoHandlerWrapper(ref)))
|
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
|
// Allows GC to clean layers up from the content store after unpacking
|
||||||
pullOpts = append(pullOpts,
|
pullOpts = append(pullOpts,
|
||||||
containerd.WithChildLabelMap(containerdimages.ChildGCLabelsFilterLayers))
|
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
|
// getLabels get image labels to be added on CRI image
|
||||||
func (c *CRIImageService) getLabels(ctx context.Context, name string) map[string]string {
|
func (c *CRIImageService) getLabels(ctx context.Context, name string) map[string]string {
|
||||||
labels := map[string]string{crilabels.ImageLabelKey: crilabels.ImageLabelValue}
|
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
|
// parse sandbox image
|
||||||
sandboxNamedRef, err := distribution.ParseDockerRef(configSandboxImage)
|
sandboxNamedRef, err := distribution.ParseDockerRef(configSandboxImage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -756,7 +757,7 @@ func (rt *pullRequestReporterRoundTripper) RoundTrip(req *http.Request) (*http.R
|
|||||||
// See https://github.com/containerd/containerd/issues/6657
|
// See https://github.com/containerd/containerd/issues/6657
|
||||||
func (c *CRIImageService) snapshotterFromPodSandboxConfig(ctx context.Context, imageRef string,
|
func (c *CRIImageService) snapshotterFromPodSandboxConfig(ctx context.Context, imageRef string,
|
||||||
s *runtime.PodSandboxConfig) (string, error) {
|
s *runtime.PodSandboxConfig) (string, error) {
|
||||||
snapshotter := c.config.ContainerdConfig.Snapshotter
|
snapshotter := c.config.Snapshotter
|
||||||
if s == nil || s.Annotations == nil {
|
if s == nil || s.Annotations == nil {
|
||||||
return snapshotter, nil
|
return snapshotter, nil
|
||||||
}
|
}
|
||||||
@ -766,13 +767,10 @@ func (c *CRIImageService) snapshotterFromPodSandboxConfig(ctx context.Context, i
|
|||||||
return snapshotter, nil
|
return snapshotter, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Find other way to retrieve sandbox runtime, this must belong to the Runtime part of the CRI.
|
if p, ok := c.runtimePlatforms[runtimeHandler]; ok && p.Snapshotter != snapshotter {
|
||||||
ociRuntime, err := c.config.GetSandboxRuntime(s, runtimeHandler)
|
snapshotter = p.Snapshotter
|
||||||
if err != nil {
|
log.G(ctx).Infof("experimental: PullImage %q for runtime %s, using snapshotter %s", imageRef, runtimeHandler, snapshotter)
|
||||||
return "", fmt.Errorf("experimental: failed to get sandbox runtime for %s: %w", runtimeHandler, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshotter = c.RuntimeSnapshotter(ctx, ociRuntime)
|
|
||||||
log.G(ctx).Infof("experimental: PullImage %q for runtime %s, using snapshotter %s", imageRef, runtimeHandler, snapshotter)
|
|
||||||
return snapshotter, nil
|
return snapshotter, nil
|
||||||
}
|
}
|
||||||
|
@ -425,11 +425,13 @@ func TestSnapshotterFromPodSandboxConfig(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.desc, func(t *testing.T) {
|
t.Run(tt.desc, func(t *testing.T) {
|
||||||
cri, _ := newTestCRIService()
|
cri, _ := newTestCRIService()
|
||||||
cri.config.ContainerdConfig.Snapshotter = defaultSnashotter
|
cri.config.Snapshotter = defaultSnashotter
|
||||||
cri.config.ContainerdConfig.Runtimes = make(map[string]criconfig.Runtime)
|
/*
|
||||||
cri.config.ContainerdConfig.Runtimes["exiting-runtime"] = criconfig.Runtime{
|
cri.config.ContainerdConfig.Runtimes = make(map[string]criconfig.Runtime)
|
||||||
Snapshotter: runtimeSnapshotter,
|
cri.config.ContainerdConfig.Runtimes["exiting-runtime"] = criconfig.Runtime{
|
||||||
}
|
Snapshotter: runtimeSnapshotter,
|
||||||
|
}
|
||||||
|
*/
|
||||||
snapshotter, err := cri.snapshotterFromPodSandboxConfig(context.Background(), "test-image", tt.podSandboxConfig)
|
snapshotter, err := cri.snapshotterFromPodSandboxConfig(context.Background(), "test-image", tt.podSandboxConfig)
|
||||||
assert.Equal(t, tt.expectSnapshotter, snapshotter)
|
assert.Equal(t, tt.expectSnapshotter, snapshotter)
|
||||||
if tt.expectErr {
|
if tt.expectErr {
|
||||||
@ -531,7 +533,8 @@ func TestImageGetLabels(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
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)
|
labels := criService.getLabels(context.Background(), tt.pullImageName)
|
||||||
assert.Equal(t, tt.expectedLabel, labels)
|
assert.Equal(t, tt.expectedLabel, labels)
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ import (
|
|||||||
"github.com/containerd/containerd/v2/pkg/cri/server/base"
|
"github.com/containerd/containerd/v2/pkg/cri/server/base"
|
||||||
imagestore "github.com/containerd/containerd/v2/pkg/cri/store/image"
|
imagestore "github.com/containerd/containerd/v2/pkg/cri/store/image"
|
||||||
snapshotstore "github.com/containerd/containerd/v2/pkg/cri/store/snapshot"
|
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/pkg/kmutex"
|
||||||
"github.com/containerd/containerd/v2/platforms"
|
"github.com/containerd/containerd/v2/platforms"
|
||||||
"github.com/containerd/containerd/v2/plugins"
|
"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)
|
return nil, fmt.Errorf("unable to init client for cri image service: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snapshotterOverrides := map[string]RuntimePlatform{}
|
||||||
imageFSPaths := map[string]string{}
|
imageFSPaths := map[string]string{}
|
||||||
// TODO: Figure out a way to break this plugin's dependency on a shared runtime config
|
// 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.`
|
// Can not use `c.RuntimeSnapshotter() yet, so hard-coding here.`
|
||||||
snapshotter := ociRuntime.Snapshotter
|
snapshotter := ociRuntime.Snapshotter
|
||||||
if 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)
|
imageFSPaths[snapshotter] = filepath.Join(c.ContainerdRootDir, plugins.SnapshotPlugin.String()+"."+snapshotter)
|
||||||
log.L.Infof("Get image filesystem path %q for snapshotter %q", imageFSPaths[snapshotter], 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)
|
imageFSPaths[snapshotter] = filepath.Join(c.ContainerdRootDir, plugins.SnapshotPlugin.String()+"."+snapshotter)
|
||||||
log.L.Infof("Get image filesystem path %q for snapshotter %q", imageFSPaths[snapshotter], snapshotter)
|
log.L.Infof("Get image filesystem path %q for snapshotter %q", imageFSPaths[snapshotter], snapshotter)
|
||||||
|
|
||||||
// TODO: Pull out image specific configs here!
|
// TODO: Pull out image specific configs here!
|
||||||
service, err := NewService(c, imageFSPaths, client)
|
service, err := NewService(c.ImageConfig, imageFSPaths, snapshotterOverrides, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create image service: %w", err)
|
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 {
|
type CRIImageService struct {
|
||||||
// config contains all configurations.
|
// config contains all configurations.
|
||||||
// TODO: Migrate configs from cri type once moved to its own plugin
|
// 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)
|
// - image decryption (moved to transfer service)
|
||||||
// - default runtime
|
// - default runtime
|
||||||
// - stats collection interval (only used to startup snapshot sync)
|
// - stats collection interval (only used to startup snapshot sync)
|
||||||
config criconfig.Config
|
config criconfig.ImageConfig
|
||||||
// client is an instance of the containerd client
|
// client is an instance of the containerd client
|
||||||
// TODO: Remove this in favor of using plugins directly
|
// TODO: Remove this in favor of using plugins directly
|
||||||
client *containerd.Client
|
client *containerd.Client
|
||||||
// imageFSPaths contains path to image filesystem for snapshotters.
|
// imageFSPaths contains path to image filesystem for snapshotters.
|
||||||
imageFSPaths map[string]string
|
imageFSPaths map[string]string
|
||||||
|
// runtimePlatforms are the platforms configured for a runtime.
|
||||||
|
runtimePlatforms map[string]RuntimePlatform
|
||||||
// imageStore stores all resources associated with images.
|
// imageStore stores all resources associated with images.
|
||||||
imageStore *imagestore.Store
|
imageStore *imagestore.Store
|
||||||
// snapshotStore stores information of all snapshots.
|
// snapshotStore stores information of all snapshots.
|
||||||
@ -140,31 +152,29 @@ type GRPCCRIImageService struct {
|
|||||||
// - Image Service (from metadata)
|
// - Image Service (from metadata)
|
||||||
// - Content store (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
|
// 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{
|
svc := CRIImageService{
|
||||||
config: config,
|
config: config,
|
||||||
client: client,
|
client: client,
|
||||||
imageStore: imagestore.NewStore(client.ImageService(), client.ContentStore(), platforms.Default()),
|
imageStore: imagestore.NewStore(client.ImageService(), client.ContentStore(), platforms.Default()),
|
||||||
imageFSPaths: imageFSPaths,
|
imageFSPaths: imageFSPaths,
|
||||||
|
runtimePlatforms: runtimePlatforms,
|
||||||
snapshotStore: snapshotstore.NewStore(),
|
snapshotStore: snapshotstore.NewStore(),
|
||||||
unpackDuplicationSuppressor: kmutex.New(),
|
unpackDuplicationSuppressor: kmutex.New(),
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshotters := map[string]snapshot.Snapshotter{}
|
snapshotters := map[string]snapshot.Snapshotter{}
|
||||||
ctx := ctrdutil.NamespacedContext()
|
|
||||||
|
|
||||||
// Add runtime specific snapshotters
|
for _, rp := range runtimePlatforms {
|
||||||
for _, runtime := range config.ContainerdConfig.Runtimes {
|
if snapshotter := svc.client.SnapshotService(rp.Snapshotter); snapshotter != nil {
|
||||||
snapshotterName := svc.RuntimeSnapshotter(ctx, runtime)
|
snapshotters[rp.Snapshotter] = snapshotter
|
||||||
if snapshotter := svc.client.SnapshotService(snapshotterName); snapshotter != nil {
|
|
||||||
snapshotters[snapshotterName] = snapshotter
|
|
||||||
} else {
|
} 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
|
// Add default snapshotter
|
||||||
snapshotterName := svc.config.ContainerdConfig.Snapshotter
|
snapshotterName := svc.config.Snapshotter
|
||||||
if snapshotter := svc.client.SnapshotService(snapshotterName); snapshotter != nil {
|
if snapshotter := svc.client.SnapshotService(snapshotterName); snapshotter != nil {
|
||||||
snapshotters[snapshotterName] = snapshotter
|
snapshotters[snapshotterName] = snapshotter
|
||||||
} else {
|
} 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.
|
// RuntimeSnapshotter overrides the default snapshotter if Snapshotter is set for this runtime.
|
||||||
// See https://github.com/containerd/containerd/issues/6657
|
// 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 {
|
func (c *CRIImageService) RuntimeSnapshotter(ctx context.Context, ociRuntime criconfig.Runtime) string {
|
||||||
if ociRuntime.Snapshotter == "" {
|
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)
|
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.
|
// newTestCRIService creates a fake criService for test.
|
||||||
func newTestCRIService() (*CRIImageService, *GRPCCRIImageService) {
|
func newTestCRIService() (*CRIImageService, *GRPCCRIImageService) {
|
||||||
service := &CRIImageService{
|
service := &CRIImageService{
|
||||||
config: testConfig,
|
config: testConfig.ImageConfig,
|
||||||
imageFSPaths: map[string]string{"overlayfs": testImageFSPath},
|
imageFSPaths: map[string]string{"overlayfs": testImageFSPath},
|
||||||
imageStore: imagestore.NewStore(nil, nil, platforms.Default()),
|
imageStore: imagestore.NewStore(nil, nil, platforms.Default()),
|
||||||
snapshotStore: snapshotstore.NewStore(),
|
snapshotStore: snapshotstore.NewStore(),
|
||||||
@ -125,9 +125,7 @@ func TestRuntimeSnapshotter(t *testing.T) {
|
|||||||
test := test
|
test := test
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
cri, _ := newTestCRIService()
|
cri, _ := newTestCRIService()
|
||||||
cri.config = criconfig.Config{
|
cri.config = criconfig.DefaultConfig().ImageConfig
|
||||||
PluginConfig: criconfig.DefaultConfig(),
|
|
||||||
}
|
|
||||||
assert.Equal(t, test.expectSnapshotter, cri.RuntimeSnapshotter(context.Background(), test.runtime))
|
assert.Equal(t, test.expectSnapshotter, cri.RuntimeSnapshotter(context.Background(), test.runtime))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,7 @@ type ImageService interface {
|
|||||||
LocalResolve(refOrID string) (imagestore.Image, error)
|
LocalResolve(refOrID string) (imagestore.Image, error)
|
||||||
GetImage(id 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)
|
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 {
|
type Controller struct {
|
||||||
|
@ -33,7 +33,6 @@ import (
|
|||||||
"github.com/containerd/containerd/v2/containers"
|
"github.com/containerd/containerd/v2/containers"
|
||||||
clabels "github.com/containerd/containerd/v2/labels"
|
clabels "github.com/containerd/containerd/v2/labels"
|
||||||
"github.com/containerd/containerd/v2/oci"
|
"github.com/containerd/containerd/v2/oci"
|
||||||
criconfig "github.com/containerd/containerd/v2/pkg/cri/config"
|
|
||||||
crilabels "github.com/containerd/containerd/v2/pkg/cri/labels"
|
crilabels "github.com/containerd/containerd/v2/pkg/cri/labels"
|
||||||
imagestore "github.com/containerd/containerd/v2/pkg/cri/store/image"
|
imagestore "github.com/containerd/containerd/v2/pkg/cri/store/image"
|
||||||
sandboxstore "github.com/containerd/containerd/v2/pkg/cri/store/sandbox"
|
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
|
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) {
|
func getMetadata(ctx context.Context, container containerd.Container) (*sandboxstore.Metadata, error) {
|
||||||
// Load sandbox metadata.
|
// Load sandbox metadata.
|
||||||
exts, err := container.Extensions(ctx)
|
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...)
|
snapshotterOpt = append(snapshotterOpt, extraSOpts...)
|
||||||
|
|
||||||
opts := []containerd.NewContainerOpts{
|
opts := []containerd.NewContainerOpts{
|
||||||
containerd.WithSnapshotter(c.runtimeSnapshotter(ctx, ociRuntime)),
|
containerd.WithSnapshotter(c.imageService.RuntimeSnapshotter(ctx, ociRuntime)),
|
||||||
customopts.WithNewSnapshot(id, containerdImage, snapshotterOpt...),
|
customopts.WithNewSnapshot(id, containerdImage, snapshotterOpt...),
|
||||||
containerd.WithSpec(spec, specOpts...),
|
containerd.WithSpec(spec, specOpts...),
|
||||||
containerd.WithContainerLabels(sandboxLabels),
|
containerd.WithContainerLabels(sandboxLabels),
|
||||||
|
@ -21,18 +21,15 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
containerdio "github.com/containerd/containerd/v2/cio"
|
containerdio "github.com/containerd/containerd/v2/cio"
|
||||||
containerd "github.com/containerd/containerd/v2/client"
|
containerd "github.com/containerd/containerd/v2/client"
|
||||||
"github.com/containerd/containerd/v2/errdefs"
|
"github.com/containerd/containerd/v2/errdefs"
|
||||||
containerdimages "github.com/containerd/containerd/v2/images"
|
|
||||||
criconfig "github.com/containerd/containerd/v2/pkg/cri/config"
|
criconfig "github.com/containerd/containerd/v2/pkg/cri/config"
|
||||||
crilabels "github.com/containerd/containerd/v2/pkg/cri/labels"
|
crilabels "github.com/containerd/containerd/v2/pkg/cri/labels"
|
||||||
"github.com/containerd/containerd/v2/pkg/cri/server/podsandbox"
|
"github.com/containerd/containerd/v2/pkg/cri/server/podsandbox"
|
||||||
"github.com/containerd/containerd/v2/pkg/netns"
|
"github.com/containerd/containerd/v2/pkg/netns"
|
||||||
"github.com/containerd/containerd/v2/platforms"
|
|
||||||
"github.com/containerd/log"
|
"github.com/containerd/log"
|
||||||
"github.com/containerd/typeurl/v2"
|
"github.com/containerd/typeurl/v2"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
@ -201,11 +198,9 @@ func (c *criService) recover(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Recover all images.
|
// Recover all images.
|
||||||
cImages, err := c.client.ListImages(ctx)
|
if err := c.ImageService.CheckImages(ctx); err != nil {
|
||||||
if err != nil {
|
return fmt.Errorf("failed to check images: %w", err)
|
||||||
return fmt.Errorf("failed to list images: %w", err)
|
|
||||||
}
|
}
|
||||||
c.loadImages(ctx, cImages)
|
|
||||||
|
|
||||||
// It's possible that containerd containers are deleted unexpectedly. In that case,
|
// 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
|
// 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)
|
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 {
|
func cleanupOrphanedIDDirs(ctx context.Context, cntrs []containerd.Container, base string) error {
|
||||||
// Cleanup orphaned id directories.
|
// Cleanup orphaned id directories.
|
||||||
dirs, err := os.ReadDir(base)
|
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)
|
PullImage(ctx context.Context, name string, credentials func(string) (string, string, error), sandboxConfig *runtime.PodSandboxConfig) (string, error)
|
||||||
UpdateImage(ctx context.Context, r string) error
|
UpdateImage(ctx context.Context, r string) error
|
||||||
|
|
||||||
|
CheckImages(ctx context.Context) error
|
||||||
|
|
||||||
GetImage(id string) (imagestore.Image, error)
|
GetImage(id string) (imagestore.Image, error)
|
||||||
GetSnapshot(key, snapshotter string) (snapshotstore.Snapshot, error)
|
GetSnapshot(key, snapshotter string) (snapshotstore.Snapshot, error)
|
||||||
|
|
||||||
LocalResolve(refOrID string) (imagestore.Image, error)
|
LocalResolve(refOrID string) (imagestore.Image, error)
|
||||||
|
|
||||||
ImageFSPaths() map[string]string
|
ImageFSPaths() map[string]string
|
||||||
|
|
||||||
//ImageFsInfo(context.Context, *ImageFsInfoRequest) (*ImageFsInfoResponse, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// criService implements CRIService.
|
// criService implements CRIService.
|
||||||
|
@ -33,8 +33,10 @@ var testConfig = criconfig.Config{
|
|||||||
PluginConfig: criconfig.PluginConfig{
|
PluginConfig: criconfig.PluginConfig{
|
||||||
SandboxImage: testSandboxImage,
|
SandboxImage: testSandboxImage,
|
||||||
TolerateMissingHugetlbController: true,
|
TolerateMissingHugetlbController: true,
|
||||||
|
ImageConfig: criconfig.ImageConfig{
|
||||||
|
Snapshotter: "overlayfs",
|
||||||
|
},
|
||||||
ContainerdConfig: criconfig.ContainerdConfig{
|
ContainerdConfig: criconfig.ContainerdConfig{
|
||||||
Snapshotter: "overlayfs",
|
|
||||||
DefaultRuntimeName: "runc",
|
DefaultRuntimeName: "runc",
|
||||||
Runtimes: map[string]criconfig.Runtime{
|
Runtimes: map[string]criconfig.Runtime{
|
||||||
"runc": {
|
"runc": {
|
||||||
|
Loading…
Reference in New Issue
Block a user