github.com/netdata/go.d.plugin@v0.58.1/modules/k8s_state/update_pod_state.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package k8s_state
     4  
     5  import (
     6  	"strings"
     7  
     8  	corev1 "k8s.io/api/core/v1"
     9  )
    10  
    11  func (ks *KubeState) updatePodState(r resource) {
    12  	if r.value() == nil {
    13  		if ps, ok := ks.state.pods[r.source()]; ok {
    14  			ps.deleted = true
    15  		}
    16  		return
    17  	}
    18  
    19  	pod, err := toPod(r)
    20  	if err != nil {
    21  		ks.Warning(err)
    22  		return
    23  	}
    24  
    25  	ps, ok := ks.state.pods[r.source()]
    26  	if !ok {
    27  		ps = newPodState()
    28  		ks.state.pods[r.source()] = ps
    29  	}
    30  
    31  	if !ok {
    32  		ps.name = pod.Name
    33  		ps.nodeName = pod.Spec.NodeName
    34  		ps.namespace = pod.Namespace
    35  		ps.creationTime = pod.CreationTimestamp.Time
    36  		ps.uid = string(pod.UID)
    37  		ps.qosClass = strings.ToLower(string(pod.Status.QOSClass))
    38  		copyLabels(ps.labels, pod.Labels)
    39  		for _, ref := range pod.OwnerReferences {
    40  			if ref.Controller != nil && *ref.Controller {
    41  				ps.controllerKind = ref.Kind
    42  				ps.controllerName = ref.Name
    43  			}
    44  		}
    45  		var res struct{ rCPU, lCPU, rMem, lMem, irCPU, ilCPU, irMem, ilMem int64 }
    46  		for _, cntr := range pod.Spec.Containers {
    47  			res.rCPU += int64(cntr.Resources.Requests.Cpu().AsApproximateFloat64() * 1000)
    48  			res.lCPU += int64(cntr.Resources.Limits.Cpu().AsApproximateFloat64() * 1000)
    49  			res.rMem += cntr.Resources.Requests.Memory().Value()
    50  			res.lMem += cntr.Resources.Limits.Memory().Value()
    51  		}
    52  		for _, cntr := range pod.Spec.InitContainers {
    53  			res.irCPU += int64(cntr.Resources.Requests.Cpu().AsApproximateFloat64() * 1000)
    54  			res.ilCPU += int64(cntr.Resources.Limits.Cpu().AsApproximateFloat64() * 1000)
    55  			res.irMem += cntr.Resources.Requests.Memory().Value()
    56  			res.ilMem += cntr.Resources.Limits.Memory().Value()
    57  		}
    58  		ps.reqCPU = max(res.rCPU, res.irCPU)
    59  		ps.limitCPU = max(res.lCPU, res.ilCPU)
    60  		ps.reqMem = max(res.rMem, res.irMem)
    61  		ps.limitMem = max(res.lMem, res.ilMem)
    62  	}
    63  	if ps.nodeName == "" {
    64  		ps.nodeName = pod.Spec.NodeName
    65  	}
    66  
    67  	for _, c := range pod.Status.Conditions {
    68  		switch c.Type {
    69  		case corev1.ContainersReady:
    70  			ps.condContainersReady = c.Status
    71  		case corev1.PodInitialized:
    72  			ps.condPodInitialized = c.Status
    73  		case corev1.PodReady:
    74  			ps.condPodReady = c.Status
    75  		case corev1.PodScheduled:
    76  			ps.condPodScheduled = c.Status
    77  		}
    78  	}
    79  
    80  	ps.phase = pod.Status.Phase
    81  
    82  	for _, cs := range ps.containers {
    83  		for _, r := range cs.stateWaitingReasons {
    84  			r.active = false
    85  		}
    86  		for _, r := range cs.stateTerminatedReasons {
    87  			r.active = false
    88  		}
    89  	}
    90  
    91  	for _, cntr := range pod.Status.ContainerStatuses {
    92  		cs, ok := ps.containers[cntr.Name]
    93  		if !ok {
    94  			cs = newContainerState()
    95  			ps.containers[cntr.Name] = cs
    96  		}
    97  		if !ok {
    98  			cs.name = cntr.Name
    99  			cs.podName = pod.Name
   100  			cs.namespace = pod.Namespace
   101  			cs.nodeName = pod.Spec.NodeName
   102  			cs.uid = extractContainerID(cntr.ContainerID)
   103  		}
   104  		cs.ready = cntr.Ready
   105  		cs.restarts = int64(cntr.RestartCount)
   106  		cs.stateRunning = cntr.State.Running != nil
   107  		cs.stateWaiting = cntr.State.Waiting != nil
   108  		cs.stateTerminated = cntr.State.Terminated != nil
   109  
   110  		if cntr.State.Waiting != nil {
   111  			reason := cntr.State.Waiting.Reason
   112  			r, ok := cs.stateWaitingReasons[reason]
   113  			if !ok {
   114  				r = &containerStateReason{new: true, reason: reason}
   115  				cs.stateWaitingReasons[reason] = r
   116  			}
   117  			r.active = true
   118  		}
   119  
   120  		if cntr.State.Terminated != nil {
   121  			reason := cntr.State.Terminated.Reason
   122  			r, ok := cs.stateTerminatedReasons[reason]
   123  			if !ok {
   124  				r = &containerStateReason{new: true, reason: reason}
   125  				cs.stateTerminatedReasons[reason] = r
   126  			}
   127  			r.active = true
   128  		}
   129  	}
   130  
   131  	for _, cntr := range pod.Status.InitContainerStatuses {
   132  		cs, ok := ps.initContainers[cntr.Name]
   133  		if !ok {
   134  			cs = newContainerState()
   135  			ps.initContainers[cntr.Name] = cs
   136  		}
   137  		if !ok {
   138  			cs.name = cntr.Name
   139  			cs.podName = pod.Name
   140  			cs.namespace = pod.Namespace
   141  			cs.nodeName = pod.Spec.NodeName
   142  			cs.uid = extractContainerID(cntr.ContainerID)
   143  		}
   144  		cs.ready = cntr.Ready
   145  		cs.restarts = int64(cntr.RestartCount)
   146  		cs.stateRunning = cntr.State.Running != nil
   147  		cs.stateWaiting = cntr.State.Waiting != nil
   148  		cs.stateTerminated = cntr.State.Terminated != nil
   149  	}
   150  }
   151  
   152  func max(a, b int64) int64 {
   153  	if a < b {
   154  		return b
   155  	}
   156  	return a
   157  }
   158  
   159  func extractContainerID(id string) string {
   160  	// docker://d98...
   161  	if i := strings.LastIndexByte(id, '/'); i != -1 {
   162  		id = id[i+1:]
   163  	}
   164  	return id
   165  }