Merge pull request #117717 from saschagrunert/invalid-signature-error

Add support for CRI `ErrSignatureValidationFailed`
This commit is contained in:
Kubernetes Prow Robot 2023-05-05 10:39:25 -07:00 committed by GitHub
commit af92da5cb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 11 deletions

View File

@ -29,6 +29,7 @@ import (
"k8s.io/klog/v2"
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
crierrors "k8s.io/cri-api/pkg/errors"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/kubelet/events"
)
@ -158,14 +159,8 @@ func (m *imageManager) EnsureImageExists(ctx context.Context, pod *v1.Pod, conta
m.logIt(ref, v1.EventTypeWarning, events.FailedToPullImage, logPrefix, fmt.Sprintf("Failed to pull image %q: %v", container.Image, imagePullResult.err), klog.Warning)
m.backOff.Next(backOffKey, m.backOff.Clock.Now())
// Error assertions via errors.Is is not supported by gRPC (remote runtime) errors right now.
// See https://github.com/grpc/grpc-go/issues/3616
if imagePullResult.err.Error() == ErrRegistryUnavailable.Error() {
msg := fmt.Sprintf("image pull failed for %s because the registry is unavailable.", container.Image)
return "", msg, imagePullResult.err
}
return "", imagePullResult.err.Error(), ErrImagePull
msg, err := evalCRIPullErr(container, imagePullResult.err)
return "", msg, err
}
m.podPullingTimeRecorder.RecordImageFinishedPulling(pod.UID)
m.logIt(ref, v1.EventTypeNormal, events.PulledImage, logPrefix, fmt.Sprintf("Successfully pulled image %q in %v (%v including waiting)",
@ -174,6 +169,23 @@ func (m *imageManager) EnsureImageExists(ctx context.Context, pod *v1.Pod, conta
return imagePullResult.imageRef, "", nil
}
func evalCRIPullErr(container *v1.Container, err error) (errMsg string, errRes error) {
// Error assertions via errors.Is is not supported by gRPC (remote runtime) errors right now.
// See https://github.com/grpc/grpc-go/issues/3616
if err.Error() == crierrors.ErrRegistryUnavailable.Error() {
errMsg = fmt.Sprintf("image pull failed for %s because the registry is unavailable.", container.Image)
return errMsg, crierrors.ErrRegistryUnavailable
}
if err.Error() == crierrors.ErrSignatureValidationFailed.Error() {
errMsg = fmt.Sprintf("image pull failed for %s because the signature validation failed.", container.Image)
return errMsg, crierrors.ErrSignatureValidationFailed
}
// Fallback for no specific error
return err.Error(), ErrImagePull
}
// applyDefaultImageTag parses a docker image string, if it doesn't contain any tag or digest,
// a default tag will be applied.
func applyDefaultImageTag(image string) (string, error) {

View File

@ -29,6 +29,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/flowcontrol"
crierrors "k8s.io/cri-api/pkg/errors"
. "k8s.io/kubernetes/pkg/kubelet/container"
ctest "k8s.io/kubernetes/pkg/kubelet/container/testing"
testingclock "k8s.io/utils/clock/testing"
@ -413,3 +414,46 @@ func TestMaxParallelImagePullsLimit(t *testing.T) {
wg.Wait()
fakeRuntime.AssertCallCounts("PullImage", 7)
}
func TestEvalCRIPullErr(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
name string
input error
assert func(string, error)
}{
{
name: "fallback error",
input: errors.New("test"),
assert: func(msg string, err error) {
assert.ErrorIs(t, err, ErrImagePull)
assert.Contains(t, msg, "test")
},
},
{
name: "registry is unavailable",
input: crierrors.ErrRegistryUnavailable,
assert: func(msg string, err error) {
assert.ErrorIs(t, err, crierrors.ErrRegistryUnavailable)
assert.Contains(t, msg, "registry is unavailable")
},
},
{
name: "signature is invalid",
input: crierrors.ErrSignatureValidationFailed,
assert: func(msg string, err error) {
assert.ErrorIs(t, err, crierrors.ErrSignatureValidationFailed)
assert.Contains(t, msg, "signature validation failed")
},
},
} {
testInput := tc.input
testAssert := tc.assert
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
msg, err := evalCRIPullErr(&v1.Container{}, testInput)
testAssert(msg, err)
})
}
}

View File

@ -37,9 +37,6 @@ var (
// ErrImageNeverPull - Required Image is absent on host and PullPolicy is NeverPullImage
ErrImageNeverPull = errors.New("ErrImageNeverPull")
// ErrRegistryUnavailable - Get http error when pulling image from registry
ErrRegistryUnavailable = errors.New("RegistryUnavailable")
// ErrInvalidImageName - Unable to parse the image name.
ErrInvalidImageName = errors.New("InvalidImageName")
)

View File

@ -17,10 +17,20 @@ limitations under the License.
package errors
import (
"errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var (
// ErrRegistryUnavailable - Get http error on the PullImage RPC call.
ErrRegistryUnavailable = errors.New("RegistryUnavailable")
// ErrSignatureValidationFailed - Unable to validate the image signature on the PullImage RPC call.
ErrSignatureValidationFailed = errors.New("SignatureValidationFailed")
)
// IsNotFound returns a boolean indicating whether the error
// is grpc not found error.
// See https://github.com/grpc/grpc/blob/master/doc/statuscodes.md