Skip to content

Commit

Permalink
feat: bedrock support (#389)
Browse files Browse the repository at this point in the history
* feat: updated the bedrock secret setting

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: updated CONTRIBUTING.md

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

* chore: updated chart

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>

---------

Signed-off-by: Alex Jones <alexsimonjones@gmail.com>
  • Loading branch information
AlexsJones committed Mar 28, 2024
1 parent e4391ab commit 796f212
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 21 deletions.
12 changes: 12 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ In the scenario where you are testing an uncomitted or unreleased K8sGPT with yo
by running again `LOCAL_MODE=1 make run` and in your local K8sGPT clone you can run `k8sgpt serve` or simply ` go run main.go serve`
Note: You should always deploy a K8sGPT Custom Resource so the operator's reconcilaition can be triggered and you can set arbitrary values for the k8sgpt's version since you will bypass them.

### Testing with GRPCurl

It is possible to test the operator's GRPC API with the grpcurl tool.
This enables you to test the K8sGPT GRPC API without the need of the K8sGPT Operator.

Example:
```
grpcurl -plaintext -d '{ "backend": "amazonbedrock", "explain": true}' localhost:8080 schema.v1.ServerService/Analyze
```

For API details visit the spec on [buf](https://buf.build/k8sgpt-ai/k8sgpt)

## Help
Feel free to join our slack [channel](https://k8sgpt.slack.com) and open GH issues, so we can make the development experience better for all K8sGPT contributors

36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ EOF
## Other AI Backend Examples
<details>
<summary>AzureOpenAI</summary>
Expand Down Expand Up @@ -277,6 +278,39 @@ EOF
<details>
<summary>Amazon Bedrock</summary>
</details>
1. Install the operator from the [Installation](#installation) section.
2. Create secret:
```sh
kubectl create secret generic bedrock-sample-secret --from-literal=AWS_ACCESS_KEY_ID="$(echo $AWS_ACCESS_KEY_ID)" --from-literal=AWS_ACCESS_KEY="$(echo $AWS_ACCESS_KEY)" -n k8sgpt-operator-system
```
3. Apply the K8sGPT configuration object:
```
kubectl apply -f - << EOF
apiVersion: core.k8sgpt.ai/v1alpha1
kind: K8sGPT
metadata:
name: k8sgpt-sample
namespace: k8sgpt-operator-system
spec:
ai:
enabled: true
secret:
name: bedrock-sample-secret
model: anthropic.claude-v2
region: eu-central-1
backend: amazonbedrock
noCache: false
repository: ghcr.io/k8sgpt-ai/k8sgpt
version: v0.3.29
EOF
```
<details>
<summary>LocalAI</summary>
Expand Down Expand Up @@ -305,7 +339,7 @@ EOF
```
Note: ensure that the value of `baseUrl` is a properly constructed [DNS name](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#services) for the LocalAI Service. It should take the form: `http://local-ai.<namespace_local_ai_was_installed_in>.svc.cluster.local:8080/v1`.
4. Same as step 4. in the example above.
1. Same as step 4. in the example above.
</details>
Expand Down
3 changes: 3 additions & 0 deletions api/v1alpha1/k8sgpt_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ type AISpec struct {
Backend string `json:"backend"`
BackOff *BackOff `json:"backOff,omitempty"`
BaseUrl string `json:"baseUrl,omitempty"`
Region string `json:"region,omitempty"`
// +kubebuilder:default:=gpt-3.5-turbo
Model string `json:"model,omitempty"`
Engine string `json:"engine,omitempty"`
Expand Down Expand Up @@ -140,6 +141,8 @@ const (
)

// K8sGPTStatus defines the observed state of K8sGPT
// show the current backend used
// +kubebuilder:printcolumn:name="Backend",type="string",JSONPath=".spec.ai.backend",description="The current backend used"
type K8sGPTStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
Expand Down
7 changes: 5 additions & 2 deletions chart/operator/templates/k8sgpt-crd.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
Expand Down Expand Up @@ -74,6 +75,8 @@ spec:
model:
default: gpt-3.5-turbo
type: string
region:
type: string
secret:
properties:
key:
Expand Down Expand Up @@ -194,7 +197,7 @@ spec:
type: string
type: object
status:
description: K8sGPTStatus defines the observed state of K8sGPT
description: K8sGPTStatus defines the observed state of K8sGPT show the current backend used
type: object
type: object
served: true
Expand All @@ -206,4 +209,4 @@ status:
kind: ""
plural: ""
conditions: []
storedVersions: []
storedVersions: []
5 changes: 4 additions & 1 deletion config/crd/bases/core.k8sgpt.ai_k8sgpts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ spec:
model:
default: gpt-3.5-turbo
type: string
region:
type: string
secret:
properties:
key:
Expand Down Expand Up @@ -194,7 +196,8 @@ spec:
type: string
type: object
status:
description: K8sGPTStatus defines the observed state of K8sGPT
description: K8sGPTStatus defines the observed state of K8sGPT show the
current backend used
type: object
type: object
served: true
Expand Down
4 changes: 2 additions & 2 deletions config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: controller
newName: ghcr.io/k8sgpt-ai/k8sgpt-operator
newTag: feature-integration-support-4
newName: tibbar/k8sgpt-operator
newTag: tmp-010
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module github.com/k8sgpt-ai/k8sgpt-operator
go 1.21

require (
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240128172516-6bf6a55ff115.2
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.32.0-20240128172516-6bf6a55ff115.1
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240213144542-6e830f3fdf19.2
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.33.0-20240213144542-6e830f3fdf19.1
github.com/onsi/ginkgo/v2 v2.16.0
github.com/onsi/gomega v1.32.0
github.com/prometheus/client_golang v1.19.0
Expand Down Expand Up @@ -91,7 +91,9 @@ require (
golang.org/x/time v0.3.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
22 changes: 14 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240128172516-6bf6a55ff115.2 h1:wCvkSdoAF1di3X07+0za7cydd57yXe8Px8q8Gv5me1U=
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240128172516-6bf6a55ff115.2/go.mod h1:RX8MKkcN5AzJMjQ649kSzZKyYo3imsJCMQjQHJKgRpQ=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.28.1-20240128172516-6bf6a55ff115.4/go.mod h1:i/s4ALHwKvjA1oGNKpoHg0FpEOTbufoOm/NdTE6YQAE=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.32.0-20240128172516-6bf6a55ff115.1 h1:Gmrk0ASd78N487ATP3++w6i4iZ4HyUTIdYpE4Ib0CPI=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.32.0-20240128172516-6bf6a55ff115.1/go.mod h1:IThjyuPqz3nkYBGZMUzrHTQhYDedkvBonqAgLcG7sHc=
buf.build/gen/go/grpc-ecosystem/grpc-gateway/grpc/go v1.3.0-20231027202514-3f42134f4c56.2/go.mod h1:FL988BzZirjg37E5k8AJR39eQ6/n/esl7iEEF63xniA=
buf.build/gen/go/grpc-ecosystem/grpc-gateway/protocolbuffers/go v1.28.1-20231027202514-3f42134f4c56.4/go.mod h1:92ejKVTiuvnKoAtRlpJpIxKfloI935DDqhs0NCRx+KM=
buf.build/gen/go/grpc-ecosystem/grpc-gateway/protocolbuffers/go v1.33.0-20231027202514-3f42134f4c56.1/go.mod h1:DBJo17ITWaACJE5Kqb+81Ekkq0BpTsNmgv7cX1tMVpY=
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240213144542-6e830f3fdf19.2 h1:dHSIT1w+0rtb//msVrp/RwrgHIeflbaTMKuF9Lx9HBI=
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240213144542-6e830f3fdf19.2/go.mod h1:EWMdFAEvu6GDt7jvAgoBS/WgXlyDsM7yist2SrcnS3s=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.28.1-20240213144542-6e830f3fdf19.4/go.mod h1:WyRj8OIsAABLNsAELw73BT16v7vvJdEVv771fxX9pJI=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.33.0-20240213144542-6e830f3fdf19.1 h1:ctQgUFe6yA9/XRmorc4tMPK1Z5ZSA7bB2mPvtn3ZT0I=
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.33.0-20240213144542-6e830f3fdf19.1/go.mod h1:QwDvmBCDx7mFDbKgaR6mWS2+oUs8mPLV6tNk9kV+Ctk=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
Expand Down Expand Up @@ -1213,8 +1216,12 @@ google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZV
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE=
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8=
google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
Expand Down Expand Up @@ -1271,7 +1278,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
56 changes: 52 additions & 4 deletions pkg/resources/k8sgpt.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,32 @@ const (
DestroyOp
)

func addSecretAsEnvToDeployment(secretName string, secretKey string,
config v1alpha1.K8sGPT, c client.Client,
deployment *appsv1.Deployment) error {
secret := &corev1.Secret{}
er := c.Get(context.Background(), types.NamespacedName{Name: secretName,
Namespace: config.Namespace}, secret)
if er != nil {
return err.New("secret does not exist, cannot add to env of deployment")
}
envVar := v1.EnvVar{
Name: secretKey,
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: secretName,
},
Key: secretKey,
},
},
}
deployment.Spec.Template.Spec.Containers[0].Env = append(
deployment.Spec.Template.Spec.Containers[0].Env, envVar,
)
return nil
}

// GetService Create service for K8sGPT
func GetService(config v1alpha1.K8sGPT) (*corev1.Service, error) {
// Create service
Expand Down Expand Up @@ -179,7 +205,7 @@ func GetClusterRole(config v1alpha1.K8sGPT) (*r1.ClusterRole, error) {
}

// GetDeployment Create deployment with the latest K8sGPT image
func GetDeployment(config v1alpha1.K8sGPT, outOfClusterMode bool) (*appsv1.Deployment, error) {
func GetDeployment(config v1alpha1.K8sGPT, outOfClusterMode bool, c client.Client) (*appsv1.Deployment, error) {

// Create deployment
image := config.Spec.Repository + ":" + config.Spec.Version
Expand Down Expand Up @@ -303,7 +329,8 @@ func GetDeployment(config v1alpha1.K8sGPT, outOfClusterMode bool) (*appsv1.Deplo
},
})
}
if config.Spec.AI.Secret != nil {
// This check is necessary for the simple OpenAI journey, let's keep it here and guard from breaking other types of backend
if config.Spec.AI.Secret != nil && config.Spec.AI.Backend != v1alpha1.AmazonBedrock {
password := corev1.EnvVar{
Name: "K8SGPT_PASSWORD",
ValueFrom: &corev1.EnvVarSource{
Expand Down Expand Up @@ -367,7 +394,28 @@ func GetDeployment(config v1alpha1.K8sGPT, outOfClusterMode bool) (*appsv1.Deplo
deployment.Spec.Template.Spec.Containers[0].Env, engine,
)
} else if config.Spec.AI.Engine != "" && config.Spec.AI.Backend != v1alpha1.AzureOpenAI {
return &appsv1.Deployment{}, err.New("Engine is supported only by azureopenai provider.")
return &appsv1.Deployment{}, err.New("engine is supported only by azureopenai provider")
}
// Add checks for amazonbedrock
if config.Spec.AI.Backend == v1alpha1.AmazonBedrock {
if config.Spec.AI.Secret == nil {
return &appsv1.Deployment{}, err.New("secret is required for amazonbedrock backend")
}
if err := addSecretAsEnvToDeployment(config.Spec.AI.Secret.Name, "AWS_ACCESS_KEY_ID", config, c, &deployment); err != nil {
return &appsv1.Deployment{}, err
}
if err := addSecretAsEnvToDeployment(config.Spec.AI.Secret.Name, "AWS_SECRET_ACCESS_KEY", config, c, &deployment); err != nil {
return &appsv1.Deployment{}, err
}
if config.Spec.AI.Region == "" {
return &appsv1.Deployment{}, err.New("default region is required for amazonbedrock backend")
}
deployment.Spec.Template.Spec.Containers[0].Env = append(
deployment.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
Name: "AWS_DEFAULT_REGION",
Value: config.Spec.AI.Region,
},
)
}
return &deployment, nil
}
Expand Down Expand Up @@ -409,7 +457,7 @@ func Sync(ctx context.Context, c client.Client,

objs = append(objs, svc)

deployment, er := GetDeployment(config, outOfClusterMode)
deployment, er := GetDeployment(config, outOfClusterMode, c)
if er != nil {
return er
}
Expand Down

0 comments on commit 796f212

Please sign in to comment.