diff --git a/pkg/kubelet/apis/config/validation/validation.go b/pkg/kubelet/apis/config/validation/validation.go index 29d74a70e71..6f5197ca92c 100644 --- a/pkg/kubelet/apis/config/validation/validation.go +++ b/pkg/kubelet/apis/config/validation/validation.go @@ -32,7 +32,7 @@ import ( tracingapi "k8s.io/component-base/tracing/api/v1" "k8s.io/kubernetes/pkg/features" kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config" - "k8s.io/kubernetes/pkg/kubelet/images" + imagepullmanager "k8s.io/kubernetes/pkg/kubelet/images/pullmanager" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" utilfs "k8s.io/kubernetes/pkg/util/filesystem" utiltaints "k8s.io/kubernetes/pkg/util/taints" @@ -301,7 +301,7 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration, featur if len(kc.PreloadedImagesVerificationAllowlist) > 0 && kc.ImagePullCredentialsVerificationPolicy != string(kubeletconfig.NeverVerifyAllowlistedImages) { allErrors = append(allErrors, fmt.Errorf("invalid configuration: can't set `preloadedImagesVerificationAllowlist` if `imagePullCredentialsVertificationPolicy` is not \"NeverVerifyAllowlistedImages\"")) - } else if err := images.ValidateAllowlistImagesPatterns(kc.PreloadedImagesVerificationAllowlist); err != nil { + } else if err := imagepullmanager.ValidateAllowlistImagesPatterns(kc.PreloadedImagesVerificationAllowlist); err != nil { allErrors = append(allErrors, fmt.Errorf("invalid configuration: invalid image pattern in `preloadedImagesVerificationAllowlist`: %w", err)) } } else { diff --git a/pkg/kubelet/images/image_manager.go b/pkg/kubelet/images/image_manager.go index 2dd96cd589a..b76f87d19aa 100644 --- a/pkg/kubelet/images/image_manager.go +++ b/pkg/kubelet/images/image_manager.go @@ -39,6 +39,7 @@ import ( kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/events" + "k8s.io/kubernetes/pkg/kubelet/images/pullmanager" "k8s.io/kubernetes/pkg/kubelet/metrics" "k8s.io/kubernetes/pkg/util/parsers" ) @@ -52,7 +53,7 @@ type ImagePodPullingTimeRecorder interface { type imageManager struct { recorder record.EventRecorder imageService kubecontainer.ImageService - imagePullManager ImagePullManager + imagePullManager pullmanager.ImagePullManager backOff *flowcontrol.Backoff prevPullErrMsg sync.Map @@ -70,7 +71,7 @@ func NewImageManager( recorder record.EventRecorder, nodeKeyring credentialprovider.DockerKeyring, imageService kubecontainer.ImageService, - imagePullManager ImagePullManager, + imagePullManager pullmanager.ImagePullManager, imageBackOff *flowcontrol.Backoff, serialized bool, maxParallelImagePulls *int32, diff --git a/pkg/kubelet/images/image_manager_test.go b/pkg/kubelet/images/image_manager_test.go index 03ab7e822b4..2f945348300 100644 --- a/pkg/kubelet/images/image_manager_test.go +++ b/pkg/kubelet/images/image_manager_test.go @@ -42,6 +42,7 @@ import ( kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config" . "k8s.io/kubernetes/pkg/kubelet/container" ctest "k8s.io/kubernetes/pkg/kubelet/container/testing" + "k8s.io/kubernetes/pkg/kubelet/images/pullmanager" "k8s.io/kubernetes/test/utils/ktesting" testingclock "k8s.io/utils/clock/testing" "k8s.io/utils/ptr" @@ -513,7 +514,7 @@ func (m *mockPodPullingTimeRecorder) reset() { } type mockImagePullManager struct { - NoopImagePullManager + pullmanager.NoopImagePullManager imageAllowlist map[string]sets.Set[kubeletconfiginternal.ImagePullSecret] allowAll bool diff --git a/pkg/kubelet/images/pullmanager/doc.go b/pkg/kubelet/images/pullmanager/doc.go new file mode 100644 index 00000000000..dbce837b6df --- /dev/null +++ b/pkg/kubelet/images/pullmanager/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2025 The Kubernetes 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. +*/ + +// pullmanager package keeps the implementation of the image pull manager and +// image credential verification policies +package pullmanager diff --git a/pkg/kubelet/images/fs_pullrecords.go b/pkg/kubelet/images/pullmanager/fs_pullrecords.go similarity index 99% rename from pkg/kubelet/images/fs_pullrecords.go rename to pkg/kubelet/images/pullmanager/fs_pullrecords.go index fa16b1efec3..6dcee5f13c4 100644 --- a/pkg/kubelet/images/fs_pullrecords.go +++ b/pkg/kubelet/images/pullmanager/fs_pullrecords.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package images +package pullmanager import ( "bytes" diff --git a/pkg/kubelet/images/image_pull_manager.go b/pkg/kubelet/images/pullmanager/image_pull_manager.go similarity index 96% rename from pkg/kubelet/images/image_pull_manager.go rename to pkg/kubelet/images/pullmanager/image_pull_manager.go index 5407fb64854..6e0ee04833b 100644 --- a/pkg/kubelet/images/image_pull_manager.go +++ b/pkg/kubelet/images/pullmanager/image_pull_manager.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package images +package pullmanager import ( "context" @@ -367,19 +367,6 @@ func (f *PullManager) getIntentCounterForImage(image string) int32 { return intentNum } -var _ ImagePullManager = &NoopImagePullManager{} - -type NoopImagePullManager struct{} - -func (m *NoopImagePullManager) RecordPullIntent(_ string) error { return nil } -func (m *NoopImagePullManager) RecordImagePulled(_, _ string, _ *kubeletconfiginternal.ImagePullCredentials) { -} -func (m *NoopImagePullManager) RecordImagePullFailed(image string) {} -func (m *NoopImagePullManager) MustAttemptImagePull(_, _ string, _ []kubeletconfiginternal.ImagePullSecret) bool { - return false -} -func (m *NoopImagePullManager) PruneUnknownRecords(_ []string, _ time.Time) {} - // searchForExistingTagDigest loops through the `image` RepoDigests and RepoTags // and tries to find all image digests/tags in `inFlightPulls`, which is a map of // containerImage -> pulling intent path. diff --git a/pkg/kubelet/images/image_pull_manager_test.go b/pkg/kubelet/images/pullmanager/image_pull_manager_test.go similarity index 99% rename from pkg/kubelet/images/image_pull_manager_test.go rename to pkg/kubelet/images/pullmanager/image_pull_manager_test.go index 320375630f7..6b8a7c6ac48 100644 --- a/pkg/kubelet/images/image_pull_manager_test.go +++ b/pkg/kubelet/images/pullmanager/image_pull_manager_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package images +package pullmanager import ( "io/fs" diff --git a/pkg/kubelet/images/image_pull_policies.go b/pkg/kubelet/images/pullmanager/image_pull_policies.go similarity index 99% rename from pkg/kubelet/images/image_pull_policies.go rename to pkg/kubelet/images/pullmanager/image_pull_policies.go index fa85788ef9e..2642275a3d5 100644 --- a/pkg/kubelet/images/image_pull_policies.go +++ b/pkg/kubelet/images/pullmanager/image_pull_policies.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package images +package pullmanager import ( "fmt" diff --git a/pkg/kubelet/images/image_pull_policies_test.go b/pkg/kubelet/images/pullmanager/image_pull_policies_test.go similarity index 99% rename from pkg/kubelet/images/image_pull_policies_test.go rename to pkg/kubelet/images/pullmanager/image_pull_policies_test.go index 718671777cf..eb8af5ee0f6 100644 --- a/pkg/kubelet/images/image_pull_policies_test.go +++ b/pkg/kubelet/images/pullmanager/image_pull_policies_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package images +package pullmanager import ( "reflect" diff --git a/pkg/kubelet/images/pullmanager/interfaces.go b/pkg/kubelet/images/pullmanager/interfaces.go new file mode 100644 index 00000000000..3fc05c3a975 --- /dev/null +++ b/pkg/kubelet/images/pullmanager/interfaces.go @@ -0,0 +1,110 @@ +/* +Copyright 2025 The Kubernetes 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 pullmanager + +import ( + "time" + + kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config" +) + +// ImagePullManager keeps the state of images that were pulled and which are +// currently still being pulled. +// It should keep an internal state of images currently being pulled by the kubelet +// in order to determine whether to destroy a "pulling" record should an image +// pull fail. +type ImagePullManager interface { + // RecordPullIntent records an intent to pull an image and should be called + // before a pull of the image occurs. + // + // RecordPullIntent() should be called before every image pull. Each call of + // RecordPullIntent() must match exactly one call of RecordImagePulled()/RecordImagePullFailed(). + // + // `image` is the content of the pod's container `image` field. + RecordPullIntent(image string) error + // RecordImagePulled writes a record of an image being successfully pulled + // with ImagePullCredentials. + // + // `credentials` must not be nil and must contain either exactly one Kubernetes + // Secret coordinates in the `.KubernetesSecrets` slice or set `.NodePodsAccessible` + // to `true`. + // + // `image` is the content of the pod's container `image` field. + RecordImagePulled(image, imageRef string, credentials *kubeletconfiginternal.ImagePullCredentials) + // RecordImagePullFailed should be called if an image failed to pull. + // + // Internally, it lowers its reference counter for the given image. If the + // counter reaches zero, the pull intent record for the image is removed. + // + // `image` is the content of the pod's container `image` field. + RecordImagePullFailed(image string) + // MustAttemptImagePull evaluates the policy for the image specified in + // `image` and if the policy demands verification, it checks the internal + // cache to see if there's a record of pulling the image with the presented + // set of credentials or if the image can be accessed by any of the node's pods. + // + // Returns true if the policy demands verification and no record of the pull + // was found in the cache. + // + // `image` is the content of the pod's container `image` field. + MustAttemptImagePull(image, imageRef string, credentials []kubeletconfiginternal.ImagePullSecret) bool + // PruneUnknownRecords deletes all of the cache ImagePulledRecords for each of the images + // whose imageRef does not appear in the `imageList` iff such an record was last updated + // _before_ the `until` timestamp. + // + // This method is only expected to be called by the kubelet's image garbage collector. + // `until` is a timestamp created _before_ the `imageList` was requested from the CRI. + PruneUnknownRecords(imageList []string, until time.Time) +} + +// PullRecordsAccessor allows unified access to ImagePullIntents/ImagePulledRecords +// irregardless of the backing database implementation +type PullRecordsAccessor interface { + // ListImagePullIntents lists all the ImagePullIntents in the database. + // ImagePullIntents that cannot be decoded will not appear in the list. + // Returns nil and an error if there was a problem reading from the database. + // + // This method may return partial success in case there were errors listing + // the results. A list of records that were successfully read and an aggregated + // error is returned in that case. + ListImagePullIntents() ([]*kubeletconfiginternal.ImagePullIntent, error) + // ImagePullIntentExists returns whether a valid ImagePullIntent is present + // for the given image. + ImagePullIntentExists(image string) (bool, error) + // WriteImagePullIntent writes a an intent record for the image into the database + WriteImagePullIntent(image string) error + // DeleteImagePullIntent removes an `image` intent record from the database + DeleteImagePullIntent(image string) error + + // ListImagePulledRecords lists the database ImagePulledRecords. + // Records that cannot be decoded will be ignored. + // Returns an error if there was a problem reading from the database. + // + // This method may return partial success in case there were errors listing + // the results. A list of records that were successfully read and an aggregated + // error is returned in that case. + ListImagePulledRecords() ([]*kubeletconfiginternal.ImagePulledRecord, error) + // GetImagePulledRecord fetches an ImagePulledRecord for the given `imageRef`. + // If a file for the `imageRef` is present but the contents cannot be decoded, + // it returns a exists=true with err equal to the decoding error. + GetImagePulledRecord(imageRef string) (record *kubeletconfiginternal.ImagePulledRecord, exists bool, err error) + // WriteImagePulledRecord writes an ImagePulledRecord into the database. + WriteImagePulledRecord(record *kubeletconfiginternal.ImagePulledRecord) error + // DeleteImagePulledRecord removes an ImagePulledRecord for `imageRef` from the + // database. + DeleteImagePulledRecord(imageRef string) error +} diff --git a/pkg/kubelet/images/locks.go b/pkg/kubelet/images/pullmanager/locks.go similarity index 98% rename from pkg/kubelet/images/locks.go rename to pkg/kubelet/images/pullmanager/locks.go index c60c09f24cb..a1cae9c64b3 100644 --- a/pkg/kubelet/images/locks.go +++ b/pkg/kubelet/images/pullmanager/locks.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package images +package pullmanager import ( "hash/fnv" diff --git a/pkg/kubelet/images/pullmanager/noop_pull_manager.go b/pkg/kubelet/images/pullmanager/noop_pull_manager.go new file mode 100644 index 00000000000..51838d79163 --- /dev/null +++ b/pkg/kubelet/images/pullmanager/noop_pull_manager.go @@ -0,0 +1,36 @@ +/* +Copyright 2025 The Kubernetes 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 pullmanager + +import ( + "time" + + kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config" +) + +var _ ImagePullManager = &NoopImagePullManager{} + +type NoopImagePullManager struct{} + +func (m *NoopImagePullManager) RecordPullIntent(_ string) error { return nil } +func (m *NoopImagePullManager) RecordImagePulled(_, _ string, _ *kubeletconfiginternal.ImagePullCredentials) { +} +func (m *NoopImagePullManager) RecordImagePullFailed(image string) {} +func (m *NoopImagePullManager) MustAttemptImagePull(_, _ string, _ []kubeletconfiginternal.ImagePullSecret) bool { + return false +} +func (m *NoopImagePullManager) PruneUnknownRecords(_ []string, _ time.Time) {} diff --git a/pkg/kubelet/images/testdata/pulled/sha256-38a8906435c4dd5f4258899d46621bfd8eea3ad6ff494ee3c2f17ef0321625bd b/pkg/kubelet/images/pullmanager/testdata/pulled/sha256-38a8906435c4dd5f4258899d46621bfd8eea3ad6ff494ee3c2f17ef0321625bd similarity index 100% rename from pkg/kubelet/images/testdata/pulled/sha256-38a8906435c4dd5f4258899d46621bfd8eea3ad6ff494ee3c2f17ef0321625bd rename to pkg/kubelet/images/pullmanager/testdata/pulled/sha256-38a8906435c4dd5f4258899d46621bfd8eea3ad6ff494ee3c2f17ef0321625bd diff --git a/pkg/kubelet/images/testdata/pulled/sha256-a2eace2182b24cdbbb730798e47b10709b9ef5e0f0c1624a3bc06c8ca987727a b/pkg/kubelet/images/pullmanager/testdata/pulled/sha256-a2eace2182b24cdbbb730798e47b10709b9ef5e0f0c1624a3bc06c8ca987727a similarity index 100% rename from pkg/kubelet/images/testdata/pulled/sha256-a2eace2182b24cdbbb730798e47b10709b9ef5e0f0c1624a3bc06c8ca987727a rename to pkg/kubelet/images/pullmanager/testdata/pulled/sha256-a2eace2182b24cdbbb730798e47b10709b9ef5e0f0c1624a3bc06c8ca987727a diff --git a/pkg/kubelet/images/testdata/pulled/sha256-b3c0cc4278800b03a308ceb2611161430df571ca733122f0a40ac8b9792a9064 b/pkg/kubelet/images/pullmanager/testdata/pulled/sha256-b3c0cc4278800b03a308ceb2611161430df571ca733122f0a40ac8b9792a9064 similarity index 100% rename from pkg/kubelet/images/testdata/pulled/sha256-b3c0cc4278800b03a308ceb2611161430df571ca733122f0a40ac8b9792a9064 rename to pkg/kubelet/images/pullmanager/testdata/pulled/sha256-b3c0cc4278800b03a308ceb2611161430df571ca733122f0a40ac8b9792a9064 diff --git a/pkg/kubelet/images/testdata/pulled/sha256-f8778b6393eaf39315e767a58cbeacf2c4b270d94b4d6926ee993d9e49444991 b/pkg/kubelet/images/pullmanager/testdata/pulled/sha256-f8778b6393eaf39315e767a58cbeacf2c4b270d94b4d6926ee993d9e49444991 similarity index 100% rename from pkg/kubelet/images/testdata/pulled/sha256-f8778b6393eaf39315e767a58cbeacf2c4b270d94b4d6926ee993d9e49444991 rename to pkg/kubelet/images/pullmanager/testdata/pulled/sha256-f8778b6393eaf39315e767a58cbeacf2c4b270d94b4d6926ee993d9e49444991 diff --git a/pkg/kubelet/images/testdata/pulling/sha256-aef2af226629a35d5f3ef0fdbb29fdbebf038d0acd8850590e8c48e1e283aa56 b/pkg/kubelet/images/pullmanager/testdata/pulling/sha256-aef2af226629a35d5f3ef0fdbb29fdbebf038d0acd8850590e8c48e1e283aa56 similarity index 100% rename from pkg/kubelet/images/testdata/pulling/sha256-aef2af226629a35d5f3ef0fdbb29fdbebf038d0acd8850590e8c48e1e283aa56 rename to pkg/kubelet/images/pullmanager/testdata/pulling/sha256-aef2af226629a35d5f3ef0fdbb29fdbebf038d0acd8850590e8c48e1e283aa56 diff --git a/pkg/kubelet/images/testdata/pulling/sha256-ee81caca15454863449fb55a1d942904d56d5ed9f9b20a7cb3453944ea2c7e11 b/pkg/kubelet/images/pullmanager/testdata/pulling/sha256-ee81caca15454863449fb55a1d942904d56d5ed9f9b20a7cb3453944ea2c7e11 similarity index 100% rename from pkg/kubelet/images/testdata/pulling/sha256-ee81caca15454863449fb55a1d942904d56d5ed9f9b20a7cb3453944ea2c7e11 rename to pkg/kubelet/images/pullmanager/testdata/pulling/sha256-ee81caca15454863449fb55a1d942904d56d5ed9f9b20a7cb3453944ea2c7e11 diff --git a/pkg/kubelet/images/testdata/pulling/sha256-f24acc752be18b93b0504c86312bbaf482c9efb0c45e925bbccb0a591cebd7af b/pkg/kubelet/images/pullmanager/testdata/pulling/sha256-f24acc752be18b93b0504c86312bbaf482c9efb0c45e925bbccb0a591cebd7af similarity index 100% rename from pkg/kubelet/images/testdata/pulling/sha256-f24acc752be18b93b0504c86312bbaf482c9efb0c45e925bbccb0a591cebd7af rename to pkg/kubelet/images/pullmanager/testdata/pulling/sha256-f24acc752be18b93b0504c86312bbaf482c9efb0c45e925bbccb0a591cebd7af diff --git a/pkg/kubelet/images/types.go b/pkg/kubelet/images/types.go index aa6f179d542..244451cf5fc 100644 --- a/pkg/kubelet/images/types.go +++ b/pkg/kubelet/images/types.go @@ -19,11 +19,9 @@ package images import ( "context" "errors" - "time" v1 "k8s.io/api/core/v1" runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" - kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config" ) var ( @@ -54,90 +52,3 @@ type ImageManager interface { // TODO(ronl): consolidating image managing and deleting operation in this interface } - -// ImagePullManager keeps the state of images that were pulled and which are -// currently still being pulled. -// It should keep an internal state of images currently being pulled by the kubelet -// in order to determine whether to destroy a "pulling" record should an image -// pull fail. -type ImagePullManager interface { - // RecordPullIntent records an intent to pull an image and should be called - // before a pull of the image occurs. - // - // RecordPullIntent() should be called before every image pull. Each call of - // RecordPullIntent() must match exactly one call of RecordImagePulled()/RecordImagePullFailed(). - // - // `image` is the content of the pod's container `image` field. - RecordPullIntent(image string) error - // RecordImagePulled writes a record of an image being successfully pulled - // with ImagePullCredentials. - // - // `credentials` must not be nil and must contain either exactly one Kubernetes - // Secret coordinates in the `.KubernetesSecrets` slice or set `.NodePodsAccessible` - // to `true`. - // - // `image` is the content of the pod's container `image` field. - RecordImagePulled(image, imageRef string, credentials *kubeletconfiginternal.ImagePullCredentials) - // RecordImagePullFailed should be called if an image failed to pull. - // - // Internally, it lowers its reference counter for the given image. If the - // counter reaches zero, the pull intent record for the image is removed. - // - // `image` is the content of the pod's container `image` field. - RecordImagePullFailed(image string) - // MustAttemptImagePull evaluates the policy for the image specified in - // `image` and if the policy demands verification, it checks the internal - // cache to see if there's a record of pulling the image with the presented - // set of credentials or if the image can be accessed by any of the node's pods. - // - // Returns true if the policy demands verification and no record of the pull - // was found in the cache. - // - // `image` is the content of the pod's container `image` field. - MustAttemptImagePull(image, imageRef string, credentials []kubeletconfiginternal.ImagePullSecret) bool - // PruneUnknownRecords deletes all of the cache ImagePulledRecords for each of the images - // whose imageRef does not appear in the `imageList` iff such an record was last updated - // _before_ the `until` timestamp. - // - // This method is only expected to be called by the kubelet's image garbage collector. - // `until` is a timestamp created _before_ the `imageList` was requested from the CRI. - PruneUnknownRecords(imageList []string, until time.Time) -} - -// PullRecordsAccessor allows unified access to ImagePullIntents/ImagePulledRecords -// irregardless of the backing database implementation -type PullRecordsAccessor interface { - // ListImagePullIntents lists all the ImagePullIntents in the database. - // ImagePullIntents that cannot be decoded will not appear in the list. - // Returns nil and an error if there was a problem reading from the database. - // - // This method may return partial success in case there were errors listing - // the results. A list of records that were successfully read and an aggregated - // error is returned in that case. - ListImagePullIntents() ([]*kubeletconfiginternal.ImagePullIntent, error) - // ImagePullIntentExists returns whether a valid ImagePullIntent is present - // for the given image. - ImagePullIntentExists(image string) (bool, error) - // WriteImagePullIntent writes a an intent record for the image into the database - WriteImagePullIntent(image string) error - // DeleteImagePullIntent removes an `image` intent record from the database - DeleteImagePullIntent(image string) error - - // ListImagePulledRecords lists the database ImagePulledRecords. - // Records that cannot be decoded will be ignored. - // Returns an error if there was a problem reading from the database. - // - // This method may return partial success in case there were errors listing - // the results. A list of records that were successfully read and an aggregated - // error is returned in that case. - ListImagePulledRecords() ([]*kubeletconfiginternal.ImagePulledRecord, error) - // GetImagePulledRecord fetches an ImagePulledRecord for the given `imageRef`. - // If a file for the `imageRef` is present but the contents cannot be decoded, - // it returns a exists=true with err equal to the decoding error. - GetImagePulledRecord(imageRef string) (record *kubeletconfiginternal.ImagePulledRecord, exists bool, err error) - // WriteImagePulledRecord writes an ImagePulledRecord into the database. - WriteImagePulledRecord(record *kubeletconfiginternal.ImagePulledRecord) error - // DeleteImagePulledRecord removes an ImagePulledRecord for `imageRef` from the - // database. - DeleteImagePulledRecord(imageRef string) error -} diff --git a/pkg/kubelet/kuberuntime/fake_kuberuntime_manager.go b/pkg/kubelet/kuberuntime/fake_kuberuntime_manager.go index d16420a4845..6d41de84a90 100644 --- a/pkg/kubelet/kuberuntime/fake_kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/fake_kuberuntime_manager.go @@ -36,6 +36,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/images" + imagepullmanager "k8s.io/kubernetes/pkg/kubelet/images/pullmanager" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/logs" proberesults "k8s.io/kubernetes/pkg/kubelet/prober/results" @@ -135,7 +136,7 @@ func newFakeKubeRuntimeManager(runtimeService internalapi.RuntimeService, imageS kubecontainer.FilterEventRecorder(recorder), &credentialprovider.BasicDockerKeyring{}, kubeRuntimeManager, - &images.NoopImagePullManager{}, + &imagepullmanager.NoopImagePullManager{}, flowcontrol.NewBackOff(time.Second, 300*time.Second), false, ptr.To[int32](0), // No limit on max parallel image pulls, diff --git a/pkg/kubelet/kuberuntime/kuberuntime_image_test.go b/pkg/kubelet/kuberuntime/kuberuntime_image_test.go index 18b16a2744a..6368cf113d2 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_image_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_image_test.go @@ -33,6 +33,7 @@ import ( "k8s.io/kubernetes/pkg/credentialprovider" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/images" + imagepullmanager "k8s.io/kubernetes/pkg/kubelet/images/pullmanager" "k8s.io/utils/ptr" ) @@ -311,12 +312,12 @@ func TestPullWithSecrets(t *testing.T) { _, fakeImageService, fakeManager, err := createTestRuntimeManager() require.NoError(t, err) - fsRecordAccessor, err := images.NewFSPullRecordsAccessor(t.TempDir()) + fsRecordAccessor, err := imagepullmanager.NewFSPullRecordsAccessor(t.TempDir()) if err != nil { t.Fatal("failed to setup an file pull records accessor") } - imagePullManager, err := images.NewImagePullManager(context.Background(), fsRecordAccessor, images.AlwaysVerifyImagePullPolicy(), fakeManager, 10) + imagePullManager, err := imagepullmanager.NewImagePullManager(context.Background(), fsRecordAccessor, imagepullmanager.AlwaysVerifyImagePullPolicy(), fakeManager, 10) if err != nil { t.Fatal("failed to setup an image pull manager") } @@ -385,12 +386,12 @@ func TestPullWithSecretsWithError(t *testing.T) { fakeImageService.InjectError("PullImage", fmt.Errorf("test-error")) } - fsRecordAccessor, err := images.NewFSPullRecordsAccessor(t.TempDir()) + fsRecordAccessor, err := imagepullmanager.NewFSPullRecordsAccessor(t.TempDir()) if err != nil { t.Fatal("failed to setup an file pull records accessor") } - imagePullManager, err := images.NewImagePullManager(context.Background(), fsRecordAccessor, images.AlwaysVerifyImagePullPolicy(), fakeManager, 10) + imagePullManager, err := imagepullmanager.NewImagePullManager(context.Background(), fsRecordAccessor, imagepullmanager.AlwaysVerifyImagePullPolicy(), fakeManager, 10) if err != nil { t.Fatal("failed to setup an image pull manager") } diff --git a/pkg/kubelet/kuberuntime/kuberuntime_manager.go b/pkg/kubelet/kuberuntime/kuberuntime_manager.go index c616cb56940..3f92bc10c66 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_manager.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_manager.go @@ -56,6 +56,7 @@ import ( kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/events" "k8s.io/kubernetes/pkg/kubelet/images" + imagepullmanager "k8s.io/kubernetes/pkg/kubelet/images/pullmanager" runtimeutil "k8s.io/kubernetes/pkg/kubelet/kuberuntime/util" "k8s.io/kubernetes/pkg/kubelet/lifecycle" "k8s.io/kubernetes/pkg/kubelet/logs" @@ -288,9 +289,9 @@ func NewKubeGenericRuntimeManager( } var imageGCHooks []images.PostImageGCHook - var imagePullManager images.ImagePullManager = &images.NoopImagePullManager{} + var imagePullManager imagepullmanager.ImagePullManager = &imagepullmanager.NoopImagePullManager{} if utilfeature.DefaultFeatureGate.Enabled(features.KubeletEnsureSecretPulledImages) { - imagePullCredentialsVerificationPolicy, err := images.NewImagePullCredentialVerificationPolicy( + imagePullCredentialsVerificationPolicy, err := imagepullmanager.NewImagePullCredentialVerificationPolicy( kubeletconfiginternal.ImagePullCredentialsVerificationPolicy(imagePullsCredentialVerificationPolicy), preloadedImagesCredentialVerificationWhitelist) @@ -298,12 +299,12 @@ func NewKubeGenericRuntimeManager( return nil, nil, err } - fsRecordAccessor, err := images.NewFSPullRecordsAccessor(rootDirectory) + fsRecordAccessor, err := imagepullmanager.NewFSPullRecordsAccessor(rootDirectory) if err != nil { return nil, nil, fmt.Errorf("failed to setup the FSPullRecordsAccessor: %w", err) } - imagePullManager, err = images.NewImagePullManager(ctx, fsRecordAccessor, imagePullCredentialsVerificationPolicy, kubeRuntimeManager, ptr.Deref(maxParallelImagePulls, 0)) + imagePullManager, err = imagepullmanager.NewImagePullManager(ctx, fsRecordAccessor, imagePullCredentialsVerificationPolicy, kubeRuntimeManager, ptr.Deref(maxParallelImagePulls, 0)) if err != nil { return nil, nil, fmt.Errorf("failed to create image pull manager: %w", err) }