k8s.io/kubernetes@v1.29.3/pkg/kubelet/cm/topologymanager/scope.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package topologymanager 18 19 import ( 20 "sync" 21 22 "k8s.io/api/core/v1" 23 "k8s.io/klog/v2" 24 "k8s.io/kubernetes/pkg/kubelet/cm/admission" 25 "k8s.io/kubernetes/pkg/kubelet/cm/containermap" 26 "k8s.io/kubernetes/pkg/kubelet/lifecycle" 27 ) 28 29 const ( 30 // containerTopologyScope specifies the TopologyManagerScope per container. 31 containerTopologyScope = "container" 32 // podTopologyScope specifies the TopologyManagerScope per pod. 33 podTopologyScope = "pod" 34 // noneTopologyScope specifies the TopologyManagerScope when topologyPolicyName is none. 35 noneTopologyScope = "none" 36 ) 37 38 type podTopologyHints map[string]map[string]TopologyHint 39 40 // Scope interface for Topology Manager 41 type Scope interface { 42 Name() string 43 GetPolicy() Policy 44 Admit(pod *v1.Pod) lifecycle.PodAdmitResult 45 // AddHintProvider adds a hint provider to manager to indicate the hint provider 46 // wants to be consoluted with when making topology hints 47 AddHintProvider(h HintProvider) 48 // AddContainer adds pod to Manager for tracking 49 AddContainer(pod *v1.Pod, container *v1.Container, containerID string) 50 // RemoveContainer removes pod from Manager tracking 51 RemoveContainer(containerID string) error 52 // Store is the interface for storing pod topology hints 53 Store 54 } 55 56 type scope struct { 57 mutex sync.Mutex 58 name string 59 // Mapping of a Pods mapping of Containers and their TopologyHints 60 // Indexed by PodUID to ContainerName 61 podTopologyHints podTopologyHints 62 // The list of components registered with the Manager 63 hintProviders []HintProvider 64 // Topology Manager Policy 65 policy Policy 66 // Mapping of (PodUid, ContainerName) to ContainerID for Adding/Removing Pods from PodTopologyHints mapping 67 podMap containermap.ContainerMap 68 } 69 70 func (s *scope) Name() string { 71 return s.name 72 } 73 74 func (s *scope) getTopologyHints(podUID string, containerName string) TopologyHint { 75 s.mutex.Lock() 76 defer s.mutex.Unlock() 77 return s.podTopologyHints[podUID][containerName] 78 } 79 80 func (s *scope) setTopologyHints(podUID string, containerName string, th TopologyHint) { 81 s.mutex.Lock() 82 defer s.mutex.Unlock() 83 84 if s.podTopologyHints[podUID] == nil { 85 s.podTopologyHints[podUID] = make(map[string]TopologyHint) 86 } 87 s.podTopologyHints[podUID][containerName] = th 88 } 89 90 func (s *scope) GetAffinity(podUID string, containerName string) TopologyHint { 91 return s.getTopologyHints(podUID, containerName) 92 } 93 94 func (s *scope) GetPolicy() Policy { 95 return s.policy 96 } 97 98 func (s *scope) AddHintProvider(h HintProvider) { 99 s.hintProviders = append(s.hintProviders, h) 100 } 101 102 // It would be better to implement this function in topologymanager instead of scope 103 // but topologymanager do not track mapping anymore 104 func (s *scope) AddContainer(pod *v1.Pod, container *v1.Container, containerID string) { 105 s.mutex.Lock() 106 defer s.mutex.Unlock() 107 108 s.podMap.Add(string(pod.UID), container.Name, containerID) 109 } 110 111 // It would be better to implement this function in topologymanager instead of scope 112 // but topologymanager do not track mapping anymore 113 func (s *scope) RemoveContainer(containerID string) error { 114 s.mutex.Lock() 115 defer s.mutex.Unlock() 116 117 klog.InfoS("RemoveContainer", "containerID", containerID) 118 // Get the podUID and containerName associated with the containerID to be removed and remove it 119 podUIDString, containerName, err := s.podMap.GetContainerRef(containerID) 120 if err != nil { 121 return nil 122 } 123 s.podMap.RemoveByContainerID(containerID) 124 125 // In cases where a container has been restarted, it's possible that the same podUID and 126 // containerName are already associated with a *different* containerID now. Only remove 127 // the TopologyHints associated with that podUID and containerName if this is not true 128 if _, err := s.podMap.GetContainerID(podUIDString, containerName); err != nil { 129 delete(s.podTopologyHints[podUIDString], containerName) 130 if len(s.podTopologyHints[podUIDString]) == 0 { 131 delete(s.podTopologyHints, podUIDString) 132 } 133 } 134 135 return nil 136 } 137 138 func (s *scope) admitPolicyNone(pod *v1.Pod) lifecycle.PodAdmitResult { 139 for _, container := range append(pod.Spec.InitContainers, pod.Spec.Containers...) { 140 err := s.allocateAlignedResources(pod, &container) 141 if err != nil { 142 return admission.GetPodAdmitResult(err) 143 } 144 } 145 return admission.GetPodAdmitResult(nil) 146 } 147 148 // It would be better to implement this function in topologymanager instead of scope 149 // but topologymanager do not track providers anymore 150 func (s *scope) allocateAlignedResources(pod *v1.Pod, container *v1.Container) error { 151 for _, provider := range s.hintProviders { 152 err := provider.Allocate(pod, container) 153 if err != nil { 154 return err 155 } 156 } 157 return nil 158 }