Skip to content

Commit 788b7ab

Browse files
committed
kubelet: pullmanager: move to a separate package
1 parent b8fc604 commit 788b7ab

23 files changed

+190
-122
lines changed

pkg/kubelet/apis/config/validation/validation.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import (
3232
tracingapi "k8s.io/component-base/tracing/api/v1"
3333
"k8s.io/kubernetes/pkg/features"
3434
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
35-
"k8s.io/kubernetes/pkg/kubelet/images"
35+
imagepullmanager "k8s.io/kubernetes/pkg/kubelet/images/pullmanager"
3636
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
3737
utilfs "k8s.io/kubernetes/pkg/util/filesystem"
3838
utiltaints "k8s.io/kubernetes/pkg/util/taints"
@@ -301,7 +301,7 @@ func ValidateKubeletConfiguration(kc *kubeletconfig.KubeletConfiguration, featur
301301

302302
if len(kc.PreloadedImagesVerificationAllowlist) > 0 && kc.ImagePullCredentialsVerificationPolicy != string(kubeletconfig.NeverVerifyAllowlistedImages) {
303303
allErrors = append(allErrors, fmt.Errorf("invalid configuration: can't set `preloadedImagesVerificationAllowlist` if `imagePullCredentialsVertificationPolicy` is not \"NeverVerifyAllowlistedImages\""))
304-
} else if err := images.ValidateAllowlistImagesPatterns(kc.PreloadedImagesVerificationAllowlist); err != nil {
304+
} else if err := imagepullmanager.ValidateAllowlistImagesPatterns(kc.PreloadedImagesVerificationAllowlist); err != nil {
305305
allErrors = append(allErrors, fmt.Errorf("invalid configuration: invalid image pattern in `preloadedImagesVerificationAllowlist`: %w", err))
306306
}
307307
} else {

pkg/kubelet/images/image_manager.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config"
4040
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
4141
"k8s.io/kubernetes/pkg/kubelet/events"
42+
"k8s.io/kubernetes/pkg/kubelet/images/pullmanager"
4243
"k8s.io/kubernetes/pkg/kubelet/metrics"
4344
"k8s.io/kubernetes/pkg/util/parsers"
4445
)
@@ -52,7 +53,7 @@ type ImagePodPullingTimeRecorder interface {
5253
type imageManager struct {
5354
recorder record.EventRecorder
5455
imageService kubecontainer.ImageService
55-
imagePullManager ImagePullManager
56+
imagePullManager pullmanager.ImagePullManager
5657
backOff *flowcontrol.Backoff
5758
prevPullErrMsg sync.Map
5859

@@ -70,7 +71,7 @@ func NewImageManager(
7071
recorder record.EventRecorder,
7172
nodeKeyring credentialprovider.DockerKeyring,
7273
imageService kubecontainer.ImageService,
73-
imagePullManager ImagePullManager,
74+
imagePullManager pullmanager.ImagePullManager,
7475
imageBackOff *flowcontrol.Backoff,
7576
serialized bool,
7677
maxParallelImagePulls *int32,

pkg/kubelet/images/image_manager_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config"
4343
. "k8s.io/kubernetes/pkg/kubelet/container"
4444
ctest "k8s.io/kubernetes/pkg/kubelet/container/testing"
45+
"k8s.io/kubernetes/pkg/kubelet/images/pullmanager"
4546
"k8s.io/kubernetes/test/utils/ktesting"
4647
testingclock "k8s.io/utils/clock/testing"
4748
"k8s.io/utils/ptr"
@@ -513,7 +514,7 @@ func (m *mockPodPullingTimeRecorder) reset() {
513514
}
514515

515516
type mockImagePullManager struct {
516-
NoopImagePullManager
517+
pullmanager.NoopImagePullManager
517518

518519
imageAllowlist map[string]sets.Set[kubeletconfiginternal.ImagePullSecret]
519520
allowAll bool
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// pullmanager package keeps the implementation of the image pull manager and
18+
// image credential verification policies
19+
package pullmanager

pkg/kubelet/images/fs_pullrecords.go renamed to pkg/kubelet/images/pullmanager/fs_pullrecords.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package images
17+
package pullmanager
1818

1919
import (
2020
"bytes"

pkg/kubelet/images/image_pull_manager.go renamed to pkg/kubelet/images/pullmanager/image_pull_manager.go

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package images
17+
package pullmanager
1818

1919
import (
2020
"context"
@@ -367,19 +367,6 @@ func (f *PullManager) getIntentCounterForImage(image string) int32 {
367367
return intentNum
368368
}
369369

370-
var _ ImagePullManager = &NoopImagePullManager{}
371-
372-
type NoopImagePullManager struct{}
373-
374-
func (m *NoopImagePullManager) RecordPullIntent(_ string) error { return nil }
375-
func (m *NoopImagePullManager) RecordImagePulled(_, _ string, _ *kubeletconfiginternal.ImagePullCredentials) {
376-
}
377-
func (m *NoopImagePullManager) RecordImagePullFailed(image string) {}
378-
func (m *NoopImagePullManager) MustAttemptImagePull(_, _ string, _ []kubeletconfiginternal.ImagePullSecret) bool {
379-
return false
380-
}
381-
func (m *NoopImagePullManager) PruneUnknownRecords(_ []string, _ time.Time) {}
382-
383370
// searchForExistingTagDigest loops through the `image` RepoDigests and RepoTags
384371
// and tries to find all image digests/tags in `inFlightPulls`, which is a map of
385372
// containerImage -> pulling intent path.

pkg/kubelet/images/image_pull_manager_test.go renamed to pkg/kubelet/images/pullmanager/image_pull_manager_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package images
17+
package pullmanager
1818

1919
import (
2020
"io/fs"

pkg/kubelet/images/image_pull_policies.go renamed to pkg/kubelet/images/pullmanager/image_pull_policies.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package images
17+
package pullmanager
1818

1919
import (
2020
"fmt"

pkg/kubelet/images/image_pull_policies_test.go renamed to pkg/kubelet/images/pullmanager/image_pull_policies_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package images
17+
package pullmanager
1818

1919
import (
2020
"reflect"
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package pullmanager
18+
19+
import (
20+
"time"
21+
22+
kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config"
23+
)
24+
25+
// ImagePullManager keeps the state of images that were pulled and which are
26+
// currently still being pulled.
27+
// It should keep an internal state of images currently being pulled by the kubelet
28+
// in order to determine whether to destroy a "pulling" record should an image
29+
// pull fail.
30+
type ImagePullManager interface {
31+
// RecordPullIntent records an intent to pull an image and should be called
32+
// before a pull of the image occurs.
33+
//
34+
// RecordPullIntent() should be called before every image pull. Each call of
35+
// RecordPullIntent() must match exactly one call of RecordImagePulled()/RecordImagePullFailed().
36+
//
37+
// `image` is the content of the pod's container `image` field.
38+
RecordPullIntent(image string) error
39+
// RecordImagePulled writes a record of an image being successfully pulled
40+
// with ImagePullCredentials.
41+
//
42+
// `credentials` must not be nil and must contain either exactly one Kubernetes
43+
// Secret coordinates in the `.KubernetesSecrets` slice or set `.NodePodsAccessible`
44+
// to `true`.
45+
//
46+
// `image` is the content of the pod's container `image` field.
47+
RecordImagePulled(image, imageRef string, credentials *kubeletconfiginternal.ImagePullCredentials)
48+
// RecordImagePullFailed should be called if an image failed to pull.
49+
//
50+
// Internally, it lowers its reference counter for the given image. If the
51+
// counter reaches zero, the pull intent record for the image is removed.
52+
//
53+
// `image` is the content of the pod's container `image` field.
54+
RecordImagePullFailed(image string)
55+
// MustAttemptImagePull evaluates the policy for the image specified in
56+
// `image` and if the policy demands verification, it checks the internal
57+
// cache to see if there's a record of pulling the image with the presented
58+
// set of credentials or if the image can be accessed by any of the node's pods.
59+
//
60+
// Returns true if the policy demands verification and no record of the pull
61+
// was found in the cache.
62+
//
63+
// `image` is the content of the pod's container `image` field.
64+
MustAttemptImagePull(image, imageRef string, credentials []kubeletconfiginternal.ImagePullSecret) bool
65+
// PruneUnknownRecords deletes all of the cache ImagePulledRecords for each of the images
66+
// whose imageRef does not appear in the `imageList` iff such an record was last updated
67+
// _before_ the `until` timestamp.
68+
//
69+
// This method is only expected to be called by the kubelet's image garbage collector.
70+
// `until` is a timestamp created _before_ the `imageList` was requested from the CRI.
71+
PruneUnknownRecords(imageList []string, until time.Time)
72+
}
73+
74+
// PullRecordsAccessor allows unified access to ImagePullIntents/ImagePulledRecords
75+
// irregardless of the backing database implementation
76+
type PullRecordsAccessor interface {
77+
// ListImagePullIntents lists all the ImagePullIntents in the database.
78+
// ImagePullIntents that cannot be decoded will not appear in the list.
79+
// Returns nil and an error if there was a problem reading from the database.
80+
//
81+
// This method may return partial success in case there were errors listing
82+
// the results. A list of records that were successfully read and an aggregated
83+
// error is returned in that case.
84+
ListImagePullIntents() ([]*kubeletconfiginternal.ImagePullIntent, error)
85+
// ImagePullIntentExists returns whether a valid ImagePullIntent is present
86+
// for the given image.
87+
ImagePullIntentExists(image string) (bool, error)
88+
// WriteImagePullIntent writes a an intent record for the image into the database
89+
WriteImagePullIntent(image string) error
90+
// DeleteImagePullIntent removes an `image` intent record from the database
91+
DeleteImagePullIntent(image string) error
92+
93+
// ListImagePulledRecords lists the database ImagePulledRecords.
94+
// Records that cannot be decoded will be ignored.
95+
// Returns an error if there was a problem reading from the database.
96+
//
97+
// This method may return partial success in case there were errors listing
98+
// the results. A list of records that were successfully read and an aggregated
99+
// error is returned in that case.
100+
ListImagePulledRecords() ([]*kubeletconfiginternal.ImagePulledRecord, error)
101+
// GetImagePulledRecord fetches an ImagePulledRecord for the given `imageRef`.
102+
// If a file for the `imageRef` is present but the contents cannot be decoded,
103+
// it returns a exists=true with err equal to the decoding error.
104+
GetImagePulledRecord(imageRef string) (record *kubeletconfiginternal.ImagePulledRecord, exists bool, err error)
105+
// WriteImagePulledRecord writes an ImagePulledRecord into the database.
106+
WriteImagePulledRecord(record *kubeletconfiginternal.ImagePulledRecord) error
107+
// DeleteImagePulledRecord removes an ImagePulledRecord for `imageRef` from the
108+
// database.
109+
DeleteImagePulledRecord(imageRef string) error
110+
}

0 commit comments

Comments
 (0)