@@ -24,242 +24,8 @@ import (
24
24
25
25
v1 "k8s.io/api/core/v1"
26
26
"k8s.io/apimachinery/pkg/api/resource"
27
-
28
- podutil "k8s.io/kubernetes/pkg/api/v1/pod"
29
27
)
30
28
31
- // PodResourcesOptions controls the behavior of PodRequests and PodLimits.
32
- type PodResourcesOptions struct {
33
- // Reuse, if provided will be reused to accumulate resources and returned by the PodRequests or PodLimits
34
- // functions. All existing values in Reuse will be lost.
35
- Reuse v1.ResourceList
36
- // InPlacePodVerticalScalingEnabled indicates that the in-place pod vertical scaling feature gate is enabled.
37
- InPlacePodVerticalScalingEnabled bool
38
- // ExcludeOverhead controls if pod overhead is excluded from the calculation.
39
- ExcludeOverhead bool
40
- // ContainerFn is called with the effective resources required for each container within the pod.
41
- ContainerFn func (res v1.ResourceList , containerType podutil.ContainerType )
42
- // NonMissingContainerRequests if provided will replace any missing container level requests for the specified resources
43
- // with the given values. If the requests for those resources are explicitly set, even if zero, they will not be modified.
44
- NonMissingContainerRequests v1.ResourceList
45
- }
46
-
47
- // PodRequests computes the pod requests per the PodResourcesOptions supplied. If PodResourcesOptions is nil, then
48
- // the requests are returned including pod overhead. The computation is part of the API and must be reviewed
49
- // as an API change.
50
- func PodRequests (pod * v1.Pod , opts PodResourcesOptions ) v1.ResourceList {
51
- // attempt to reuse the maps if passed, or allocate otherwise
52
- reqs := reuseOrClearResourceList (opts .Reuse )
53
-
54
- var containerStatuses map [string ]* v1.ContainerStatus
55
- if opts .InPlacePodVerticalScalingEnabled {
56
- containerStatuses = make (map [string ]* v1.ContainerStatus , len (pod .Status .ContainerStatuses ))
57
- for i := range pod .Status .ContainerStatuses {
58
- containerStatuses [pod .Status .ContainerStatuses [i ].Name ] = & pod .Status .ContainerStatuses [i ]
59
- }
60
- }
61
-
62
- for _ , container := range pod .Spec .Containers {
63
- containerReqs := container .Resources .Requests
64
- if opts .InPlacePodVerticalScalingEnabled {
65
- cs , found := containerStatuses [container .Name ]
66
- if found {
67
- if pod .Status .Resize == v1 .PodResizeStatusInfeasible {
68
- containerReqs = cs .AllocatedResources .DeepCopy ()
69
- } else {
70
- containerReqs = max (container .Resources .Requests , cs .AllocatedResources )
71
- }
72
- }
73
- }
74
-
75
- if len (opts .NonMissingContainerRequests ) > 0 {
76
- containerReqs = applyNonMissing (containerReqs , opts .NonMissingContainerRequests )
77
- }
78
-
79
- if opts .ContainerFn != nil {
80
- opts .ContainerFn (containerReqs , podutil .Containers )
81
- }
82
-
83
- addResourceList (reqs , containerReqs )
84
- }
85
-
86
- restartableInitContainerReqs := v1.ResourceList {}
87
- initContainerReqs := v1.ResourceList {}
88
- // init containers define the minimum of any resource
89
- // Note: In-place resize is not allowed for InitContainers, so no need to check for ResizeStatus value
90
- //
91
- // Let's say `InitContainerUse(i)` is the resource requirements when the i-th
92
- // init container is initializing, then
93
- // `InitContainerUse(i) = sum(Resources of restartable init containers with index < i) + Resources of i-th init container`.
94
- //
95
- // See https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/753-sidecar-containers#exposing-pod-resource-requirements for the detail.
96
- for _ , container := range pod .Spec .InitContainers {
97
- containerReqs := container .Resources .Requests
98
- if len (opts .NonMissingContainerRequests ) > 0 {
99
- containerReqs = applyNonMissing (containerReqs , opts .NonMissingContainerRequests )
100
- }
101
-
102
- if container .RestartPolicy != nil && * container .RestartPolicy == v1 .ContainerRestartPolicyAlways {
103
- // and add them to the resulting cumulative container requests
104
- addResourceList (reqs , containerReqs )
105
-
106
- // track our cumulative restartable init container resources
107
- addResourceList (restartableInitContainerReqs , containerReqs )
108
- containerReqs = restartableInitContainerReqs
109
- } else {
110
- tmp := v1.ResourceList {}
111
- addResourceList (tmp , containerReqs )
112
- addResourceList (tmp , restartableInitContainerReqs )
113
- containerReqs = tmp
114
- }
115
-
116
- if opts .ContainerFn != nil {
117
- opts .ContainerFn (containerReqs , podutil .InitContainers )
118
- }
119
- maxResourceList (initContainerReqs , containerReqs )
120
- }
121
-
122
- maxResourceList (reqs , initContainerReqs )
123
-
124
- // Add overhead for running a pod to the sum of requests if requested:
125
- if ! opts .ExcludeOverhead && pod .Spec .Overhead != nil {
126
- addResourceList (reqs , pod .Spec .Overhead )
127
- }
128
-
129
- return reqs
130
- }
131
-
132
- // applyNonMissing will return a copy of the given resource list with any missing values replaced by the nonMissing values
133
- func applyNonMissing (reqs v1.ResourceList , nonMissing v1.ResourceList ) v1.ResourceList {
134
- cp := v1.ResourceList {}
135
- for k , v := range reqs {
136
- cp [k ] = v .DeepCopy ()
137
- }
138
-
139
- for k , v := range nonMissing {
140
- if _ , found := reqs [k ]; ! found {
141
- rk := cp [k ]
142
- rk .Add (v )
143
- cp [k ] = rk
144
- }
145
- }
146
- return cp
147
- }
148
-
149
- // PodLimits computes the pod limits per the PodResourcesOptions supplied. If PodResourcesOptions is nil, then
150
- // the limits are returned including pod overhead for any non-zero limits. The computation is part of the API and must be reviewed
151
- // as an API change.
152
- func PodLimits (pod * v1.Pod , opts PodResourcesOptions ) v1.ResourceList {
153
- // attempt to reuse the maps if passed, or allocate otherwise
154
- limits := reuseOrClearResourceList (opts .Reuse )
155
-
156
- for _ , container := range pod .Spec .Containers {
157
- if opts .ContainerFn != nil {
158
- opts .ContainerFn (container .Resources .Limits , podutil .Containers )
159
- }
160
- addResourceList (limits , container .Resources .Limits )
161
- }
162
-
163
- restartableInitContainerLimits := v1.ResourceList {}
164
- initContainerLimits := v1.ResourceList {}
165
- // init containers define the minimum of any resource
166
- //
167
- // Let's say `InitContainerUse(i)` is the resource requirements when the i-th
168
- // init container is initializing, then
169
- // `InitContainerUse(i) = sum(Resources of restartable init containers with index < i) + Resources of i-th init container`.
170
- //
171
- // See https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/753-sidecar-containers#exposing-pod-resource-requirements for the detail.
172
- for _ , container := range pod .Spec .InitContainers {
173
- containerLimits := container .Resources .Limits
174
- // Is the init container marked as a restartable init container?
175
- if container .RestartPolicy != nil && * container .RestartPolicy == v1 .ContainerRestartPolicyAlways {
176
- addResourceList (limits , containerLimits )
177
-
178
- // track our cumulative restartable init container resources
179
- addResourceList (restartableInitContainerLimits , containerLimits )
180
- containerLimits = restartableInitContainerLimits
181
- } else {
182
- tmp := v1.ResourceList {}
183
- addResourceList (tmp , containerLimits )
184
- addResourceList (tmp , restartableInitContainerLimits )
185
- containerLimits = tmp
186
- }
187
-
188
- if opts .ContainerFn != nil {
189
- opts .ContainerFn (containerLimits , podutil .InitContainers )
190
- }
191
- maxResourceList (initContainerLimits , containerLimits )
192
- }
193
-
194
- maxResourceList (limits , initContainerLimits )
195
-
196
- // Add overhead to non-zero limits if requested:
197
- if ! opts .ExcludeOverhead && pod .Spec .Overhead != nil {
198
- for name , quantity := range pod .Spec .Overhead {
199
- if value , ok := limits [name ]; ok && ! value .IsZero () {
200
- value .Add (quantity )
201
- limits [name ] = value
202
- }
203
- }
204
- }
205
-
206
- return limits
207
- }
208
-
209
- // addResourceList adds the resources in newList to list.
210
- func addResourceList (list , newList v1.ResourceList ) {
211
- for name , quantity := range newList {
212
- if value , ok := list [name ]; ! ok {
213
- list [name ] = quantity .DeepCopy ()
214
- } else {
215
- value .Add (quantity )
216
- list [name ] = value
217
- }
218
- }
219
- }
220
-
221
- // maxResourceList sets list to the greater of list/newList for every resource in newList
222
- func maxResourceList (list , newList v1.ResourceList ) {
223
- for name , quantity := range newList {
224
- if value , ok := list [name ]; ! ok || quantity .Cmp (value ) > 0 {
225
- list [name ] = quantity .DeepCopy ()
226
- }
227
- }
228
- }
229
-
230
- // max returns the result of max(a, b) for each named resource and is only used if we can't
231
- // accumulate into an existing resource list
232
- func max (a v1.ResourceList , b v1.ResourceList ) v1.ResourceList {
233
- result := v1.ResourceList {}
234
- for key , value := range a {
235
- if other , found := b [key ]; found {
236
- if value .Cmp (other ) <= 0 {
237
- result [key ] = other .DeepCopy ()
238
- continue
239
- }
240
- }
241
- result [key ] = value .DeepCopy ()
242
- }
243
- for key , value := range b {
244
- if _ , found := result [key ]; ! found {
245
- result [key ] = value .DeepCopy ()
246
- }
247
- }
248
- return result
249
- }
250
-
251
- // reuseOrClearResourceList is a helper for avoiding excessive allocations of
252
- // resource lists within the inner loop of resource calculations.
253
- func reuseOrClearResourceList (reuse v1.ResourceList ) v1.ResourceList {
254
- if reuse == nil {
255
- return make (v1.ResourceList , 4 )
256
- }
257
- for k := range reuse {
258
- delete (reuse , k )
259
- }
260
- return reuse
261
- }
262
-
263
29
// GetResourceRequestQuantity finds and returns the request quantity for a specific resource.
264
30
func GetResourceRequestQuantity (pod * v1.Pod , resourceName v1.ResourceName ) resource.Quantity {
265
31
requestQuantity := resource.Quantity {}
0 commit comments