node_info.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package nodeinfo
  14. import (
  15. "errors"
  16. "fmt"
  17. "sync"
  18. "sync/atomic"
  19. "k8s.io/klog"
  20. "k8s.io/api/core/v1"
  21. "k8s.io/apimachinery/pkg/api/resource"
  22. v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
  23. priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util"
  24. )
  25. var (
  26. emptyResource = Resource{}
  27. generation int64
  28. )
  29. // ImageStateSummary provides summarized information about the state of an image.
  30. type ImageStateSummary struct {
  31. // Size of the image
  32. Size int64
  33. // Used to track how many nodes have this image
  34. NumNodes int
  35. }
  36. // NodeInfo is node level aggregated information.
  37. type NodeInfo struct {
  38. // Overall node information.
  39. node *v1.Node
  40. pods []*v1.Pod
  41. podsWithAffinity []*v1.Pod
  42. usedPorts HostPortInfo
  43. // Total requested resource of all pods on this node.
  44. // It includes assumed pods which scheduler sends binding to apiserver but
  45. // didn't get it as scheduled yet.
  46. requestedResource *Resource
  47. nonzeroRequest *Resource
  48. // We store allocatedResources (which is Node.Status.Allocatable.*) explicitly
  49. // as int64, to avoid conversions and accessing map.
  50. allocatableResource *Resource
  51. // Cached taints of the node for faster lookup.
  52. taints []v1.Taint
  53. taintsErr error
  54. // imageStates holds the entry of an image if and only if this image is on the node. The entry can be used for
  55. // checking an image's existence and advanced usage (e.g., image locality scheduling policy) based on the image
  56. // state information.
  57. imageStates map[string]*ImageStateSummary
  58. // TransientInfo holds the information pertaining to a scheduling cycle. This will be destructed at the end of
  59. // scheduling cycle.
  60. // TODO: @ravig. Remove this once we have a clear approach for message passing across predicates and priorities.
  61. TransientInfo *TransientSchedulerInfo
  62. // Cached conditions of node for faster lookup.
  63. memoryPressureCondition v1.ConditionStatus
  64. diskPressureCondition v1.ConditionStatus
  65. pidPressureCondition v1.ConditionStatus
  66. // Whenever NodeInfo changes, generation is bumped.
  67. // This is used to avoid cloning it if the object didn't change.
  68. generation int64
  69. }
  70. //initializeNodeTransientInfo initializes transient information pertaining to node.
  71. func initializeNodeTransientInfo() nodeTransientInfo {
  72. return nodeTransientInfo{AllocatableVolumesCount: 0, RequestedVolumes: 0}
  73. }
  74. // nextGeneration: Let's make sure history never forgets the name...
  75. // Increments the generation number monotonically ensuring that generation numbers never collide.
  76. // Collision of the generation numbers would be particularly problematic if a node was deleted and
  77. // added back with the same name. See issue#63262.
  78. func nextGeneration() int64 {
  79. return atomic.AddInt64(&generation, 1)
  80. }
  81. // nodeTransientInfo contains transient node information while scheduling.
  82. type nodeTransientInfo struct {
  83. // AllocatableVolumesCount contains number of volumes that could be attached to node.
  84. AllocatableVolumesCount int
  85. // Requested number of volumes on a particular node.
  86. RequestedVolumes int
  87. }
  88. // TransientSchedulerInfo is a transient structure which is destructed at the end of each scheduling cycle.
  89. // It consists of items that are valid for a scheduling cycle and is used for message passing across predicates and
  90. // priorities. Some examples which could be used as fields are number of volumes being used on node, current utilization
  91. // on node etc.
  92. // IMPORTANT NOTE: Make sure that each field in this structure is documented along with usage. Expand this structure
  93. // only when absolutely needed as this data structure will be created and destroyed during every scheduling cycle.
  94. type TransientSchedulerInfo struct {
  95. TransientLock sync.Mutex
  96. // NodeTransInfo holds the information related to nodeTransientInformation. NodeName is the key here.
  97. TransNodeInfo nodeTransientInfo
  98. }
  99. // NewTransientSchedulerInfo returns a new scheduler transient structure with initialized values.
  100. func NewTransientSchedulerInfo() *TransientSchedulerInfo {
  101. tsi := &TransientSchedulerInfo{
  102. TransNodeInfo: initializeNodeTransientInfo(),
  103. }
  104. return tsi
  105. }
  106. // ResetTransientSchedulerInfo resets the TransientSchedulerInfo.
  107. func (transientSchedInfo *TransientSchedulerInfo) ResetTransientSchedulerInfo() {
  108. transientSchedInfo.TransientLock.Lock()
  109. defer transientSchedInfo.TransientLock.Unlock()
  110. // Reset TransientNodeInfo.
  111. transientSchedInfo.TransNodeInfo.AllocatableVolumesCount = 0
  112. transientSchedInfo.TransNodeInfo.RequestedVolumes = 0
  113. }
  114. // Resource is a collection of compute resource.
  115. type Resource struct {
  116. MilliCPU int64
  117. Memory int64
  118. EphemeralStorage int64
  119. // We store allowedPodNumber (which is Node.Status.Allocatable.Pods().Value())
  120. // explicitly as int, to avoid conversions and improve performance.
  121. AllowedPodNumber int
  122. // ScalarResources
  123. ScalarResources map[v1.ResourceName]int64
  124. }
  125. // NewResource creates a Resource from ResourceList
  126. func NewResource(rl v1.ResourceList) *Resource {
  127. r := &Resource{}
  128. r.Add(rl)
  129. return r
  130. }
  131. // Add adds ResourceList into Resource.
  132. func (r *Resource) Add(rl v1.ResourceList) {
  133. if r == nil {
  134. return
  135. }
  136. for rName, rQuant := range rl {
  137. switch rName {
  138. case v1.ResourceCPU:
  139. r.MilliCPU += rQuant.MilliValue()
  140. case v1.ResourceMemory:
  141. r.Memory += rQuant.Value()
  142. case v1.ResourcePods:
  143. r.AllowedPodNumber += int(rQuant.Value())
  144. case v1.ResourceEphemeralStorage:
  145. r.EphemeralStorage += rQuant.Value()
  146. default:
  147. if v1helper.IsScalarResourceName(rName) {
  148. r.AddScalar(rName, rQuant.Value())
  149. }
  150. }
  151. }
  152. }
  153. // ResourceList returns a resource list of this resource.
  154. func (r *Resource) ResourceList() v1.ResourceList {
  155. result := v1.ResourceList{
  156. v1.ResourceCPU: *resource.NewMilliQuantity(r.MilliCPU, resource.DecimalSI),
  157. v1.ResourceMemory: *resource.NewQuantity(r.Memory, resource.BinarySI),
  158. v1.ResourcePods: *resource.NewQuantity(int64(r.AllowedPodNumber), resource.BinarySI),
  159. v1.ResourceEphemeralStorage: *resource.NewQuantity(r.EphemeralStorage, resource.BinarySI),
  160. }
  161. for rName, rQuant := range r.ScalarResources {
  162. if v1helper.IsHugePageResourceName(rName) {
  163. result[rName] = *resource.NewQuantity(rQuant, resource.BinarySI)
  164. } else {
  165. result[rName] = *resource.NewQuantity(rQuant, resource.DecimalSI)
  166. }
  167. }
  168. return result
  169. }
  170. // Clone returns a copy of this resource.
  171. func (r *Resource) Clone() *Resource {
  172. res := &Resource{
  173. MilliCPU: r.MilliCPU,
  174. Memory: r.Memory,
  175. AllowedPodNumber: r.AllowedPodNumber,
  176. EphemeralStorage: r.EphemeralStorage,
  177. }
  178. if r.ScalarResources != nil {
  179. res.ScalarResources = make(map[v1.ResourceName]int64)
  180. for k, v := range r.ScalarResources {
  181. res.ScalarResources[k] = v
  182. }
  183. }
  184. return res
  185. }
  186. // AddScalar adds a resource by a scalar value of this resource.
  187. func (r *Resource) AddScalar(name v1.ResourceName, quantity int64) {
  188. r.SetScalar(name, r.ScalarResources[name]+quantity)
  189. }
  190. // SetScalar sets a resource by a scalar value of this resource.
  191. func (r *Resource) SetScalar(name v1.ResourceName, quantity int64) {
  192. // Lazily allocate scalar resource map.
  193. if r.ScalarResources == nil {
  194. r.ScalarResources = map[v1.ResourceName]int64{}
  195. }
  196. r.ScalarResources[name] = quantity
  197. }
  198. // SetMaxResource compares with ResourceList and takes max value for each Resource.
  199. func (r *Resource) SetMaxResource(rl v1.ResourceList) {
  200. if r == nil {
  201. return
  202. }
  203. for rName, rQuantity := range rl {
  204. switch rName {
  205. case v1.ResourceMemory:
  206. if mem := rQuantity.Value(); mem > r.Memory {
  207. r.Memory = mem
  208. }
  209. case v1.ResourceCPU:
  210. if cpu := rQuantity.MilliValue(); cpu > r.MilliCPU {
  211. r.MilliCPU = cpu
  212. }
  213. case v1.ResourceEphemeralStorage:
  214. if ephemeralStorage := rQuantity.Value(); ephemeralStorage > r.EphemeralStorage {
  215. r.EphemeralStorage = ephemeralStorage
  216. }
  217. default:
  218. if v1helper.IsScalarResourceName(rName) {
  219. value := rQuantity.Value()
  220. if value > r.ScalarResources[rName] {
  221. r.SetScalar(rName, value)
  222. }
  223. }
  224. }
  225. }
  226. }
  227. // NewNodeInfo returns a ready to use empty NodeInfo object.
  228. // If any pods are given in arguments, their information will be aggregated in
  229. // the returned object.
  230. func NewNodeInfo(pods ...*v1.Pod) *NodeInfo {
  231. ni := &NodeInfo{
  232. requestedResource: &Resource{},
  233. nonzeroRequest: &Resource{},
  234. allocatableResource: &Resource{},
  235. TransientInfo: NewTransientSchedulerInfo(),
  236. generation: nextGeneration(),
  237. usedPorts: make(HostPortInfo),
  238. imageStates: make(map[string]*ImageStateSummary),
  239. }
  240. for _, pod := range pods {
  241. ni.AddPod(pod)
  242. }
  243. return ni
  244. }
  245. // Node returns overall information about this node.
  246. func (n *NodeInfo) Node() *v1.Node {
  247. if n == nil {
  248. return nil
  249. }
  250. return n.node
  251. }
  252. // Pods return all pods scheduled (including assumed to be) on this node.
  253. func (n *NodeInfo) Pods() []*v1.Pod {
  254. if n == nil {
  255. return nil
  256. }
  257. return n.pods
  258. }
  259. // SetPods sets all pods scheduled (including assumed to be) on this node.
  260. func (n *NodeInfo) SetPods(pods []*v1.Pod) {
  261. n.pods = pods
  262. }
  263. // UsedPorts returns used ports on this node.
  264. func (n *NodeInfo) UsedPorts() HostPortInfo {
  265. if n == nil {
  266. return nil
  267. }
  268. return n.usedPorts
  269. }
  270. // SetUsedPorts sets the used ports on this node.
  271. func (n *NodeInfo) SetUsedPorts(newUsedPorts HostPortInfo) {
  272. n.usedPorts = newUsedPorts
  273. }
  274. // ImageStates returns the state information of all images.
  275. func (n *NodeInfo) ImageStates() map[string]*ImageStateSummary {
  276. if n == nil {
  277. return nil
  278. }
  279. return n.imageStates
  280. }
  281. // SetImageStates sets the state information of all images.
  282. func (n *NodeInfo) SetImageStates(newImageStates map[string]*ImageStateSummary) {
  283. n.imageStates = newImageStates
  284. }
  285. // PodsWithAffinity return all pods with (anti)affinity constraints on this node.
  286. func (n *NodeInfo) PodsWithAffinity() []*v1.Pod {
  287. if n == nil {
  288. return nil
  289. }
  290. return n.podsWithAffinity
  291. }
  292. // AllowedPodNumber returns the number of the allowed pods on this node.
  293. func (n *NodeInfo) AllowedPodNumber() int {
  294. if n == nil || n.allocatableResource == nil {
  295. return 0
  296. }
  297. return n.allocatableResource.AllowedPodNumber
  298. }
  299. // Taints returns the taints list on this node.
  300. func (n *NodeInfo) Taints() ([]v1.Taint, error) {
  301. if n == nil {
  302. return nil, nil
  303. }
  304. return n.taints, n.taintsErr
  305. }
  306. // SetTaints sets the taints list on this node.
  307. func (n *NodeInfo) SetTaints(newTaints []v1.Taint) {
  308. n.taints = newTaints
  309. }
  310. // MemoryPressureCondition returns the memory pressure condition status on this node.
  311. func (n *NodeInfo) MemoryPressureCondition() v1.ConditionStatus {
  312. if n == nil {
  313. return v1.ConditionUnknown
  314. }
  315. return n.memoryPressureCondition
  316. }
  317. // DiskPressureCondition returns the disk pressure condition status on this node.
  318. func (n *NodeInfo) DiskPressureCondition() v1.ConditionStatus {
  319. if n == nil {
  320. return v1.ConditionUnknown
  321. }
  322. return n.diskPressureCondition
  323. }
  324. // PIDPressureCondition returns the pid pressure condition status on this node.
  325. func (n *NodeInfo) PIDPressureCondition() v1.ConditionStatus {
  326. if n == nil {
  327. return v1.ConditionUnknown
  328. }
  329. return n.pidPressureCondition
  330. }
  331. // RequestedResource returns aggregated resource request of pods on this node.
  332. func (n *NodeInfo) RequestedResource() Resource {
  333. if n == nil {
  334. return emptyResource
  335. }
  336. return *n.requestedResource
  337. }
  338. // SetRequestedResource sets the aggregated resource request of pods on this node.
  339. func (n *NodeInfo) SetRequestedResource(newResource *Resource) {
  340. n.requestedResource = newResource
  341. }
  342. // NonZeroRequest returns aggregated nonzero resource request of pods on this node.
  343. func (n *NodeInfo) NonZeroRequest() Resource {
  344. if n == nil {
  345. return emptyResource
  346. }
  347. return *n.nonzeroRequest
  348. }
  349. // SetNonZeroRequest sets the aggregated nonzero resource request of pods on this node.
  350. func (n *NodeInfo) SetNonZeroRequest(newResource *Resource) {
  351. n.nonzeroRequest = newResource
  352. }
  353. // AllocatableResource returns allocatable resources on a given node.
  354. func (n *NodeInfo) AllocatableResource() Resource {
  355. if n == nil {
  356. return emptyResource
  357. }
  358. return *n.allocatableResource
  359. }
  360. // SetAllocatableResource sets the allocatableResource information of given node.
  361. func (n *NodeInfo) SetAllocatableResource(allocatableResource *Resource) {
  362. n.allocatableResource = allocatableResource
  363. n.generation = nextGeneration()
  364. }
  365. // GetGeneration returns the generation on this node.
  366. func (n *NodeInfo) GetGeneration() int64 {
  367. if n == nil {
  368. return 0
  369. }
  370. return n.generation
  371. }
  372. // SetGeneration sets the generation on this node. This is for testing only.
  373. func (n *NodeInfo) SetGeneration(newGeneration int64) {
  374. n.generation = newGeneration
  375. }
  376. // Clone returns a copy of this node.
  377. func (n *NodeInfo) Clone() *NodeInfo {
  378. clone := &NodeInfo{
  379. node: n.node,
  380. requestedResource: n.requestedResource.Clone(),
  381. nonzeroRequest: n.nonzeroRequest.Clone(),
  382. allocatableResource: n.allocatableResource.Clone(),
  383. taintsErr: n.taintsErr,
  384. TransientInfo: n.TransientInfo,
  385. memoryPressureCondition: n.memoryPressureCondition,
  386. diskPressureCondition: n.diskPressureCondition,
  387. pidPressureCondition: n.pidPressureCondition,
  388. usedPorts: make(HostPortInfo),
  389. imageStates: n.imageStates,
  390. generation: n.generation,
  391. }
  392. if len(n.pods) > 0 {
  393. clone.pods = append([]*v1.Pod(nil), n.pods...)
  394. }
  395. if len(n.usedPorts) > 0 {
  396. // HostPortInfo is a map-in-map struct
  397. // make sure it's deep copied
  398. for ip, portMap := range n.usedPorts {
  399. clone.usedPorts[ip] = make(map[ProtocolPort]struct{})
  400. for protocolPort, v := range portMap {
  401. clone.usedPorts[ip][protocolPort] = v
  402. }
  403. }
  404. }
  405. if len(n.podsWithAffinity) > 0 {
  406. clone.podsWithAffinity = append([]*v1.Pod(nil), n.podsWithAffinity...)
  407. }
  408. if len(n.taints) > 0 {
  409. clone.taints = append([]v1.Taint(nil), n.taints...)
  410. }
  411. return clone
  412. }
  413. // VolumeLimits returns volume limits associated with the node
  414. func (n *NodeInfo) VolumeLimits() map[v1.ResourceName]int64 {
  415. volumeLimits := map[v1.ResourceName]int64{}
  416. for k, v := range n.AllocatableResource().ScalarResources {
  417. if v1helper.IsAttachableVolumeResourceName(k) {
  418. volumeLimits[k] = v
  419. }
  420. }
  421. return volumeLimits
  422. }
  423. // String returns representation of human readable format of this NodeInfo.
  424. func (n *NodeInfo) String() string {
  425. podKeys := make([]string, len(n.pods))
  426. for i, pod := range n.pods {
  427. podKeys[i] = pod.Name
  428. }
  429. return fmt.Sprintf("&NodeInfo{Pods:%v, RequestedResource:%#v, NonZeroRequest: %#v, UsedPort: %#v, AllocatableResource:%#v}",
  430. podKeys, n.requestedResource, n.nonzeroRequest, n.usedPorts, n.allocatableResource)
  431. }
  432. func hasPodAffinityConstraints(pod *v1.Pod) bool {
  433. affinity := pod.Spec.Affinity
  434. return affinity != nil && (affinity.PodAffinity != nil || affinity.PodAntiAffinity != nil)
  435. }
  436. // AddPod adds pod information to this NodeInfo.
  437. func (n *NodeInfo) AddPod(pod *v1.Pod) {
  438. res, non0CPU, non0Mem := calculateResource(pod)
  439. n.requestedResource.MilliCPU += res.MilliCPU
  440. n.requestedResource.Memory += res.Memory
  441. n.requestedResource.EphemeralStorage += res.EphemeralStorage
  442. if n.requestedResource.ScalarResources == nil && len(res.ScalarResources) > 0 {
  443. n.requestedResource.ScalarResources = map[v1.ResourceName]int64{}
  444. }
  445. for rName, rQuant := range res.ScalarResources {
  446. n.requestedResource.ScalarResources[rName] += rQuant
  447. }
  448. n.nonzeroRequest.MilliCPU += non0CPU
  449. n.nonzeroRequest.Memory += non0Mem
  450. n.pods = append(n.pods, pod)
  451. if hasPodAffinityConstraints(pod) {
  452. n.podsWithAffinity = append(n.podsWithAffinity, pod)
  453. }
  454. // Consume ports when pods added.
  455. n.UpdateUsedPorts(pod, true)
  456. n.generation = nextGeneration()
  457. }
  458. // RemovePod subtracts pod information from this NodeInfo.
  459. func (n *NodeInfo) RemovePod(pod *v1.Pod) error {
  460. k1, err := GetPodKey(pod)
  461. if err != nil {
  462. return err
  463. }
  464. for i := range n.podsWithAffinity {
  465. k2, err := GetPodKey(n.podsWithAffinity[i])
  466. if err != nil {
  467. klog.Errorf("Cannot get pod key, err: %v", err)
  468. continue
  469. }
  470. if k1 == k2 {
  471. // delete the element
  472. n.podsWithAffinity[i] = n.podsWithAffinity[len(n.podsWithAffinity)-1]
  473. n.podsWithAffinity = n.podsWithAffinity[:len(n.podsWithAffinity)-1]
  474. break
  475. }
  476. }
  477. for i := range n.pods {
  478. k2, err := GetPodKey(n.pods[i])
  479. if err != nil {
  480. klog.Errorf("Cannot get pod key, err: %v", err)
  481. continue
  482. }
  483. if k1 == k2 {
  484. // delete the element
  485. n.pods[i] = n.pods[len(n.pods)-1]
  486. n.pods = n.pods[:len(n.pods)-1]
  487. // reduce the resource data
  488. res, non0CPU, non0Mem := calculateResource(pod)
  489. n.requestedResource.MilliCPU -= res.MilliCPU
  490. n.requestedResource.Memory -= res.Memory
  491. n.requestedResource.EphemeralStorage -= res.EphemeralStorage
  492. if len(res.ScalarResources) > 0 && n.requestedResource.ScalarResources == nil {
  493. n.requestedResource.ScalarResources = map[v1.ResourceName]int64{}
  494. }
  495. for rName, rQuant := range res.ScalarResources {
  496. n.requestedResource.ScalarResources[rName] -= rQuant
  497. }
  498. n.nonzeroRequest.MilliCPU -= non0CPU
  499. n.nonzeroRequest.Memory -= non0Mem
  500. // Release ports when remove Pods.
  501. n.UpdateUsedPorts(pod, false)
  502. n.generation = nextGeneration()
  503. return nil
  504. }
  505. }
  506. return fmt.Errorf("no corresponding pod %s in pods of node %s", pod.Name, n.node.Name)
  507. }
  508. func calculateResource(pod *v1.Pod) (res Resource, non0CPU int64, non0Mem int64) {
  509. resPtr := &res
  510. for _, c := range pod.Spec.Containers {
  511. resPtr.Add(c.Resources.Requests)
  512. non0CPUReq, non0MemReq := priorityutil.GetNonzeroRequests(&c.Resources.Requests)
  513. non0CPU += non0CPUReq
  514. non0Mem += non0MemReq
  515. // No non-zero resources for GPUs or opaque resources.
  516. }
  517. return
  518. }
  519. // UpdateUsedPorts updates the UsedPorts of NodeInfo.
  520. func (n *NodeInfo) UpdateUsedPorts(pod *v1.Pod, add bool) {
  521. for j := range pod.Spec.Containers {
  522. container := &pod.Spec.Containers[j]
  523. for k := range container.Ports {
  524. podPort := &container.Ports[k]
  525. if add {
  526. n.usedPorts.Add(podPort.HostIP, string(podPort.Protocol), podPort.HostPort)
  527. } else {
  528. n.usedPorts.Remove(podPort.HostIP, string(podPort.Protocol), podPort.HostPort)
  529. }
  530. }
  531. }
  532. }
  533. // SetNode sets the overall node information.
  534. func (n *NodeInfo) SetNode(node *v1.Node) error {
  535. n.node = node
  536. n.allocatableResource = NewResource(node.Status.Allocatable)
  537. n.taints = node.Spec.Taints
  538. for i := range node.Status.Conditions {
  539. cond := &node.Status.Conditions[i]
  540. switch cond.Type {
  541. case v1.NodeMemoryPressure:
  542. n.memoryPressureCondition = cond.Status
  543. case v1.NodeDiskPressure:
  544. n.diskPressureCondition = cond.Status
  545. case v1.NodePIDPressure:
  546. n.pidPressureCondition = cond.Status
  547. default:
  548. // We ignore other conditions.
  549. }
  550. }
  551. n.TransientInfo = NewTransientSchedulerInfo()
  552. n.generation = nextGeneration()
  553. return nil
  554. }
  555. // RemoveNode removes the overall information about the node.
  556. func (n *NodeInfo) RemoveNode(node *v1.Node) error {
  557. // We don't remove NodeInfo for because there can still be some pods on this node -
  558. // this is because notifications about pods are delivered in a different watch,
  559. // and thus can potentially be observed later, even though they happened before
  560. // node removal. This is handled correctly in cache.go file.
  561. n.node = nil
  562. n.allocatableResource = &Resource{}
  563. n.taints, n.taintsErr = nil, nil
  564. n.memoryPressureCondition = v1.ConditionUnknown
  565. n.diskPressureCondition = v1.ConditionUnknown
  566. n.pidPressureCondition = v1.ConditionUnknown
  567. n.imageStates = make(map[string]*ImageStateSummary)
  568. n.generation = nextGeneration()
  569. return nil
  570. }
  571. // FilterOutPods receives a list of pods and filters out those whose node names
  572. // are equal to the node of this NodeInfo, but are not found in the pods of this NodeInfo.
  573. //
  574. // Preemption logic simulates removal of pods on a node by removing them from the
  575. // corresponding NodeInfo. In order for the simulation to work, we call this method
  576. // on the pods returned from SchedulerCache, so that predicate functions see
  577. // only the pods that are not removed from the NodeInfo.
  578. func (n *NodeInfo) FilterOutPods(pods []*v1.Pod) []*v1.Pod {
  579. node := n.Node()
  580. if node == nil {
  581. return pods
  582. }
  583. filtered := make([]*v1.Pod, 0, len(pods))
  584. for _, p := range pods {
  585. if p.Spec.NodeName != node.Name {
  586. filtered = append(filtered, p)
  587. continue
  588. }
  589. // If pod is on the given node, add it to 'filtered' only if it is present in nodeInfo.
  590. podKey, _ := GetPodKey(p)
  591. for _, np := range n.Pods() {
  592. npodkey, _ := GetPodKey(np)
  593. if npodkey == podKey {
  594. filtered = append(filtered, p)
  595. break
  596. }
  597. }
  598. }
  599. return filtered
  600. }
  601. // GetPodKey returns the string key of a pod.
  602. func GetPodKey(pod *v1.Pod) (string, error) {
  603. uid := string(pod.UID)
  604. if len(uid) == 0 {
  605. return "", errors.New("Cannot get cache key for pod with empty UID")
  606. }
  607. return uid, nil
  608. }
  609. // Filter implements PodFilter interface. It returns false only if the pod node name
  610. // matches NodeInfo.node and the pod is not found in the pods list. Otherwise,
  611. // returns true.
  612. func (n *NodeInfo) Filter(pod *v1.Pod) bool {
  613. if pod.Spec.NodeName != n.node.Name {
  614. return true
  615. }
  616. for _, p := range n.pods {
  617. if p.Name == pod.Name && p.Namespace == pod.Namespace {
  618. return true
  619. }
  620. }
  621. return false
  622. }