-
Notifications
You must be signed in to change notification settings - Fork 41.1k
kubelet: invoke part of image verification policy earlier #133114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -178,41 +178,15 @@ func (m *imageManager) EnsureImageExists(ctx context.Context, objRef *v1.ObjectR | |
return "", message, err | ||
} | ||
|
||
if imageRef != "" && !utilfeature.DefaultFeatureGate.Enabled(features.KubeletEnsureSecretPulledImages) { | ||
msg := fmt.Sprintf("Container image %q already present on machine", requestedImage) | ||
m.logIt(objRef, v1.EventTypeNormal, events.PulledImage, logPrefix, msg, klog.Info) | ||
return imageRef, msg, nil | ||
} | ||
|
||
repoToPull, _, _, err := parsers.ParseImageName(spec.Image) | ||
if err != nil { | ||
return "", err.Error(), err | ||
} | ||
// wrap the lookup in a function to ensure that we only look up credentials once and no earlier than needed | ||
lookupPullCredentials := m.makeLookupPullCredentialsFunc(spec.Image, pod, pullSecrets, podSandboxConfig) | ||
|
||
// construct the dynamic keyring using the providers we have in the kubelet | ||
var podName, podNamespace, podUID string | ||
if utilfeature.DefaultFeatureGate.Enabled(features.KubeletServiceAccountTokenForCredentialProviders) { | ||
sandboxMetadata := podSandboxConfig.GetMetadata() | ||
|
||
podName = sandboxMetadata.Name | ||
podNamespace = sandboxMetadata.Namespace | ||
podUID = sandboxMetadata.Uid | ||
} | ||
|
||
externalCredentialProviderKeyring := credentialproviderplugin.NewExternalCredentialProviderDockerKeyring( | ||
podNamespace, | ||
podName, | ||
podUID, | ||
pod.Spec.ServiceAccountName) | ||
|
||
keyring, err := credentialprovidersecrets.MakeDockerKeyring(pullSecrets, credentialprovider.UnionDockerKeyring{m.nodeKeyring, externalCredentialProviderKeyring}) | ||
if err != nil { | ||
return "", err.Error(), err | ||
} | ||
|
||
pullCredentials, _ := keyring.Lookup(repoToPull) | ||
getPodCredentials := func() ([]kubeletconfiginternal.ImagePullSecret, *kubeletconfiginternal.ImagePullServiceAccount, error) { | ||
pullCredentials, err := lookupPullCredentials() | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
if imageRef != "" { | ||
var imagePullSecrets []kubeletconfiginternal.ImagePullSecret | ||
// we don't take the audience of the service account into account, so there can only | ||
// be one imagePullServiceAccount per pod when we try to make a decision. | ||
|
@@ -239,8 +213,18 @@ func (m *imageManager) EnsureImageExists(ctx context.Context, objRef *v1.ObjectR | |
} | ||
} | ||
|
||
pullRequired := m.imagePullManager.MustAttemptImagePull(requestedImage, imageRef, imagePullSecrets, imagePullServiceAccount) | ||
if !pullRequired { | ||
return imagePullSecrets, imagePullServiceAccount, nil | ||
} | ||
|
||
if imageRef != "" { | ||
if !utilfeature.DefaultFeatureGate.Enabled(features.KubeletEnsureSecretPulledImages) { | ||
msg := fmt.Sprintf("Container image %q already present on machine", requestedImage) | ||
m.logIt(objRef, v1.EventTypeNormal, events.PulledImage, logPrefix, msg, klog.Info) | ||
return imageRef, msg, nil | ||
} | ||
if pullRequired, err := m.imagePullManager.MustAttemptImagePull(requestedImage, imageRef, getPodCredentials); err != nil { | ||
return "", err.Error(), err | ||
} else if !pullRequired { | ||
msg := fmt.Sprintf("Container image %q already present on machine and can be accessed by the pod", requestedImage) | ||
m.logIt(objRef, v1.EventTypeNormal, events.PulledImage, logPrefix, msg, klog.Info) | ||
return imageRef, msg, nil | ||
|
@@ -254,9 +238,47 @@ func (m *imageManager) EnsureImageExists(ctx context.Context, objRef *v1.ObjectR | |
return "", msg, err | ||
} | ||
|
||
pullCredentials, err := lookupPullCredentials() | ||
if err != nil { | ||
return "", err.Error(), err | ||
} | ||
|
||
return m.pullImage(ctx, logPrefix, objRef, pod.UID, requestedImage, spec, pullCredentials, podSandboxConfig) | ||
} | ||
|
||
func (m *imageManager) makeLookupPullCredentialsFunc(image string, pod *v1.Pod, pullSecrets []v1.Secret, podSandboxConfig *runtimeapi.PodSandboxConfig) func() ([]credentialprovider.TrackedAuthConfig, error) { | ||
return sync.OnceValues(func() ([]credentialprovider.TrackedAuthConfig, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do we need to wrap it in OnceValues? It is only called once anyways as far as I can tell There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the returned lookup function might be called twice in some cases:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. my question was mostly because I do not know exact behavior of I will need to review the sequence you suggested. I plan to take it again later during 1.35, please ping if you think it is critical to do earleir There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No. It caches both values.
An error in that place shows that something is seriously misconfigured, so it is unlikely that retrying makes sense. A mere failure to lookup credentials from the keyring does not return an error. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not because of this PR, I mean. The relevant method's signature does not include // pkg/credentialprovider/keyring.go
type DockerKeyring interface {
Lookup(image string) ([]TrackedAuthConfig, bool)
}
I think this change should be in place when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Besides, I would like to make sure the result of the credential lookup matches what the authz check received in the context of a single
This likely prevents us from moving the feature to Beta. It's not critical right now, but let's please make sure we pay attention to this PR early in 1.35. |
||
repoToPull, _, _, err := parsers.ParseImageName(image) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// construct the dynamic keyring using the providers we have in the kubelet | ||
var podName, podNamespace, podUID string | ||
if utilfeature.DefaultFeatureGate.Enabled(features.KubeletServiceAccountTokenForCredentialProviders) { | ||
sandboxMetadata := podSandboxConfig.GetMetadata() | ||
|
||
podName = sandboxMetadata.Name | ||
podNamespace = sandboxMetadata.Namespace | ||
podUID = sandboxMetadata.Uid | ||
} | ||
|
||
externalCredentialProviderKeyring := credentialproviderplugin.NewExternalCredentialProviderDockerKeyring( | ||
podNamespace, | ||
podName, | ||
podUID, | ||
pod.Spec.ServiceAccountName) | ||
|
||
keyring, err := credentialprovidersecrets.MakeDockerKeyring(pullSecrets, credentialprovider.UnionDockerKeyring{m.nodeKeyring, externalCredentialProviderKeyring}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
pullCredentials, _ := keyring.Lookup(repoToPull) | ||
return pullCredentials, nil | ||
}) | ||
} | ||
|
||
func (m *imageManager) pullImage(ctx context.Context, logPrefix string, objRef *v1.ObjectReference, podUID types.UID, image string, imgSpec kubecontainer.ImageSpec, pullCredentials []credentialprovider.TrackedAuthConfig, podSandboxConfig *runtimeapi.PodSandboxConfig) (imageRef, message string, err error) { | ||
var pullSucceeded bool | ||
var finalPullCredentials *credentialprovider.TrackedAuthConfig | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keeping this code block where it was before will simlpify the review. Took me some time to understand what happened here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what the code originally looked like before #133079. I'd rather it stayed here.