mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-23 10:26:22 +00:00
Fix lint issues. Address review comments. - Modify BackoffError to hold an absolute timestamp instead of duration - Update pod sync loop to calculate the proper enqueue time based off this timestamp Fix merge conflict error. Address review comments.
187 lines
6.0 KiB
Go
187 lines
6.0 KiB
Go
/*
|
|
Copyright 2015 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package container
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
|
)
|
|
|
|
// BackoffError should be used whenever an error needs to specify a particular backoff duration
|
|
// to the Kubelet.
|
|
type BackoffError struct {
|
|
error
|
|
backoffTime time.Time
|
|
}
|
|
|
|
func NewBackoffError(err error, backoffTime time.Time) *BackoffError {
|
|
return &BackoffError{
|
|
error: err,
|
|
backoffTime: backoffTime,
|
|
}
|
|
}
|
|
|
|
// BackoffTime returns the expected expiration time of the backoff.
|
|
func (e *BackoffError) BackoffTime() time.Time {
|
|
return e.backoffTime
|
|
}
|
|
|
|
// MinBackoffExpiration recursively searches through err for BackoffErrors and returns
|
|
// the minimum of all found backoff times.
|
|
func MinBackoffExpiration(err error) (time.Time, bool) {
|
|
var ae utilerrors.Aggregate
|
|
var be *BackoffError
|
|
switch {
|
|
case errors.As(err, &be):
|
|
return be.BackoffTime(), true
|
|
case errors.As(err, &ae):
|
|
var min time.Time
|
|
found := false
|
|
for _, e := range ae.Errors() {
|
|
if backoff, ok := MinBackoffExpiration(e); ok {
|
|
if !found || backoff.Before(min) {
|
|
min = backoff
|
|
found = true
|
|
}
|
|
}
|
|
}
|
|
return min, found
|
|
default:
|
|
if e := errors.Unwrap(err); e != nil {
|
|
return MinBackoffExpiration(e)
|
|
}
|
|
return time.Time{}, false
|
|
}
|
|
}
|
|
|
|
// TODO(random-liu): We need to better organize runtime errors for introspection.
|
|
|
|
// ErrCrashLoopBackOff returned when a container Terminated and Kubelet is backing off the restart.
|
|
var ErrCrashLoopBackOff = errors.New("CrashLoopBackOff")
|
|
|
|
var (
|
|
// ErrContainerNotFound returned when a container in the given pod with the
|
|
// given container name was not found, amongst those managed by the kubelet.
|
|
ErrContainerNotFound = errors.New("no matching container")
|
|
)
|
|
|
|
var (
|
|
// ErrRunContainer returned when runtime failed to start any of pod's container.
|
|
ErrRunContainer = errors.New("RunContainerError")
|
|
// ErrKillContainer returned when runtime failed to kill any of pod's containers.
|
|
ErrKillContainer = errors.New("KillContainerError")
|
|
// ErrCreatePodSandbox returned when runtime failed to create a sandbox for pod.
|
|
ErrCreatePodSandbox = errors.New("CreatePodSandboxError")
|
|
// ErrConfigPodSandbox returned when runetime failed to get pod sandbox config from pod.
|
|
ErrConfigPodSandbox = errors.New("ConfigPodSandboxError")
|
|
// ErrKillPodSandbox returned when runtime failed to stop pod's sandbox.
|
|
ErrKillPodSandbox = errors.New("KillPodSandboxError")
|
|
// ErrResizePodInPlace returned when runtime failed to resize a pod.
|
|
ErrResizePodInPlace = errors.New("ResizePodInPlaceError")
|
|
)
|
|
|
|
// SyncAction indicates different kind of actions in SyncPod() and KillPod(). Now there are only actions
|
|
// about start/kill container and setup/teardown network.
|
|
type SyncAction string
|
|
|
|
const (
|
|
// StartContainer action
|
|
StartContainer SyncAction = "StartContainer"
|
|
// KillContainer action
|
|
KillContainer SyncAction = "KillContainer"
|
|
// SetupNetwork action
|
|
SetupNetwork SyncAction = "SetupNetwork"
|
|
// TeardownNetwork action
|
|
TeardownNetwork SyncAction = "TeardownNetwork"
|
|
// InitContainer action
|
|
InitContainer SyncAction = "InitContainer"
|
|
// CreatePodSandbox action
|
|
CreatePodSandbox SyncAction = "CreatePodSandbox"
|
|
// ConfigPodSandbox action
|
|
ConfigPodSandbox SyncAction = "ConfigPodSandbox"
|
|
// KillPodSandbox action
|
|
KillPodSandbox SyncAction = "KillPodSandbox"
|
|
// ResizePodInPlace action is included whenever any containers in the pod are resized without restart
|
|
ResizePodInPlace SyncAction = "ResizePodInPlace"
|
|
)
|
|
|
|
// SyncResult is the result of sync action.
|
|
type SyncResult struct {
|
|
// The associated action of the result
|
|
Action SyncAction
|
|
// The target of the action, now the target can only be:
|
|
// * Container: Target should be container name
|
|
// * Network: Target is useless now, we just set it as pod full name now
|
|
Target interface{}
|
|
// Brief error reason
|
|
Error error
|
|
// Human readable error reason
|
|
Message string
|
|
}
|
|
|
|
// NewSyncResult generates new SyncResult with specific Action and Target
|
|
func NewSyncResult(action SyncAction, target interface{}) *SyncResult {
|
|
return &SyncResult{Action: action, Target: target}
|
|
}
|
|
|
|
// Fail fails the SyncResult with specific error and message
|
|
func (r *SyncResult) Fail(err error, msg string) {
|
|
r.Error, r.Message = err, msg
|
|
}
|
|
|
|
// PodSyncResult is the summary result of SyncPod() and KillPod()
|
|
type PodSyncResult struct {
|
|
// Result of different sync actions
|
|
SyncResults []*SyncResult
|
|
// Error encountered in SyncPod() and KillPod() that is not already included in SyncResults
|
|
SyncError error
|
|
}
|
|
|
|
// AddSyncResult adds multiple SyncResult to current PodSyncResult
|
|
func (p *PodSyncResult) AddSyncResult(result ...*SyncResult) {
|
|
p.SyncResults = append(p.SyncResults, result...)
|
|
}
|
|
|
|
// AddPodSyncResult merges a PodSyncResult to current one
|
|
func (p *PodSyncResult) AddPodSyncResult(result PodSyncResult) {
|
|
p.AddSyncResult(result.SyncResults...)
|
|
p.SyncError = result.SyncError
|
|
}
|
|
|
|
// Fail fails the PodSyncResult with an error occurred in SyncPod() and KillPod() itself
|
|
func (p *PodSyncResult) Fail(err error) {
|
|
p.SyncError = err
|
|
}
|
|
|
|
// Error returns an error summarizing all the errors in PodSyncResult
|
|
func (p *PodSyncResult) Error() error {
|
|
errlist := []error{}
|
|
if p.SyncError != nil {
|
|
errlist = append(errlist, fmt.Errorf("failed to SyncPod: %w", p.SyncError))
|
|
}
|
|
for _, result := range p.SyncResults {
|
|
if result.Error != nil {
|
|
errlist = append(errlist, fmt.Errorf("failed to %q for %q with %w: %q", result.Action, result.Target,
|
|
result.Error, result.Message))
|
|
}
|
|
}
|
|
return utilerrors.NewAggregate(errlist)
|
|
}
|