mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-05 23:47:50 +00:00
Add init container loading to the kubelet
This commit is contained in:
@@ -879,6 +879,109 @@ func deleteNS(c *client.Client, namespace string, timeout time.Duration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ContainerInitInvariant(older, newer runtime.Object) error {
|
||||
oldPod := older.(*api.Pod)
|
||||
newPod := newer.(*api.Pod)
|
||||
if len(oldPod.Spec.InitContainers) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(oldPod.Spec.InitContainers) != len(newPod.Spec.InitContainers) {
|
||||
return fmt.Errorf("init container list changed")
|
||||
}
|
||||
if oldPod.UID != newPod.UID {
|
||||
return fmt.Errorf("two different pods exist in the condition: %s vs %s", oldPod.UID, newPod.UID)
|
||||
}
|
||||
if err := initContainersInvariants(oldPod); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := initContainersInvariants(newPod); err != nil {
|
||||
return err
|
||||
}
|
||||
oldInit, _, _ := podInitialized(oldPod)
|
||||
newInit, _, _ := podInitialized(newPod)
|
||||
if oldInit && !newInit {
|
||||
// TODO: we may in the future enable resetting PodInitialized = false if the kubelet needs to restart it
|
||||
// from scratch
|
||||
return fmt.Errorf("pod cannot be initialized and then regress to not being initialized")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func podInitialized(pod *api.Pod) (ok bool, failed bool, err error) {
|
||||
allInit := true
|
||||
initFailed := false
|
||||
for _, s := range pod.Status.InitContainerStatuses {
|
||||
switch {
|
||||
case initFailed && s.State.Waiting == nil:
|
||||
return allInit, initFailed, fmt.Errorf("container %s is after a failed container but isn't waiting", s.Name)
|
||||
case allInit && s.State.Waiting == nil:
|
||||
return allInit, initFailed, fmt.Errorf("container %s is after an initializing container but isn't waiting", s.Name)
|
||||
case s.State.Terminated == nil:
|
||||
allInit = false
|
||||
case s.State.Terminated.ExitCode != 0:
|
||||
allInit = false
|
||||
initFailed = true
|
||||
case !s.Ready:
|
||||
return allInit, initFailed, fmt.Errorf("container %s initialized but isn't marked as ready", s.Name)
|
||||
}
|
||||
}
|
||||
return allInit, initFailed, nil
|
||||
}
|
||||
|
||||
func initContainersInvariants(pod *api.Pod) error {
|
||||
allInit, initFailed, err := podInitialized(pod)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !allInit || initFailed {
|
||||
for _, s := range pod.Status.ContainerStatuses {
|
||||
if s.State.Waiting == nil || s.RestartCount != 0 {
|
||||
return fmt.Errorf("container %s is not waiting but initialization not complete", s.Name)
|
||||
}
|
||||
if s.State.Waiting.Reason != "PodInitializing" {
|
||||
return fmt.Errorf("container %s should have reason PodInitializing: %s", s.Name, s.State.Waiting.Reason)
|
||||
}
|
||||
}
|
||||
}
|
||||
_, c := api.GetPodCondition(&pod.Status, api.PodInitialized)
|
||||
if c == nil {
|
||||
return fmt.Errorf("pod does not have initialized condition")
|
||||
}
|
||||
if c.LastTransitionTime.IsZero() {
|
||||
return fmt.Errorf("PodInitialized condition should always have a transition time")
|
||||
}
|
||||
switch {
|
||||
case c.Status == api.ConditionUnknown:
|
||||
return fmt.Errorf("PodInitialized condition should never be Unknown")
|
||||
case c.Status == api.ConditionTrue && (initFailed || !allInit):
|
||||
return fmt.Errorf("PodInitialized condition was True but all not all containers initialized")
|
||||
case c.Status == api.ConditionFalse && (!initFailed && allInit):
|
||||
return fmt.Errorf("PodInitialized condition was False but all containers initialized")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type InvariantFunc func(older, newer runtime.Object) error
|
||||
|
||||
func CheckInvariants(events []watch.Event, fns ...InvariantFunc) error {
|
||||
errs := sets.NewString()
|
||||
for i := range events {
|
||||
j := i + 1
|
||||
if j >= len(events) {
|
||||
continue
|
||||
}
|
||||
for _, fn := range fns {
|
||||
if err := fn(events[i].Object, events[j].Object); err != nil {
|
||||
errs.Insert(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
if errs.Len() > 0 {
|
||||
return fmt.Errorf("invariants violated:\n* %s", strings.Join(errs.List(), "\n* "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Waits default amount of time (PodStartTimeout) for the specified pod to become running.
|
||||
// Returns an error if timeout occurs first, or pod goes in to failed state.
|
||||
func WaitForPodRunningInNamespace(c *client.Client, podName string, namespace string) error {
|
||||
@@ -2218,7 +2321,11 @@ func DumpNodeDebugInfo(c *client.Client, nodeNames []string) {
|
||||
continue
|
||||
}
|
||||
for _, p := range podList.Items {
|
||||
Logf("%v started at %v (%d container statuses recorded)", p.Name, p.Status.StartTime, len(p.Status.ContainerStatuses))
|
||||
Logf("%v started at %v (%d+%d container statuses recorded)", p.Name, p.Status.StartTime, len(p.Status.InitContainerStatuses), len(p.Status.ContainerStatuses))
|
||||
for _, c := range p.Status.InitContainerStatuses {
|
||||
Logf("\tInit container %v ready: %v, restart count %v",
|
||||
c.Name, c.Ready, c.RestartCount)
|
||||
}
|
||||
for _, c := range p.Status.ContainerStatuses {
|
||||
Logf("\tContainer %v ready: %v, restart count %v",
|
||||
c.Name, c.Ready, c.RestartCount)
|
||||
|
||||
Reference in New Issue
Block a user