...
1
2
3
4
19
20 package oom
21
22 import (
23 "fmt"
24 "os"
25 "path"
26 "path/filepath"
27 "strconv"
28 "time"
29
30 cmutil "k8s.io/kubernetes/pkg/kubelet/cm/util"
31
32 "k8s.io/klog/v2"
33 )
34
35 func NewOOMAdjuster() *OOMAdjuster {
36 oomAdjuster := &OOMAdjuster{
37 pidLister: getPids,
38 ApplyOOMScoreAdj: applyOOMScoreAdj,
39 }
40 oomAdjuster.ApplyOOMScoreAdjContainer = oomAdjuster.applyOOMScoreAdjContainer
41 return oomAdjuster
42 }
43
44 func getPids(cgroupName string) ([]int, error) {
45 return cmutil.GetPids(filepath.Join("/", cgroupName))
46 }
47
48
49
50 func applyOOMScoreAdj(pid int, oomScoreAdj int) error {
51 if pid < 0 {
52 return fmt.Errorf("invalid PID %d specified for oom_score_adj", pid)
53 }
54
55 var pidStr string
56 if pid == 0 {
57 pidStr = "self"
58 } else {
59 pidStr = strconv.Itoa(pid)
60 }
61
62 maxTries := 2
63 oomScoreAdjPath := path.Join("/proc", pidStr, "oom_score_adj")
64 value := strconv.Itoa(oomScoreAdj)
65 klog.V(4).Infof("attempting to set %q to %q", oomScoreAdjPath, value)
66 var err error
67 for i := 0; i < maxTries; i++ {
68 err = os.WriteFile(oomScoreAdjPath, []byte(value), 0700)
69 if err != nil {
70 if os.IsNotExist(err) {
71 klog.V(2).Infof("%q does not exist", oomScoreAdjPath)
72 return os.ErrNotExist
73 }
74
75 klog.V(3).Info(err)
76 time.Sleep(100 * time.Millisecond)
77 continue
78 }
79 return nil
80 }
81 if err != nil {
82 klog.V(2).Infof("failed to set %q to %q: %v", oomScoreAdjPath, value, err)
83 }
84 return err
85 }
86
87
88
89 func (oomAdjuster *OOMAdjuster) applyOOMScoreAdjContainer(cgroupName string, oomScoreAdj, maxTries int) error {
90 adjustedProcessSet := make(map[int]bool)
91 for i := 0; i < maxTries; i++ {
92 continueAdjusting := false
93 pidList, err := oomAdjuster.pidLister(cgroupName)
94 if err != nil {
95 if os.IsNotExist(err) {
96
97 return os.ErrNotExist
98 }
99 continueAdjusting = true
100 klog.V(10).Infof("Error getting process list for cgroup %s: %+v", cgroupName, err)
101 } else if len(pidList) == 0 {
102 klog.V(10).Infof("Pid list is empty")
103 continueAdjusting = true
104 } else {
105 for _, pid := range pidList {
106 if !adjustedProcessSet[pid] {
107 klog.V(10).Infof("pid %d needs to be set", pid)
108 if err = oomAdjuster.ApplyOOMScoreAdj(pid, oomScoreAdj); err == nil {
109 adjustedProcessSet[pid] = true
110 } else if err == os.ErrNotExist {
111 continue
112 } else {
113 klog.V(10).Infof("cannot adjust oom score for pid %d - %v", pid, err)
114 continueAdjusting = true
115 }
116
117 }
118 }
119 }
120 if !continueAdjusting {
121 return nil
122 }
123
124
125
126
127
128 }
129 return fmt.Errorf("exceeded maxTries, some processes might not have desired OOM score")
130 }
131
View as plain text