diff --git a/.gitignore b/.gitignore index 23779b29d6..94bc3e2a3f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store k8sgpt* +!charts/k8sgpt *.vscode dist/ diff --git a/Makefile b/Makefile index 07398de4cc..deae8e9f7e 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,8 @@ ROOT_PACKAGE=github.com/k8sgpt-ai/k8sgpt SHELL := /bin/bash DIRS=$(shell ls) GO=go +GOOS ?= $(shell go env GOOS) +GOARCH ?= $(shell go env GOARCH) .DEFAULT_GOAL := help @@ -61,17 +63,21 @@ tidy: ## deploy: Deploy k8sgpt .PHONY: deploy -deploy: +deploy: helm @echo "===========> Deploying k8sgpt" - @$(call funcsecret) + $(HELM) install k8sgpt charts/k8sgpt -n k8sgpt --create-namespace + +## update: Update k8sgpt +.PHONY: update +update: helm + @echo "===========> Updating k8sgpt" + $(HELM) upgrade k8sgpt charts/k8sgpt -n k8sgpt ## undeploy: Undeploy k8sgpt .PHONY: undeploy -undeploy: +undeploy: helm @echo "===========> Undeploying k8sgpt" - kubectl delete secret ai-backend-secret --namespace=k8sgpt - kubectl delete -f container/manifests - kubectl delete ns k8sgpt + $(HELM) uninstall k8sgpt -n k8sgpt ## docker-build: Build docker image .PHONY: docker-build @@ -79,7 +85,6 @@ docker-build: @echo "===========> Building docker image" docker buildx build --build-arg=VERSION="$$(git describe --tags --abbrev=0)" --build-arg=COMMIT="$$(git rev-parse --short HEAD)" --build-arg DATE="$$(date +%FT%TZ)" --platform="linux/amd64,linux/arm64" -t ${IMG} -f container/Dockerfile . --push - ## fmt: Run go fmt against code. .PHONY: fmt fmt: @@ -137,11 +142,16 @@ copyright.add: tools.verify.addlicense # @addlicense -y $(shell date +"%Y") -v -c "K8sgpt AI." -f $(LICENSE_TEMPLATE) $(CODE_DIRS) @echo "===========> End the copyright is added..." -define funcsecret -ifndef SECRET - $(error SECRET environment variable is not set) -endif - kubectl create ns k8sgpt || true - kubectl create secret generic ai-backend-secret --from-literal=secret-key=$(SECRET) --namespace=k8sgpt || true - kubectl apply -f container/manifests -endef \ No newline at end of file +# ===== +# Tools + +HELM_VERSION ?= v3.11.3 + +helm: + if ! test -f $(OUTPUT_DIR)/helm-$(GOOS)-$(GOARCH); then \ + curl -L https://get.helm.sh/helm-$(HELM_VERSION)-$(GOOS)-$(GOARCH).tar.gz | tar xz; \ + mv $(GOOS)-$(GOARCH)/helm $(OUTPUT_DIR)/helm-$(GOOS)-$(GOARCH); \ + chmod +x $(OUTPUT_DIR)/helm-$(GOOS)-$(GOARCH); \ + rm -rf ./$(GOOS)-$(GOARCH)/; \ + fi +HELM=$(OUTPUT_DIR)/helm-$(GOOS)-$(GOARCH) \ No newline at end of file diff --git a/charts/k8sgpt/Chart.yaml b/charts/k8sgpt/Chart.yaml new file mode 100644 index 0000000000..04a8cf55d7 --- /dev/null +++ b/charts/k8sgpt/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: v0.2.4 #x-release-please-version +description: A Helm chart for K8SGPT +name: k8sgpt +type: application +version: 1.0.0 diff --git a/charts/k8sgpt/templates/_helpers.tpl b/charts/k8sgpt/templates/_helpers.tpl new file mode 100644 index 0000000000..dfa8d4b26a --- /dev/null +++ b/charts/k8sgpt/templates/_helpers.tpl @@ -0,0 +1,44 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "k8sgpt.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "k8sgpt.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "k8sgpt.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "k8sgpt.labels" -}} +helm.sh/chart: {{ include "k8sgpt.chart" . }} +app.kubernetes.io/name: {{ include "k8sgpt.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/k8sgpt/templates/deployment.yaml b/charts/k8sgpt/templates/deployment.yaml new file mode 100644 index 0000000000..41cc7874f6 --- /dev/null +++ b/charts/k8sgpt/templates/deployment.yaml @@ -0,0 +1,47 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "k8sgpt.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + {{- if .Values.deployment.annotations }} + annotations: + {{- toYaml .Values.deployment.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "k8sgpt.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ include "k8sgpt.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "k8sgpt.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + serviceAccountName: k8sgpt + containers: + - name: k8sgpt-container + imagePullPolicy: {{ .Values.deployment.imagePullPolicy }} + image: {{ .Values.deployment.image.repository }}:{{ .Values.deployment.image.tag | default .Chart.AppVersion }} + ports: + - containerPort: 8080 + args: ["serve"] + {{- if .Values.deployment.resources }} + resources: + {{- toYaml .Values.deployment.resources | nindent 10 }} + {{- end }} + env: + - name: K8SGPT_MODEL + value: {{ .Values.deployment.env.model }} + - name: K8SGPT_BACKEND + value: {{ .Values.deployment.env.backend }} + {{- if .Values.secret.secretKey }} + - name: K8SGPT_PASSWORD + valueFrom: + secretKeyRef: + name: ai-backend-secret + key: secret-key + {{- end }} diff --git a/container/manifests/role.yaml b/charts/k8sgpt/templates/role.yaml similarity index 50% rename from container/manifests/role.yaml rename to charts/k8sgpt/templates/role.yaml index ebdf1c254b..91c8bec61c 100644 --- a/container/manifests/role.yaml +++ b/charts/k8sgpt/templates/role.yaml @@ -1,7 +1,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: k8sgpt-cluster-role-all + name: {{ template "k8sgpt.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "k8sgpt.labels" . | nindent 4 }} rules: - apiGroups: - '*' diff --git a/charts/k8sgpt/templates/rolebinding.yaml b/charts/k8sgpt/templates/rolebinding.yaml new file mode 100644 index 0000000000..ae397e4299 --- /dev/null +++ b/charts/k8sgpt/templates/rolebinding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "k8sgpt.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "k8sgpt.labels" . | nindent 4 }} +subjects: +- kind: ServiceAccount + name: {{ template "k8sgpt.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +roleRef: + kind: ClusterRole + name: k8sgpt-cluster-role-all + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/charts/k8sgpt/templates/sa.yaml b/charts/k8sgpt/templates/sa.yaml new file mode 100644 index 0000000000..b8d7b7d713 --- /dev/null +++ b/charts/k8sgpt/templates/sa.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "k8sgpt.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "k8sgpt.labels" . | nindent 4 }} \ No newline at end of file diff --git a/charts/k8sgpt/templates/secret.yaml b/charts/k8sgpt/templates/secret.yaml new file mode 100644 index 0000000000..600d16bb01 --- /dev/null +++ b/charts/k8sgpt/templates/secret.yaml @@ -0,0 +1,10 @@ +{{- if .Values.secret.secretKey }} +apiVersion: v1 +data: + secret-key: {{ .Values.secret.secretKey }} +kind: Secret +metadata: + name: ai-backend-secret + namespace: {{ .Release.Namespace | quote }} +type: Opaque +{{- end}} \ No newline at end of file diff --git a/charts/k8sgpt/templates/service.yaml b/charts/k8sgpt/templates/service.yaml new file mode 100644 index 0000000000..76dabf90a8 --- /dev/null +++ b/charts/k8sgpt/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "k8sgpt.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "k8sgpt.labels" . | nindent 4 }} + {{- if .Values.service.annotations }} + annotations: + {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + selector: + app.kubernetes.io/name: {{ include "k8sgpt.name" . }} + ports: + - name: http + port: 8080 + targetPort: 8080 + type: {{ .Values.service.type }} diff --git a/charts/k8sgpt/templates/serviceMonitor.yaml b/charts/k8sgpt/templates/serviceMonitor.yaml new file mode 100644 index 0000000000..bcee7053f9 --- /dev/null +++ b/charts/k8sgpt/templates/serviceMonitor.yaml @@ -0,0 +1,18 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "k8sgpt.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "k8sgpt.labels" . | nindent 4 }} +spec: + endpoints: + - honorLabels: true + path: /metrics + port: http + selector: + matchLabels: + app.kubernetes.io/name: {{ include "k8sgpt.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} \ No newline at end of file diff --git a/charts/k8sgpt/values.yaml b/charts/k8sgpt/values.yaml new file mode 100644 index 0000000000..4f199a7101 --- /dev/null +++ b/charts/k8sgpt/values.yaml @@ -0,0 +1,26 @@ +deployment: + image: + repository: ghcr.io/k8sgpt-ai/k8sgpt + tag: "" # defaults to Chart.appVersion if unspecified + imagePullPolicy: Always + annotations: {} + env: + model: "gpt-3.5-turbo" + backend: "openai" # one of: [ openai | llama ] + resources: + limits: + cpu: "1" + memory: "512Mi" + requests: + cpu: "0.2" + memory: "156Mi" + +secret: + secretKey: "" # base64 encoded OpenAI token + +service: + type: ClusterIP + annotations: {} + +serviceMonitor: + enabled: false \ No newline at end of file diff --git a/container/manifests/deployment.yaml b/container/manifests/deployment.yaml deleted file mode 100644 index 7feb71c01c..0000000000 --- a/container/manifests/deployment.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: k8sgpt-deployment - namespace: k8sgpt - labels: - app: k8sgpt -spec: - replicas: 1 - selector: - matchLabels: - app: k8sgpt - template: - metadata: - labels: - app: k8sgpt - spec: - serviceAccountName: k8sgpt - containers: - - name: k8sgpt-container - imagePullPolicy: Always - image: ghcr.io/k8sgpt-ai/k8sgpt:v0.2.8 #x-release-please-version - ports: - - containerPort: 8080 - args: ["serve"] - resources: - limits: - cpu: "1" - memory: "512Mi" - requests: - cpu: "0.2" - memory: "156Mi" - env: - - name: K8SGPT_MODEL - value: "gpt-3.5-turbo" - - name: K8SGPT_BACKEND - value: "openai" - - name: K8SGPT_PASSWORD - valueFrom: - secretKeyRef: - name: ai-backend-secret - key: secret-key diff --git a/container/manifests/rolebinding.yaml b/container/manifests/rolebinding.yaml deleted file mode 100644 index f103c15534..0000000000 --- a/container/manifests/rolebinding.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: k8sgpt-rolebinding - namespace: k8sgpt -subjects: -- kind: ServiceAccount - name: k8sgpt - namespace: k8sgpt -roleRef: - kind: ClusterRole - name: k8sgpt-cluster-role-all - apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/container/manifests/sa.yaml b/container/manifests/sa.yaml deleted file mode 100644 index 09e7185bb0..0000000000 --- a/container/manifests/sa.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: k8sgpt - namespace: k8sgpt \ No newline at end of file diff --git a/container/manifests/service.yaml b/container/manifests/service.yaml deleted file mode 100644 index 77425a32fb..0000000000 --- a/container/manifests/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: k8sgpt-service - namespace: k8sgpt - labels: - app: k8sgpt -spec: - selector: - app: k8sgpt - ports: - - name: http - port: 8080 - targetPort: 8080 - type: ClusterIP diff --git a/container/manifests/serviceMonitor.yaml b/container/manifests/serviceMonitor.yaml deleted file mode 100644 index 094e7e74a8..0000000000 --- a/container/manifests/serviceMonitor.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - labels: - app: k8sgpt - name: k8sgpt-service-monitor - namespace: k8sgpt -spec: - endpoints: - - honorLabels: true - path: /metrics - port: http - selector: - matchLabels: - app: k8sgpt