Skip to content

Commit

Permalink
Add retry on image push 5xx errors
Browse files Browse the repository at this point in the history
Some registries can be flaky and return intermittent 5xx errors. This
change allows those errors to be retried, similarly to network-level
errors.

Note that this needs the upstream containerd fix
containerd/containerd#5276 to work reliably.

This was tested with a registry that was modified to return 504 on every
other manifest PUT. Without the change, exports to the registry fail
every other attempt.  With the change and the related containerd change,
exports to the registry always succeed.

Signed-off-by: Aaron Lehmann <alehmann@netflix.com>
  • Loading branch information
aaronlehmann committed Mar 27, 2021
1 parent 4e69662 commit d3b96f4
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 2 deletions.
2 changes: 1 addition & 1 deletion util/contentutil/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func CopyChain(ctx context.Context, ingester content.Ingester, provider content.
handlers := []images.Handler{
images.ChildrenHandler(provider),
filterHandler,
retryhandler.New(remotes.FetchHandler(ingester, &localFetcher{provider}), nil),
retryhandler.New(remotes.FetchHandler(ingester, &localFetcher{provider}), func(_ []byte) {}),
}

if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion util/imageutil/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func Config(ctx context.Context, str string, resolver remotes.Resolver, cache Co
children := childrenConfigHandler(cache, platform)

handlers := []images.Handler{
retryhandler.New(remotes.FetchHandler(cache, fetcher), nil),
retryhandler.New(remotes.FetchHandler(cache, fetcher), func(_ []byte) {}),
children,
}
if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
Expand Down
1 change: 1 addition & 0 deletions util/progress/logs/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func (sw *streamWriter) Close() error {
func LoggerFromContext(ctx context.Context) func([]byte) {
return func(dt []byte) {
pw, _, _ := progress.FromContext(ctx)
defer pw.Close()
pw.Write(identity.NewID(), client.VertexLog{
Stream: stderr,
Data: []byte(dt),
Expand Down
9 changes: 9 additions & 0 deletions util/resolver/retryhandler/retry.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/containerd/containerd/images"
remoteserrors "github.com/containerd/containerd/remotes/errors"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -48,6 +49,14 @@ func New(f images.HandlerFunc, logger func([]byte)) images.HandlerFunc {
}

func retryError(err error) bool {
// Retry on 5xx errors
var errUnexpectedStatus remoteserrors.ErrUnexpectedStatus
if errors.As(err, &errUnexpectedStatus) &&
errUnexpectedStatus.StatusCode >= 500 &&
errUnexpectedStatus.StatusCode <= 599 {
return true
}

if errors.Is(err, io.EOF) || errors.Is(err, syscall.ECONNRESET) || errors.Is(err, syscall.EPIPE) {
return true
}
Expand Down

0 comments on commit d3b96f4

Please sign in to comment.