From 3d5c572474e3da4b16403e77c333d704c88af57d Mon Sep 17 00:00:00 2001 From: Kay Yan Date: Thu, 26 Dec 2024 11:34:11 +0000 Subject: [PATCH] feat: Add Resource Configuration Options to K8sGPT CRD Signed-off-by: Kay Yan --- api/v1alpha1/k8sgpt_types.go | 26 ++++----- api/v1alpha1/k8sgpt_types_test.go | 13 +++++ api/v1alpha1/zz_generated.deepcopy.go | 6 +++ config/crd/bases/core.k8sgpt.ai_k8sgpts.yaml | 55 ++++++++++++++++++++ config/samples/custom_analzyer_example.yaml | 7 +++ pkg/resources/k8sgpt.go | 5 ++ 6 files changed, 100 insertions(+), 12 deletions(-) diff --git a/api/v1alpha1/k8sgpt_types.go b/api/v1alpha1/k8sgpt_types.go index 3afe8850..1fd57c00 100644 --- a/api/v1alpha1/k8sgpt_types.go +++ b/api/v1alpha1/k8sgpt_types.go @@ -17,6 +17,7 @@ limitations under the License. package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -136,18 +137,19 @@ type ImagePullSecrets struct { type K8sGPTSpec struct { Version string `json:"version,omitempty"` // +kubebuilder:default:=ghcr.io/k8sgpt-ai/k8sgpt - Repository string `json:"repository,omitempty"` - ImagePullSecrets []ImagePullSecrets `json:"imagePullSecrets,omitempty"` - NoCache bool `json:"noCache,omitempty"` - CustomAnalyzers []CustomAnalyzer `json:"customAnalyzers,omitempty"` - Filters []string `json:"filters,omitempty"` - ExtraOptions *ExtraOptionsRef `json:"extraOptions,omitempty"` - Sink *WebhookRef `json:"sink,omitempty"` - AI *AISpec `json:"ai,omitempty"` - RemoteCache *RemoteCacheRef `json:"remoteCache,omitempty"` - Integrations *Integrations `json:"integrations,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - TargetNamespace string `json:"targetNamespace,omitempty"` + Repository string `json:"repository,omitempty"` + ImagePullSecrets []ImagePullSecrets `json:"imagePullSecrets,omitempty"` + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` + NoCache bool `json:"noCache,omitempty"` + CustomAnalyzers []CustomAnalyzer `json:"customAnalyzers,omitempty"` + Filters []string `json:"filters,omitempty"` + ExtraOptions *ExtraOptionsRef `json:"extraOptions,omitempty"` + Sink *WebhookRef `json:"sink,omitempty"` + AI *AISpec `json:"ai,omitempty"` + RemoteCache *RemoteCacheRef `json:"remoteCache,omitempty"` + Integrations *Integrations `json:"integrations,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + TargetNamespace string `json:"targetNamespace,omitempty"` // Define the kubeconfig the Deployment must use. // If empty, the Deployment will use the ServiceAccount provided by Kubernetes itself. Kubeconfig *SecretRef `json:"kubeconfig,omitempty"` diff --git a/api/v1alpha1/k8sgpt_types_test.go b/api/v1alpha1/k8sgpt_types_test.go index 39c397e5..68f7eb23 100644 --- a/api/v1alpha1/k8sgpt_types_test.go +++ b/api/v1alpha1/k8sgpt_types_test.go @@ -21,6 +21,8 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) @@ -44,6 +46,16 @@ var _ = Describe("The test cases for the K8sGPT CRDs", func() { version = "v1alpha1" language = "english" anonymize = true + resource = corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1"), + corev1.ResourceMemory: resource.MustParse("512Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("0.2"), + corev1.ResourceMemory: resource.MustParse("156Mi"), + }, + } Namespace = "k8sGPT" @@ -72,6 +84,7 @@ var _ = Describe("The test cases for the K8sGPT CRDs", func() { NodeSelector: map[string]string{ "nodepool": "management", }, + Resources: &resource, }, } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 7bc5b0f5..b4535d8e 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package v1alpha1 import ( + "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -321,6 +322,11 @@ func (in *K8sGPTSpec) DeepCopyInto(out *K8sGPTSpec) { *out = make([]ImagePullSecrets, len(*in)) copy(*out, *in) } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } if in.CustomAnalyzers != nil { in, out := &in.CustomAnalyzers, &out.CustomAnalyzers *out = make([]CustomAnalyzer, len(*in)) diff --git a/config/crd/bases/core.k8sgpt.ai_k8sgpts.yaml b/config/crd/bases/core.k8sgpt.ai_k8sgpts.yaml index 9c466afb..39967143 100644 --- a/config/crd/bases/core.k8sgpt.ai_k8sgpts.yaml +++ b/config/crd/bases/core.k8sgpt.ai_k8sgpts.yaml @@ -203,6 +203,61 @@ spec: repository: default: ghcr.io/k8sgpt-ai/k8sgpt type: string + resources: + description: ResourceRequirements describes the compute resource requirements. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object sink: properties: channel: diff --git a/config/samples/custom_analzyer_example.yaml b/config/samples/custom_analzyer_example.yaml index 099ca245..bfc17721 100644 --- a/config/samples/custom_analzyer_example.yaml +++ b/config/samples/custom_analzyer_example.yaml @@ -29,3 +29,10 @@ spec: # enabled: false # namespace: trivy-system # skipInstall: false + # resources: + # limits: + # cpu: 1 + # memory: 512Mi + # requests: + # cpu: 200m + # memory: 156Mi \ No newline at end of file diff --git a/pkg/resources/k8sgpt.go b/pkg/resources/k8sgpt.go index 0aae1b36..a15c5d95 100644 --- a/pkg/resources/k8sgpt.go +++ b/pkg/resources/k8sgpt.go @@ -320,6 +320,11 @@ func GetDeployment(config v1alpha1.K8sGPT, outOfClusterMode bool, c client.Clien deployment.Spec.Template.Spec.Containers[0].Env, baseUrl, ) } + + // Configure the k8sgpt deployment resource if required + if config.Spec.Resources != nil { + deployment.Spec.Template.Spec.Containers[0].Resources = *config.Spec.Resources + } // Engine is required only when azureopenai is the ai backend if config.Spec.AI.Engine != "" && config.Spec.AI.Backend == v1alpha1.AzureOpenAI { engine := corev1.EnvVar{