├── .github └── dependabot.yml ├── .gitignore ├── .golangci.yaml ├── .trivyignore ├── LICENSE ├── Makefile ├── PROJECT ├── README.md ├── SECURITY.md ├── api └── v1 │ ├── common.go │ ├── cstates_types.go │ ├── groupversion_info.go │ ├── powerconfig_types.go │ ├── powernode_types.go │ ├── powerpod_types.go │ ├── powerprofile_types.go │ ├── powerworkload_types.go │ ├── timeofday_types.go │ ├── timeofdaycronjob_types.go │ ├── uncore_types.go │ └── zz_generated.deepcopy.go ├── build ├── Dockerfile ├── Dockerfile.nodeagent ├── manager │ └── main.go ├── manifests │ ├── ocp │ │ └── power-node-agent-ds.yaml │ └── power-node-agent-ds.yaml └── nodeagent │ └── main.go ├── ci ├── sdle │ ├── Jenkinsfile │ └── sdle-tools.yaml └── verify │ └── Jenkinsfile ├── config ├── certmanager │ ├── certificate.yaml │ ├── kustomization.yaml │ └── kustomizeconfig.yaml ├── crd │ ├── bases │ │ ├── power.intel.com_cstates.yaml │ │ ├── power.intel.com_powerconfigs.yaml │ │ ├── power.intel.com_powernodes.yaml │ │ ├── power.intel.com_powerpods.yaml │ │ ├── power.intel.com_powerprofiles.yaml │ │ ├── power.intel.com_powerworkloads.yaml │ │ ├── power.intel.com_timeofdaycronjobs.yaml │ │ ├── power.intel.com_timeofdays.yaml │ │ └── power.intel.com_uncores.yaml │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ └── patches │ │ ├── cainjection_in_configs.yaml │ │ ├── cainjection_in_cstates.yaml │ │ ├── cainjection_in_pods.yaml │ │ ├── cainjection_in_powerconfigs.yaml │ │ ├── cainjection_in_powernodes.yaml │ │ ├── cainjection_in_powerpods.yaml │ │ ├── cainjection_in_powerprofiles.yaml │ │ ├── cainjection_in_powerworkloads.yaml │ │ ├── cainjection_in_profiles.yaml │ │ ├── cainjection_in_timeofdaycronjobs.yaml │ │ ├── cainjection_in_timeofdays.yaml │ │ ├── cainjection_in_uncores.yaml │ │ ├── webhook_in_configs.yaml │ │ ├── webhook_in_cstates.yaml │ │ ├── webhook_in_pods.yaml │ │ ├── webhook_in_powerconfigs.yaml │ │ ├── webhook_in_powernodes.yaml │ │ ├── webhook_in_powerpods.yaml │ │ ├── webhook_in_powerprofiles.yaml │ │ ├── webhook_in_powerworkloads.yaml │ │ ├── webhook_in_profiles.yaml │ │ ├── webhook_in_timeofdaycronjobs.yaml │ │ ├── webhook_in_timeofdays.yaml │ │ └── webhook_in_uncores.yaml ├── default │ ├── kustomization.yaml │ ├── manager_auth_proxy_patch.yaml │ ├── manager_webhook_patch.yaml │ └── webhookcainjection_patch.yaml ├── manager │ ├── kustomization.yaml │ ├── manager.yaml │ └── ocp │ │ ├── kustomization.yaml │ │ └── manager.yaml ├── manifests │ ├── bases │ │ └── intel-kubernetes-power-manager.clusterserviceversion.yaml │ └── kustomization.yaml ├── prometheus │ ├── kustomization.yaml │ └── monitor.yaml ├── rbac │ ├── auth_proxy_client_clusterrole.yaml │ ├── auth_proxy_role.yaml │ ├── auth_proxy_role_binding.yaml │ ├── auth_proxy_service.yaml │ ├── cstates_editor_role.yaml │ ├── cstates_viewer_role.yaml │ ├── kustomization.yaml │ ├── namespace.yaml │ ├── ocp │ │ ├── rbac.yaml │ │ └── role.yaml │ ├── rbac.yaml │ ├── role.yaml │ ├── uncore_editor_role.yaml │ ├── uncore_viewer_role.yaml │ ├── user_role.yaml │ └── user_role_binding.yaml ├── samples │ ├── kustomization.yaml │ ├── power_v1_cstates.yaml │ ├── power_v1_powerconfig.yaml │ ├── power_v1_shared_profile.yaml │ ├── power_v1_shared_workload.yaml │ ├── power_v1_timeofday.yaml │ └── power_v1_uncore.yaml ├── scorecard │ ├── bases │ │ └── config.yaml │ ├── kustomization.yaml │ └── patches │ │ ├── basic.config.yaml │ │ └── olm.config.yaml └── webhook │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ └── service.yaml ├── controllers ├── common.go ├── common_test.go ├── cstates_controller.go ├── cstates_controller_test.go ├── powerconfig_controller.go ├── powerconfig_controller_test.go ├── powernode_controller.go ├── powernode_controller_test.go ├── powerpod_controller.go ├── powerpod_controller_test.go ├── powerprofile_controller.go ├── powerprofile_controller_test.go ├── powerworkload_controller.go ├── powerworkload_controller_test.go ├── test_helper_test.go ├── timeofday_controller.go ├── timeofday_controller_test.go ├── timeofdaycronjob_controller.go ├── timeofdaycronjob_controller_test.go ├── uncore_controller.go └── uncore_controller_test.go ├── diagrams-docs ├── README.md ├── TimeOfDay-sequence.png ├── TimeOfDay-sequence.puml ├── cstate-sequence.png ├── cstate-sequence.puml ├── pm-sequence.png ├── pm-sequence.puml ├── power-arch.png ├── power-arch.puml ├── power-com.png ├── power-com.puml ├── scaling-driver-sequence.png ├── scaling-driver-sequence.puml ├── uncore-sequence.png └── uncore-sequence.puml ├── examples ├── example-cstates.yaml ├── example-pod.yaml ├── example-powerconfig.yaml ├── example-shared-profile.yaml ├── example-shared-workload.yaml ├── example-timeofday.yaml └── example-uncore.yaml ├── go.mod ├── go.sum ├── hack └── boilerplate.go.txt ├── helm ├── crds │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ │ ├── _helpers.tpl │ │ └── crds.yaml │ └── values.yaml ├── kubernetes-power-manager │ ├── Chart.lock │ ├── Chart.yaml │ ├── templates │ │ ├── _helpers.tpl │ │ └── template.yaml │ └── values.yaml └── manager-chart-library │ ├── .helmignore │ ├── Chart.yaml │ └── templates │ ├── _deployment.tpl │ ├── _helpers.tpl │ ├── _namespace.tpl │ ├── _new-shared-power-profile.tpl │ ├── _power-config.tpl │ ├── _rbac.tpl │ └── _shared-power-profile.tpl ├── pkg ├── cpuset │ ├── cpuset.go │ └── cpuset_test.go ├── podresourcesclient │ ├── podresourcesclient.go │ └── podresourcesclient_test.go ├── podstate │ ├── podstate.go │ └── podstate_test.go ├── state │ ├── state.go │ └── state_test.go └── util │ ├── util.go │ └── util_test.go └── testbin ├── setup-envtest.sh └── spam_crds.sh /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gomod" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | #bin 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Kubernetes Generated files - skip generated files, except for vendored files 17 | 18 | !vendor/**/zz_generated.* 19 | 20 | # editor and IDE paraphernalia 21 | .idea 22 | *.swp 23 | *.swo 24 | *~ 25 | 26 | go.work 27 | go.work.sum -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | run: 2 | skip-files: 3 | # exclude tests 4 | - "_test\\.go$" 5 | output: 6 | sort-results: true 7 | -------------------------------------------------------------------------------- /.trivyignore: -------------------------------------------------------------------------------- 1 | # Power Manager needs write access to root files 2 | AVD-KSV-0014 3 | # Power Manager needs securityContext.privileged 4 | AVD-KSV-0017 5 | # complains about wildcard in rbac but we need full privelages for those resources 6 | AVD-KSV-0045 7 | # libnghttp2 issue with redhat image. Latest base image not fixed yet 8 | CVE-2024-27316 9 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | domain: intel.com 2 | layout: 3 | - go.kubebuilder.io/v2 4 | plugins: 5 | go.sdk.operatorframework.io/v2-alpha: {} 6 | projectName: intel-kubernetes-power-manager 7 | repo: github.com/intel/kubernetes-power-manager 8 | resources: 9 | - domain: intel.com 10 | group: power 11 | kind: PowerNode 12 | path: github.com/intel/kubernetes-power-manager/api/v1 13 | version: v1 14 | - domain: intel.com 15 | group: power 16 | kind: PowerProfile 17 | path: github.com/intel/kubernetes-power-manager/api/v1 18 | version: v1 19 | - domain: intel.com 20 | group: power 21 | kind: PowerPod 22 | path: github.com/intel/kubernetes-power-manager/api/v1 23 | version: v1 24 | - domain: intel.com 25 | group: power 26 | kind: PowerConfig 27 | path: github.com/intel/kubernetes-power-manager/api/v1 28 | version: v1 29 | - api: 30 | crdVersion: v1beta1 31 | namespaced: true 32 | controller: true 33 | domain: intel.com 34 | group: power 35 | kind: Time 36 | path: github.com/intel/kubernetes-power-manager/api/v1 37 | version: v1 38 | - api: 39 | crdVersion: v1beta1 40 | namespaced: true 41 | controller: true 42 | domain: intel.com 43 | group: power 44 | kind: TimeOfDay 45 | path: github.com/intel/kubernetes-power-manager/api/v1 46 | version: v1 47 | version: "3" 48 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 19 | 20 | # Security Policy 21 | 22 | ## Report a Vulnerability 23 | 24 | Please report security issues or vulnerabilities to the [Intel® Security Center]. 25 | 26 | For more information on how Intel® works to resolve security issues, see 27 | [Vulnerability Handling Guidelines]. 28 | 29 | [Intel® Security Center]:https://www.intel.com/security 30 | 31 | [Vulnerability Handling Guidelines]:https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html 32 | -------------------------------------------------------------------------------- /api/v1/common.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | "k8s.io/apimachinery/pkg/runtime" 22 | ) 23 | 24 | type StatusErrors struct { 25 | Errors []string `json:"errors,omitempty"` 26 | } 27 | 28 | // +kubebuilder:object:generate=false 29 | type PowerCRWithStatusErrors interface { 30 | metav1.Object 31 | runtime.Object 32 | SetStatusErrors(errs *[]string) 33 | GetStatusErrors() *[]string 34 | } 35 | -------------------------------------------------------------------------------- /api/v1/cstates_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 24 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 25 | 26 | // CStatesSpec defines the desired state of CStates 27 | type CStatesSpec struct { 28 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 29 | // Important: Run "make" to regenerate code after modifying this file 30 | 31 | SharedPoolCStates map[string]bool `json:"sharedPoolCStates,omitempty"` 32 | ExclusivePoolCStates map[string]map[string]bool `json:"exclusivePoolCStates,omitempty"` 33 | IndividualCoreCStates map[string]map[string]bool `json:"individualCoreCStates,omitempty"` 34 | } 35 | 36 | // CStatesStatus defines the observed state of CStates 37 | type CStatesStatus struct { 38 | StatusErrors `json:",inline,omitempty"` 39 | } 40 | 41 | //+kubebuilder:object:root=true 42 | //+kubebuilder:subresource:status 43 | 44 | // CStates is the Schema for the cstates API 45 | type CStates struct { 46 | metav1.TypeMeta `json:",inline"` 47 | metav1.ObjectMeta `json:"metadata,omitempty"` 48 | 49 | Spec CStatesSpec `json:"spec,omitempty"` 50 | Status CStatesStatus `json:"status,omitempty"` 51 | } 52 | 53 | //+kubebuilder:object:root=true 54 | 55 | // CStatesList contains a list of CStates 56 | type CStatesList struct { 57 | metav1.TypeMeta `json:",inline"` 58 | metav1.ListMeta `json:"metadata,omitempty"` 59 | Items []CStates `json:"items"` 60 | } 61 | 62 | func (csts *CStates) SetStatusErrors(errs *[]string) { 63 | csts.Status.Errors = *errs 64 | } 65 | 66 | func (csts *CStates) GetStatusErrors() *[]string { 67 | return &csts.Status.Errors 68 | } 69 | 70 | func init() { 71 | SchemeBuilder.Register(&CStates{}, &CStatesList{}) 72 | } 73 | -------------------------------------------------------------------------------- /api/v1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 contains API Schema definitions for the power v1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=power.intel.com 20 | package v1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "power.intel.com", Version: "v1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /api/v1/powerconfig_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 24 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 25 | 26 | // PowerConfigSpec defines the desired state of PowerConfig 27 | type PowerConfigSpec struct { 28 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 29 | // Important: Run "make" to regenerate code after modifying this file 30 | 31 | // The label on the Nodes you the Operator will look for to deploy the Node Agent 32 | PowerNodeSelector map[string]string `json:"powerNodeSelector,omitempty"` 33 | 34 | // The PowerProfiles that will be created by the Operator 35 | PowerProfiles []string `json:"powerProfiles,omitempty"` 36 | 37 | // The CustomDevices include alternative devices that represent other resources 38 | CustomDevices []string `json:"customDevices,omitempty"` 39 | } 40 | 41 | // PowerConfigStatus defines the observed state of PowerConfig 42 | type PowerConfigStatus struct { 43 | // The Nodes that the Node Agent has been deployed to 44 | Nodes []string `json:"nodes,omitempty"` 45 | StatusErrors `json:",inline,omitempty"` 46 | } 47 | 48 | // +kubebuilder:object:root=true 49 | // +kubebuilder:subresource:status 50 | 51 | // PowerConfig is the Schema for the powerconfigs API 52 | type PowerConfig struct { 53 | metav1.TypeMeta `json:",inline"` 54 | metav1.ObjectMeta `json:"metadata,omitempty"` 55 | 56 | Spec PowerConfigSpec `json:"spec,omitempty"` 57 | Status PowerConfigStatus `json:"status,omitempty"` 58 | } 59 | 60 | // +kubebuilder:object:root=true 61 | 62 | // PowerConfigList contains a list of PowerConfig 63 | type PowerConfigList struct { 64 | metav1.TypeMeta `json:",inline"` 65 | metav1.ListMeta `json:"metadata,omitempty"` 66 | Items []PowerConfig `json:"items"` 67 | } 68 | 69 | func init() { 70 | SchemeBuilder.Register(&PowerConfig{}, &PowerConfigList{}) 71 | } 72 | -------------------------------------------------------------------------------- /api/v1/powernode_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 24 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 25 | 26 | // PowerNodeSpec defines the desired state of PowerNode 27 | type PowerNodeSpec struct { 28 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 29 | // Important: Run "make" to regenerate code after modifying this file 30 | 31 | // The name of the node 32 | NodeName string `json:"nodeName,omitempty"` 33 | 34 | PowerProfiles []string `json:"powerProfiles,omitempty"` 35 | 36 | PowerWorkloads []string `json:"powerWorkloads,omitempty"` 37 | 38 | SharedPool string `json:"sharedPool,omitempty"` 39 | 40 | UnaffectedCores string `json:"unaffectedCores,omitempty"` 41 | 42 | ReservedPools []string `json:"reservedPools,omitempty"` 43 | 44 | // Information about the containers in the cluster utilizing some PowerWorkload 45 | PowerContainers []Container `json:"powerContainers,omitempty"` 46 | 47 | // The CustomDevices include alternative devices that represent other resources 48 | CustomDevices []string `json:"customDevices,omitempty"` 49 | 50 | // The PowerProfiles in the cluster that are currently being used by Pods 51 | //ActiveProfiles map[string]bool `json:"activeProfiles,omitempty"` 52 | 53 | // Information about the active PowerWorkloads in the cluster 54 | //ActiveWorkloads []WorkloadInfo `json:"activeWorkloads,omitempty"` 55 | 56 | // Shows what cores are in the Default and Shared Pools 57 | //SharedPool SharedPoolInfo `json:"sharedPools,omitempty"` 58 | 59 | // The CPUs that are not effected by any Power Profiles 60 | //UneffectedCpus []int `json:"uneffectedCpus,omitempty"` 61 | } 62 | 63 | // PowerNodeStatus defines the observed state of PowerNode 64 | type PowerNodeStatus struct { 65 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 66 | // Important: Run "make" to regenerate code after modifying this file 67 | 68 | // The state of the Guaranteed Pods and Shared Pool in a cluster 69 | PowerNodeCPUState `json:"powerNodeCPUState,omitempty"` 70 | } 71 | 72 | type PowerNodeCPUState struct { 73 | // The CPUs that are currently part of the Shared pool on a Node 74 | SharedPool []uint `json:"sharedPool,omitempty"` 75 | 76 | // Pods that are requesting CPUs in the Guaranteed QoS class 77 | GuaranteedPods []GuaranteedPod `json:"guaranteedPods,omitempty"` 78 | } 79 | 80 | type GuaranteedPod struct { 81 | // The name of the Node the Pod is running on 82 | Node string `json:"node,omitempty"` 83 | 84 | // The name of the Pod 85 | Name string `json:"name,omitempty"` 86 | 87 | Namespace string `json:"namespace,omitempty"` 88 | 89 | // The UID of the Pod 90 | UID string `json:"uid,omitempty"` 91 | 92 | // The Containers that are running in the Pod 93 | Containers []Container `json:"containers,omitempty"` 94 | } 95 | 96 | type Container struct { 97 | // The name of the Container 98 | Name string `json:"name,omitempty"` 99 | 100 | // The ID of the Container 101 | Id string `json:"id,omitempty"` 102 | 103 | // The name of the Pod the Container is running on 104 | Pod string `json:"pod,omitempty"` 105 | 106 | // The exclusive CPUs given to this Container 107 | ExclusiveCPUs []uint `json:"exclusiveCpus,omitempty"` 108 | 109 | // The PowerProfile that the Container is utilizing 110 | PowerProfile string `json:"powerProfile,omitempty"` 111 | 112 | // The PowerWorkload that the Container is utilizing 113 | Workload string `json:"workload,omitempty"` 114 | } 115 | 116 | type WorkloadInfo struct { 117 | // The name of the PowerWorkload 118 | Name string `json:"name,omitempty"` 119 | 120 | // The CPUs that are utilizing the PowerWorkload 121 | CpuIds []uint `json:"cores,omitempty"` 122 | } 123 | 124 | type SharedPoolInfo struct { 125 | // The name or either Default or Shared pool 126 | Profile string `json:"name,omitempty"` 127 | 128 | // The cores that are a part of this Shared Pool 129 | CpuIds []uint `json:"sharedPoolCpuIds,omitempty"` 130 | } 131 | 132 | // +kubebuilder:object:root=true 133 | // +kubebuilder:subresource:status 134 | 135 | // PowerNode is the Schema for the powernodes API 136 | type PowerNode struct { 137 | metav1.TypeMeta `json:",inline"` 138 | metav1.ObjectMeta `json:"metadata,omitempty"` 139 | 140 | Spec PowerNodeSpec `json:"spec,omitempty"` 141 | Status PowerNodeStatus `json:"status,omitempty"` 142 | } 143 | 144 | // +kubebuilder:object:root=true 145 | 146 | // PowerNodeList contains a list of PowerNode 147 | type PowerNodeList struct { 148 | metav1.TypeMeta `json:",inline"` 149 | metav1.ListMeta `json:"metadata,omitempty"` 150 | Items []PowerNode `json:"items"` 151 | } 152 | 153 | func init() { 154 | SchemeBuilder.Register(&PowerNode{}, &PowerNodeList{}) 155 | } 156 | -------------------------------------------------------------------------------- /api/v1/powerpod_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 24 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 25 | 26 | // PowerPodSpec defines the desired state of PowerPod 27 | type PowerPodSpec struct { 28 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 29 | // Important: Run "make" to regenerate code after modifying this file 30 | } 31 | 32 | // PowerPodStatus defines the observed state of PowerPod 33 | type PowerPodStatus struct { 34 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 35 | // Important: Run "make" to regenerate code after modifying this file 36 | } 37 | 38 | // +kubebuilder:object:root=true 39 | // +kubebuilder:subresource:status 40 | 41 | // PowerPod is the Schema for the powerpods API 42 | type PowerPod struct { 43 | metav1.TypeMeta `json:",inline"` 44 | metav1.ObjectMeta `json:"metadata,omitempty"` 45 | 46 | Spec PowerPodSpec `json:"spec,omitempty"` 47 | Status PowerPodStatus `json:"status,omitempty"` 48 | } 49 | 50 | // +kubebuilder:object:root=true 51 | 52 | // PowerPodList contains a list of PowerPod 53 | type PowerPodList struct { 54 | metav1.TypeMeta `json:",inline"` 55 | metav1.ListMeta `json:"metadata,omitempty"` 56 | Items []PowerPod `json:"items"` 57 | } 58 | 59 | func init() { 60 | SchemeBuilder.Register(&PowerPod{}, &PowerPodList{}) 61 | } 62 | -------------------------------------------------------------------------------- /api/v1/powerprofile_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // PowerProfileSpec defines the desired state of PowerProfile 24 | type PowerProfileSpec struct { 25 | // Important: Run "make" to regenerate code after modifying this file 26 | 27 | // The name of the PowerProfile 28 | Name string `json:"name"` 29 | 30 | Shared bool `json:"shared,omitempty"` 31 | // Max frequency cores can run at 32 | Max int `json:"max,omitempty"` 33 | 34 | // Min frequency cores can run at 35 | Min int `json:"min,omitempty"` 36 | 37 | // The priority value associated with this Power Profile 38 | Epp string `json:"epp,omitempty"` 39 | 40 | // Governor to be used 41 | //+kubebuilder:default=powersave 42 | Governor string `json:"governor,omitempty"` 43 | } 44 | 45 | // PowerProfileStatus defines the observed state of PowerProfile 46 | type PowerProfileStatus struct { 47 | // The ID given to the power profile 48 | ID int `json:"id,omitempty"` 49 | StatusErrors `json:",inline,omitempty"` 50 | } 51 | 52 | // +kubebuilder:object:root=true 53 | // +kubebuilder:subresource:status 54 | 55 | // PowerProfile is the Schema for the powerprofiles API 56 | type PowerProfile struct { 57 | metav1.TypeMeta `json:",inline"` 58 | metav1.ObjectMeta `json:"metadata,omitempty"` 59 | 60 | Spec PowerProfileSpec `json:"spec,omitempty"` 61 | Status PowerProfileStatus `json:"status,omitempty"` 62 | } 63 | 64 | // +kubebuilder:object:root=true 65 | 66 | // PowerProfileList contains a list of PowerProfile 67 | type PowerProfileList struct { 68 | metav1.TypeMeta `json:",inline"` 69 | metav1.ListMeta `json:"metadata,omitempty"` 70 | Items []PowerProfile `json:"items"` 71 | } 72 | 73 | func (prfl *PowerProfile) SetStatusErrors(errs *[]string) { 74 | prfl.Status.Errors = *errs 75 | } 76 | func (prfl *PowerProfile) GetStatusErrors() *[]string { 77 | return &prfl.Status.Errors 78 | } 79 | 80 | func init() { 81 | SchemeBuilder.Register(&PowerProfile{}, &PowerProfileList{}) 82 | } 83 | -------------------------------------------------------------------------------- /api/v1/powerworkload_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 24 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 25 | 26 | type WorkloadNode struct { 27 | Name string `json:"name,omitempty"` 28 | 29 | Containers []Container `json:"containers,omitempty"` 30 | 31 | CpuIds []uint `json:"cpuIds,omitempty"` 32 | } 33 | 34 | // PowerWorkloadSpec defines the desired state of PowerWorkload 35 | type PowerWorkloadSpec struct { 36 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 37 | // Important: Run "make" to regenerate code after modifying this file 38 | 39 | // The name of the workload 40 | Name string `json:"name"` 41 | 42 | // AllCores determines if the Workload is to be applied to all cores (i.e. use the Default Workload) 43 | AllCores bool `json:"allCores,omitempty"` 44 | 45 | // Reserved CPUs are the CPUs that have been reserved by Kubelet for use by the Kubernetes admin process 46 | // This list must match the list in the user's Kubelet configuration 47 | ReservedCPUs []ReservedSpec `json:"reservedCPUs,omitempty"` 48 | 49 | // The labels signifying the nodes the user wants to use 50 | PowerNodeSelector map[string]string `json:"powerNodeSelector,omitempty"` 51 | 52 | // Holds the info on the node name and cpu ids for each node 53 | //Node NodeInfo `json:"nodeInfo,omitempty"` 54 | 55 | Node WorkloadNode `json:"workloadNodes,omitempty"` 56 | 57 | // PowerProfile is the Profile that this PowerWorkload is based on 58 | PowerProfile string `json:"powerProfile,omitempty"` 59 | } 60 | 61 | type ReservedSpec struct { 62 | Cores []uint `json:"cores"` 63 | PowerProfile string `json:"powerProfile,omitempty"` 64 | } 65 | 66 | // PowerWorkloadStatus defines the observed state of PowerWorkload 67 | type PowerWorkloadStatus struct { 68 | // The Node that this Shared PowerWorkload is associated with 69 | Node string `json:"node:,omitempty"` 70 | StatusErrors `json:",inline,omitempty"` 71 | } 72 | 73 | // +kubebuilder:object:root=true 74 | // +kubebuilder:subresource:status 75 | 76 | // PowerWorkload is the Schema for the powerworkloads API 77 | type PowerWorkload struct { 78 | metav1.TypeMeta `json:",inline"` 79 | metav1.ObjectMeta `json:"metadata,omitempty"` 80 | 81 | Spec PowerWorkloadSpec `json:"spec,omitempty"` 82 | Status PowerWorkloadStatus `json:"status,omitempty"` 83 | } 84 | 85 | // +kubebuilder:object:root=true 86 | 87 | // PowerWorkloadList contains a list of PowerWorkload 88 | type PowerWorkloadList struct { 89 | metav1.TypeMeta `json:",inline"` 90 | metav1.ListMeta `json:"metadata,omitempty"` 91 | Items []PowerWorkload `json:"items"` 92 | } 93 | 94 | func (wrkld *PowerWorkload) SetStatusErrors(errs *[]string) { 95 | wrkld.Status.Errors = *errs 96 | } 97 | 98 | func (wrkld *PowerWorkload) GetStatusErrors() *[]string { 99 | return &wrkld.Status.Errors 100 | } 101 | 102 | func init() { 103 | SchemeBuilder.Register(&PowerWorkload{}, &PowerWorkloadList{}) 104 | } 105 | -------------------------------------------------------------------------------- /api/v1/timeofday_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 24 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 25 | 26 | type ScheduleInfo struct { 27 | Time string `json:"time"` 28 | 29 | PowerProfile *string `json:"powerProfile,omitempty"` 30 | Pods *[]PodInfo `json:"pods,omitempty"` 31 | CState *CStatesSpec `json:"cState,omitempty"` 32 | } 33 | 34 | // TimeOfDaySpec defines the desired state of TimeOfDay 35 | type TimeOfDaySpec struct { 36 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 37 | // Important: Run "make" to regenerate code after modifying this file 38 | 39 | // Time Zone to use for scheduling 40 | TimeZone string `json:"timeZone,omitempty"` 41 | 42 | // Schedule for adjusting performance mode 43 | Schedule []ScheduleInfo `json:"schedule"` 44 | ReservedCPUs *[]uint `json:"reservedCPUs,omitempty"` 45 | } 46 | 47 | // TimeOfDayStatus defines the observed state of TimeOfDay 48 | type TimeOfDayStatus struct { 49 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 50 | // Important: Run "make" to regenerate code after modifying this file 51 | 52 | // The time of the last update 53 | LastSchedule string `json:"lastSchedule,omitempty"` 54 | 55 | // The time of the next update 56 | NextSchedule string `json:"nextSchedule,omitempty"` 57 | 58 | // PowerProfile associated with Time of Day 59 | PowerProfile string `json:"powerProfile,omitempty"` 60 | 61 | StatusErrors `json:",inline,omitempty"` 62 | } 63 | 64 | //+kubebuilder:object:root=true 65 | //+kubebuilder:subresource:status 66 | 67 | // TimeOfDay is the Schema for the timeofdays API 68 | type TimeOfDay struct { 69 | metav1.TypeMeta `json:",inline"` 70 | metav1.ObjectMeta `json:"metadata,omitempty"` 71 | 72 | Spec TimeOfDaySpec `json:"spec,omitempty"` 73 | Status TimeOfDayStatus `json:"status,omitempty"` 74 | } 75 | 76 | //+kubebuilder:object:root=true 77 | 78 | // TimeOfDayList contains a list of TimeOfDay 79 | type TimeOfDayList struct { 80 | metav1.TypeMeta `json:",inline"` 81 | metav1.ListMeta `json:"metadata,omitempty"` 82 | Items []TimeOfDay `json:"items"` 83 | } 84 | 85 | func (tod *TimeOfDay) SetStatusErrors(errs *[]string) { 86 | tod.Status.Errors = *errs 87 | } 88 | 89 | func (tod *TimeOfDay) GetStatusErrors() *[]string { 90 | return &tod.Status.Errors 91 | } 92 | 93 | func init() { 94 | SchemeBuilder.Register(&TimeOfDay{}, &TimeOfDayList{}) 95 | } 96 | -------------------------------------------------------------------------------- /api/v1/timeofdaycronjob_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | v1 "k8s.io/api/core/v1" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | //batchv1 "k8s.io/api/batch/v1" 23 | ) 24 | 25 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 26 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 27 | 28 | // TimeOfDayCronJobSpec defines the desired state of TimeOfDayCronJob 29 | type TimeOfDayCronJobSpec struct { 30 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 31 | // Important: Run "make" to regenerate code after modifying this file 32 | Hour int `json:"hour"` 33 | Minute int `json:"minute"` 34 | Second int `json:"second,omitempty"` 35 | TimeZone *string `json:"timeZone"` 36 | Profile *string `json:"profile"` 37 | Pods *[]PodInfo `json:"pods,omitempty"` 38 | ReservedCPUs *[]uint `json:"reservedCPUs,omitempty"` 39 | CState *CStatesSpec `json:"cState,omitempty"` 40 | } 41 | 42 | type PodInfo struct { 43 | Labels metav1.LabelSelector `json:"labels"` 44 | Target string `json:"target"` 45 | } 46 | 47 | // TimeOfDayCronJobStatus defines the observed state of TimeOfDayCronJob 48 | type TimeOfDayCronJobStatus struct { 49 | Active []v1.ObjectReference `json:"active,omitempty"` 50 | LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"` 51 | LastSuccessfulTime *metav1.Time `json:"lastSuccessfulTime,omitempty"` 52 | 53 | StatusErrors `json:",inline,omitempty"` 54 | } 55 | 56 | //+kubebuilder:object:root=true 57 | //+kubebuilder:subresource:status 58 | 59 | // TimeOfDayCronJob is the Schema for the timeofdaycronjobs API 60 | type TimeOfDayCronJob struct { 61 | metav1.TypeMeta `json:",inline"` 62 | metav1.ObjectMeta `json:"metadata,omitempty"` 63 | Spec TimeOfDayCronJobSpec `json:"spec,omitempty"` 64 | Status TimeOfDayCronJobStatus `json:"status,omitempty"` 65 | } 66 | 67 | //+kubebuilder:object:root=true 68 | 69 | // TimeOfDayCronJobList contains a list of TimeOfDayCronJob 70 | type TimeOfDayCronJobList struct { 71 | metav1.TypeMeta `json:",inline"` 72 | metav1.ListMeta `json:"metadata,omitempty"` 73 | Items []TimeOfDayCronJob `json:"items"` 74 | } 75 | 76 | func (todcr *TimeOfDayCronJob) SetStatusErrors(errs *[]string) { 77 | todcr.Status.Errors = *errs 78 | } 79 | func (todcr *TimeOfDayCronJob) GetStatusErrors() *[]string { 80 | return &todcr.Status.Errors 81 | } 82 | 83 | func init() { 84 | SchemeBuilder.Register(&TimeOfDayCronJob{}, &TimeOfDayCronJobList{}) 85 | } 86 | -------------------------------------------------------------------------------- /api/v1/uncore_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 24 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 25 | 26 | // UncoreSpec defines the desired state of Uncore 27 | type UncoreSpec struct { 28 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 29 | // Important: Run "make" to regenerate code after modifying this file 30 | 31 | SysMax *uint `json:"sysMax,omitempty"` 32 | SysMin *uint `json:"sysMin,omitempty"` 33 | DieSelectors *[]DieSelector `json:"dieSelector,omitempty"` 34 | } 35 | 36 | type DieSelector struct { 37 | Package *uint `json:"package"` 38 | Die *uint `json:"die,omitempty"` 39 | Min *uint `json:"min"` 40 | Max *uint `json:"max"` 41 | } 42 | 43 | // UncoreStatus defines the observed state of Uncore 44 | type UncoreStatus struct { 45 | StatusErrors `json:",inline,omitempty"` 46 | } 47 | 48 | //+kubebuilder:object:root=true 49 | //+kubebuilder:subresource:status 50 | 51 | // Uncore is the Schema for the uncores API 52 | type Uncore struct { 53 | metav1.TypeMeta `json:",inline"` 54 | metav1.ObjectMeta `json:"metadata,omitempty"` 55 | 56 | Spec UncoreSpec `json:"spec,omitempty"` 57 | Status UncoreStatus `json:"status,omitempty"` 58 | } 59 | 60 | //+kubebuilder:object:root=true 61 | 62 | // UncoreList contains a list of Uncore 63 | type UncoreList struct { 64 | metav1.TypeMeta `json:",inline"` 65 | metav1.ListMeta `json:"metadata,omitempty"` 66 | Items []Uncore `json:"items"` 67 | } 68 | 69 | func (ucnre *Uncore) SetStatusErrors(err *[]string) { 70 | ucnre.Status.Errors = *err 71 | } 72 | 73 | func (ucnre *Uncore) GetStatusErrors() *[]string { 74 | return &ucnre.Status.Errors 75 | } 76 | 77 | func init() { 78 | SchemeBuilder.Register(&Uncore{}, &UncoreList{}) 79 | } 80 | -------------------------------------------------------------------------------- /build/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BASE_IMAGE=scratch 2 | # Build the manager binary 3 | FROM golang@sha256:f43c6f049f04cbbaeb28f0aad3eea15274a7d0a7899a617d0037aec48d7ab010 as builder 4 | 5 | WORKDIR /workspace 6 | # Copy the Go Modules manifests 7 | COPY go.mod go.mod 8 | COPY go.sum go.sum 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | # Copy the go source 14 | COPY build/manager/main.go main.go 15 | COPY api/ api/ 16 | COPY controllers/ controllers/ 17 | COPY pkg/ pkg/ 18 | 19 | # Build 20 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go 21 | 22 | FROM ${BASE_IMAGE} 23 | ARG MANIFEST=build/manifests/power-node-agent-ds.yaml 24 | WORKDIR / 25 | COPY LICENSE /licenses/LICENSE 26 | COPY --from=builder /workspace/manager . 27 | COPY ${MANIFEST} /power-manifests/ 28 | USER 10001 29 | 30 | ENTRYPOINT ["/manager"] 31 | -------------------------------------------------------------------------------- /build/Dockerfile.nodeagent: -------------------------------------------------------------------------------- 1 | ARG BASE_IMAGE=scratch 2 | 3 | # Build the manager binary 4 | FROM golang@sha256:f43c6f049f04cbbaeb28f0aad3eea15274a7d0a7899a617d0037aec48d7ab010 as builder 5 | WORKDIR /workspace 6 | # Copy the Go Modules manifests 7 | COPY go.mod go.mod 8 | COPY go.sum go.sum 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | # Copy the go source 14 | COPY build/nodeagent/main.go main.go 15 | COPY api/ api/ 16 | COPY controllers/ controllers/ 17 | COPY pkg/ pkg/ 18 | 19 | # Build 20 | RUN mkdir -p /install_root/etc && groupadd -g 1099 "kpm" && useradd -g "kpm" -u 10001 -s /sbin/nologin power-node-agent && tail -1 /etc/passwd > /install_root/etc/passwd \ 21 | && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o /install_root/nodeagent ./main.go 22 | 23 | FROM ${BASE_IMAGE} 24 | WORKDIR / 25 | COPY LICENSE /licenses/LICENSE 26 | COPY --from=builder /install_root . 27 | USER 10001 28 | 29 | ENTRYPOINT ["/nodeagent"] 30 | -------------------------------------------------------------------------------- /build/manager/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | 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 main 18 | 19 | import ( 20 | "flag" 21 | "os" 22 | "time" 23 | 24 | "go.uber.org/zap/zapcore" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 27 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 28 | _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" 29 | ctrl "sigs.k8s.io/controller-runtime" 30 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 31 | "sigs.k8s.io/controller-runtime/pkg/metrics/server" 32 | 33 | powerv1 "github.com/intel/kubernetes-power-manager/api/v1" 34 | 35 | "github.com/intel/kubernetes-power-manager/controllers" 36 | "github.com/intel/kubernetes-power-manager/pkg/state" 37 | // +kubebuilder:scaffold:imports 38 | ) 39 | 40 | var ( 41 | scheme = runtime.NewScheme() 42 | setupLog = ctrl.Log.WithName("setup") 43 | ) 44 | 45 | func init() { 46 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 47 | 48 | utilruntime.Must(powerv1.AddToScheme(scheme)) 49 | // +kubebuilder:scaffold:scheme 50 | } 51 | 52 | func main() { 53 | var metricsAddr string 54 | var enableLeaderElection bool 55 | flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.") 56 | flag.BoolVar(&enableLeaderElection, "enable-leader-election", true, 57 | "Enable leader election for controller manager. "+ 58 | "Enabling this will ensure there is only one active controller manager.") 59 | 60 | logOpts := zap.Options{} 61 | logOpts.BindFlags(flag.CommandLine) 62 | flag.Parse() 63 | 64 | ctrl.SetLogger(zap.New( 65 | zap.UseDevMode(true), 66 | func(opts *zap.Options) { 67 | opts.TimeEncoder = zapcore.ISO8601TimeEncoder 68 | }, 69 | zap.UseFlagOptions(&logOpts), 70 | ), 71 | ) 72 | renewDeadline := time.Second * time.Duration(20) 73 | leaseDuration := time.Second * time.Duration(30) 74 | mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ 75 | Scheme: scheme, 76 | Metrics: server.Options{BindAddress: metricsAddr}, 77 | LeaderElection: enableLeaderElection, 78 | LeaderElectionID: "power-operator-6846766c", 79 | RenewDeadline: &renewDeadline, 80 | LeaseDuration: &leaseDuration, 81 | }) 82 | if err != nil { 83 | setupLog.Error(err, "unable to start manager") 84 | os.Exit(1) 85 | } 86 | 87 | state := state.NewPowerNodeData() 88 | 89 | if err = (&controllers.PowerConfigReconciler{ 90 | Client: mgr.GetClient(), 91 | Log: ctrl.Log.WithName("controllers").WithName("PowerConfig"), 92 | Scheme: mgr.GetScheme(), 93 | State: state, 94 | }).SetupWithManager(mgr); err != nil { 95 | setupLog.Error(err, "unable to create controller", "controller", "PowerConfig") 96 | os.Exit(1) 97 | } 98 | // +kubebuilder:scaffold:builder 99 | 100 | setupLog.Info("starting manager") 101 | if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { 102 | setupLog.Error(err, "problem running manager") 103 | os.Exit(1) 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /build/manifests/ocp/power-node-agent-ds.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: power-node-agent 5 | namespace: intel-power 6 | spec: 7 | selector: 8 | matchLabels: 9 | name: power-node-agent-pod 10 | template: 11 | metadata: 12 | namespace: intel-power 13 | labels: 14 | name: power-node-agent-pod 15 | spec: 16 | serviceAccountName: intel-power-node-agent 17 | containers: 18 | - image: intel/power-node-agent_ocp-4.13:v2.3.1 19 | imagePullPolicy: IfNotPresent 20 | securityContext: 21 | privileged: true 22 | runAsUser: 0 23 | name: power-node-agent 24 | args: [ "--zap-log-level","3" ] 25 | env: 26 | - name: NODE_NAME 27 | valueFrom: 28 | fieldRef: 29 | fieldPath: spec.nodeName 30 | resources: 31 | limits: 32 | cpu: 100m 33 | memory: 64Mi 34 | requests: 35 | cpu: 100m 36 | memory: 64Mi 37 | volumeMounts: 38 | - mountPath: /sys/devices/system/cpu 39 | name: cpusetup 40 | - mountPath: /sys/fs/cgroup 41 | name: cgroup 42 | readOnly: true 43 | - mountPath: /var/lib/kubelet/pod-resources/ 44 | name: kubesock 45 | readOnly: true 46 | volumes: 47 | - name: cpusetup 48 | hostPath: 49 | path: /sys/devices/system/cpu 50 | - name: cgroup 51 | hostPath: 52 | path: /sys/fs/cgroup 53 | - name: kubesock 54 | hostPath: 55 | path: /var/lib/kubelet/pod-resources 56 | -------------------------------------------------------------------------------- /build/manifests/power-node-agent-ds.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: power-node-agent 5 | namespace: intel-power 6 | spec: 7 | selector: 8 | matchLabels: 9 | name: power-node-agent-pod 10 | template: 11 | metadata: 12 | namespace: intel-power 13 | labels: 14 | name: power-node-agent-pod 15 | spec: 16 | serviceAccountName: intel-power-node-agent 17 | containers: 18 | - image: intel/power-node-agent:v2.5.0 19 | imagePullPolicy: IfNotPresent 20 | securityContext: 21 | privileged: true 22 | runAsUser: 0 23 | name: power-node-agent 24 | args: [ "--zap-log-level","3" ] 25 | env: 26 | - name: NODE_NAME 27 | valueFrom: 28 | fieldRef: 29 | fieldPath: spec.nodeName 30 | resources: 31 | limits: 32 | cpu: 100m 33 | memory: 64Mi 34 | requests: 35 | cpu: 100m 36 | memory: 64Mi 37 | volumeMounts: 38 | - mountPath: /sys/devices/system/cpu 39 | name: cpusetup 40 | - mountPath: /sys/fs/cgroup 41 | name: cgroup 42 | readOnly: true 43 | - mountPath: /var/lib/kubelet/pod-resources/ 44 | name: kubesock 45 | readOnly: true 46 | volumes: 47 | - name: cpusetup 48 | hostPath: 49 | path: /sys/devices/system/cpu 50 | - name: cgroup 51 | hostPath: 52 | path: /sys/fs/cgroup 53 | - name: kubesock 54 | hostPath: 55 | path: /var/lib/kubelet/pod-resources 56 | -------------------------------------------------------------------------------- /ci/sdle/sdle-tools.yaml: -------------------------------------------------------------------------------- 1 | kind: Pod 2 | apiVersion: v1 3 | spec: 4 | containers: 5 | - name: ubuntu-env 6 | image: amr-registry.caas.intel.com/owr/ubuntu:20.04 7 | tty: true 8 | imagePullPolicy: IfNotPresent 9 | command: ["cat"] 10 | - name: abi-env 11 | image: amr-registry.caas.intel.com/owr/abi_lnx:latest 12 | tty: true 13 | imagePullPolicy: Always 14 | command: ["cat"] 15 | - name: trivy-env 16 | image: aquasec/trivy 17 | tty: true 18 | imagePullPolicy: IfNotPresent 19 | command: ["cat"] 20 | - name: kubesec-env 21 | image: kubesec/kubesec 22 | tty: true 23 | imagePullPolicy: Always 24 | - name: alpine-env 25 | image: alpine 26 | tty: true 27 | imagePullPolicy: IfNotPresent 28 | command: ["cat"] 29 | - name: hadolint-env 30 | image: hadolint/hadolint:latest-debian 31 | tty: true 32 | imagePullPolicy: Always 33 | command: ["cat"] 34 | - name: shellcheck-env 35 | image: koalaman/shellcheck-alpine 36 | tty: true 37 | imagePullPolicy: Always 38 | command: ["cat"] 39 | - name: kaniko-env 40 | image: gcr.io/kaniko-project/executor:debug 41 | tty: true 42 | imagePullPolicy: IfNotPresent 43 | command: ["/busybox/sleep","infinity"] 44 | # ephemeral image registry, available at localhost:5000 only for the lifetime of the pipeline 45 | - name: image-registry 46 | image: registry:2 47 | imagePullPolicy: IfNotPresent 48 | -------------------------------------------------------------------------------- /ci/verify/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent { 3 | label 'tweedledum' 4 | } 5 | triggers { 6 | cron('@midnight') 7 | } 8 | tools { 9 | go "$GO_VERSION" 10 | } 11 | environment { 12 | LIBRARY_BRANCH = "main" 13 | GOLANGCI_LINT_VERSION = "1.58.2" 14 | GOLANGCI_LINT_URL = credentials("golang-ci-lint-url") 15 | } 16 | stages { 17 | stage('Prerequisites') { 18 | steps { 19 | sh ''' 20 | curl -sSfL ${GOLANGCI_LINT_URL} | sh -s v${GOLANGCI_LINT_VERSION} 21 | ''' 22 | } 23 | } 24 | stage('Checkout-Library') { 25 | environment { 26 | LIBRARY_REPO = credentials("power-library-private-repo") 27 | } 28 | steps { 29 | script { 30 | dir('library') { 31 | checkout([$class: 'GitSCM', 32 | branches: [[name: 'main']], 33 | userRemoteConfigs: [[url: env.LIBRARY_REPO, credentialsId: 'sys_rmcci_github']] 34 | ]) 35 | sh 'git checkout origin/${LIBRARY_BRANCH}' 36 | } 37 | sh 'echo "replace github.com/intel/power-optimization-library => ./library" >> go.mod' 38 | sh "sed -i 's/COPY go\\.sum go\\.sum/COPY go\\.sum go\\.sum\\nCOPY \\.\\/library \\.\\/library/' build/Dockerfile" 39 | sh "sed -i 's/COPY go\\.sum go\\.sum/COPY go\\.sum go\\.sum\\nCOPY \\.\\/library \\.\\/library/' build/Dockerfile.nodeagent" 40 | } 41 | } 42 | } 43 | stage('Static analysis') { 44 | steps { 45 | sh ''' 46 | ./bin/golangci-lint run 47 | ''' 48 | } 49 | } 50 | stage('Build') { 51 | steps { 52 | echo 'Building..' 53 | sh 'go mod tidy' 54 | sh 'make build' 55 | } 56 | } 57 | stage('Coverage') { 58 | steps { 59 | echo 'Testing..' 60 | sh 'make coverage' 61 | } 62 | } 63 | stage('Race Test') { 64 | steps { 65 | echo 'Testing..' 66 | sh 'make race' 67 | } 68 | } 69 | } 70 | post { 71 | always { 72 | cleanWs( 73 | cleanWhenAborted: true, 74 | cleanWhenFailure: true, 75 | cleanWhenNotBuilt: true, 76 | cleanWhenSuccess: true, 77 | cleanWhenUnstable: true, 78 | deleteDirs: true, 79 | disableDeferredWipeout: true 80 | ) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /config/certmanager/certificate.yaml: -------------------------------------------------------------------------------- 1 | # The following manifests contain a self-signed issuer CR and a certificate CR. 2 | # More document can be found at https://docs.cert-manager.io 3 | # WARNING: Targets CertManager 0.11 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for 4 | # breaking changes 5 | apiVersion: cert-manager.io/v1alpha2 6 | kind: Issuer 7 | metadata: 8 | name: selfsigned-issuer 9 | namespace: system 10 | spec: 11 | selfSigned: { } 12 | --- 13 | apiVersion: cert-manager.io/v1alpha2 14 | kind: Certificate 15 | metadata: 16 | name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml 17 | namespace: system 18 | spec: 19 | # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize 20 | dnsNames: 21 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc 22 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local 23 | issuerRef: 24 | kind: Issuer 25 | name: selfsigned-issuer 26 | secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize 27 | -------------------------------------------------------------------------------- /config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /config/crd/bases/power.intel.com_cstates.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.14.0 7 | name: cstates.power.intel.com 8 | spec: 9 | group: power.intel.com 10 | names: 11 | kind: CStates 12 | listKind: CStatesList 13 | plural: cstates 14 | singular: cstates 15 | scope: Namespaced 16 | versions: 17 | - name: v1 18 | schema: 19 | openAPIV3Schema: 20 | description: CStates is the Schema for the cstates API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: CStatesSpec defines the desired state of CStates 41 | properties: 42 | exclusivePoolCStates: 43 | additionalProperties: 44 | additionalProperties: 45 | type: boolean 46 | type: object 47 | type: object 48 | individualCoreCStates: 49 | additionalProperties: 50 | additionalProperties: 51 | type: boolean 52 | type: object 53 | type: object 54 | sharedPoolCStates: 55 | additionalProperties: 56 | type: boolean 57 | type: object 58 | type: object 59 | status: 60 | description: CStatesStatus defines the observed state of CStates 61 | properties: 62 | errors: 63 | items: 64 | type: string 65 | type: array 66 | type: object 67 | type: object 68 | served: true 69 | storage: true 70 | subresources: 71 | status: {} 72 | -------------------------------------------------------------------------------- /config/crd/bases/power.intel.com_powerconfigs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.14.0 7 | name: powerconfigs.power.intel.com 8 | spec: 9 | group: power.intel.com 10 | names: 11 | kind: PowerConfig 12 | listKind: PowerConfigList 13 | plural: powerconfigs 14 | singular: powerconfig 15 | scope: Namespaced 16 | versions: 17 | - name: v1 18 | schema: 19 | openAPIV3Schema: 20 | description: PowerConfig is the Schema for the powerconfigs API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: PowerConfigSpec defines the desired state of PowerConfig 41 | properties: 42 | customDevices: 43 | description: The CustomDevices include alternative devices that represent 44 | other resources 45 | items: 46 | type: string 47 | type: array 48 | powerNodeSelector: 49 | additionalProperties: 50 | type: string 51 | description: The label on the Nodes you the Operator will look for 52 | to deploy the Node Agent 53 | type: object 54 | powerProfiles: 55 | description: The PowerProfiles that will be created by the Operator 56 | items: 57 | type: string 58 | type: array 59 | type: object 60 | status: 61 | description: PowerConfigStatus defines the observed state of PowerConfig 62 | properties: 63 | errors: 64 | items: 65 | type: string 66 | type: array 67 | nodes: 68 | description: The Nodes that the Node Agent has been deployed to 69 | items: 70 | type: string 71 | type: array 72 | type: object 73 | type: object 74 | served: true 75 | storage: true 76 | subresources: 77 | status: {} 78 | -------------------------------------------------------------------------------- /config/crd/bases/power.intel.com_powerpods.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.14.0 7 | name: powerpods.power.intel.com 8 | spec: 9 | group: power.intel.com 10 | names: 11 | kind: PowerPod 12 | listKind: PowerPodList 13 | plural: powerpods 14 | singular: powerpod 15 | scope: Namespaced 16 | versions: 17 | - name: v1 18 | schema: 19 | openAPIV3Schema: 20 | description: PowerPod is the Schema for the powerpods API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: PowerPodSpec defines the desired state of PowerPod 41 | type: object 42 | status: 43 | description: PowerPodStatus defines the observed state of PowerPod 44 | type: object 45 | type: object 46 | served: true 47 | storage: true 48 | subresources: 49 | status: {} 50 | -------------------------------------------------------------------------------- /config/crd/bases/power.intel.com_powerprofiles.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.14.0 7 | name: powerprofiles.power.intel.com 8 | spec: 9 | group: power.intel.com 10 | names: 11 | kind: PowerProfile 12 | listKind: PowerProfileList 13 | plural: powerprofiles 14 | singular: powerprofile 15 | scope: Namespaced 16 | versions: 17 | - name: v1 18 | schema: 19 | openAPIV3Schema: 20 | description: PowerProfile is the Schema for the powerprofiles API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: PowerProfileSpec defines the desired state of PowerProfile 41 | properties: 42 | epp: 43 | description: The priority value associated with this Power Profile 44 | type: string 45 | governor: 46 | default: powersave 47 | description: Governor to be used 48 | type: string 49 | max: 50 | description: Max frequency cores can run at 51 | type: integer 52 | min: 53 | description: Min frequency cores can run at 54 | type: integer 55 | name: 56 | description: The name of the PowerProfile 57 | type: string 58 | shared: 59 | type: boolean 60 | required: 61 | - name 62 | type: object 63 | status: 64 | description: PowerProfileStatus defines the observed state of PowerProfile 65 | properties: 66 | errors: 67 | items: 68 | type: string 69 | type: array 70 | id: 71 | description: The ID given to the power profile 72 | type: integer 73 | type: object 74 | type: object 75 | served: true 76 | storage: true 77 | subresources: 78 | status: {} 79 | -------------------------------------------------------------------------------- /config/crd/bases/power.intel.com_powerworkloads.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.14.0 7 | name: powerworkloads.power.intel.com 8 | spec: 9 | group: power.intel.com 10 | names: 11 | kind: PowerWorkload 12 | listKind: PowerWorkloadList 13 | plural: powerworkloads 14 | singular: powerworkload 15 | scope: Namespaced 16 | versions: 17 | - name: v1 18 | schema: 19 | openAPIV3Schema: 20 | description: PowerWorkload is the Schema for the powerworkloads API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: PowerWorkloadSpec defines the desired state of PowerWorkload 41 | properties: 42 | allCores: 43 | description: AllCores determines if the Workload is to be applied 44 | to all cores (i.e. use the Default Workload) 45 | type: boolean 46 | name: 47 | description: The name of the workload 48 | type: string 49 | powerNodeSelector: 50 | additionalProperties: 51 | type: string 52 | description: The labels signifying the nodes the user wants to use 53 | type: object 54 | powerProfile: 55 | description: PowerProfile is the Profile that this PowerWorkload is 56 | based on 57 | type: string 58 | reservedCPUs: 59 | description: |- 60 | Reserved CPUs are the CPUs that have been reserved by Kubelet for use by the Kubernetes admin process 61 | This list must match the list in the user's Kubelet configuration 62 | items: 63 | properties: 64 | cores: 65 | items: 66 | type: integer 67 | type: array 68 | powerProfile: 69 | type: string 70 | required: 71 | - cores 72 | type: object 73 | type: array 74 | workloadNodes: 75 | properties: 76 | containers: 77 | items: 78 | properties: 79 | exclusiveCpus: 80 | description: The exclusive CPUs given to this Container 81 | items: 82 | type: integer 83 | type: array 84 | id: 85 | description: The ID of the Container 86 | type: string 87 | name: 88 | description: The name of the Container 89 | type: string 90 | pod: 91 | description: The name of the Pod the Container is running 92 | on 93 | type: string 94 | powerProfile: 95 | description: The PowerProfile that the Container is utilizing 96 | type: string 97 | workload: 98 | description: The PowerWorkload that the Container is utilizing 99 | type: string 100 | type: object 101 | type: array 102 | cpuIds: 103 | items: 104 | type: integer 105 | type: array 106 | name: 107 | type: string 108 | type: object 109 | required: 110 | - name 111 | type: object 112 | status: 113 | description: PowerWorkloadStatus defines the observed state of PowerWorkload 114 | properties: 115 | errors: 116 | items: 117 | type: string 118 | type: array 119 | 'node:': 120 | description: The Node that this Shared PowerWorkload is associated 121 | with 122 | type: string 123 | type: object 124 | type: object 125 | served: true 126 | storage: true 127 | subresources: 128 | status: {} 129 | -------------------------------------------------------------------------------- /config/crd/bases/power.intel.com_uncores.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.14.0 7 | name: uncores.power.intel.com 8 | spec: 9 | group: power.intel.com 10 | names: 11 | kind: Uncore 12 | listKind: UncoreList 13 | plural: uncores 14 | singular: uncore 15 | scope: Namespaced 16 | versions: 17 | - name: v1 18 | schema: 19 | openAPIV3Schema: 20 | description: Uncore is the Schema for the uncores API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: UncoreSpec defines the desired state of Uncore 41 | properties: 42 | dieSelector: 43 | items: 44 | properties: 45 | die: 46 | type: integer 47 | max: 48 | type: integer 49 | min: 50 | type: integer 51 | package: 52 | type: integer 53 | required: 54 | - max 55 | - min 56 | - package 57 | type: object 58 | type: array 59 | sysMax: 60 | type: integer 61 | sysMin: 62 | type: integer 63 | type: object 64 | status: 65 | description: UncoreStatus defines the observed state of Uncore 66 | properties: 67 | errors: 68 | items: 69 | type: string 70 | type: array 71 | type: object 72 | type: object 73 | served: true 74 | storage: true 75 | subresources: 76 | status: {} 77 | -------------------------------------------------------------------------------- /config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/power.intel.com_powernodes.yaml 6 | - bases/power.intel.com_powerprofiles.yaml 7 | - bases/power.intel.com_powerworkloads.yaml 8 | - bases/power.intel.com_powerpods.yaml 9 | - bases/power.intel.com_powerconfigs.yaml 10 | - bases/power.intel.com_cstates.yaml 11 | - bases/power.intel.com_timeofdays.yaml 12 | - bases/power.intel.com_timeofdaycronjobs.yaml 13 | - bases/power.intel.com_uncores.yaml 14 | # +kubebuilder:scaffold:crdkustomizeresource 15 | 16 | patchesStrategicMerge: 17 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 18 | # patches here are for enabling the conversion webhook for each CRD 19 | #- patches/webhook_in_profiles.yaml 20 | #- patches/webhook_in_configs.yaml 21 | #- patches/webhook_in_pods.yaml 22 | #- patches/webhook_in_powernodes.yaml 23 | #- patches/webhook_in_powerprofiles.yaml 24 | #- patches/webhook_in_powerworkloads.yaml 25 | #- patches/webhook_in_powerpods.yaml 26 | #- patches/webhook_in_powerconfigs.yaml 27 | #- patches/webhook_in_cstates.yaml 28 | #- patches/webhook_in_timeofdays.yaml 29 | #- patches/webhook_in_timeofdaycronjobs.yaml 30 | #- patches/webhook_in_uncores.yaml 31 | # +kubebuilder:scaffold:crdkustomizewebhookpatch 32 | 33 | # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. 34 | # patches here are for enabling the CA injection for each CRD 35 | #- patches/cainjection_in_profiles.yaml 36 | #- patches/cainjection_in_configs.yaml 37 | #- patches/cainjection_in_pods.yaml 38 | #- patches/cainjection_in_powernodes.yaml 39 | #- patches/cainjection_in_powerprofiles.yaml 40 | #- patches/cainjection_in_powerworkloads.yaml 41 | #- patches/cainjection_in_powerpods.yaml 42 | #- patches/cainjection_in_powerconfigs.yaml 43 | #- patches/cainjection_in_cstates.yaml 44 | #- patches/cainjection_in_timeofdays.yaml 45 | #- patches/cainjection_in_timeofdaycronjobs.yaml 46 | #- patches/cainjection_in_uncores.yaml 47 | # +kubebuilder:scaffold:crdkustomizecainjectionpatch 48 | 49 | # the following config is for teaching kustomize how to do kustomization for CRDs. 50 | configurations: 51 | - kustomizeconfig.yaml 52 | -------------------------------------------------------------------------------- /config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | group: apiextensions.k8s.io 8 | path: spec/conversion/webhookClientConfig/service/name 9 | 10 | namespace: 11 | - kind: CustomResourceDefinition 12 | group: apiextensions.k8s.io 13 | path: spec/conversion/webhookClientConfig/service/namespace 14 | create: false 15 | 16 | varReference: 17 | - path: metadata/annotations 18 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_configs.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: configs.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_cstates.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: cstates.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_pods.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: pods.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_powerconfigs.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: powerconfigs.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_powernodes.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: powernodes.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_powerpods.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: powerpods.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_powerprofiles.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: powerprofiles.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_powerworkloads.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: powerworkloads.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_profiles.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: profiles.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_timeofdaycronjobs.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: timeofdaycronjobs.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_timeofdays.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: timeofdays.power.intel.com 9 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_uncores.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: uncores.power.intel.com 8 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_configs.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: configs.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_cstates.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: cstates.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_pods.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: pods.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_powerconfigs.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: powerconfigs.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_powernodes.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: powernodes.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_powerpods.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: powerpods.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_powerprofiles.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: powerprofiles.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_powerworkloads.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: powerworkloads.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_profiles.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: profiles.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_timeofdaycronjobs.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: timeofdaycronjobs.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_timeofdays.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: timeofdays.power.intel.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_uncores.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: uncores.power.intel.com 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: intel-power 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | 10 | # Labels to add to all resources and selectors. 11 | #commonLabels: 12 | # someName: someValue 13 | 14 | apiVersion: kustomize.config.k8s.io/v1beta1 15 | kind: Kustomization 16 | resources: 17 | - ../crd 18 | - ../rbac 19 | - ../manager 20 | -------------------------------------------------------------------------------- /config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 14 | args: 15 | - "--secure-listen-address=0.0.0.0:8443" 16 | - "--upstream=http://127.0.0.1:8080/" 17 | - "--logtostderr=true" 18 | - "--v=10" 19 | ports: 20 | - containerPort: 8443 21 | name: https 22 | - name: manager 23 | args: 24 | - "--metrics-addr=127.0.0.1:8080" 25 | - "--enable-leader-election" 26 | -------------------------------------------------------------------------------- /config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1beta1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | --- 10 | apiVersion: admissionregistration.k8s.io/v1beta1 11 | kind: ValidatingWebhookConfiguration 12 | metadata: 13 | name: validating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | -------------------------------------------------------------------------------- /config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: controller 7 | newName: controller 8 | newTag: latest 9 | -------------------------------------------------------------------------------- /config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: intel-power 6 | labels: 7 | control-plane: controller-manager 8 | spec: 9 | selector: 10 | matchLabels: 11 | control-plane: controller-manager 12 | replicas: 1 13 | template: 14 | metadata: 15 | labels: 16 | control-plane: controller-manager 17 | spec: 18 | serviceAccountName: intel-power-operator 19 | containers: 20 | - command: 21 | - /manager 22 | args: 23 | - --enable-leader-election 24 | - --zap-log-level 25 | - "3" 26 | imagePullPolicy: IfNotPresent 27 | image: intel/power-operator:v2.5.0 28 | securityContext: 29 | allowPrivilegeEscalation: false 30 | capabilities: 31 | drop: [ "ALL" ] 32 | runAsNonRoot: true 33 | runAsUser: 10001 34 | seccompProfile: 35 | type: RuntimeDefault 36 | name: manager 37 | resources: 38 | limits: 39 | cpu: 100m 40 | memory: 64Mi 41 | requests: 42 | cpu: 100m 43 | memory: 64Mi 44 | volumeMounts: 45 | - mountPath: /sys/fs/cgroup 46 | name: cgroup 47 | mountPropagation: HostToContainer 48 | readOnly: true 49 | terminationGracePeriodSeconds: 10 50 | volumes: 51 | - name: cgroup 52 | hostPath: 53 | path: /sys/fs/cgroup 54 | -------------------------------------------------------------------------------- /config/manager/ocp/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: controller 7 | newName: controller 8 | newTag: latest 9 | -------------------------------------------------------------------------------- /config/manager/ocp/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: intel-power 6 | labels: 7 | control-plane: controller-manager 8 | spec: 9 | selector: 10 | matchLabels: 11 | control-plane: controller-manager 12 | replicas: 1 13 | template: 14 | metadata: 15 | labels: 16 | control-plane: controller-manager 17 | spec: 18 | serviceAccountName: intel-power-operator 19 | containers: 20 | - command: 21 | - /manager 22 | args: 23 | - --enable-leader-election 24 | - --zap-log-level 25 | - "3" 26 | env: 27 | - name: RELATED_IMAGE_AGENT 28 | value: intel/power-node-agent_ocp-4.13:v2.3.1 29 | imagePullPolicy: IfNotPresent 30 | image: intel/power-operator_ocp-4.13:v2.3.1 31 | securityContext: 32 | allowPrivilegeEscalation: false 33 | capabilities: 34 | drop: [ "ALL" ] 35 | runAsNonRoot: true 36 | runAsUser: 10001 37 | seccompProfile: 38 | type: RuntimeDefault 39 | name: manager 40 | resources: 41 | limits: 42 | cpu: 100m 43 | memory: 64Mi 44 | requests: 45 | cpu: 100m 46 | memory: 64Mi 47 | volumeMounts: 48 | - mountPath: /sys/fs/cgroup 49 | name: cgroup 50 | mountPropagation: HostToContainer 51 | readOnly: true 52 | terminationGracePeriodSeconds: 10 53 | volumes: 54 | - name: cgroup 55 | hostPath: 56 | path: /sys/fs/cgroup 57 | -------------------------------------------------------------------------------- /config/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # These resources constitute the fully configured set of manifests 2 | # used to generate the 'manifests/' directory in a bundle. 3 | resources: 4 | - bases/intel-kubernetes-power-manager.clusterserviceversion.yaml 5 | - ../default 6 | - ../samples 7 | - ../scorecard 8 | -------------------------------------------------------------------------------- /config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | # Prometheus Monitor Service (Metrics) 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | labels: 6 | control-plane: controller-manager 7 | name: controller-manager-metrics-monitor 8 | namespace: system 9 | spec: 10 | endpoints: 11 | - path: /metrics 12 | port: https 13 | selector: 14 | matchLabels: 15 | control-plane: controller-manager 16 | -------------------------------------------------------------------------------- /config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: [ "/metrics" ] 7 | verbs: [ "get" ] 8 | -------------------------------------------------------------------------------- /config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: [ "authentication.k8s.io" ] 7 | resources: 8 | - tokenreviews 9 | verbs: [ "create" ] 10 | - apiGroups: [ "authorization.k8s.io" ] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: [ "create" ] 14 | -------------------------------------------------------------------------------- /config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /config/rbac/cstates_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit cstates. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: cstates-editor-role 6 | rules: 7 | - apiGroups: 8 | - power.intel.com 9 | resources: 10 | - cstates 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - power.intel.com 21 | resources: 22 | - cstates/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /config/rbac/cstates_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view cstates. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: cstates-viewer-role 6 | rules: 7 | - apiGroups: 8 | - power.intel.com 9 | resources: 10 | - cstates 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - power.intel.com 17 | resources: 18 | - cstates/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ./rbac.yaml 3 | - ./role.yaml 4 | # Comment the following 4 lines if you want to disable 5 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 6 | # which protects your /metrics endpoint. 7 | # - auth_proxy_service.yaml 8 | # - auth_proxy_role.yaml 9 | # - auth_proxy_role_binding.yaml 10 | # - auth_proxy_client_clusterrole.yaml 11 | - user_role_binding.yaml 12 | - cstates_editor_role.yaml 13 | # we're adding the namespace in the config/default/kustomize.yaml 14 | # - namespace.yaml 15 | - uncore_editor_role.yaml 16 | - user_role.yaml 17 | - cstates_viewer_role.yaml 18 | - uncore_viewer_role.yaml 19 | -------------------------------------------------------------------------------- /config/rbac/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: intel-power 7 | -------------------------------------------------------------------------------- /config/rbac/ocp/rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: intel-power-operator 5 | namespace: intel-power 6 | 7 | --- 8 | 9 | apiVersion: v1 10 | kind: ServiceAccount 11 | metadata: 12 | name: intel-power-node-agent 13 | namespace: intel-power 14 | 15 | --- 16 | 17 | apiVersion: rbac.authorization.k8s.io/v1 18 | kind: Role 19 | metadata: 20 | name: operator-custom-resource-definitions-role 21 | namespace: intel-power 22 | rules: 23 | - apiGroups: [ "", "power.intel.com", "apps", "coordination.k8s.io" ] 24 | resources: [ "powerconfigs", "powerconfigs/status", "powerprofiles", "powerprofiles/status", "events", "daemonsets", "configmaps", "configmaps/status", "leases","uncores" ] 25 | verbs: [ "*" ] 26 | - apiGroups: 27 | - security.openshift.io 28 | resourceNames: 29 | - privileged 30 | resources: 31 | - securitycontextconstraints 32 | verbs: 33 | - use 34 | --- 35 | 36 | apiVersion: rbac.authorization.k8s.io/v1 37 | kind: RoleBinding 38 | metadata: 39 | name: operator-custom-resource-definitions-role-binding 40 | namespace: intel-power 41 | subjects: 42 | - kind: ServiceAccount 43 | name: intel-power-operator 44 | namespace: intel-power 45 | roleRef: 46 | kind: Role 47 | name: operator-custom-resource-definitions-role 48 | apiGroup: rbac.authorization.k8s.io 49 | 50 | --- 51 | 52 | apiVersion: rbac.authorization.k8s.io/v1 53 | kind: ClusterRole 54 | metadata: 55 | name: operator-nodes 56 | rules: 57 | - apiGroups: [ "", "power.intel.com", "apps" ] 58 | resources: [ "nodes", "nodes/status", "configmaps", "configmaps/status", "powerconfigs", "powerconfigs/status", "powerprofiles", "powerprofiles/status", "powerworkloads", "powerworkloads/status", "powernodes", "powernodes/status", "events", "daemonsets","uncores" ] 59 | verbs: [ "*" ] 60 | 61 | --- 62 | 63 | apiVersion: rbac.authorization.k8s.io/v1 64 | kind: ClusterRoleBinding 65 | metadata: 66 | name: operator-nodes-binding 67 | subjects: 68 | - kind: ServiceAccount 69 | name: intel-power-operator 70 | namespace: intel-power 71 | roleRef: 72 | kind: ClusterRole 73 | name: operator-nodes 74 | apiGroup: rbac.authorization.k8s.io 75 | 76 | --- 77 | 78 | apiVersion: rbac.authorization.k8s.io/v1 79 | kind: ClusterRole 80 | metadata: 81 | name: node-agent-cluster-resources 82 | rules: 83 | - apiGroups: [ "", "batch", "power.intel.com" ] 84 | resources: [ "nodes", "nodes/status", "pods", "pods/status", "cronjobs", "cronjobs/status", "powerprofiles", "powerprofiles/status", "powerworkloads", "powerworkloads/status", "powernodes", "powernodes/status", "cstates", "cstates/status", "timeofdays", "timeofdays/status", "timeofdaycronjobs", "timeofdaycronjobs/status","uncores" ] 85 | verbs: [ "*" ] 86 | - apiGroups: 87 | - security.openshift.io 88 | resourceNames: 89 | - privileged 90 | resources: 91 | - securitycontextconstraints 92 | verbs: 93 | - use 94 | --- 95 | 96 | apiVersion: rbac.authorization.k8s.io/v1 97 | kind: ClusterRoleBinding 98 | metadata: 99 | name: node-agent-cluster-resources-binding 100 | subjects: 101 | - kind: ServiceAccount 102 | name: intel-power-node-agent 103 | namespace: intel-power 104 | roleRef: 105 | kind: ClusterRole 106 | name: node-agent-cluster-resources 107 | apiGroup: rbac.authorization.k8s.io 108 | 109 | --- 110 | -------------------------------------------------------------------------------- /config/rbac/ocp/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: manager-role 7 | rules: 8 | - apiGroups: 9 | - power.intel.com 10 | resources: 11 | - cstates 12 | verbs: 13 | - create 14 | - delete 15 | - get 16 | - list 17 | - patch 18 | - update 19 | - watch 20 | - apiGroups: 21 | - power.intel.com 22 | resources: 23 | - cstates/status 24 | verbs: 25 | - get 26 | - patch 27 | - update 28 | - apiGroups: 29 | - power.intel.com 30 | resources: 31 | - powerconfigs 32 | verbs: 33 | - create 34 | - delete 35 | - get 36 | - list 37 | - patch 38 | - update 39 | - watch 40 | - apiGroups: 41 | - power.intel.com 42 | resources: 43 | - powerconfigs/status 44 | verbs: 45 | - get 46 | - patch 47 | - update 48 | - apiGroups: 49 | - power.intel.com 50 | resources: 51 | - powernodes 52 | verbs: 53 | - create 54 | - delete 55 | - get 56 | - list 57 | - patch 58 | - update 59 | - watch 60 | - apiGroups: 61 | - power.intel.com 62 | resources: 63 | - powernodes/status 64 | verbs: 65 | - get 66 | - patch 67 | - update 68 | - apiGroups: 69 | - power.intel.com 70 | resources: 71 | - powerpods 72 | verbs: 73 | - create 74 | - delete 75 | - get 76 | - list 77 | - patch 78 | - update 79 | - watch 80 | - apiGroups: 81 | - power.intel.com 82 | resources: 83 | - powerpods/status 84 | verbs: 85 | - get 86 | - patch 87 | - update 88 | - apiGroups: 89 | - power.intel.com 90 | resources: 91 | - powerprofiles 92 | verbs: 93 | - create 94 | - delete 95 | - get 96 | - list 97 | - patch 98 | - update 99 | - watch 100 | - apiGroups: 101 | - power.intel.com 102 | resources: 103 | - powerprofiles/status 104 | verbs: 105 | - get 106 | - patch 107 | - update 108 | - apiGroups: 109 | - power.intel.com 110 | resources: 111 | - powerworkloads 112 | verbs: 113 | - create 114 | - delete 115 | - get 116 | - list 117 | - patch 118 | - update 119 | - watch 120 | - apiGroups: 121 | - power.intel.com 122 | resources: 123 | - powerworkloads/status 124 | verbs: 125 | - get 126 | - patch 127 | - update 128 | - apiGroups: 129 | - power.intel.com 130 | resources: 131 | - timeofdays 132 | verbs: 133 | - create 134 | - delete 135 | - get 136 | - list 137 | - patch 138 | - update 139 | - watch 140 | - apiGroups: 141 | - power.intel.com 142 | resources: 143 | - timeofdays/status 144 | verbs: 145 | - get 146 | - patch 147 | - update 148 | - apiGroups: 149 | - power.intel.com 150 | resources: 151 | - uncores 152 | verbs: 153 | - create 154 | - delete 155 | - get 156 | - list 157 | - patch 158 | - update 159 | - watch 160 | - apiGroups: 161 | - power.intel.com 162 | resources: 163 | - uncores/finalizers 164 | verbs: 165 | - update 166 | - apiGroups: 167 | - power.intel.com 168 | resources: 169 | - uncores/status 170 | verbs: 171 | - get 172 | - patch 173 | - update 174 | - apiGroups: 175 | - security.openshift.io 176 | resourceNames: 177 | - privileged 178 | resources: 179 | - securitycontextconstraints 180 | verbs: 181 | - use 182 | -------------------------------------------------------------------------------- /config/rbac/rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: intel-power-operator 5 | namespace: intel-power 6 | 7 | --- 8 | 9 | apiVersion: v1 10 | kind: ServiceAccount 11 | metadata: 12 | name: intel-power-node-agent 13 | namespace: intel-power 14 | 15 | --- 16 | 17 | apiVersion: rbac.authorization.k8s.io/v1 18 | kind: Role 19 | metadata: 20 | name: operator-custom-resource-definitions-role 21 | namespace: intel-power 22 | rules: 23 | - apiGroups: [ "", "power.intel.com", "apps", "coordination.k8s.io" ] 24 | resources: [ "powerconfigs", "powerconfigs/status", "powerprofiles", "powerprofiles/status", "events", "daemonsets", "configmaps", "configmaps/status", "leases","uncores" ] 25 | verbs: [ "*" ] 26 | --- 27 | 28 | apiVersion: rbac.authorization.k8s.io/v1 29 | kind: RoleBinding 30 | metadata: 31 | name: operator-custom-resource-definitions-role-binding 32 | namespace: intel-power 33 | subjects: 34 | - kind: ServiceAccount 35 | name: intel-power-operator 36 | namespace: intel-power 37 | roleRef: 38 | kind: Role 39 | name: operator-custom-resource-definitions-role 40 | apiGroup: rbac.authorization.k8s.io 41 | 42 | --- 43 | 44 | apiVersion: rbac.authorization.k8s.io/v1 45 | kind: ClusterRole 46 | metadata: 47 | name: operator-nodes 48 | rules: 49 | - apiGroups: [ "", "power.intel.com", "apps" ] 50 | resources: [ "nodes", "nodes/status", "configmaps", "configmaps/status", "powerconfigs", "powerconfigs/status", "powerprofiles", "powerprofiles/status", "powerworkloads", "powerworkloads/status", "powernodes", "powernodes/status", "events", "daemonsets","uncores" ] 51 | verbs: [ "*" ] 52 | 53 | --- 54 | 55 | apiVersion: rbac.authorization.k8s.io/v1 56 | kind: ClusterRoleBinding 57 | metadata: 58 | name: operator-nodes-binding 59 | subjects: 60 | - kind: ServiceAccount 61 | name: intel-power-operator 62 | namespace: intel-power 63 | roleRef: 64 | kind: ClusterRole 65 | name: operator-nodes 66 | apiGroup: rbac.authorization.k8s.io 67 | 68 | --- 69 | 70 | apiVersion: rbac.authorization.k8s.io/v1 71 | kind: ClusterRole 72 | metadata: 73 | name: node-agent-cluster-resources 74 | rules: 75 | - apiGroups: [ "", "batch", "power.intel.com" ] 76 | resources: [ "nodes", "nodes/status", "pods", "pods/status", "cronjobs", "cronjobs/status", "powerprofiles", "powerprofiles/status", "powerworkloads", "powerworkloads/status", "powernodes", "powernodes/status", "cstates", "cstates/status", "timeofdays", "timeofdays/status", "timeofdaycronjobs", "timeofdaycronjobs/status","uncores" ] 77 | verbs: [ "*" ] 78 | --- 79 | 80 | apiVersion: rbac.authorization.k8s.io/v1 81 | kind: ClusterRoleBinding 82 | metadata: 83 | name: node-agent-cluster-resources-binding 84 | subjects: 85 | - kind: ServiceAccount 86 | name: intel-power-node-agent 87 | namespace: intel-power 88 | roleRef: 89 | kind: ClusterRole 90 | name: node-agent-cluster-resources 91 | apiGroup: rbac.authorization.k8s.io 92 | 93 | --- 94 | -------------------------------------------------------------------------------- /config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: manager-role 7 | rules: 8 | - apiGroups: 9 | - power.intel.com 10 | resources: 11 | - cstates 12 | verbs: 13 | - create 14 | - delete 15 | - get 16 | - list 17 | - patch 18 | - update 19 | - watch 20 | - apiGroups: 21 | - power.intel.com 22 | resources: 23 | - cstates/status 24 | verbs: 25 | - get 26 | - patch 27 | - update 28 | - apiGroups: 29 | - power.intel.com 30 | resources: 31 | - powerconfigs 32 | verbs: 33 | - create 34 | - delete 35 | - get 36 | - list 37 | - patch 38 | - update 39 | - watch 40 | - apiGroups: 41 | - power.intel.com 42 | resources: 43 | - powerconfigs/status 44 | verbs: 45 | - get 46 | - patch 47 | - update 48 | - apiGroups: 49 | - power.intel.com 50 | resources: 51 | - powernodes 52 | verbs: 53 | - create 54 | - delete 55 | - get 56 | - list 57 | - patch 58 | - update 59 | - watch 60 | - apiGroups: 61 | - power.intel.com 62 | resources: 63 | - powernodes/status 64 | verbs: 65 | - get 66 | - patch 67 | - update 68 | - apiGroups: 69 | - power.intel.com 70 | resources: 71 | - powerpods 72 | verbs: 73 | - create 74 | - delete 75 | - get 76 | - list 77 | - patch 78 | - update 79 | - watch 80 | - apiGroups: 81 | - power.intel.com 82 | resources: 83 | - powerpods/status 84 | verbs: 85 | - get 86 | - patch 87 | - update 88 | - apiGroups: 89 | - power.intel.com 90 | resources: 91 | - powerprofiles 92 | verbs: 93 | - create 94 | - delete 95 | - get 96 | - list 97 | - patch 98 | - update 99 | - watch 100 | - apiGroups: 101 | - power.intel.com 102 | resources: 103 | - powerprofiles/status 104 | verbs: 105 | - get 106 | - patch 107 | - update 108 | - apiGroups: 109 | - power.intel.com 110 | resources: 111 | - powerworkloads 112 | verbs: 113 | - create 114 | - delete 115 | - get 116 | - list 117 | - patch 118 | - update 119 | - watch 120 | - apiGroups: 121 | - power.intel.com 122 | resources: 123 | - powerworkloads/status 124 | verbs: 125 | - get 126 | - patch 127 | - update 128 | - apiGroups: 129 | - power.intel.com 130 | resources: 131 | - timeofdays 132 | verbs: 133 | - create 134 | - delete 135 | - get 136 | - list 137 | - patch 138 | - update 139 | - watch 140 | - apiGroups: 141 | - power.intel.com 142 | resources: 143 | - timeofdays/status 144 | verbs: 145 | - get 146 | - patch 147 | - update 148 | - apiGroups: 149 | - power.intel.com 150 | resources: 151 | - uncores 152 | verbs: 153 | - create 154 | - delete 155 | - get 156 | - list 157 | - patch 158 | - update 159 | - watch 160 | - apiGroups: 161 | - power.intel.com 162 | resources: 163 | - uncores/finalizers 164 | verbs: 165 | - update 166 | - apiGroups: 167 | - power.intel.com 168 | resources: 169 | - uncores/status 170 | verbs: 171 | - get 172 | - patch 173 | - update 174 | -------------------------------------------------------------------------------- /config/rbac/uncore_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit uncores. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: uncore-editor-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: kubernetes-power-manager 10 | app.kubernetes.io/part-of: kubernetes-power-manager 11 | app.kubernetes.io/managed-by: kustomize 12 | name: uncore-editor-role 13 | rules: 14 | - apiGroups: 15 | - power.intel.com 16 | resources: 17 | - uncores 18 | verbs: 19 | - create 20 | - delete 21 | - get 22 | - list 23 | - patch 24 | - update 25 | - watch 26 | - apiGroups: 27 | - power.intel.com 28 | resources: 29 | - uncores/status 30 | verbs: 31 | - get 32 | -------------------------------------------------------------------------------- /config/rbac/uncore_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view uncores. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: uncore-viewer-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: kubernetes-power-manager 10 | app.kubernetes.io/part-of: kubernetes-power-manager 11 | app.kubernetes.io/managed-by: kustomize 12 | name: uncore-viewer-role 13 | rules: 14 | - apiGroups: 15 | - power.intel.com 16 | resources: 17 | - uncores 18 | verbs: 19 | - get 20 | - list 21 | - watch 22 | - apiGroups: 23 | - power.intel.com 24 | resources: 25 | - uncores/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/user_role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: user-role 7 | rules: 8 | - apiGroups: 9 | - power.intel.com 10 | resources: 11 | - powerconfigs 12 | verbs: 13 | - get 14 | - list 15 | - update 16 | - watch 17 | - apiGroups: 18 | - power.intel.com 19 | resources: 20 | - powerconfigs/status 21 | verbs: 22 | - get 23 | - update 24 | - apiGroups: 25 | - power.intel.com 26 | resources: 27 | - powernodes 28 | verbs: 29 | - get 30 | - list 31 | - update 32 | - watch 33 | - apiGroups: 34 | - power.intel.com 35 | resources: 36 | - powernodes/status 37 | verbs: 38 | - get 39 | - update 40 | - apiGroups: 41 | - power.intel.com 42 | resources: 43 | - powerpods 44 | verbs: 45 | - get 46 | - list 47 | - update 48 | - watch 49 | - apiGroups: 50 | - power.intel.com 51 | resources: 52 | - powerpods/status 53 | verbs: 54 | - get 55 | - update 56 | - apiGroups: 57 | - power.intel.com 58 | resources: 59 | - powerprofiles 60 | verbs: 61 | - get 62 | - list 63 | - update 64 | - watch 65 | - apiGroups: 66 | - power.intel.com 67 | resources: 68 | - powerprofiles/status 69 | verbs: 70 | - get 71 | - update 72 | - apiGroups: 73 | - power.intel.com 74 | resources: 75 | - powerworkloads 76 | verbs: 77 | - get 78 | - list 79 | - update 80 | - watch 81 | - apiGroups: 82 | - power.intel.com 83 | resources: 84 | - powerworkloads/status 85 | verbs: 86 | - get 87 | - update 88 | - apiGroups: 89 | - power.intel.com 90 | resources: 91 | - timeofdays 92 | verbs: 93 | - get 94 | - list 95 | - update 96 | - watch 97 | - apiGroups: 98 | - power.intel.com 99 | resources: 100 | - timeofdays/status 101 | verbs: 102 | - get 103 | - update 104 | -------------------------------------------------------------------------------- /config/rbac/user_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: pm_user 5 | subjects: 6 | - kind: User 7 | name: default 8 | namespace: intel-power 9 | apiGroup: rbac.authorization.k8s.io 10 | roleRef: 11 | apiGroup: rbac.authorization.k8s.io 12 | kind: ClusterRole 13 | name: user-role -------------------------------------------------------------------------------- /config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - power_v1_uncore.yaml 3 | - power_v1_cstates.yaml 4 | - power_v1_powerconfig.yaml 5 | - power_v1_shared_profile.yaml 6 | - power_v1_shared_workload.yaml 7 | - power_v1_timeofday.yaml 8 | #+kubebuilder:scaffold:manifestskustomizesamples 9 | -------------------------------------------------------------------------------- /config/samples/power_v1_cstates.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: CStates 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: CStates 6 | app.kubernetes.io/instance: 7 | app.kubernetes.io/part-of: kubernetes-power-manager 8 | app.kubernetes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: kubernetes-power-manager 10 | # Replace with the name of the node to configure the C-States on that node 11 | name: 12 | namespace: intel-power 13 | spec: 14 | sharedPoolCStates: 15 | C1: true 16 | exclusivePoolCStates: 17 | performance: 18 | C1: false 19 | individualCoreCStates: 20 | "5": 21 | C1: true 22 | C6: false 23 | -------------------------------------------------------------------------------- /config/samples/power_v1_powerconfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: PowerConfig 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: PowerConfig 6 | app.kubernetes.io/instance: power-config 7 | app.kubernetes.io/part-of: kubernetes-power-manager 8 | app.kubernetes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: kubernetes-power-manager 10 | name: power-config 11 | namespace: intel-power 12 | spec: 13 | powerNodeSelector: 14 | # Add labels here for the Nodes you want the PowerNodeAgent to be applied to 15 | feature.node.kubernetes.io/power-node: "true" 16 | powerProfiles: 17 | # Add wanted PowerProfiles here; valid entries are as follows: 18 | - balance-performance 19 | - balance-power 20 | - performance 21 | -------------------------------------------------------------------------------- /config/samples/power_v1_shared_profile.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: PowerProfile 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: PowerProfile 6 | app.kubernetes.io/instance: shared 7 | app.kubernetes.io/part-of: kubernetes-power-manager 8 | app.kubernetes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: kubernetes-power-manager 10 | name: shared 11 | namespace: intel-power 12 | spec: 13 | name: "shared" 14 | max: 1000 15 | min: 1000 16 | epp: "power" 17 | shared: true 18 | governor: "powersave" 19 | -------------------------------------------------------------------------------- /config/samples/power_v1_shared_workload.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: PowerWorkload 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: PowerWorkload 6 | app.kubernetes.io/instance: shared--workload 7 | app.kubernetes.io/part-of: kubernetes-power-manager 8 | app.kubernetes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: kubernetes-power-manager 10 | # Replace with the Node associated with PowerWorkload 11 | name: shared--workload 12 | namespace: intel-power 13 | spec: 14 | # Replace with the Node associated with PowerWorkload 15 | name: "shared--workload" 16 | allCores: true 17 | reservedCPUs: 18 | # IMPORTANT: The CPUs in reservedCPUs should match the value of the reserved system CPUs in your Kubelet config file 19 | - 0 20 | - 1 21 | powerNodeSelector: 22 | # The label must be as below, as this workload will be specific to the Node 23 | kubernetes.io/hostname: 24 | # Replace this value with the intended shared PowerProfile 25 | powerProfile: "shared" 26 | -------------------------------------------------------------------------------- /config/samples/power_v1_timeofday.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: TimeOfDay 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: TimeOfDay 6 | app.kubernetes.io/instance: timeofday-sample 7 | app.kubernetes.io/part-of: kubernetes-power-manager 8 | app.kubernetes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: kubernetes-power-manager 10 | name: timeofday-sample 11 | namespace: intel-power 12 | spec: 13 | timeZone: "Eire" 14 | schedule: 15 | - time: "10:04" 16 | # this sets the profile for the shared pool 17 | powerProfile: balance-power 18 | # this transitions exclusive pods matching a given label from one profile to another 19 | # please ensure that only pods to be used by power manager have this label 20 | pods: 21 | - labels: 22 | matchLabels: 23 | power: "true" 24 | target: performance 25 | - labels: 26 | matchLabels: 27 | special: "false" 28 | target: balance-performance 29 | # this field simply takes a cstate spec 30 | cState: 31 | sharedPoolCStates: 32 | C1: false 33 | C6: true 34 | - time: "14:48:00" 35 | powerProfile: shared 36 | cState: 37 | sharedPoolCStates: 38 | C1: true 39 | C6: false 40 | pods: 41 | - labels: 42 | matchLabels: 43 | power: "true" 44 | target: performance 45 | - labels: 46 | matchLabels: 47 | special: "false" 48 | target: balance-power 49 | - time: "14:35" 50 | powerProfile: balance-power 51 | reservedCPUs: [ 0,1 ] 52 | -------------------------------------------------------------------------------- /config/samples/power_v1_uncore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: Uncore 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: Uncore 6 | app.kubernetes.io/instance: uncore-sample 7 | app.kubernetes.io/part-of: kubernetes-power-manager 8 | app.kubernetes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: kubernetes-power-manager 10 | name: 11 | namespace: intel-power 12 | spec: 13 | sysMax: 2300000 14 | sysMin: 1300000 15 | dieSelector: 16 | - package: 0 17 | die: 0 18 | min: 1500000 19 | max: 2400000 20 | -------------------------------------------------------------------------------- /config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [ ] 8 | -------------------------------------------------------------------------------- /config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | patches: 6 | - path: patches/basic.config.yaml 7 | target: 8 | group: scorecard.operatorframework.io 9 | kind: Configuration 10 | name: config 11 | version: v1alpha3 12 | - path: patches/olm.config.yaml 13 | target: 14 | group: scorecard.operatorframework.io 15 | kind: Configuration 16 | name: config 17 | version: v1alpha3 18 | -------------------------------------------------------------------------------- /config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.1.0 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.1.0 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.1.0 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | - op: add 22 | path: /stages/0/tests/- 23 | value: 24 | entrypoint: 25 | - scorecard-test 26 | - olm-crds-have-resources 27 | image: quay.io/operator-framework/scorecard-test:v1.1.0 28 | labels: 29 | suite: olm 30 | test: olm-crds-have-resources-test 31 | - op: add 32 | path: /stages/0/tests/- 33 | value: 34 | entrypoint: 35 | - scorecard-test 36 | - olm-spec-descriptors 37 | image: quay.io/operator-framework/scorecard-test:v1.1.0 38 | labels: 39 | suite: olm 40 | test: olm-spec-descriptors-test 41 | - op: add 42 | path: /stages/0/tests/- 43 | value: 44 | entrypoint: 45 | - scorecard-test 46 | - olm-status-descriptors 47 | image: quay.io/operator-framework/scorecard-test:v1.1.0 48 | labels: 49 | suite: olm 50 | test: olm-status-descriptors-test 51 | -------------------------------------------------------------------------------- /config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /config/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting vars. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | 24 | varReference: 25 | - path: metadata/annotations 26 | -------------------------------------------------------------------------------- /config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: webhook-service 5 | namespace: system 6 | spec: 7 | ports: 8 | - port: 443 9 | targetPort: 9443 10 | selector: 11 | control-plane: controller-manager 12 | -------------------------------------------------------------------------------- /controllers/common.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package controllers 15 | 16 | import ( 17 | "context" 18 | "reflect" 19 | 20 | "github.com/go-logr/logr" 21 | powerv1 "github.com/intel/kubernetes-power-manager/api/v1" 22 | "github.com/intel/kubernetes-power-manager/pkg/util" 23 | "sigs.k8s.io/controller-runtime/pkg/client" 24 | ) 25 | 26 | // write errors to the status filed, pass nil to clear errors, will only do update resource is valid and not being deleted 27 | // if object already has the correct errors it will not be updated in the API 28 | func writeUpdatedStatusErrsIfRequired(ctx context.Context, statusWriter client.SubResourceWriter, object powerv1.PowerCRWithStatusErrors, objectErrors error) error { 29 | var err error 30 | // if invalid or marked for deletion don't do anything 31 | if object.GetUID() == "" || object.GetDeletionTimestamp() != nil { 32 | return err 33 | } 34 | errList := util.UnpackErrsToStrings(objectErrors) 35 | // no updates are needed 36 | if reflect.DeepEqual(*errList, *object.GetStatusErrors()) { 37 | return err 38 | } 39 | object.SetStatusErrors(errList) 40 | err = statusWriter.Update(ctx, object) 41 | if err != nil { 42 | logr.FromContextOrDiscard(ctx).Error(err, "failed to write status update") 43 | } 44 | return err 45 | } 46 | -------------------------------------------------------------------------------- /controllers/common_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | package controllers 15 | 16 | import ( 17 | "context" 18 | "fmt" 19 | "testing" 20 | 21 | powerv1 "github.com/intel/kubernetes-power-manager/api/v1" 22 | "github.com/stretchr/testify/assert" 23 | "github.com/stretchr/testify/mock" 24 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | "sigs.k8s.io/controller-runtime/pkg/client" 26 | fakeClient "sigs.k8s.io/controller-runtime/pkg/client/fake" 27 | "sigs.k8s.io/controller-runtime/pkg/client/interceptor" 28 | ) 29 | 30 | func Test_writeStatusErrors(t *testing.T) { 31 | var object powerv1.PowerCRWithStatusErrors 32 | var errorList error 33 | var ctx = context.Background() 34 | clientMockObj := mock.Mock{} 35 | clientFuncs := interceptor.Funcs{ 36 | SubResourceUpdate: func(ctx context.Context, client client.Client, subResourceName string, obj client.Object, opts ...client.SubResourceUpdateOption) error { 37 | return clientMockObj.MethodCalled("SubResourceUpdate", ctx, client, subResourceName, obj, opts).Error(0) 38 | }, 39 | } 40 | clientStatusWriter := fakeClient.NewClientBuilder().WithInterceptorFuncs(clientFuncs).Build().Status() 41 | 42 | object = &powerv1.Uncore{} 43 | assert.Nil(t, writeUpdatedStatusErrsIfRequired(ctx, nil, object, nil), "invalid object should return nil without doing anything") 44 | 45 | deletionTimestamp := v1.Now() 46 | object = &powerv1.CStates{ 47 | ObjectMeta: v1.ObjectMeta{ 48 | DeletionTimestamp: &deletionTimestamp, 49 | }, 50 | } 51 | assert.Nil(t, writeUpdatedStatusErrsIfRequired(ctx, nil, object, nil), "object marked for deletion should return nil without doing anything") 52 | 53 | object = &powerv1.PowerProfile{ 54 | ObjectMeta: v1.ObjectMeta{ 55 | UID: "not empty", 56 | }, 57 | Status: powerv1.PowerProfileStatus{ 58 | StatusErrors: powerv1.StatusErrors{ 59 | Errors: []string{"err1"}, 60 | }, 61 | }, 62 | } 63 | errorList = fmt.Errorf("err1") 64 | assert.Nil(t, writeUpdatedStatusErrsIfRequired(ctx, nil, object, errorList), "no updates should be needed") 65 | 66 | object = &powerv1.PowerWorkload{ 67 | ObjectMeta: v1.ObjectMeta{ 68 | UID: "not empty", 69 | }, 70 | } 71 | clientMockObj.On("SubResourceUpdate", ctx, mock.Anything, "status", &powerv1.PowerWorkload{ 72 | ObjectMeta: v1.ObjectMeta{ 73 | UID: "not empty", 74 | }, 75 | Status: powerv1.PowerWorkloadStatus{ 76 | StatusErrors: powerv1.StatusErrors{ 77 | Errors: []string{"err1"}, 78 | }, 79 | }, 80 | }, mock.Anything).Return(nil) 81 | errorList = fmt.Errorf("err1") 82 | assert.Nil(t, writeUpdatedStatusErrsIfRequired(ctx, clientStatusWriter, object, errorList), "API should get updated with object with errors") 83 | 84 | object = &powerv1.TimeOfDay{ 85 | ObjectMeta: v1.ObjectMeta{ 86 | UID: "not empty", 87 | }, 88 | } 89 | 90 | clientMockObj = mock.Mock{} 91 | updateErr := fmt.Errorf("update error") 92 | clientMockObj.On("SubResourceUpdate", ctx, mock.Anything, "status", mock.Anything, mock.Anything).Return(updateErr) 93 | assert.ErrorIs(t, writeUpdatedStatusErrsIfRequired(ctx, clientStatusWriter, object, fmt.Errorf("err2")), updateErr, "error updating APi should return that error") 94 | 95 | } 96 | -------------------------------------------------------------------------------- /diagrams-docs/README.md: -------------------------------------------------------------------------------- 1 | # Power Manger Architectural and Sequence Diagrams 2 | 3 | An up-to-date architectural and sequence diagram will be available here. 4 | With each update or release an updated diagram will be available with the version number attached. 5 | 6 | ## Install PlnatUML 7 | 8 | - install plantuml.jar: http://sourceforge.net/projects/plantuml/files/plantuml.jar/download 9 | - To run PlantUML you need: 10 | - Java: https://www.java.com/en/download/ 11 | - Graphviz (optional): https://plantuml.com/graphviz-dot 12 | 13 | - Example 14 | - Create file: sequenceDiagram.txt 15 | - example code: 16 | @startuml 17 | Alice -> Bob: test 18 | @enduml 19 | - Run: java -jar plantuml.jar sequenceDiagram.txt 20 | - Output file sequenceDiagram.png will be created with the diagram 21 | 22 | ## Creating Power Manager Diagrams 23 | 24 | - Running pm-sequenc.puml in this directory: 25 | - java -jar plantuml.jar pm-sequence.puml 26 | - output file is pm-sequence.png 27 | - Running the Power Manager overall architecture diagram 28 | - java -jar plantuml.jar power-arch.puml 29 | - output file is power-arch.png 30 | - Running the Power Manager components diagram 31 | - java -jar plantuml.jar power-com.puml 32 | - output file is power-com.png 33 | 34 | ## Summary of elements in the K8s Cluster 35 | 36 | ## Control Plane ~ Master Node 37 | 38 | The elements of the control plane detect and react to cluster events as well as make broad choices about the cluster. 39 | Kubernetes is dependent on a number of control plane-based administrative services. 40 | These services control things like task scheduling, cluster state persistence, and communication between cluster 41 | components. 42 | 43 | ### API Server (kube-apiserver) 44 | 45 | • API server exposes the Kubernetes API. 46 | • Entry point for REST/kubectl — It is the front end for the Kubernetes control plane. 47 | • It tracks the state of all cluster components and managing the interaction between them. 48 | • It is designed to scale horizontally. 49 | • It consumes YAML/JSON manifest files. 50 | • It validates and processes the requests made via API. 51 | 52 | ### etcd (key-value store) 53 | 54 | • It is a consistent, distributed, and highly-available key value store. 55 | • It is stateful, persistent storage that stores all of Kubernetes cluster data (cluster state and config). 56 | • It is the source of truth for the cluster. 57 | • It can be part of the control plane, or, it can be configured externally. 58 | 59 | ### Scheduler (kube-scheduler) 60 | 61 | • It schedules pods to worker nodes. 62 | • It watches api-server for newly created Pods with no assigned node, and selects a healthy node for them to run on. 63 | • If there are no suitable nodes, the pods are put in a pending state until such a healthy node appears. 64 | • It watches API Server for new work tasks. 65 | 66 | #### Factors taken into account for scheduling decisions include: 67 | 68 | • Individual and collective resource requirements. 69 | • Hardware/software/policy constraints. 70 | • Affinity and anti-affinity specifications. 71 | • Data locality. 72 | • Inter-workload interference. 73 | • Deadlines and taints. 74 | 75 | ### Controller Manager (kube-controller-manager) 76 | 77 | • It watches the desired state of the objects it manages and watches their current state through the API server. 78 | • It takes corrective steps to make sure that the current state is the same as the desired state. 79 | • It is controller of controllers. It runs controller processes. Logically, each controller is a separate process, but to reduce complexity, they are all compiled into a single binary and run in a single process. 80 | 81 | ## Worker Node 82 | 83 | Node components run on every node, maintaining running pods and providing the Kubernetes runtime environment. 84 | 85 | ### kubelet 86 | 87 | • It is an agent that runs on each node in the cluster. 88 | • It acts as a conduit between the API server and the node. 89 | • It makes sure that containers are running in a Pod and they are healthy. 90 | • It instantiates and executes Pods. 91 | • It watches API Server for work tasks. 92 | • It gets instructions from master and reports back to Masters. 93 | 94 | ### kube-proxy 95 | 96 | • It is networking component that plays vital role in networking. 97 | • It manages IP translation and routing. 98 | • It is a network proxy that runs on each node in cluster. 99 | • It maintains network rules on nodes. These network rules allow network communication to Pods from inside or outside of cluster. 100 | • It ensure each Pod gets unique IP address. 101 | • It makes possible that all containers in a pod share a single IP. 102 | • It facilitating Kubernetes networking services and load-balancing across all pods in a service. 103 | • It deals with individual host sub-netting and ensure that the services are available to external parties. 104 | 105 | ### Container runtime 106 | 107 | • The container runtime is the software that is responsible for running containers (in Pods). 108 | • To run the containers, each worker node has a container runtime engine. 109 | • It pulls images from a container image registry and starts and stops containers. 110 | -------------------------------------------------------------------------------- /diagrams-docs/TimeOfDay-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/kubernetes-power-manager/e6bed6d30b6caed0c92132990264d9351a3ecb70/diagrams-docs/TimeOfDay-sequence.png -------------------------------------------------------------------------------- /diagrams-docs/TimeOfDay-sequence.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam noteBorderColor Black 3 | skinparam noteBorderThickness 1 4 | skinparam noteBackgroundColor Yellow 5 | skinparam legendBackgroundColor WhiteSmoke 6 | 7 | skinparam sequence { 8 | BoxBorderColor Black 9 | BoxFontSize 20 10 | 11 | ArrowColor Black 12 | ArrowThickness 1 13 | 14 | ActorBorderColor Black 15 | ActorBorderThickness 3 16 | ActorBackgroundColor Business 17 | ActorFontSize 15 18 | 19 | ParticipantBorderColor Black 20 | ParticipantBorderThickness 1 21 | ParticipantBackgroundColor Business 22 | ParticipantFontSize 15 23 | 24 | LifeLineBorderColor Black 25 | LifeLineBorderThickness 1 26 | LifeLineBackgroundColor LightGray 27 | } 28 | 29 | 30 | legend top right 31 | |= |= Legend | 32 | | | Control Plane ~ Master Node | 33 | | | Worker Node | 34 | | | Power Manager System Setup | 35 | | | Power Manager Configuration | 36 | | | Power Manager Deployment | 37 | endlegend 38 | 39 | actor Georgina 40 | participant apiSrv as "API-Server" #LightBlue 41 | participant etcd as "etcd" #LightBlue 42 | participant cntrlMgr as "Controller Manager" #LightBlue 43 | participant sched as "Scheduler" #LightBlue 44 | participant powerOperator as "Power Operator" #LightBlue 45 | participant kubelet as "Kubelet" #LightGreen 46 | participant agent as "Power Node Agent" #LightGreen 47 | participant library as "Power Optimization Library" #LightGreen 48 | participant objects as "K8s Objects" #LightGreen 49 | participant proxy as "Kube-Proxy" #LightGreen 50 | 51 | title : Interactions between the Control Plane (master node) and the Worker Node 52 | 53 | 54 | 55 | == Power Manager Initialization == 56 | autonumber 57 | 58 | Georgina -> proxy : Ensure correct proxy configuration 59 | 60 | Georgina -> kubelet: Confirm CPU Manager policy 61 | note right #DarkGray: cpuManagerPolicy = "static" 62 | 63 | Georgina -> kubelet: Reserve System CPUs 64 | note right #DarkGray: reservedSystemCPUs = "0" 65 | 66 | kubelet -> agent: Create Namespace 67 | note right #LightYellow: apply config/rbac/namespace.yaml 68 | 69 | kubelet -> agent: Create RBAC and Service Accounts 70 | note right #LightYellow: apply config/rbac/rbac.yaml 71 | 72 | kubelet -> objects: Create CRDs 73 | note right #LightYellow: make 74 | 75 | kubelet -> agent: Label nodes 76 | note right #LightYellow: label node feature.node.kubernetes.io/power-node=”true” 77 | 78 | autonumber stop 79 | 80 | 81 | == Power Manager Deployment == 82 | autonumber 83 | 84 | kubelet -> agent: Deploy Controller Manager 85 | note right #Orange: apply config/manager/manager.yaml 86 | 87 | powerOperator -> library: Deploy the config 88 | note right #Orange: examples/example-powerconfig.yaml 89 | 90 | agent -> library: Set Shared Profile 91 | note right #Orange: examples/example-shared-profile.yaml 92 | 93 | agent -> library: Deploy th Workload 94 | note right #Orange: examples/example-shared-workload.yaml 95 | 96 | agent -> library: Deploy Pod 97 | note right #Orange: examples/example-pod.yaml 98 | 99 | autonumber stop 100 | 101 | == Power Manager additional functionality == 102 | 103 | 104 | == Time of Day == 105 | autonumber 106 | 107 | kubelet -> agent: Deploy Controller Manager 108 | note right #Orange: apply config/manager/manager.yaml 109 | 110 | powerOperator -> library: Deploy the config 111 | note right #Orange: examples/example-powerconfig.yaml 112 | 113 | agent -> library: Set Shared Profile 114 | note right #Orange: examples/example-shared-profile.yaml 115 | 116 | agent -> library: Deploy th Workload 117 | note right #Orange: examples/example-shared-workload.yaml 118 | 119 | agent -> library: Deploy Pod 120 | note right #Orange: examples/example-pod.yaml 121 | 122 | agent -> library: Set Time of Day functionality 123 | note right #Orange: examples/example-timeofday 124 | 125 | autonumber stop 126 | 127 | @enduml -------------------------------------------------------------------------------- /diagrams-docs/cstate-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/kubernetes-power-manager/e6bed6d30b6caed0c92132990264d9351a3ecb70/diagrams-docs/cstate-sequence.png -------------------------------------------------------------------------------- /diagrams-docs/cstate-sequence.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam noteBorderColor Black 3 | skinparam noteBorderThickness 1 4 | skinparam noteBackgroundColor Yellow 5 | skinparam legendBackgroundColor WhiteSmoke 6 | 7 | skinparam sequence { 8 | BoxBorderColor Black 9 | BoxFontSize 20 10 | 11 | ArrowColor Black 12 | ArrowThickness 1 13 | 14 | ActorBorderColor Black 15 | ActorBorderThickness 3 16 | ActorBackgroundColor Business 17 | ActorFontSize 15 18 | 19 | ParticipantBorderColor Black 20 | ParticipantBorderThickness 1 21 | ParticipantBackgroundColor Business 22 | ParticipantFontSize 15 23 | 24 | LifeLineBorderColor Black 25 | LifeLineBorderThickness 1 26 | LifeLineBackgroundColor LightGray 27 | } 28 | 29 | 30 | legend top right 31 | |= |= Legend | 32 | | | Control Plane ~ Master Node | 33 | | | Worker Node | 34 | | | Power Manager System Setup | 35 | | | Power Manager Configuration | 36 | | | Power Manager Deployment | 37 | endlegend 38 | 39 | actor Georgina 40 | participant apiSrv as "API-Server" #LightBlue 41 | participant etcd as "etcd" #LightBlue 42 | participant cntrlMgr as "Controller Manager" #LightBlue 43 | participant sched as "Scheduler" #LightBlue 44 | participant powerOperator as "Power Operator" #LightBlue 45 | participant kubelet as "Kubelet" #LightGreen 46 | participant agent as "Power Node Agent" #LightGreen 47 | participant library as "Power Optimization Library" #LightGreen 48 | participant objects as "K8s Objects" #LightGreen 49 | participant proxy as "Kube-Proxy" #LightGreen 50 | 51 | title : Interactions between the Control Plane (master node) and the Worker Node 52 | 53 | == Power Manager Initialization == 54 | autonumber 55 | 56 | Georgina -> proxy : Ensure correct proxy configuration 57 | 58 | Georgina -> kubelet: Confirm CPU Manager policy 59 | note right #DarkGray: cpuManagerPolicy = "static" 60 | 61 | Georgina -> kubelet: Reserve System CPUs 62 | note right #DarkGray: reservedSystemCPUs = "0" 63 | 64 | kubelet -> agent: Create Namespace 65 | note right #LightYellow: apply config/rbac/namespace.yaml 66 | 67 | kubelet -> agent: Create RBAC and Service Accounts 68 | note right #LightYellow: apply config/rbac/rbac.yaml 69 | 70 | kubelet -> objects: Create CRDs 71 | note right #LightYellow: make 72 | 73 | kubelet -> agent: Label nodes 74 | note right #LightYellow: label node feature.node.kubernetes.io/power-node=”true” 75 | 76 | autonumber stop 77 | 78 | 79 | == Power Manager Deployment == 80 | autonumber 81 | 82 | kubelet -> agent: Deploy Controller Manager 83 | note right #Orange: apply config/manager/manager.yaml 84 | 85 | powerOperator -> library: Deploy the config 86 | note right #Orange: examples/example-powerconfig.yaml 87 | 88 | agent -> library: Set Shared Profile 89 | note right #Orange: examples/example-shared-profile.yaml 90 | 91 | agent -> library: Deploy th Workload 92 | note right #Orange: examples/example-shared-workload.yaml 93 | 94 | agent -> library: Deploy Pod 95 | note right #Orange: examples/example-pod.yaml 96 | 97 | autonumber stop 98 | 99 | == Power Manager additional functionality == 100 | 101 | == C-State == 102 | autonumber 103 | 104 | kubelet -> agent: Deploy Controller Manager 105 | note right #Orange: apply config/manager/manager.yaml 106 | 107 | powerOperator -> library: Deploy the config 108 | note right #Orange: examples/example-powerconfig.yaml 109 | 110 | agent -> library: Set Shared Profile 111 | note right #Orange: examples/example-shared-profile.yaml 112 | 113 | agent -> library: Deploy th Workload 114 | note right #Orange: examples/example-shared-workload.yaml 115 | 116 | agent -> library: Deploy Pod 117 | note right #Orange: examples/example-pod.yaml 118 | 119 | agent -> library: Set C-State functionality 120 | note right #Orange: examples/example-cstates 121 | 122 | autonumber stop 123 | 124 | @enduml -------------------------------------------------------------------------------- /diagrams-docs/pm-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/kubernetes-power-manager/e6bed6d30b6caed0c92132990264d9351a3ecb70/diagrams-docs/pm-sequence.png -------------------------------------------------------------------------------- /diagrams-docs/power-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/kubernetes-power-manager/e6bed6d30b6caed0c92132990264d9351a3ecb70/diagrams-docs/power-arch.png -------------------------------------------------------------------------------- /diagrams-docs/power-arch.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | 25 | 26 | 27 | actor Developer 28 | actor Georgina 29 | 30 | title Kubernetes Power Manager Architectural Diagram 31 | skinparam roundCorner 15 32 | rectangle "Kubernetes Cluster" { 33 | 34 | node "Control-Plane (Master Node)" { 35 | 36 | agent "etcd" as etcd 37 | agent "Power Operator" as po #effbda 38 | agent "\t\t\tAPI Server\t\t\t" as api 39 | agent "Scheduler" as sch 40 | agent "Controller Manager" as cm 41 | 42 | etcd -down-> api 43 | po <--> api 44 | api <--> sch 45 | api <-down-> cm 46 | 47 | 48 | } 49 | 50 | Developer -left-> api #red;line.dashed : kubectl 51 | 52 | node "Worker Node" { 53 | 54 | agent "Kube-Proxy" as proxy 55 | agent "Kubelet" as kube 56 | agent "Power Node Agent" as pna #effbda 57 | agent "Power Optimization\n Library" as pol #effbfa 58 | agent "K8s Objects" as obj 59 | 60 | pna <-right- kube 61 | pna <--> pol 62 | obj <-down-> pna 63 | } 64 | 65 | 66 | proxy <-Left- Georgina #red;line.dashed; 67 | api <-ri-> proxy 68 | api <--> kube 69 | } 70 | 71 | @enduml 72 | 73 | -------------------------------------------------------------------------------- /diagrams-docs/power-com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/kubernetes-power-manager/e6bed6d30b6caed0c92132990264d9351a3ecb70/diagrams-docs/power-com.png -------------------------------------------------------------------------------- /diagrams-docs/power-com.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | 25 | 26 | 27 | 28 | title Kubernetes Power Manager components Diagram 29 | skinparam roundCorner 15 30 | node "Power Node Agent" { 31 | 32 | rectangle "C-State \nController" 33 | rectangle "Power Node \nController" 34 | rectangle "Power Pod \nController" 35 | rectangle "Power Profile \nController" 36 | rectangle "Power Workload \nController" 37 | rectangle "Time Of Day \nController" 38 | rectangle "Time of Day \nCronJob Controller" 39 | 40 | } 41 | 42 | node "Power Optimization Library" { 43 | 44 | rectangle "C-State" 45 | rectangle "P-States" 46 | rectangle "Core" 47 | rectangle "Host" 48 | rectangle "Power" 49 | rectangle "Pool" 50 | rectangle "Power Profiles" 51 | } 52 | 53 | node "Power Operator" { 54 | 55 | rectangle "Power Config\nController" 56 | 57 | } 58 | @enduml 59 | 60 | -------------------------------------------------------------------------------- /diagrams-docs/scaling-driver-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/kubernetes-power-manager/e6bed6d30b6caed0c92132990264d9351a3ecb70/diagrams-docs/scaling-driver-sequence.png -------------------------------------------------------------------------------- /diagrams-docs/scaling-driver-sequence.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam noteBorderColor Black 3 | skinparam noteBorderThickness 1 4 | skinparam noteBackgroundColor Yellow 5 | skinparam legendBackgroundColor WhiteSmoke 6 | 7 | skinparam sequence { 8 | BoxBorderColor Black 9 | BoxFontSize 20 10 | 11 | ArrowColor Black 12 | ArrowThickness 1 13 | 14 | ActorBorderColor Black 15 | ActorBorderThickness 3 16 | ActorBackgroundColor Business 17 | ActorFontSize 15 18 | 19 | ParticipantBorderColor Black 20 | ParticipantBorderThickness 1 21 | ParticipantBackgroundColor Business 22 | ParticipantFontSize 15 23 | 24 | LifeLineBorderColor Black 25 | LifeLineBorderThickness 1 26 | LifeLineBackgroundColor LightGray 27 | } 28 | 29 | 30 | legend top right 31 | |= |= Legend | 32 | | | Control Plane ~ Master Node | 33 | | | Worker Node | 34 | | | Power Manager System Setup | 35 | | | Power Manager Configuration | 36 | | | Power Manager Deployment | 37 | endlegend 38 | 39 | actor Georgina 40 | participant apiSrv as "API-Server" #LightBlue 41 | participant etcd as "etcd" #LightBlue 42 | participant cntrlMgr as "Controller Manager" #LightBlue 43 | participant sched as "Scheduler" #LightBlue 44 | participant powerOperator as "Power Operator" #LightBlue 45 | participant kubelet as "Kubelet" #LightGreen 46 | participant agent as "Power Node Agent" #LightGreen 47 | participant library as "Power Optimization Library" #LightGreen 48 | participant objects as "K8s Objects" #LightGreen 49 | participant proxy as "Kube-Proxy" #LightGreen 50 | 51 | title : Interactions between the Control Plane (master node) and the Worker Node 52 | 53 | 54 | 55 | == Power Manager Initialization == 56 | autonumber 57 | 58 | Georgina -> proxy : Ensure correct proxy configuration 59 | 60 | Georgina -> kubelet: Confirm CPU Manager policy 61 | note right #DarkGray: cpuManagerPolicy = "static" 62 | 63 | Georgina -> kubelet: Reserve System CPUs 64 | note right #DarkGray: reservedSystemCPUs = "0" 65 | 66 | kubelet -> agent: Create Namespace 67 | note right #LightYellow: apply config/rbac/namespace.yaml 68 | 69 | kubelet -> agent: Create RBAC and Service Accounts 70 | note right #LightYellow: apply config/rbac/rbac.yaml 71 | 72 | kubelet -> objects: Create CRDs 73 | note right #LightYellow: make 74 | 75 | kubelet -> agent: Label nodes 76 | note right #LightYellow: label node feature.node.kubernetes.io/power-node=”true” 77 | 78 | autonumber stop 79 | 80 | 81 | == Power Manager Deployment == 82 | autonumber 83 | 84 | kubelet -> agent: Deploy Controller Manager 85 | note right #Orange: apply config/manager/manager.yaml 86 | 87 | powerOperator -> library: Deploy the config 88 | note right #Orange: examples/example-powerconfig.yaml 89 | 90 | agent -> library: Set Shared Profile 91 | note right #Orange: examples/example-shared-profile.yaml 92 | 93 | agent -> library: Deploy th Workload 94 | note right #Orange: examples/example-shared-workload.yaml 95 | 96 | agent -> library: Deploy Pod 97 | note right #Orange: examples/example-pod.yaml 98 | 99 | autonumber stop 100 | 101 | == Power Manager additional functionality == 102 | 103 | == Scaling Driver == 104 | autonumber 105 | 106 | kubelet -> agent: Deploy Controller Manager 107 | note right #Orange: apply config/manager/manager.yaml 108 | 109 | powerOperator -> library: Deploy the config 110 | note right #Orange: examples/example-powerconfig.yaml 111 | 112 | agent -> library: Set Shared Profile \nand configure the scaling driver governor 113 | note right #Orange: examples/example-shared-profile.yaml 114 | 115 | agent -> library: Deploy th Workload 116 | note right #Orange: examples/example-shared-workload.yaml 117 | 118 | agent -> library: Deploy Pod 119 | note right #Orange: examples/example-pod.yaml 120 | 121 | autonumber stop 122 | 123 | 124 | @enduml -------------------------------------------------------------------------------- /diagrams-docs/uncore-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/kubernetes-power-manager/e6bed6d30b6caed0c92132990264d9351a3ecb70/diagrams-docs/uncore-sequence.png -------------------------------------------------------------------------------- /diagrams-docs/uncore-sequence.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam noteBorderColor Black 3 | skinparam noteBorderThickness 1 4 | skinparam noteBackgroundColor Yellow 5 | skinparam legendBackgroundColor WhiteSmoke 6 | 7 | skinparam sequence { 8 | BoxBorderColor Black 9 | BoxFontSize 20 10 | 11 | ArrowColor Black 12 | ArrowThickness 1 13 | 14 | ActorBorderColor Black 15 | ActorBorderThickness 3 16 | ActorBackgroundColor Business 17 | ActorFontSize 15 18 | 19 | ParticipantBorderColor Black 20 | ParticipantBorderThickness 1 21 | ParticipantBackgroundColor Business 22 | ParticipantFontSize 15 23 | 24 | LifeLineBorderColor Black 25 | LifeLineBorderThickness 1 26 | LifeLineBackgroundColor LightGray 27 | } 28 | 29 | 30 | legend top right 31 | |= |= Legend | 32 | | | Control Plane ~ Master Node | 33 | | | Worker Node | 34 | | | Power Manager System Setup | 35 | | | Power Manager Configuration | 36 | | | Power Manager Deployment | 37 | endlegend 38 | 39 | actor Georgina 40 | participant apiSrv as "API-Server" #LightBlue 41 | participant etcd as "etcd" #LightBlue 42 | participant cntrlMgr as "Controller Manager" #LightBlue 43 | participant sched as "Scheduler" #LightBlue 44 | participant powerOperator as "Power Operator" #LightBlue 45 | participant kubelet as "Kubelet" #LightGreen 46 | participant agent as "Power Node Agent" #LightGreen 47 | participant library as "Power Optimization Library" #LightGreen 48 | participant objects as "K8s Objects" #LightGreen 49 | participant proxy as "Kube-Proxy" #LightGreen 50 | 51 | title : Interactions between the Control Plane (master node) and the Worker Node 52 | 53 | 54 | == Power Manager Initialization == 55 | autonumber 56 | 57 | Georgina -> proxy : Ensure correct proxy configuration 58 | 59 | Georgina -> kubelet: Confirm CPU Manager policy 60 | note right #DarkGray: cpuManagerPolicy = "static" 61 | 62 | Georgina -> kubelet: Reserve System CPUs 63 | note right #DarkGray: reservedSystemCPUs = "0" 64 | 65 | kubelet -> agent: Create Namespace 66 | note right #LightYellow: apply config/rbac/namespace.yaml 67 | 68 | kubelet -> agent: Create RBAC and Service Accounts 69 | note right #LightYellow: apply config/rbac/rbac.yaml 70 | 71 | kubelet -> objects: Create CRDs 72 | note right #LightYellow: make 73 | 74 | kubelet -> agent: Label nodes 75 | note right #LightYellow: label node feature.node.kubernetes.io/power-node=”true” 76 | 77 | autonumber stop 78 | 79 | 80 | == Power Manager Deployment == 81 | autonumber 82 | 83 | kubelet -> agent: Deploy Controller Manager 84 | note right #Orange: apply config/manager/manager.yaml 85 | 86 | powerOperator -> library: Deploy the config 87 | note right #Orange: examples/example-powerconfig.yaml 88 | 89 | agent -> library: Set Shared Profile 90 | note right #Orange: examples/example-shared-profile.yaml 91 | 92 | agent -> library: Deploy th Workload 93 | note right #Orange: examples/example-shared-workload.yaml 94 | 95 | agent -> library: Deploy Pod 96 | note right #Orange: examples/example-pod.yaml 97 | 98 | autonumber stop 99 | 100 | == Power Manager additional functionality == 101 | 102 | == Uncore == 103 | autonumber 104 | 105 | Georgina -> kubelet: Confirm Kernel verson 106 | note right #DarkGray: kernel 5.6+ required for uncore 107 | 108 | 109 | kubelet -> library: Set Freq in Die and Pkg 110 | note right #Orange: examples/example-uncore 111 | 112 | kubelet -> agent: Deploy Controller Manager 113 | note right #Orange: apply config/manager/manager.yaml 114 | 115 | powerOperator -> library: Deploy the config 116 | note right #Orange: examples/example-powerconfig.yaml 117 | 118 | agent -> library: Set Shared Profile 119 | note right #Orange: examples/example-shared-profile.yaml 120 | 121 | agent -> library: Deploy th Workload 122 | note right #Orange: examples/example-shared-workload.yaml 123 | 124 | agent -> library: Deploy Pod 125 | note right #Orange: examples/example-pod.yaml 126 | 127 | 128 | autonumber stop 129 | 130 | 131 | 132 | @enduml -------------------------------------------------------------------------------- /examples/example-cstates.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: CStates 3 | metadata: 4 | # Replace with the name of the node to configure the C-States on that node 5 | name: 6 | namespace: intel-power 7 | spec: 8 | sharedPoolCStates: 9 | C1: true 10 | exclusivePoolCStates: 11 | performance: 12 | C1: false 13 | individualCoreCStates: 14 | "5": 15 | C1: true 16 | C6: false -------------------------------------------------------------------------------- /examples/example-pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: example-power-pod 5 | spec: 6 | containers: 7 | - name: example-power-container 8 | image: ubuntu 9 | command: [ "/bin/sh" ] 10 | args: [ "-c", "sleep 15000" ] 11 | resources: 12 | requests: 13 | memory: "200Mi" 14 | cpu: "2" 15 | # Replace with the PowerProfile you wish to request 16 | # IMPORTANT: The number of requested PowerProfiles must match the number of requested CPUs 17 | # IMPORTANT: If they do not match, the Pod will be successfully scheduled, but the PowerWorkload for the Pod will not be created 18 | power.intel.com/performance: "2" 19 | limits: 20 | memory: "200Mi" 21 | cpu: "2" 22 | # Replace with the PowerProfile you wish to request 23 | # IMPORTANT: The number of requested PowerProfiles must match the number of requested CPUs 24 | # IMPORTANT: If they do not match, the Pod will be successfully scheduled, but the PowerWorkload for the Pod will not be created 25 | power.intel.com/performance: "2" 26 | -------------------------------------------------------------------------------- /examples/example-powerconfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: PowerConfig 3 | metadata: 4 | name: power-config 5 | namespace: intel-power 6 | spec: 7 | powerNodeSelector: 8 | # Add labels here for the Nodes you want the PowerNodeAgent to be applied to 9 | feature.node.kubernetes.io/power-node: "true" 10 | powerProfiles: 11 | # Add wanted PowerProfiles here; valid entries are as follows: 12 | - balance-performance 13 | - balance-power 14 | - "performance" 15 | -------------------------------------------------------------------------------- /examples/example-shared-profile.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: PowerProfile 3 | metadata: 4 | name: shared 5 | namespace: intel-power 6 | spec: 7 | name: "shared" 8 | max: 1000 9 | min: 1000 10 | epp: "power" 11 | shared: true 12 | governor: "powersave" 13 | -------------------------------------------------------------------------------- /examples/example-shared-workload.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: PowerWorkload 3 | metadata: 4 | # Replace with the Node associated with PowerWorkload 5 | name: shared--workload 6 | namespace: intel-power 7 | spec: 8 | # Replace with the Node associated with PowerWorkload 9 | name: "shared--workload" 10 | allCores: true 11 | reservedCPUs: 12 | # IMPORTANT: The CPUs in reservedCPUs should match the value of the reserved system CPUs in your Kubelet config file 13 | - cores: [0, 1] 14 | # A profile can be applied to these reserved cores like so: 15 | # powerProfile: "performance" 16 | powerNodeSelector: 17 | # The label must be as below, as this workload will be specific to the Node 18 | kubernetes.io/hostname: 19 | # Replace this value with the intended shared PowerProfile 20 | powerProfile: "shared" 21 | -------------------------------------------------------------------------------- /examples/example-timeofday.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: TimeOfDay 3 | metadata: 4 | # Replace with the name of the node to use TOD on 5 | name: 6 | namespace: intel-power 7 | spec: 8 | timeZone: "Eire" 9 | schedule: 10 | - time: "10:04" 11 | # this sets the profile for the shared pool 12 | powerProfile: balance-power 13 | # this transitions exclusive pods matching a given label from one profile to another 14 | # please ensure that only pods to be used by power manager have this label 15 | pods: 16 | - labels: 17 | matchLabels: 18 | power: "true" 19 | target: performance 20 | - labels: 21 | matchLabels: 22 | special: "false" 23 | target: balance-performance 24 | # this field simply takes a cstate spec 25 | cState: 26 | sharedPoolCStates: 27 | C1: false 28 | C6: true 29 | - time: "14:48:00" 30 | powerProfile: shared 31 | cState: 32 | sharedPoolCStates: 33 | C1: true 34 | C6: false 35 | pods: 36 | - labels: 37 | matchLabels: 38 | power: "true" 39 | target: performance 40 | - labels: 41 | matchLabels: 42 | special: "false" 43 | target: balance-power 44 | - time: "14:35" 45 | powerProfile: balance-power 46 | reservedCPUs: [ 0,1 ] 47 | -------------------------------------------------------------------------------- /examples/example-uncore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: power.intel.com/v1 2 | kind: Uncore 3 | metadata: 4 | name: 5 | namespace: intel-power 6 | spec: 7 | sysMax: 2300000 8 | sysMin: 1300000 9 | dieSelector: 10 | - package: 0 11 | die: 0 12 | min: 1500000 13 | max: 2400000 14 | # - package: 0 15 | # die: 1 16 | # min: 1200000 17 | # max: 2400000 -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/intel/kubernetes-power-manager 2 | 3 | go 1.22.3 4 | 5 | require ( 6 | github.com/go-logr/logr v1.4.2 7 | github.com/intel/power-optimization-library v1.5.0 8 | github.com/stretchr/testify v1.9.0 9 | go.uber.org/zap v1.27.0 10 | google.golang.org/grpc v1.64.0 11 | k8s.io/api v0.29.3 12 | k8s.io/apimachinery v0.29.3 13 | k8s.io/client-go v0.29.3 14 | k8s.io/klog/v2 v2.120.1 15 | k8s.io/kubelet v0.29.3 16 | sigs.k8s.io/controller-runtime v0.17.3 17 | ) 18 | 19 | require ( 20 | github.com/beorn7/perks v1.0.1 // indirect 21 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 22 | github.com/davecgh/go-spew v1.1.1 // indirect 23 | github.com/emicklei/go-restful/v3 v3.11.0 // indirect 24 | github.com/evanphx/json-patch v5.6.0+incompatible // indirect 25 | github.com/evanphx/json-patch/v5 v5.8.0 // indirect 26 | github.com/fsnotify/fsnotify v1.7.0 // indirect 27 | github.com/go-logr/zapr v1.3.0 // indirect 28 | github.com/go-openapi/jsonpointer v0.19.6 // indirect 29 | github.com/go-openapi/jsonreference v0.20.2 // indirect 30 | github.com/go-openapi/swag v0.22.3 // indirect 31 | github.com/gogo/protobuf v1.3.2 // indirect 32 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 33 | github.com/golang/protobuf v1.5.4 // indirect 34 | github.com/google/gnostic-models v0.6.8 // indirect 35 | github.com/google/go-cmp v0.6.0 // indirect 36 | github.com/google/gofuzz v1.2.0 // indirect 37 | github.com/google/uuid v1.6.0 // indirect 38 | github.com/imdario/mergo v0.3.13 // indirect 39 | github.com/josharian/intern v1.0.0 // indirect 40 | github.com/json-iterator/go v1.1.12 // indirect 41 | github.com/mailru/easyjson v0.7.7 // indirect 42 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect 43 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 44 | github.com/modern-go/reflect2 v1.0.2 // indirect 45 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 46 | github.com/pkg/errors v0.9.1 // indirect 47 | github.com/pmezard/go-difflib v1.0.0 // indirect 48 | github.com/prometheus/client_golang v1.18.0 // indirect 49 | github.com/prometheus/client_model v0.5.0 // indirect 50 | github.com/prometheus/common v0.45.0 // indirect 51 | github.com/prometheus/procfs v0.12.0 // indirect 52 | github.com/spf13/pflag v1.0.5 // indirect 53 | github.com/stretchr/objx v0.5.2 // indirect 54 | go.uber.org/multierr v1.11.0 // indirect 55 | golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect 56 | golang.org/x/net v0.23.0 // indirect 57 | golang.org/x/oauth2 v0.18.0 // indirect 58 | golang.org/x/sys v0.18.0 // indirect 59 | golang.org/x/term v0.18.0 // indirect 60 | golang.org/x/text v0.14.0 // indirect 61 | golang.org/x/time v0.3.0 // indirect 62 | gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect 63 | google.golang.org/appengine v1.6.8 // indirect 64 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect 65 | google.golang.org/protobuf v1.33.0 // indirect 66 | gopkg.in/inf.v0 v0.9.1 // indirect 67 | gopkg.in/yaml.v2 v2.4.0 // indirect 68 | gopkg.in/yaml.v3 v3.0.1 // indirect 69 | k8s.io/apiextensions-apiserver v0.29.2 // indirect 70 | k8s.io/component-base v0.29.3 // indirect 71 | k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect 72 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect 73 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 74 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect 75 | sigs.k8s.io/yaml v1.4.0 // indirect 76 | ) 77 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | 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 | */ -------------------------------------------------------------------------------- /helm/crds/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /helm/crds/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: crds 3 | description: A Helm chart for Kubernetes Power Manager CRDs 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 2.5.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "v2.5.0" 25 | -------------------------------------------------------------------------------- /helm/crds/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "crds.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "crds.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "crds.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "crds.labels" -}} 37 | helm.sh/chart: {{ include "crds.chart" . }} 38 | {{ include "crds.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "crds.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "crds.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "crds.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "crds.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /helm/crds/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for crds. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | -------------------------------------------------------------------------------- /helm/kubernetes-power-manager/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: manager-chart-library 3 | repository: file://../manager-chart-library 4 | version: 0.1.0 5 | digest: sha256:c551fc8bb470130752c3746c51dbc010a685b1abdd69c4e6cf38b3a949212dd4 6 | generated: "2023-10-24T09:31:12.409824943Z" 7 | -------------------------------------------------------------------------------- /helm/kubernetes-power-manager/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: kubernetes-power-manager 3 | description: A Helm chart for Intel's Kubernetes Power Manager 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. 11 | # For example they can be used to abtract common and re-usable boiler plate yaml files. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the chart version. This version number should be incremented each time you make changes 17 | # to the chart and its templates, including the app version. 18 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 19 | version: 2.5.0 20 | 21 | # This is the version number of the application being deployed. This version number should be 22 | # incremented each time you make changes to the application. Versions are not expected to 23 | # follow Semantic Versioning. They should reflect the version the application is using. 24 | # It is recommended to use it with quotes. 25 | appVersion: "v2.5.0" 26 | dependencies: 27 | - name: manager-chart-library 28 | version: 0.1.0 29 | repository: file://../manager-chart-library 30 | -------------------------------------------------------------------------------- /helm/kubernetes-power-manager/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "kubernetes-power-manager.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "kubernetes-power-manager.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "kubernetes-power-manager.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "kubernetes-power-manager.labels" -}} 37 | helm.sh/chart: {{ include "kubernetes-power-manager.chart" . }} 38 | {{ include "kubernetes-power-manager.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "kubernetes-power-manager.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "kubernetes-power-manager.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "kubernetes-power-manager.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "kubernetes-power-manager.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /helm/kubernetes-power-manager/templates/template.yaml: -------------------------------------------------------------------------------- 1 | {{- include "manager-chart-library.namespace" . }} 2 | --- 3 | {{- include "manager-chart-library.operatorserviceaccount" . }} 4 | --- 5 | {{- include "manager-chart-library.agentserviceaccount" . }} 6 | --- 7 | {{- include "manager-chart-library.operatorrole" . }} 8 | --- 9 | {{- include "manager-chart-library.operatorrolebinding" . }} 10 | --- 11 | {{- include "manager-chart-library.operatorclusterrole" . }} 12 | --- 13 | {{- include "manager-chart-library.operatorclusterrolebinding" . }} 14 | --- 15 | {{- include "manager-chart-library.agentclusterrole" . }} 16 | --- 17 | {{- include "manager-chart-library.agentclusterrolebinding" . }} 18 | --- 19 | {{- include "manager-chart-library.deployment" . }} 20 | --- 21 | {{- include "manager-chart-library.powerconfig" . }} 22 | --- 23 | {{- if eq (semver "2.2.0" | (semver .Chart.Version).Compare) 1}} 24 | {{- include "manager-chart-library.new-shared-profile" . }} 25 | {{- else }} 26 | {{- include "manager-chart-library.shared-profile" . }} 27 | {{- end }} 28 | # above checks the version to decide which template to use -------------------------------------------------------------------------------- /helm/kubernetes-power-manager/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for kubernetes-power-manager. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | # Intel Power namespace 6 | namespace: 7 | label: controller-manager 8 | name: intel-power 9 | 10 | # Service Account for the overarching operator 11 | operatorserviceaccount: 12 | name: intel-power-operator 13 | namespace: intel-power 14 | 15 | # Service Account for the Power Node Agent 16 | agentserviceaccount: 17 | name: intel-power-node-agent 18 | namespace: intel-power 19 | 20 | # Role for the overarching operator 21 | operatorrole: 22 | name: operator-custom-resource-definitions-role 23 | namespace: intel-power 24 | resources: ["powerconfigs", "powerconfigs/status", "powerprofiles", "powerprofiles/status", "events", "daemonsets", "configmaps", "configmaps/status", "leases", "uncores"] 25 | 26 | # Role Binding for the overarching operator 27 | operatorrolebinding: 28 | name: operator-custom-resource-definitions-role-binding 29 | namespace: intel-power 30 | serviceaccount: 31 | name: intel-power-operator 32 | namespace: intel-power 33 | rolename: operator-custom-resource-definitions-role 34 | 35 | # Cluster Role for the overarching operator 36 | operatorclusterrole: 37 | name: operator-nodes 38 | resources: ["nodes", "nodes/status", "configmaps", "configmaps/status", "powerconfigs", "powerconfigs/status", "powerprofiles", "powerprofiles/status", "powerworkloads", "powerworkloads/status", "powernodes", "powernodes/status", "events", "daemonsets", "uncores"] 39 | 40 | # Cluster Role Binding for the overarching operator 41 | operatorclusterrolebinding: 42 | name: operator-nodes-binding 43 | serviceaccount: 44 | name: intel-power-operator 45 | namespace: intel-power 46 | clusterrolename: operator-nodes 47 | 48 | # Cluster Role for the Power Node Agent 49 | agentclusterrole: 50 | name: node-agent-cluster-resources 51 | resources: ["nodes", "nodes/status", "pods", "pods/status", "cronjobs", "cronjobs/status", "powerprofiles", "powerprofiles/status", "powerworkloads", "powerworkloads/status", "powernodes", "powernodes/status", "cstates", "cstates/status", "timeofdays", "timeofdays/status", "timeofdaycronjobs", "timeofdaycronjobs/status", "uncores"] 52 | # Cluster Role Binding for the Power Node Agent 53 | agentclusterrolebinding: 54 | name: node-agent-cluster-resources-binding 55 | serviceaccount: 56 | name: intel-power-node-agent 57 | namespace: intel-power 58 | clusterrolename: node-agent-cluster-resources 59 | 60 | # Deployment for the overarching operator 61 | operator: 62 | name: controller-manager 63 | namespace: intel-power 64 | labels: 65 | controlplane: controller-manager 66 | replicas: 1 67 | container: 68 | serviceaccount: 69 | name: intel-power-operator 70 | command: /manager 71 | args: --enable-leader-election 72 | image: intel/power-operator:v2.5.0 73 | name: manager 74 | cpu: 75 | limits: 100m 76 | requests: 100m 77 | memory: 78 | limits: 30Mi 79 | requests: 30Mi 80 | 81 | # Values for the PowerConfig 82 | powerconfig: 83 | name: power-config 84 | namespace: intel-power 85 | nodeselector: 86 | label: "feature.node.kubernetes.io/power-node" 87 | value: 'true' 88 | 89 | # Values for the Shared PowerProfile 90 | sharedprofile: 91 | name: shared 92 | namespace: intel-power 93 | spec: 94 | name: "shared" 95 | max: 1000 96 | min: 1000 97 | epp: "power" 98 | governor: "powersave" 99 | -------------------------------------------------------------------------------- /helm/manager-chart-library/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /helm/manager-chart-library/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: manager-chart-library 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: library 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /helm/manager-chart-library/templates/_deployment.tpl: -------------------------------------------------------------------------------- 1 | {{- define "manager-chart-library.deployment" -}} 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: {{ .Values.operator.name }} 6 | namespace: {{ .Values.operator.namespace }} 7 | labels: 8 | control-plane: {{ .Values.operator.labels.controlplane }} 9 | spec: 10 | selector: 11 | matchLabels: 12 | control-plane: {{ .Values.operator.labels.controlplane }} 13 | replicas: {{ .Values.operator.replicas }} 14 | template: 15 | metadata: 16 | labels: 17 | control-plane: {{ .Values.operator.labels.controlplane }} 18 | spec: 19 | serviceAccountName: {{ .Values.operator.container.serviceaccount.name }} 20 | containers: 21 | - command: 22 | - {{ .Values.operator.container.command }} 23 | args: 24 | - {{ .Values.operator.container.args }} 25 | imagePullPolicy: IfNotPresent 26 | image: {{ .Values.operator.container.image }} 27 | securityContext: 28 | allowPrivilegeEscalation: false 29 | capabilities: 30 | drop: ["ALL"] 31 | name: {{ .Values.operator.container.name }} 32 | resources: 33 | limits: 34 | cpu: {{ .Values.operator.container.cpu.limits }} 35 | memory: {{ .Values.operator.container.memory.limits }} 36 | requests: 37 | cpu: {{ .Values.operator.container.cpu.requests }} 38 | memory: {{ .Values.operator.container.memory.requests }} 39 | volumeMounts: 40 | - mountPath: /sys/fs 41 | name: cgroup 42 | mountPropagation: HostToContainer 43 | readOnly: true 44 | terminationGracePeriodSeconds: 10 45 | volumes: 46 | - name: cgroup 47 | hostPath: 48 | path: /sys/fs 49 | 50 | {{- end -}} -------------------------------------------------------------------------------- /helm/manager-chart-library/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "manager-chart-library.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "kubernetes-power-manager-v2.0.0.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "kubernetes-power-manager-v2.0.0.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "kubernetes-power-manager-v2.0.0.labels" -}} 37 | helm.sh/chart: {{ include "kubernetes-power-manager-v2.0.0.chart" . }} 38 | {{ include "kubernetes-power-manager-v2.0.0.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "kubernetes-power-manager-v2.0.0.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "kubernetes-power-manager-v2.0.0.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "kubernetes-power-manager-v2.0.0.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "kubernetes-power-manager-v2.0.0.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /helm/manager-chart-library/templates/_namespace.tpl: -------------------------------------------------------------------------------- 1 | {{- define "manager-chart-library.namespace" -}} 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | labels: 6 | control-plane: {{ .Values.namespace.label }} 7 | name: {{ .Values.namespace.name }} 8 | 9 | {{- end -}} -------------------------------------------------------------------------------- /helm/manager-chart-library/templates/_new-shared-power-profile.tpl: -------------------------------------------------------------------------------- 1 | {{- define "manager-chart-library.new-shared-profile" -}} 2 | apiVersion: power.intel.com/v1 3 | kind: PowerProfile 4 | metadata: 5 | name: {{ .Values.sharedprofile.name }} 6 | namespace: {{ .Values.sharedprofile.namespace }} 7 | spec: 8 | name: {{ .Values.sharedprofile.spec.name }} 9 | max: {{ .Values.sharedprofile.spec.max }} 10 | min: {{ .Values.sharedprofile.spec.min }} 11 | epp: {{ .Values.sharedprofile.spec.epp }} 12 | governor: {{ .Values.sharedprofile.spec.governor }} 13 | shared: true 14 | {{- end -}} -------------------------------------------------------------------------------- /helm/manager-chart-library/templates/_power-config.tpl: -------------------------------------------------------------------------------- 1 | {{- define "manager-chart-library.powerconfig" -}} 2 | apiVersion: power.intel.com/v1 3 | kind: PowerConfig 4 | metadata: 5 | name: {{ .Values.powerconfig.name }} 6 | namespace: {{ .Values.powerconfig.namespace }} 7 | spec: 8 | powerNodeSelector: 9 | {{ .Values.powerconfig.nodeselector.label }}: "{{ .Values.powerconfig.nodeselector.value }}" 10 | powerProfiles: 11 | - "performance" 12 | - "balance-performance" 13 | - "balance-power" 14 | 15 | {{- end -}} 16 | -------------------------------------------------------------------------------- /helm/manager-chart-library/templates/_rbac.tpl: -------------------------------------------------------------------------------- 1 | {{- define "manager-chart-library.operatorserviceaccount" -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ .Values.operatorserviceaccount.name }} 6 | namespace: {{ .Values.operatorserviceaccount.namespace }} 7 | 8 | {{- end -}} 9 | 10 | {{- define "manager-chart-library.agentserviceaccount" -}} 11 | apiVersion: v1 12 | kind: ServiceAccount 13 | metadata: 14 | name: {{ .Values.agentserviceaccount.name }} 15 | namespace: {{ .Values.agentserviceaccount.namespace }} 16 | 17 | {{- end -}} 18 | 19 | {{- define "manager-chart-library.operatorrole" -}} 20 | apiVersion: rbac.authorization.k8s.io/v1 21 | kind: Role 22 | metadata: 23 | name: {{ .Values.operatorrole.name }} 24 | namespace: {{ .Values.operatorrole.namespace }} 25 | rules: 26 | - apiGroups: ["", "power.intel.com", "apps", "coordination.k8s.io"] 27 | resources: 28 | {{ range .Values.operatorrole.resources }} 29 | - {{ . }} 30 | {{ end }} 31 | verbs: ["*"] 32 | {{- if .Values.ocp }} 33 | - apiGroups: 34 | - security.openshift.io 35 | resourceNames: 36 | - privileged 37 | resources: 38 | - securitycontextconstraints 39 | verbs: 40 | - use 41 | {{- end -}} 42 | 43 | {{- end -}} 44 | 45 | {{- define "manager-chart-library.operatorrolebinding" -}} 46 | apiVersion: rbac.authorization.k8s.io/v1 47 | kind: RoleBinding 48 | metadata: 49 | name: {{ .Values.operatorrolebinding.name }} 50 | namespace: {{ .Values.operatorrolebinding.namespace }} 51 | subjects: 52 | - kind: ServiceAccount 53 | name: {{ .Values.operatorrolebinding.serviceaccount.name }} 54 | namespace: {{ .Values.operatorrolebinding.serviceaccount.namespace }} 55 | roleRef: 56 | kind: Role 57 | name: {{ .Values.operatorrolebinding.rolename }} 58 | apiGroup: rbac.authorization.k8s.io 59 | 60 | {{- end -}} 61 | 62 | {{- define "manager-chart-library.operatorclusterrole" -}} 63 | apiVersion: rbac.authorization.k8s.io/v1 64 | kind: ClusterRole 65 | metadata: 66 | name: {{ .Values.operatorclusterrole.name }} 67 | rules: 68 | - apiGroups: ["", "power.intel.com", "apps"] 69 | resources: 70 | {{ range .Values.operatorclusterrole.resources }} 71 | - {{ . }} 72 | {{ end }} 73 | verbs: ["*"] 74 | 75 | {{- end -}} 76 | 77 | {{- define "manager-chart-library.operatorclusterrolebinding" -}} 78 | apiVersion: rbac.authorization.k8s.io/v1 79 | kind: ClusterRoleBinding 80 | metadata: 81 | name: {{ .Values.operatorclusterrolebinding.name }} 82 | subjects: 83 | - kind: ServiceAccount 84 | name: {{ .Values.operatorclusterrolebinding.serviceaccount.name }} 85 | namespace: {{ .Values.operatorclusterrolebinding.serviceaccount.namespace }} 86 | roleRef: 87 | kind: ClusterRole 88 | name: {{ .Values.operatorclusterrolebinding.clusterrolename }} 89 | apiGroup: rbac.authorization.k8s.io 90 | 91 | {{- end -}} 92 | 93 | {{- define "manager-chart-library.agentclusterrole" -}} 94 | apiVersion: rbac.authorization.k8s.io/v1 95 | kind: ClusterRole 96 | metadata: 97 | name: {{ .Values.agentclusterrole.name }} 98 | rules: 99 | - apiGroups: ["", "batch", "power.intel.com"] 100 | resources: 101 | {{ range .Values.agentclusterrole.resources }} 102 | - {{ . }} 103 | {{ end }} 104 | verbs: ["*"] 105 | {{- if .Values.ocp }} 106 | - apiGroups: 107 | - security.openshift.io 108 | resourceNames: 109 | - privileged 110 | resources: 111 | - securitycontextconstraints 112 | verbs: 113 | - use 114 | {{- end -}} 115 | 116 | {{- end -}} 117 | 118 | {{- define "manager-chart-library.agentclusterrolebinding" -}} 119 | apiVersion: rbac.authorization.k8s.io/v1 120 | kind: ClusterRoleBinding 121 | metadata: 122 | name: {{ .Values.agentclusterrolebinding.name }} 123 | subjects: 124 | - kind: ServiceAccount 125 | name: {{ .Values.agentclusterrolebinding.serviceaccount.name }} 126 | namespace: {{ .Values.agentclusterrolebinding.serviceaccount.namespace }} 127 | roleRef: 128 | kind: ClusterRole 129 | name: {{ .Values.agentclusterrolebinding.clusterrolename }} 130 | apiGroup: rbac.authorization.k8s.io 131 | 132 | {{- end -}} -------------------------------------------------------------------------------- /helm/manager-chart-library/templates/_shared-power-profile.tpl: -------------------------------------------------------------------------------- 1 | {{- define "manager-chart-library.shared-profile" -}} 2 | apiVersion: power.intel.com/v1 3 | kind: PowerProfile 4 | metadata: 5 | name: {{ .Values.sharedprofile.name }} 6 | namespace: {{ .Values.sharedprofile.namespace }} 7 | spec: 8 | name: {{ .Values.sharedprofile.spec.name }} 9 | max: {{ .Values.sharedprofile.spec.max }} 10 | min: {{ .Values.sharedprofile.spec.min }} 11 | epp: {{ .Values.sharedprofile.spec.epp }} 12 | governor: {{ .Values.sharedprofile.spec.governor }} 13 | {{- end -}} -------------------------------------------------------------------------------- /pkg/podresourcesclient/podresourcesclient_test.go: -------------------------------------------------------------------------------- 1 | package podresourcesclient 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/stretchr/testify/assert" 7 | "google.golang.org/grpc" 8 | podresourcesapi "k8s.io/kubelet/pkg/apis/podresources/v1" 9 | "testing" 10 | ) 11 | 12 | type fakePodResourcesClient struct { 13 | listResponse *podresourcesapi.ListPodResourcesResponse 14 | } 15 | 16 | func (f *fakePodResourcesClient) List(ctx context.Context, in *podresourcesapi.ListPodResourcesRequest, opts ...grpc.CallOption) (*podresourcesapi.ListPodResourcesResponse, error) { 17 | return f.listResponse, nil 18 | } 19 | 20 | func (f *fakePodResourcesClient) GetAllocatableResources(ctx context.Context, in *podresourcesapi.AllocatableResourcesRequest, opts ...grpc.CallOption) (*podresourcesapi.AllocatableResourcesResponse, error) { 21 | return &podresourcesapi.AllocatableResourcesResponse{}, nil 22 | } 23 | 24 | func (f *fakePodResourcesClient) Get(ctx context.Context, in *podresourcesapi.GetPodResourcesRequest, opts ...grpc.CallOption) (*podresourcesapi.GetPodResourcesResponse, error) { 25 | return &podresourcesapi.GetPodResourcesResponse{}, nil 26 | } 27 | func createFakePodResourcesListerClient(fakePodResources []*podresourcesapi.PodResources) *PodResourcesClient { 28 | fakeListResponse := &podresourcesapi.ListPodResourcesResponse{ 29 | PodResources: fakePodResources, 30 | } 31 | 32 | podResourcesListerClient := &fakePodResourcesClient{} 33 | podResourcesListerClient.listResponse = fakeListResponse 34 | return &PodResourcesClient{Client: podResourcesListerClient, CpuControlPlaneClient: podResourcesListerClient} 35 | } 36 | 37 | func TestPodResourcesClient_listPodResources(t *testing.T) { 38 | podResources := []*podresourcesapi.PodResources{ 39 | { 40 | Name: "test-pod-1", 41 | Namespace: "default", 42 | Containers: []*podresourcesapi.ContainerResources{ 43 | { 44 | Name: "test-container-1", 45 | CpuIds: []int64{1, 5, 8}, 46 | }, 47 | }, 48 | }, 49 | } 50 | podClient := createFakePodResourcesListerClient(podResources) 51 | resp, err := podClient.listResources(false) 52 | assert.ElementsMatch(t, resp.PodResources, podResources) 53 | assert.NoError(t, err) 54 | } 55 | 56 | func TestPodResourcesClient_GetContainerCPUs(t *testing.T) { 57 | podResources := []*podresourcesapi.PodResources{ 58 | { 59 | Name: "test-pod-1", 60 | Namespace: "default", 61 | Containers: []*podresourcesapi.ContainerResources{ 62 | { 63 | Name: "test-container-1", 64 | CpuIds: []int64{1, 5, 8}, 65 | }, 66 | }, 67 | }, 68 | } 69 | podClient := createFakePodResourcesListerClient(podResources) 70 | cpus, err := podClient.GetContainerCPUs("test-pod-1", "test-container-1") 71 | assert.Equal(t, "1,5,8", cpus) 72 | assert.NoError(t, err) 73 | 74 | cpus, err = podClient.GetContainerCPUs("non-existent", "") 75 | assert.Empty(t, cpus) 76 | assert.ErrorContains(t, err, "not found") 77 | } 78 | 79 | func Test_cpuIDsToString(t *testing.T) { 80 | 81 | assert.Equal(t, "0-5", cpuIDsToString([]int64{0, 1, 2, 3, 4, 5})) 82 | assert.Equal(t, "0-2,4-6", cpuIDsToString([]int64{0, 1, 2, 4, 5, 6})) 83 | assert.Equal(t, "0-1,8", cpuIDsToString([]int64{0, 8, 1})) 84 | assert.Equal(t, "", cpuIDsToString([]int64{})) 85 | assert.Equal(t, "0,2", cpuIDsToString([]int64{0, 0, 0, 2, 2, 2, 0, 2, 0, 2, 0})) 86 | maxSize := 9999 87 | cpuIds := make([]int64, maxSize) 88 | for i := range cpuIds { 89 | cpuIds[i] = int64(i) 90 | } 91 | assert.Equal(t, fmt.Sprint("0-", maxSize-1), cpuIDsToString(cpuIds)) 92 | 93 | } 94 | -------------------------------------------------------------------------------- /pkg/podstate/podstate.go: -------------------------------------------------------------------------------- 1 | package podstate 2 | 3 | import ( 4 | powerv1 "github.com/intel/kubernetes-power-manager/api/v1" 5 | ) 6 | 7 | type State struct { 8 | GuaranteedPods []powerv1.GuaranteedPod 9 | } 10 | 11 | func NewState() (*State, error) { 12 | state := &State{} 13 | guaranteedPods := make([]powerv1.GuaranteedPod, 0) 14 | state.GuaranteedPods = guaranteedPods 15 | 16 | return state, nil 17 | } 18 | 19 | func (s *State) UpdateStateGuaranteedPods(guaranteedPod powerv1.GuaranteedPod) error { 20 | for i, existingPod := range s.GuaranteedPods { 21 | if existingPod.Name == guaranteedPod.Name && existingPod.Namespace == guaranteedPod.Namespace { 22 | s.GuaranteedPods[i] = guaranteedPod 23 | return nil 24 | } 25 | } 26 | 27 | s.GuaranteedPods = append(s.GuaranteedPods, guaranteedPod) 28 | return nil 29 | } 30 | 31 | func (s *State) GetPodFromState(podName string, podNamespace string) powerv1.GuaranteedPod { 32 | for _, existingPod := range s.GuaranteedPods { 33 | if existingPod.Name == podName && existingPod.Namespace == podNamespace { 34 | return existingPod 35 | } 36 | } 37 | 38 | return powerv1.GuaranteedPod{} 39 | } 40 | 41 | func (s *State) GetCPUsFromPodState(podState powerv1.GuaranteedPod) []uint { 42 | cpus := make([]uint, 0) 43 | for _, container := range podState.Containers { 44 | cpus = append(cpus, container.ExclusiveCPUs...) 45 | } 46 | 47 | return cpus 48 | } 49 | 50 | func (s *State) DeletePodFromState(podName string, podNamespace string) error { 51 | for i, pod := range s.GuaranteedPods { 52 | if pod.Name == podName && pod.Namespace == podNamespace { 53 | s.GuaranteedPods = append(s.GuaranteedPods[:i], s.GuaranteedPods[i+1:]...) 54 | } 55 | } 56 | 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /pkg/podstate/podstate_test.go: -------------------------------------------------------------------------------- 1 | package podstate 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | powerv1 "github.com/intel/kubernetes-power-manager/api/v1" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestNewState(t *testing.T) { 12 | state, err := NewState() 13 | 14 | //Test case -- verifying that no error is returned 15 | assert.Nil(t, err) 16 | 17 | //Test case -- verifying that a state object is returned 18 | if state == nil { 19 | t.Errorf("Expected a State object, but got nil") 20 | } 21 | 22 | //Test case -- verifying that the GuaranteedPods slice is empty 23 | if len(state.GuaranteedPods) != 0 { 24 | t.Errorf("Expected GuaranteedPods to be empty, but got %v", state.GuaranteedPods) 25 | } 26 | } 27 | 28 | func TestUpdateStateGuaranteedPods(t *testing.T) { 29 | state := &State{ 30 | GuaranteedPods: []powerv1.GuaranteedPod{ 31 | {Name: "pod1"}, 32 | {Name: "pod2"}, 33 | {Name: "pod3"}, 34 | }, 35 | } 36 | 37 | //Test case -- updating an existing pod 38 | err := state.UpdateStateGuaranteedPods(powerv1.GuaranteedPod{Name: "pod2"}) 39 | assert.Nil(t, err) 40 | assert.Equal(t, state.GuaranteedPods[1].Name, "pod2") 41 | 42 | //Test case -- adding a new pod 43 | err = state.UpdateStateGuaranteedPods(powerv1.GuaranteedPod{Name: "pod4"}) 44 | assert.Nil(t, err) 45 | assert.Equal(t, state.GuaranteedPods[len(state.GuaranteedPods)-1].Name, "pod4") 46 | } 47 | 48 | func TestGetPodFromState(t *testing.T) { 49 | //Test case -- a state instance with some sample data 50 | state := &State{ 51 | GuaranteedPods: []powerv1.GuaranteedPod{ 52 | {Name: "pod1"}, 53 | {Name: "pod2"}, 54 | }, 55 | } 56 | 57 | //Test case -- Existing pod in the state 58 | existingPodName := "pod1" 59 | existingPod := state.GetPodFromState(existingPodName, "") 60 | assert.Equal(t, existingPodName, existingPod.Name) 61 | 62 | //Test case -- Non-Existing pod in the state 63 | nonExistingPodName := "pod4" 64 | nonExistingPod := state.GetPodFromState(nonExistingPodName, "") 65 | if !reflect.DeepEqual(nonExistingPod, powerv1.GuaranteedPod{}) { 66 | t.Errorf("Expected: empty pod. Actual: Got pod %+v", nonExistingPod) 67 | } 68 | } 69 | 70 | func TestGetCPUsFromPodState(t *testing.T) { 71 | //Test case -- sample pod state with two containers 72 | podState := powerv1.GuaranteedPod{ 73 | Containers: []powerv1.Container{ 74 | {ExclusiveCPUs: []uint{1, 2}}, 75 | {ExclusiveCPUs: []uint{3}}, 76 | }, 77 | } 78 | 79 | //Creating a state instance 80 | state := &State{} 81 | cpus := state.GetCPUsFromPodState(podState) 82 | expectedCPUs := []uint{1, 2, 3} 83 | 84 | assert.Equal(t, expectedCPUs, cpus) 85 | 86 | } 87 | 88 | func TestDeletePodFromState(t *testing.T) { 89 | //Create a state instance with some sample data 90 | 91 | state := &State{ 92 | GuaranteedPods: []powerv1.GuaranteedPod{ 93 | {Name: "pod1"}, 94 | {Name: "pod2"}, 95 | }, 96 | } 97 | 98 | //Test case: Delteing an existing pod 99 | podToDelete := "pod1" 100 | err := state.DeletePodFromState(podToDelete, "") 101 | assert.Nil(t, err) 102 | 103 | for _, pod := range state.GuaranteedPods { 104 | if pod.Name == podToDelete { 105 | t.Errorf("Expected: pod %q to be deleted. Actual: Still exists", podToDelete) 106 | } 107 | } 108 | 109 | //Test case -- Deleting a non-existing pod 110 | nonExistingPodState := "pod3" 111 | err = state.DeletePodFromState(nonExistingPodState, "") 112 | assert.Nil(t, err) 113 | } 114 | -------------------------------------------------------------------------------- /pkg/state/state.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | import ( 4 | powerv1 "github.com/intel/kubernetes-power-manager/api/v1" 5 | ) 6 | 7 | type PowerNodeData struct { 8 | PowerNodeList []string 9 | } 10 | 11 | func NewPowerNodeData() *PowerNodeData { 12 | return &PowerNodeData{ 13 | PowerNodeList: []string{}, 14 | } 15 | } 16 | 17 | func (nd *PowerNodeData) UpdatePowerNodeData(nodeName string) { 18 | for _, node := range nd.PowerNodeList { 19 | if nodeName == node { 20 | return 21 | } 22 | } 23 | 24 | nd.PowerNodeList = append(nd.PowerNodeList, nodeName) 25 | } 26 | 27 | func (nd *PowerNodeData) DeletePowerNodeData(nodeName string) { 28 | for index, node := range nd.PowerNodeList { 29 | if node == nodeName { 30 | nd.PowerNodeList = append(nd.PowerNodeList[:index], nd.PowerNodeList[index+1:]...) 31 | } 32 | } 33 | } 34 | 35 | func (nd *PowerNodeData) Difference(nodeInfo []powerv1.WorkloadNode) []string { 36 | difference := make([]string, 0) 37 | 38 | for _, node := range nd.PowerNodeList { 39 | if NodeNotInNodeInfo(node, nodeInfo) { 40 | difference = append(difference, node) 41 | } 42 | } 43 | 44 | return difference 45 | } 46 | 47 | func NodeNotInNodeInfo(nodeName string, nodeInfo []powerv1.WorkloadNode) bool { 48 | for _, node := range nodeInfo { 49 | if nodeName == node.Name { 50 | return false 51 | } 52 | } 53 | 54 | return true 55 | } 56 | -------------------------------------------------------------------------------- /pkg/state/state_test.go: -------------------------------------------------------------------------------- 1 | package state 2 | 3 | import ( 4 | "testing" 5 | 6 | powerv1 "github.com/intel/kubernetes-power-manager/api/v1" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func equalSlice(a, b []string) bool { 11 | if len(a) != len(b) { 12 | return false 13 | } 14 | for i, v := range a { 15 | if v != b[i] { 16 | return false 17 | } 18 | } 19 | return true 20 | } 21 | 22 | func TestNewPowerNodeData(t *testing.T) { 23 | // calling the function to create a new PowerNodeData object 24 | powerNodeData := NewPowerNodeData() 25 | 26 | // asserting that the PowerNodeList field is empty 27 | expected := []string{} 28 | assert.Equal(t, powerNodeData.PowerNodeList, expected, "PowerNodeList field is not empty.") 29 | 30 | //making sure that list contains only newly added node 31 | for i := 0; i < len(expected); i++ { 32 | assert.Equal(t, powerNodeData.PowerNodeList, expected, "PowerNodeList field is not empty.") 33 | break 34 | } 35 | } 36 | 37 | func TestUpdatePowerNodeData(t *testing.T) { 38 | nd := NewPowerNodeData() 39 | 40 | nodeName := "GenericNode" 41 | nd.UpdatePowerNodeData(nodeName) 42 | 43 | found := false 44 | for _, node := range nd.PowerNodeList { 45 | if node == nodeName { 46 | found = true 47 | break 48 | } 49 | } 50 | if !found { 51 | t.Errorf("Failed to add nodeName to PowerNodeList. Got: %v, Expected: %s", nd.PowerNodeList, nodeName) 52 | } 53 | 54 | // calling the UpdatePowerNodeData function again with the same generic node 55 | nd.UpdatePowerNodeData(nodeName) 56 | 57 | // making sure that the PowerNodeList remains unchanged 58 | assert.Equal(t, len(nd.PowerNodeList), 1, "PowerNodeList field is not empty.") 59 | } 60 | 61 | func TestDeletePowerNodeData(t *testing.T) { 62 | testData := &PowerNodeData{ 63 | PowerNodeList: []string{"node1", "node2", "node3"}, //generic nodes 64 | } 65 | 66 | testData.DeletePowerNodeData("node2") //deleting node2 67 | 68 | expected := []string{"node1", "node3"} 69 | 70 | if !equalSlice(testData.PowerNodeList, expected) { 71 | t.Fatalf("Expected %v but got %v", expected, testData.PowerNodeList) 72 | } 73 | } 74 | 75 | func TestDifference(t *testing.T) { 76 | testData := &PowerNodeData{ 77 | PowerNodeList: []string{"node1", "node2", "node3"}, 78 | } 79 | 80 | nodeInfo := []powerv1.WorkloadNode{ 81 | {Name: "node1"}, 82 | {Name: "node3"}, 83 | } 84 | 85 | expected := []string{"node2"} 86 | 87 | result := testData.Difference(nodeInfo) 88 | for i, node := range result { 89 | assert.Equal(t, node, expected[i], "PowerNodeList field is not empty.") 90 | break 91 | } 92 | } 93 | 94 | func TestNodeNotInNodeInfo(t *testing.T) { 95 | nodeInfo := []powerv1.WorkloadNode{ 96 | {Name: "node1"}, 97 | {Name: "node2"}, 98 | {Name: "node3"}, 99 | } 100 | 101 | testCases := []struct { 102 | nodeName string 103 | expected bool 104 | }{ 105 | {"node1", false}, 106 | {"node2", false}, 107 | {"node3", false}, 108 | {"node4", true}, 109 | {"node5", true}, 110 | } 111 | 112 | for _, testCase := range testCases { 113 | result := NodeNotInNodeInfo(testCase.nodeName, nodeInfo) 114 | if result != testCase.expected { 115 | t.Errorf("For nodeName: %v, expected %v, but got %v", testCase.nodeName, testCase.expected, result) 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /pkg/util/util.go: -------------------------------------------------------------------------------- 1 | //go:build freebsd || linux || darwin 2 | // +build freebsd linux darwin 3 | 4 | /* 5 | Copyright 2017 The Kubernetes Authors. 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | http://www.apache.org/licenses/LICENSE-2.0 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 util 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | corev1 "k8s.io/api/core/v1" 23 | "k8s.io/klog/v2" 24 | "net" 25 | "net/url" 26 | ) 27 | 28 | const ( 29 | // unixProtocol is the network protocol of unix socket. 30 | unixProtocol = "unix" 31 | ) 32 | 33 | // GetAddressAndDialer returns the address parsed from the given endpoint and a context dialer. 34 | func GetAddressAndDialer(endpoint string) (string, func(ctx context.Context, addr string) (net.Conn, error), error) { 35 | protocol, addr, err := parseEndpointWithFallbackProtocol(endpoint, unixProtocol) 36 | if err != nil { 37 | return "", nil, err 38 | } 39 | if protocol != unixProtocol { 40 | return "", nil, fmt.Errorf("only support unix socket endpoint") 41 | } 42 | 43 | return addr, dial, nil 44 | } 45 | 46 | func dial(ctx context.Context, addr string) (net.Conn, error) { 47 | return (&net.Dialer{}).DialContext(ctx, unixProtocol, addr) 48 | } 49 | 50 | func parseEndpointWithFallbackProtocol(endpoint string, fallbackProtocol string) (protocol string, addr string, err error) { 51 | if protocol, addr, err = parseEndpoint(endpoint); err != nil && protocol == "" { 52 | fallbackEndpoint := fallbackProtocol + "://" + endpoint 53 | protocol, addr, err = parseEndpoint(fallbackEndpoint) 54 | if err == nil { 55 | klog.Warningf("Using %q as endpoint is deprecated, please consider using full url format %q.", endpoint, fallbackEndpoint) 56 | } 57 | } 58 | return 59 | } 60 | 61 | func parseEndpoint(endpoint string) (string, string, error) { 62 | u, err := url.Parse(endpoint) 63 | if err != nil { 64 | return "", "", err 65 | } 66 | 67 | switch u.Scheme { 68 | case "tcp": 69 | return "tcp", u.Host, nil 70 | 71 | case "unix": 72 | return "unix", u.Path, nil 73 | 74 | case "": 75 | return "", "", fmt.Errorf("using %q as endpoint is deprecated, please consider using full url format", endpoint) 76 | 77 | default: 78 | return u.Scheme, "", fmt.Errorf("protocol %q not supported", u.Scheme) 79 | } 80 | } 81 | 82 | func CPUInCPUList(cpu uint, cpuList []uint) bool { 83 | for _, cpuListID := range cpuList { 84 | if cpuListID == cpu { 85 | return true 86 | } 87 | } 88 | 89 | return false 90 | } 91 | 92 | func NodeNameInNodeList(name string, nodeList []corev1.Node) bool { 93 | for _, node := range nodeList { 94 | if node.Name == name { 95 | return true 96 | } 97 | } 98 | 99 | return false 100 | } 101 | 102 | func StringInStringList(item string, itemList []string) bool { 103 | for _, i := range itemList { 104 | if i == item { 105 | return true 106 | } 107 | } 108 | 109 | return false 110 | } 111 | 112 | // UnpackErrsToStrings will try to unpack a multi-error to a list of strings, if possible, if not it will return string 113 | // representation as a first element 114 | func UnpackErrsToStrings(err error) *[]string { 115 | if err == nil { 116 | return &[]string{} 117 | } 118 | 119 | switch joinedErr := err.(type) { 120 | case interface{ Unwrap() []error }: 121 | stringErrs := make([]string, len(joinedErr.Unwrap())) 122 | for i, individualErr := range joinedErr.Unwrap() { 123 | stringErrs[i] = individualErr.Error() 124 | } 125 | return &stringErrs 126 | default: 127 | return &[]string{err.Error()} 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /testbin/setup-envtest.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o pipefail 19 | 20 | # Turn colors in this script off by setting the NO_COLOR variable in your 21 | # environment to any value: 22 | # 23 | # $ NO_COLOR=1 test.sh 24 | NO_COLOR=${NO_COLOR:-""} 25 | if [ -z "$NO_COLOR" ]; then 26 | header=$'\e[1;33m' 27 | reset=$'\e[0m' 28 | else 29 | header='' 30 | reset='' 31 | fi 32 | 33 | function header_text { 34 | echo "$header$*$reset" 35 | } 36 | 37 | function setup_envtest_env { 38 | header_text "setting up env vars" 39 | 40 | # Setup env vars 41 | KUBEBUILDER_ASSETS=${KUBEBUILDER_ASSETS:-""} 42 | if [[ -z "${KUBEBUILDER_ASSETS}" ]]; then 43 | export KUBEBUILDER_ASSETS=$1/bin 44 | fi 45 | } 46 | 47 | # fetch k8s API gen tools and make it available under envtest_root_dir/bin. 48 | # 49 | # Skip fetching and untaring the tools by setting the SKIP_FETCH_TOOLS variable 50 | # in your environment to any value: 51 | # 52 | # $ SKIP_FETCH_TOOLS=1 ./check-everything.sh 53 | # 54 | # If you skip fetching tools, this script will use the tools already on your 55 | # machine. 56 | function fetch_envtest_tools { 57 | SKIP_FETCH_TOOLS=${SKIP_FETCH_TOOLS:-""} 58 | if [ -n "$SKIP_FETCH_TOOLS" ]; then 59 | return 0 60 | fi 61 | 62 | tmp_root=/tmp 63 | envtest_root_dir=$tmp_root/envtest 64 | 65 | k8s_version="${ENVTEST_K8S_VERSION:-1.16.4}" 66 | goarch="$(go env GOARCH)" 67 | goos="$(go env GOOS)" 68 | 69 | if [[ "$goos" != "linux" && "$goos" != "darwin" ]]; then 70 | echo "OS '$goos' not supported. Aborting." >&2 71 | return 1 72 | fi 73 | 74 | local dest_dir="${1}" 75 | 76 | # use the pre-existing version in the temporary folder if it matches our k8s version 77 | if [[ -x "${dest_dir}/bin/kube-apiserver" ]]; then 78 | version=$("${dest_dir}"/bin/kube-apiserver --version) 79 | if [[ $version == *"${k8s_version}"* ]]; then 80 | header_text "Using cached envtest tools from ${dest_dir}" 81 | return 0 82 | fi 83 | fi 84 | 85 | header_text "fetching envtest tools@${k8s_version} (into '${dest_dir}')" 86 | envtest_tools_archive_name="kubebuilder-tools-$k8s_version-$goos-$goarch.tar.gz" 87 | envtest_tools_download_url="https://storage.googleapis.com/kubebuilder-tools/$envtest_tools_archive_name" 88 | 89 | envtest_tools_archive_path="$tmp_root/$envtest_tools_archive_name" 90 | if [ ! -f $envtest_tools_archive_path ]; then 91 | curl -sL ${envtest_tools_download_url} -o "$envtest_tools_archive_path" 92 | fi 93 | 94 | mkdir -p "${dest_dir}" 95 | tar -C "${dest_dir}" --strip-components=1 -zvxf "$envtest_tools_archive_path" 96 | } 97 | -------------------------------------------------------------------------------- /testbin/spam_crds.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | actions=("deletePod" "createPod") 4 | profiles=("balance-performance" "performance" "balance-power") 5 | 6 | podList=() 7 | deletePod(){ 8 | if [ ${#podList[@]} -eq 0 ]; then 9 | return 10 | fi 11 | 12 | local pod=${podList[$RANDOM % ${#podList[@]} ]} 13 | echo deletePod $pod 14 | kubectl delete pod $pod & 15 | podList=("${podList[@]/$pod}") 16 | } 17 | 18 | createPod(){ 19 | local podName=pod$RANDOM 20 | local CPUs=$((RANDOM%3+1)) 21 | local profile=${profiles[ $RANDOM % ${#profiles[@]} ]} 22 | 23 | podList+=("$podName") 24 | 25 | cat << EOF | kubectl apply -f - 26 | apiVersion: v1 27 | kind: Pod 28 | metadata: 29 | name: $podName 30 | spec: 31 | containers: 32 | - name: example-power-container 33 | image: ubuntu 34 | command: ["/bin/sh"] 35 | args: ["-c", "sleep infinity"] 36 | resources: 37 | requests: 38 | memory: "200Mi" 39 | cpu: "$CPUs" 40 | power.intel.com/$profile: "$CPUs" 41 | limits: 42 | memory: "200Mi" 43 | cpu: "$CPUs" 44 | power.intel.com/$profile: "$CPUs" 45 | EOF 46 | } 47 | 48 | count=1 49 | MAXCOUNT=100 50 | 51 | while [ "$count" -le $MAXCOUNT ]; do 52 | ${actions[ $RANDOM % ${#actions[@]} ]} 53 | sleep 2 54 | done 55 | --------------------------------------------------------------------------------