#IT star is not a dream

Posted by egg82 on Fri, 21 Feb 2020 12:10:28 +0100

PLEG (podlifecycle event generator) is mainly used to detect the running state of Pod periodically, so as to compare the state generating events before and after Pod and trigger kubelet to verify the state of Pod container. Let's explore its internal implementation mechanism

1. Graphic design

1.1 Pod event generation


Pod event generation is mainly based on the status comparison before and after the corresponding pod. First, obtain the list of all the pod's of the current node through runtime, and save the corresponding status, so that in the next training cycle, the container of the pod whose status changes can be found through the comparison of the status before and after, and generate the corresponding event

1.2 event notification and status synchronization


After the Pod event is generated, the corresponding event will be synchronized to the state synchronization thread through the pipeline. When the state synchronization thread senses the change event of the Pod, it will compare and synchronize with the target state of the Pod, and call the Runtime to perform the final verification operation. At the same time, in the next round, it will get the state from the Runtime again, so as to constantly verify the state of the Pod until the target state

2. Pod record

The Pod record is actually a map, and the information of the Pod returned from the Runtime of the polling cycle before and after is saved through the podRecord

type podRecord struct {
    old     *kubecontainer.Pod
    current *kubecontainer.Pod
}

type podRecords map[types.UID]*podRecord

3. Pod event generator

3.1 get Pod status

First, get the status of all pod s of the current node through runtime

    // Get all the pods.
    podList, err := g.runtime.GetPods(true)
    if err != nil {
        klog.Errorf("GenericPLEG: Unable to retrieve pods: %v", err)
        return
    }

3.2 generating events by comparing Pod information

    eventsByPodID := map[types.UID][]*PodLifecycleEvent{}
    for pid := range g.podRecords {
        // Get previous Pod information
        oldPod := g.podRecords.getOld(pid)
        pod := g.podRecords.getCurrent(pid)
        // Get all container collections of the current Pod
        allContainers := getContainersFromPods(oldPod, pod)
        for _, container := range allContainers {
            //
            events := computeEvents(oldPod, pod, &container.ID)
            for _, e := range events {
                // Update events event for pod
                updateEvents(eventsByPodID, e)
            }
        }
    }

3.3 generating comparison container state events

Pod events are generated mainly through the state of the underlying container, and the state before and after each container will be compared to get the change event

func generateEvents(podID types.UID, cid string, oldState, newState plegContainerState) []*PodLifecycleEvent {
    if newState == oldState {
        return nil
    }

    klog.V(4).Infof("GenericPLEG: %v/%v: %v -> %v", podID, cid, oldState, newState)
    switch newState {
    case plegContainerRunning:
        return []*PodLifecycleEvent{{ID: podID, Type: ContainerStarted, Data: cid}}
    case plegContainerExited:
        return []*PodLifecycleEvent{{ID: podID, Type: ContainerDied, Data: cid}}
    case plegContainerUnknown:
        return []*PodLifecycleEvent{{ID: podID, Type: ContainerChanged, Data: cid}}
    case plegContainerNonExistent:
        switch oldState {
        case plegContainerExited:
            // We already reported that the container died before.
            return []*PodLifecycleEvent{{ID: podID, Type: ContainerRemoved, Data: cid}}
        default:
            return []*PodLifecycleEvent{{ID: podID, Type: ContainerDied, Data: cid}, {ID: podID, Type: ContainerRemoved, Data: cid}}
        }
    default:
        panic(fmt.Sprintf("unrecognized container state: %v", newState))
    }
}

4. Overview of the overall event process


There are many PLEG like designs in k8s. The overall design goal is to constantly adjust the event changes and actual expected state, so as to achieve the final expected state. In the future, I will try to give only the core code of the component, sort out and clear the core data structure and algorithm in the whole process

k8s source reading e-book address: https://www.yuque.com/baxiaoshi/tyado3

Topics: kubelet