Open Wouter0100 opened 2 years ago
/triage accepted
Can I take this? @dprotaso
Sure - the change will need to be done upstream in ggcr
/assign @jwcesign
I created an upstream issue and asked for input from the maintainers - https://github.com/google/go-containerregistry/issues/1431
@Wouter0100 another workaround is to specify the registry secret with the repository
ie. registry.com/foo
and registry.com/bar
can you try that?
I think only change the logic in knative serving is better. Because if change go-containerregistry
, the API return results will be changed, it has influence with who use go-containerregistry
:
file: serving/pkg/reconciler/revision/resolve.go
// Resolve resolves the image references that use tags to digests.
func (r *digestResolver) Resolve(
ctx context.Context,
image string,
opt k8schain.Options,
registriesToSkip sets.String) (string, error) {
if _, err := name.NewDigest(image, name.WeakValidation); err == nil {
// Already a digest
return image, nil
}
tag, err := name.NewTag(image, name.WeakValidation)
if err != nil {
return "", fmt.Errorf("failed to parse image name %q into a tag: %w", image, err)
}
if registriesToSkip.Has(tag.Registry.RegistryStr()) {
return "", nil
}
if len(opt.ImagePullSecrets) == 0 {
resolveDigest, err := r.ResolveWithSingleImagePullSecret(ctx, tag, opt)
if err != nil {
return "", err
}
return resolveDigest, nil
}
var resolveErrors []error
for _, v := range opt.ImagePullSecrets {
singleImagePullSecretOpt := opt
singleImagePullSecretOpt.ImagePullSecrets = []string{v}
resolveDigest, err := r.ResolveWithSingleImagePullSecret(ctx, tag, singleImagePullSecretOpt)
if err == nil {
return resolveDigest, nil
}
resolveErrors = append(resolveErrors, err)
}
return "", utilerrors.NewAggregate(resolveErrors)
}
func (r *digestResolver) ResolveWithSingleImagePullSecret(
ctx context.Context,
tag name.Tag,
opt k8schain.Options) (string, error) {
kc, err := k8schain.New(ctx, r.client, opt)
if err != nil {
return "", err
}
desc, err := remote.Head(tag, remote.WithContext(ctx), remote.WithTransport(r.transport), remote.WithAuthFromKeychain(kc), remote.WithUserAgent(r.userAgent))
if err != nil {
return "", err
}
return fmt.Sprintf("%s@%s", tag.Repository.String(), desc.Digest), nil
}
cc @dprotaso , what u think
My only concern with that solution is that it'll enumerate over extra keychains excessively - and we've seen some keychains in the past be really slow (ie. 2s).
return authn.NewMultiKeychain(
k8s,
authn.DefaultKeychain,
google.Keychain,
amazonKeychain,
azureKeychain,
), nil
I think the workaround I mentioned above is fine while we figure out a way to solve this upstream
go-containerregistry
maintainer tries to work on abother approach, when finished, I will sync and add ut for this issue
When having multiple pullSecrets for the same registry in the same Service Account, Knative fails to detect the correct set of credentials and fails at the first. The kubelet has a loop build in that allows this setup.
What version of Knative?
1.1.0
Expected Behavior
To attempt each imagePullSecret in the associated Service Account when resolving the tag of an image and continue deploying the revision.
Actual Behavior
It fails at the first pull secret, from which the credentials do not match and does not attempt the next pull secret.
Steps to Reproduce the Problem
kubernetes.io/dockerconfigjson
-secrets for the same registry with different username/password.Workaround
We disabled tag resolving by setting
registries-skipping-tag-resolving
inconfig-deployment
to our registry.