-
-
Notifications
You must be signed in to change notification settings - Fork 70
Feature: Add Dockerfile and Helm chart for Kubernetes deployment #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
SantiagoDePolonia
merged 27 commits into
ENTERPILOT:main
from
kowtom:feature/kubernetes-helm-chart
Jan 16, 2026
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
bf831dc
Add dockerfile
kowtom 3531cad
Add helm chart
kowtom 437f8e1
Pin package versions and reference tags
kowtom b413a4d
Merge remote-tracking branch 'origin/main' into feature/kubernetes-he…
kowtom a26288f
Ignore dependencies
kowtom 2a4ee12
Update helm/gomodel/Chart.yaml
kowtom aca491f
Remove misleading comment
kowtom 850f38d
Make it fail when neither TargetCPU nor TargetMemory is provided
kowtom d8b5933
Fail when invalid PDB configuration is provided
kowtom a472ac1
Add json scheme for validation
kowtom 8ad61c1
Make secret configuration more dynamic
kowtom c525911
Use default user provided by distroless nonroot
kowtom 0b1edd2
Get rid of the redundant gomodel directory in helm
kowtom 205f677
Pin version and update redis
kowtom c11b6bd
Replace placeholder
kowtom 9845aec
Add dockerignore
kowtom 53154a8
Add validation for parentRef.name
kowtom e857e38
Update .dockerignore
SantiagoDePolonia cf02acd
Add todo
kowtom bee7cf5
Correct readme
kowtom b5eef50
Require redis url when cache type is redis
kowtom fd0b251
Add credentials validation for each provider
kowtom 065167c
Remove local cache
kowtom fbe2fb4
Fix formatting
kowtom c792a7f
Allow empty redis url when the bitnami subchart is used
kowtom 80072d1
Fix copying
kowtom d9a55be
Update paths in readme
kowtom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| # =================== | ||
| # Git | ||
| # =================== | ||
| .git | ||
| .gitignore | ||
|
|
||
| # =================== | ||
| # Build artifacts | ||
| # =================== | ||
| bin/ | ||
| gomodel | ||
| coverage.out | ||
|
|
||
| # =================== | ||
| # Tests | ||
| # =================== | ||
| tests/ | ||
| **/*_test.go | ||
|
|
||
| # =================== | ||
| # Documentation | ||
| # =================== | ||
| *.md | ||
| LICENSE | ||
|
|
||
| # =================== | ||
| # CI/CD & Release | ||
| # =================== | ||
| .github/ | ||
| .goreleaser.yaml | ||
|
|
||
| # =================== | ||
| # Development tooling | ||
| # =================== | ||
| .golangci.yml | ||
| .pre-commit-config.yaml | ||
| Makefile | ||
|
|
||
| # =================== | ||
| # Docker & Kubernetes | ||
| # =================== | ||
| Dockerfile | ||
| .dockerignore | ||
| docker-compose.yaml | ||
| helm/ | ||
| prometheus.yml | ||
|
|
||
| # =================== | ||
| # IDE & Editor configs | ||
| # =================== | ||
| .claude/ | ||
| .vscode/ | ||
| .idea/ | ||
| *.swp | ||
| *.swo | ||
| *~ | ||
|
|
||
| # =================== | ||
| # Environment & Secrets | ||
| # =================== | ||
| .env | ||
| .env.* | ||
|
|
||
| # =================== | ||
| # Miscellaneous | ||
| # =================== | ||
| .cache/ | ||
| *.bck.yml | ||
| repomix-output.* | ||
| session-*.md | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,3 +12,6 @@ | |
| /*.bck.yml | ||
| /repomix-output.* | ||
| /coverage.out | ||
|
|
||
| # Helm chart dependencies | ||
| **/charts/*.tgz | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # Build stage | ||
| FROM golang:1.24-alpine3.23 AS builder | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| # Install ca-certificates for HTTPS requests | ||
| RUN apk add --no-cache ca-certificates=20251003-r0 | ||
|
|
||
| # Download dependencies first for better layer caching | ||
| COPY go.mod go.sum ./ | ||
| RUN go mod download | ||
|
|
||
| # Copy source and build | ||
| COPY . . | ||
|
coderabbitai[bot] marked this conversation as resolved.
kowtom marked this conversation as resolved.
|
||
| RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /gomodel ./cmd/gomodel | ||
|
kowtom marked this conversation as resolved.
|
||
|
|
||
| # Runtime stage | ||
| FROM gcr.io/distroless/static-debian12:nonroot | ||
|
kowtom marked this conversation as resolved.
|
||
|
|
||
| # Copy binary and ca-certificates | ||
| COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ | ||
| COPY --from=builder /gomodel /gomodel | ||
| COPY --from=builder /app/config/*.yaml /app/config/ | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| EXPOSE 8080 | ||
|
|
||
| ENTRYPOINT ["/gomodel"] | ||
|
SantiagoDePolonia marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| dependencies: | ||
| - name: redis | ||
| repository: oci://registry-1.docker.io/bitnamicharts | ||
| version: 24.1.0 | ||
| digest: sha256:46e96c6627f431805f1ded87a1d15a25c3aaf648a1242343f52b8c6a51e2cb2f | ||
| generated: "2026-01-08T06:38:01.742616425+01:00" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| apiVersion: v2 | ||
| name: gomodel | ||
| description: High-performance AI gateway for multiple LLM providers (OpenAI, Anthropic, Gemini, Groq, xAI) | ||
| type: application | ||
| version: 0.1.0 | ||
| appVersion: "1.0.0" | ||
|
|
||
| keywords: | ||
| - llm | ||
| - ai | ||
| - gateway | ||
| - openai | ||
| - anthropic | ||
| - gemini | ||
| - groq | ||
| - xai | ||
| - proxy | ||
|
|
||
| home: https://github.com/ENTERPILOT/GOModel | ||
| sources: | ||
| - https://github.com/ENTERPILOT/GOModel | ||
|
|
||
| maintainers: | ||
| - name: GOModel Team | ||
|
SantiagoDePolonia marked this conversation as resolved.
|
||
|
|
||
| dependencies: | ||
| - name: redis | ||
| version: "^24.0.0" | ||
| repository: oci://registry-1.docker.io/bitnamicharts | ||
| condition: redis.enabled | ||
|
coderabbitai[bot] marked this conversation as resolved.
kowtom marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| # GOModel Helm Chart | ||
|
|
||
| High-performance AI gateway for multiple LLM providers (OpenAI, Anthropic, Gemini, Groq, xAI). | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Kubernetes 1.29+ (for Gateway API v1 support) | ||
| - Helm 3.x | ||
| - (Optional) Prometheus Operator for ServiceMonitor support | ||
|
|
||
| ## Installation | ||
|
|
||
| ### Add the Helm repository (if published) | ||
|
|
||
| ```bash | ||
| helm repo add gomodel https://your-org.github.io/gomodel | ||
| helm repo update | ||
| ``` | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| ### Install from local chart | ||
|
|
||
| ```bash | ||
| # Basic install with OpenAI | ||
| helm install gomodel ./helm \ | ||
| -n gomodel --create-namespace \ | ||
| --set providers.openai.enabled=true \ | ||
| --set providers.openai.apiKey="sk-..." | ||
|
|
||
| # Multi-provider setup with Redis cache | ||
| helm install gomodel ./helm \ | ||
| -n gomodel --create-namespace \ | ||
| --set providers.openai.enabled=true \ | ||
| --set providers.openai.apiKey="sk-..." \ | ||
| --set providers.anthropic.enabled=true \ | ||
| --set providers.anthropic.apiKey="sk-ant-..." \ | ||
| --set redis.enabled=true | ||
|
|
||
| # Using existing secrets (GitOps-friendly) | ||
| helm install gomodel ./helm \ | ||
| -n gomodel --create-namespace \ | ||
| --set providers.existingSecret="llm-api-keys" \ | ||
| --set providers.openai.enabled=true \ | ||
| --set providers.anthropic.enabled=true | ||
| ``` | ||
|
|
||
| ## Configuration | ||
|
|
||
| ### Key Values | ||
|
|
||
| | Parameter | Description | Default | | ||
| |-----------|-------------|---------| | ||
| | `replicaCount` | Number of replicas | `2` | | ||
| | `image.repository` | Image repository | `enterpilot/gomodel` | | ||
| | `image.tag` | Image tag | `""` (uses appVersion) | | ||
|
SantiagoDePolonia marked this conversation as resolved.
|
||
| | `server.port` | Server port | `8080` | | ||
| | `server.bodySizeLimit` | Max request body size | `"10M"` | | ||
| | `auth.masterKey` | Master key for auth | `""` | | ||
| | `auth.existingSecret` | Existing secret for auth | `""` | | ||
| | `providers.existingSecret` | Existing secret for API keys | `""` | | ||
| | `providers.openai.enabled` | Enable OpenAI | `false` | | ||
| | `providers.anthropic.enabled` | Enable Anthropic | `false` | | ||
| | `providers.gemini.enabled` | Enable Gemini | `false` | | ||
| | `providers.groq.enabled` | Enable Groq | `false` | | ||
| | `providers.xai.enabled` | Enable xAI | `false` | | ||
| | `cache.type` | Cache type (local/redis) | `"redis"` | | ||
| | `redis.enabled` | Deploy Redis subchart | `true` | | ||
| | `metrics.enabled` | Enable Prometheus metrics | `true` | | ||
| | `metrics.serviceMonitor.enabled` | Create ServiceMonitor | `false` | | ||
| | `ingress.enabled` | Enable Ingress | `false` | | ||
| | `gateway.enabled` | Enable Gateway API HTTPRoute | `false` | | ||
| | `autoscaling.enabled` | Enable HPA | `false` | | ||
|
|
||
| ### Using Existing Secrets | ||
|
|
||
| Create a secret with your API keys: | ||
|
|
||
| ```yaml | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: llm-api-keys | ||
| type: Opaque | ||
| stringData: | ||
| OPENAI_API_KEY: "sk-..." | ||
| ANTHROPIC_API_KEY: "sk-ant-..." | ||
| GEMINI_API_KEY: "..." | ||
| ``` | ||
|
|
||
| Then reference it: | ||
|
|
||
| ```bash | ||
| helm install gomodel ./helm \ | ||
| --set providers.existingSecret="llm-api-keys" \ | ||
| --set providers.openai.enabled=true | ||
| ``` | ||
|
|
||
| ### Ingress Example | ||
|
|
||
| ```yaml | ||
| ingress: | ||
| enabled: true | ||
| className: nginx | ||
| annotations: | ||
| cert-manager.io/cluster-issuer: letsencrypt-prod | ||
| hosts: | ||
| - host: gomodel.example.com | ||
| paths: | ||
| - path: / | ||
| pathType: Prefix | ||
| tls: | ||
| - secretName: gomodel-tls | ||
| hosts: | ||
| - gomodel.example.com | ||
| ``` | ||
|
|
||
| ### Gateway API Example | ||
|
|
||
| ```yaml | ||
| gateway: | ||
| enabled: true | ||
| parentRef: | ||
| name: my-gateway | ||
| namespace: gateway-system | ||
| hostnames: | ||
| - gomodel.example.com | ||
| ``` | ||
|
|
||
| ## Upgrading | ||
|
|
||
| ```bash | ||
| helm upgrade gomodel ./helm -n gomodel -f values.yaml | ||
| ``` | ||
|
|
||
| ## Uninstalling | ||
|
|
||
| ```bash | ||
| helm uninstall gomodel -n gomodel | ||
| ``` | ||
|
|
||
| # Todo | ||
|
|
||
| - Add a values-demo.yaml file with a demo setup ready to run | ||
| - Consider adding prometheus + grafana stack as an optional subchart | ||
| - Add an example for production-ready redis configuration with persistence and authentication enabled | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| Thank you for installing {{ .Chart.Name }}! | ||
|
|
||
| Your release is named: {{ .Release.Name }} | ||
|
|
||
| To get the application URL: | ||
| {{- if .Values.ingress.enabled }} | ||
| {{- range $host := .Values.ingress.hosts }} | ||
| http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ (first $host.paths).path }} | ||
| {{- end }} | ||
| {{- else if .Values.gateway.enabled }} | ||
| Configure your Gateway to route traffic to the service. | ||
| Service: {{ include "gomodel.fullname" . }}:{{ .Values.service.port }} | ||
| {{- else if contains "NodePort" .Values.service.type }} | ||
| export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "gomodel.fullname" . }}) | ||
| export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") | ||
| echo http://$NODE_IP:$NODE_PORT | ||
| {{- else if contains "LoadBalancer" .Values.service.type }} | ||
| NOTE: It may take a few minutes for the LoadBalancer IP to be available. | ||
| You can watch the status with: kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "gomodel.fullname" . }} | ||
| export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "gomodel.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") | ||
| echo http://$SERVICE_IP:{{ .Values.service.port }} | ||
| {{- else if contains "ClusterIP" .Values.service.type }} | ||
| kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "gomodel.fullname" . }} 8080:{{ .Values.service.port }} | ||
| echo "Visit http://127.0.0.1:8080 to use the API" | ||
| {{- end }} | ||
|
|
||
| {{- if not .Values.auth.masterKey }} | ||
| {{- if not .Values.auth.existingSecret }} | ||
|
|
||
| ⚠️ WARNING: No authentication configured! | ||
| The gateway is running in UNSAFE MODE without authentication. | ||
| Set auth.masterKey or auth.existingSecret for production use. | ||
| {{- end }} | ||
| {{- end }} | ||
|
|
||
| {{- $enabledProviders := list }} | ||
| {{- if .Values.providers.openai.enabled }}{{ $enabledProviders = append $enabledProviders "openai" }}{{ end }} | ||
| {{- if .Values.providers.anthropic.enabled }}{{ $enabledProviders = append $enabledProviders "anthropic" }}{{ end }} | ||
| {{- if .Values.providers.gemini.enabled }}{{ $enabledProviders = append $enabledProviders "gemini" }}{{ end }} | ||
| {{- if .Values.providers.groq.enabled }}{{ $enabledProviders = append $enabledProviders "groq" }}{{ end }} | ||
| {{- if .Values.providers.xai.enabled }}{{ $enabledProviders = append $enabledProviders "xai" }}{{ end }} | ||
|
|
||
| {{- if eq (len $enabledProviders) 0 }} | ||
|
|
||
| ⚠️ WARNING: No providers enabled! | ||
| Enable at least one provider (e.g., providers.openai.enabled=true) | ||
| {{- else }} | ||
|
|
||
| Enabled providers: {{ join ", " $enabledProviders }} | ||
| {{- end }} | ||
|
|
||
| To check the logs: | ||
| kubectl logs --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "gomodel.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -f | ||
|
|
||
| To test the health endpoint: | ||
| kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "gomodel.fullname" . }} 8080:{{ .Values.service.port }} & | ||
| curl http://127.0.0.1:8080/health | ||
|
kowtom marked this conversation as resolved.
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.