Skip to content

Commit 3e8155e

Browse files
authored
Merge pull request kubernetes#86899 from SataQiu/enable-pull-retry-20200107
kubeadm: support automatic retry after failing to pull image
2 parents e265afa + c7234aa commit 3e8155e

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

cmd/kubeadm/app/constants/constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ const (
181181
PatchNodeTimeout = 2 * time.Minute
182182
// TLSBootstrapTimeout specifies how long kubeadm should wait for the kubelet to perform the TLS Bootstrap
183183
TLSBootstrapTimeout = 2 * time.Minute
184+
// PullImageRetry specifies how many times ContainerRuntime retries when pulling image failed
185+
PullImageRetry = 5
184186
// PrepullImagesInParallelTimeout specifies how long kubeadm should wait for prepulling images in parallel before timing out
185187
PrepullImagesInParallelTimeout = 10 * time.Second
186188

cmd/kubeadm/app/preflight/checks_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,9 +762,18 @@ func TestImagePullCheck(t *testing.T) {
762762
// Test case1: pull only img3
763763
func() ([]byte, []byte, error) { return nil, nil, nil },
764764
// Test case 2: fail to pull image2 and image3
765+
// If the pull fails, it will be retried 5 times (see PullImageRetry in constants/constants.go)
765766
func() ([]byte, []byte, error) { return nil, nil, nil },
766767
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
767768
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
769+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
770+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
771+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
772+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
773+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
774+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
775+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
776+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
768777
},
769778
}
770779

@@ -780,6 +789,14 @@ func TestImagePullCheck(t *testing.T) {
780789
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
781790
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
782791
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
792+
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
793+
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
794+
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
795+
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
796+
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
797+
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
798+
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
799+
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
783800
},
784801
LookPathFunc: func(cmd string) (string, error) { return "/usr/bin/docker", nil },
785802
}

cmd/kubeadm/app/util/runtime/runtime.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,28 @@ func (runtime *DockerRuntime) RemoveContainers(containers []string) error {
151151

152152
// PullImage pulls the image
153153
func (runtime *CRIRuntime) PullImage(image string) error {
154-
out, err := runtime.exec.Command("crictl", "-r", runtime.criSocket, "pull", image).CombinedOutput()
155-
if err != nil {
156-
return errors.Wrapf(err, "output: %s, error", string(out))
154+
var err error
155+
var out []byte
156+
for i := 0; i < constants.PullImageRetry; i++ {
157+
out, err = runtime.exec.Command("crictl", "-r", runtime.criSocket, "pull", image).CombinedOutput()
158+
if err == nil {
159+
return nil
160+
}
157161
}
158-
return nil
162+
return errors.Wrapf(err, "output: %s, error", out)
159163
}
160164

161165
// PullImage pulls the image
162166
func (runtime *DockerRuntime) PullImage(image string) error {
163-
out, err := runtime.exec.Command("docker", "pull", image).CombinedOutput()
164-
if err != nil {
165-
return errors.Wrapf(err, "output: %s, error", string(out))
167+
var err error
168+
var out []byte
169+
for i := 0; i < constants.PullImageRetry; i++ {
170+
out, err = runtime.exec.Command("docker", "pull", image).CombinedOutput()
171+
if err == nil {
172+
return nil
173+
}
166174
}
167-
return nil
175+
return errors.Wrapf(err, "output: %s, error", out)
168176
}
169177

170178
// ImageExists checks to see if the image exists on the system

cmd/kubeadm/app/util/runtime/runtime_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,18 @@ func TestPullImage(t *testing.T) {
229229
fcmd := fakeexec.FakeCmd{
230230
CombinedOutputScript: []fakeexec.FakeAction{
231231
func() ([]byte, []byte, error) { return nil, nil, nil },
232+
// If the pull fails, it will be retried 5 times (see PullImageRetry in constants/constants.go)
233+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
234+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
235+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
236+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
232237
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
233238
func() ([]byte, []byte, error) { return nil, nil, nil },
239+
// If the pull fails, it will be retried 5 times (see PullImageRetry in constants/constants.go)
240+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
241+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
242+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
243+
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
234244
func() ([]byte, []byte, error) { return []byte("error"), nil, &fakeexec.FakeExitError{Status: 1} },
235245
},
236246
}

0 commit comments

Comments
 (0)