github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/orm/executor/executor.go (about) 1 /* 2 Copyright 2022 The Katalyst 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 executor 18 19 import ( 20 "fmt" 21 22 v1 "k8s.io/api/core/v1" 23 "k8s.io/klog/v2" 24 "k8s.io/kubelet/pkg/apis/resourceplugin/v1alpha1" 25 26 "github.com/kubewharf/katalyst-core/pkg/agent/qrm-plugins/util" 27 "github.com/kubewharf/katalyst-core/pkg/util/cgroup/common" 28 cgroupmgr "github.com/kubewharf/katalyst-core/pkg/util/cgroup/manager" 29 "github.com/kubewharf/katalyst-core/pkg/util/native" 30 ) 31 32 type Executor interface { 33 UpdateContainerResources(pod *v1.Pod, container *v1.Container, resourceAllocation map[string]*v1alpha1.ResourceAllocationInfo) error 34 } 35 36 type Impl struct { 37 cgroupManager cgroupmgr.Manager 38 } 39 40 func NewExecutor(cgroupManager cgroupmgr.Manager) Executor { 41 return &Impl{ 42 cgroupManager: cgroupManager, 43 } 44 } 45 46 // UpdateContainerResources update container resources by resourceAllocation 47 func (ei *Impl) UpdateContainerResources(pod *v1.Pod, container *v1.Container, resourceAllocation map[string]*v1alpha1.ResourceAllocationInfo) error { 48 if pod == nil || container == nil { 49 klog.Warningf("UpdateContainerResources, pod or container is nil") 50 return nil 51 } 52 if len(resourceAllocation) == 0 { 53 return fmt.Errorf("empty resourceAllocation for pod: %v, container: %v", pod.Name, container.Name) 54 } 55 56 CPUSetData := &common.CPUSetData{} 57 58 for _, resourceAllocationInfo := range resourceAllocation { 59 switch resourceAllocationInfo.OciPropertyName { 60 case util.OCIPropertyNameCPUSetCPUs: 61 if resourceAllocationInfo.AllocationResult != "" { 62 CPUSetData.CPUs = resourceAllocationInfo.AllocationResult 63 } 64 case util.OCIPropertyNameCPUSetMems: 65 if resourceAllocationInfo.AllocationResult != "" { 66 CPUSetData.Mems = resourceAllocationInfo.AllocationResult 67 } 68 default: 69 70 } 71 } 72 73 absCgroupPath, err := ei.containerCgroupPath(pod, container) 74 if err != nil { 75 klog.Errorf("[ORM] containerCgroupPath fail, pod: %v, container: %v, err: %v", pod.Name, container.Name, err) 76 return err 77 } 78 79 err = ei.commitCPUSet(absCgroupPath, CPUSetData) 80 if err != nil { 81 klog.Errorf("[ORM] commitCPUSet fail, pod: %v, container: %v, err: %v", pod.Name, container.Name, err) 82 return err 83 } 84 85 return nil 86 } 87 88 // applyCPUSet apply CPUSet data by cgroupManager 89 func (ei *Impl) applyCPUSet(absCgroupPath string, data *common.CPUSetData) error { 90 return ei.cgroupManager.ApplyCPUSet(absCgroupPath, data) 91 } 92 93 // commitCPUSet rollback if any data apply failed in data 94 // consider if such operation is necessary, for runc does not guarantee the atomicity of cgroup subsystem settings either 95 // https://github.com/opencontainers/runc/blob/main/libcontainer/cgroups/fs/cpuset.go#L27 96 func (ei *Impl) commitCPUSet(absCgroupPath string, data *common.CPUSetData) error { 97 CPUSetStats, err := ei.cgroupManager.GetCPUSet(absCgroupPath) 98 if err != nil { 99 return err 100 } 101 102 err = ei.applyCPUSet(absCgroupPath, data) 103 if err != nil { 104 // rollback 105 rollbackErr := ei.applyCPUSet(absCgroupPath, &common.CPUSetData{ 106 CPUs: CPUSetStats.CPUs, 107 Mems: CPUSetStats.Mems, 108 }) 109 if rollbackErr == nil { 110 err = fmt.Errorf("applyCPUSet fail, CPUSet rollback, err: %v", err) 111 return err 112 } else { 113 err = fmt.Errorf("applyCPUSet fail, rollback fail, err: %v, rollbackErr: %v", err, rollbackErr) 114 return err 115 } 116 } 117 118 return nil 119 } 120 121 func (ei *Impl) containerCgroupPath(pod *v1.Pod, container *v1.Container) (string, error) { 122 containerID, err := native.GetContainerID(pod, container.Name) 123 if err != nil { 124 return "", err 125 } 126 127 absCgroupPath, err := common.GetContainerAbsCgroupPath(common.CgroupSubsysCPUSet, string(pod.UID), containerID) 128 if err != nil { 129 return "", err 130 } 131 132 return absCgroupPath, nil 133 }