diff --git a/.github/workflows/helm_checks.yaml b/.github/workflows/helm_checks.yaml index 1230ee6..bd6de06 100644 --- a/.github/workflows/helm_checks.yaml +++ b/.github/workflows/helm_checks.yaml @@ -48,4 +48,4 @@ jobs: env: LANGSMITH_LICENSE_KEY: ${{ secrets.LANGSMITH_LICENSE_KEY }} LANGGRAPH_CLOUD_LICENSE_KEY: ${{ secrets.LANGGRAPH_CLOUD_LICENSE_KEY }} - run: ct install --target-branch ${{ github.event.repository.default_branch }} --charts charts/${{ matrix.chart-name }} --helm-extra-set-args "--set=frontend.service.type=ClusterIP --set=config.langsmithLicenseKey=$LANGSMITH_LICENSE_KEY --set=config.langGraphCloudLicenseKey=$LANGGRAPH_CLOUD_LICENSE_KEY --set=apiServer.service.type=ClusterIP" + run: ct install --target-branch ${{ github.event.repository.default_branch }} --charts charts/${{ matrix.chart-name }} --helm-extra-set-args "--set=frontend.service.type=ClusterIP --set=config.langsmithLicenseKey=$LANGSMITH_LICENSE_KEY --set=config.langGraphCloudLicenseKey=$LANGGRAPH_CLOUD_LICENSE_KEY --set=apiServer.service.type=ClusterIP --set=studio.service.type=ClusterIP" diff --git a/charts/langgraph-cloud/Chart.yaml b/charts/langgraph-cloud/Chart.yaml index 1c96cf7..43a5aac 100644 --- a/charts/langgraph-cloud/Chart.yaml +++ b/charts/langgraph-cloud/Chart.yaml @@ -5,5 +5,5 @@ maintainers: email: ankush@langchain.dev description: Helm chart to deploy the LangGraph Cloud application and all services it depends on. type: application -version: 0.1.5 +version: 0.1.6 appVersion: "0.2.0" diff --git a/charts/langgraph-cloud/README.md b/charts/langgraph-cloud/README.md index 82d2d79..d348146 100644 --- a/charts/langgraph-cloud/README.md +++ b/charts/langgraph-cloud/README.md @@ -1,6 +1,6 @@ # langgraph-cloud -![Version: 0.1.5](https://img.shields.io/badge/Version-0.1.5-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.2.0](https://img.shields.io/badge/AppVersion-0.2.0-informational?style=flat-square) +![Version: 0.1.6](https://img.shields.io/badge/Version-0.1.6-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.2.0](https://img.shields.io/badge/AppVersion-0.2.0-informational?style=flat-square) Helm chart to deploy the LangGraph Cloud application and all services it depends on. @@ -205,11 +205,15 @@ the same format as the secret in the corresponding `secrets.yaml` file. Note: AP | images.redisImage.pullPolicy | string | `"IfNotPresent"` | | | images.redisImage.repository | string | `"docker.io/redis"` | | | images.redisImage.tag | string | `"6"` | | +| images.studioImage.pullPolicy | string | `"Always"` | | +| images.studioImage.repository | string | `"docker.io/langchain/langgraph-debugger"` | | +| images.studioImage.tag | string | `"latest"` | | | ingress.annotations | object | `{}` | | | ingress.enabled | bool | `false` | | | ingress.hostname | string | `""` | | | ingress.ingressClassName | string | `""` | | | ingress.labels | object | `{}` | | +| ingress.studioHostname | string | `""` | | | ingress.tls | list | `[]` | | | nameOverride | string | `""` | Provide a name in place of `langgraph-cloud` for the chart | | redis.containerPort | int | `6379` | | @@ -262,6 +266,40 @@ the same format as the secret in the corresponding `secrets.yaml` file. Note: AP | redis.serviceAccount.create | bool | `true` | | | redis.serviceAccount.labels | object | `{}` | | | redis.serviceAccount.name | string | `""` | | +| studio.autoscaling.enabled | bool | `false` | | +| studio.autoscaling.maxReplicas | int | `5` | | +| studio.autoscaling.minReplicas | int | `1` | | +| studio.autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| studio.containerPort | int | `3968` | | +| studio.deployment.affinity | object | `{}` | | +| studio.deployment.annotations | object | `{}` | | +| studio.deployment.extraEnv | list | `[]` | | +| studio.deployment.labels | object | `{}` | | +| studio.deployment.nodeSelector | object | `{}` | | +| studio.deployment.podSecurityContext | object | `{}` | | +| studio.deployment.replicaCount | int | `1` | | +| studio.deployment.resources.limits.cpu | string | `"1000m"` | | +| studio.deployment.resources.limits.memory | string | `"2Gi"` | | +| studio.deployment.resources.requests.cpu | string | `"500m"` | | +| studio.deployment.resources.requests.memory | string | `"1Gi"` | | +| studio.deployment.securityContext | object | `{}` | | +| studio.deployment.sidecars | list | `[]` | | +| studio.deployment.tolerations | list | `[]` | | +| studio.deployment.volumeMounts | list | `[]` | | +| studio.deployment.volumes | list | `[]` | | +| studio.enabled | bool | `true` | | +| studio.name | string | `"studio"` | | +| studio.service.annotations | object | `{}` | | +| studio.service.httpPort | int | `80` | | +| studio.service.httpsPort | int | `443` | | +| studio.service.labels | object | `{}` | | +| studio.service.loadBalancerIP | string | `""` | | +| studio.service.loadBalancerSourceRanges | list | `[]` | | +| studio.service.type | string | `"LoadBalancer"` | | +| studio.serviceAccount.annotations | object | `{}` | | +| studio.serviceAccount.create | bool | `true` | | +| studio.serviceAccount.labels | object | `{}` | | +| studio.serviceAccount.name | string | `""` | | ## Configs @@ -363,6 +401,6 @@ the same format as the secret in the corresponding `secrets.yaml` file. Note: AP | Ankush | | | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) +Autogenerated from chart metadata using [helm-docs v1.11.3](https://github.com/norwoodj/helm-docs/releases/v1.11.3) ## Docs Generated by [helm-docs](https://github.com/norwoodj/helm-docs) `helm-docs -t ./charts/langgraph-cloud/README.md.gotmpl` diff --git a/charts/langgraph-cloud/templates/NOTES.txt b/charts/langgraph-cloud/templates/NOTES.txt index 445f51b..d6b4858 100644 --- a/charts/langgraph-cloud/templates/NOTES.txt +++ b/charts/langgraph-cloud/templates/NOTES.txt @@ -1 +1,25 @@ -This is the LangGraph Cloud application helm chart. All pods should be running! +Thank you for installing LangGraph Cloud! + +This chart deploys a LangGraph Cloud instance. All pods should be running! You can access the docs for your API Server by running the following command: + + kubectl port-forward svc/langgraph-api-server 8080:80 + +Then you can access the LangGraph API Server Docs at http://localhost:8080/docs + +If you have configured a LoadBalancer service for the LangGraph API Server, you can access the LangGraph API Server by running the following command: + + kubectl get svc langgraph-api-server + +Then you can access the LangGraph API Server at http://. + +If you have enabled the studio, you can access the LangGraph Studio by running the following command: + + kubectl port-forward svc/langgraph-cloud-studio 8080:80 + +Then you can access the LangGraph Studio at http://localhost:8080. Note that it will by default point to the ingress.hostname parameter. You can update this by changing the baseUrl parameter in the url. + +If you have configured a LoadBalancer service for the LangGraph Studio, you can access the LangGraph Studio by running the following command: + + kubectl get svc langgraph-cloud-studio + +Then you can access the LangGraph Studio at http://. diff --git a/charts/langgraph-cloud/templates/_helpers.tpl b/charts/langgraph-cloud/templates/_helpers.tpl index 589d29e..040f75f 100644 --- a/charts/langgraph-cloud/templates/_helpers.tpl +++ b/charts/langgraph-cloud/templates/_helpers.tpl @@ -127,3 +127,11 @@ the user or some other secret provisioning mechanism {{ default "default" .Values.redis.serviceAccount.name }} {{- end -}} {{- end -}} + +{{- define "studio.serviceAccountName" -}} +{{- if .Values.studio.serviceAccount.create -}} + {{ default (printf "%s-%s" (include "langGraphCloud.fullname" .) .Values.studio.name) .Values.studio.serviceAccount.name | trunc 63 | trimSuffix "-" }} +{{- else -}} + {{ default "default" .Values.studio.serviceAccount.name }} +{{- end -}} +{{- end -}} diff --git a/charts/langgraph-cloud/templates/ingress.yaml b/charts/langgraph-cloud/templates/ingress.yaml index 493e793..1626612 100644 --- a/charts/langgraph-cloud/templates/ingress.yaml +++ b/charts/langgraph-cloud/templates/ingress.yaml @@ -31,4 +31,16 @@ spec: name: {{ include "langGraphCloud.fullname" . }}-{{ .Values.apiServer.name }} port: number: {{ .Values.apiServer.service.httpPort }} + {{- if .Values.studio.enabled }} + - host: {{ .Values.ingress.studioHostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "langGraphCloud.fullname" . }}-{{ .Values.studio.name }} + port: + number: {{ .Values.studio.service.httpPort }} + {{- end }} {{- end }} diff --git a/charts/langgraph-cloud/templates/studio/deployment.yaml b/charts/langgraph-cloud/templates/studio/deployment.yaml new file mode 100644 index 0000000..c8ff2fd --- /dev/null +++ b/charts/langgraph-cloud/templates/studio/deployment.yaml @@ -0,0 +1,106 @@ +{{- if .Values.studio.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "langGraphCloud.fullname" . }}-{{ .Values.studio.name }} + labels: + {{- include "langGraphCloud.labels" . | nindent 4 }} + {{- with.Values.studio.deployment.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- include "langGraphCloud.annotations" . | nindent 4 }} + {{- with.Values.studio.deployment.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if not .Values.studio.autoscaling.enabled }} + replicas: {{ .Values.studio.deployment.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "langGraphCloud.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: {{ include "langGraphCloud.fullname" . }}-{{ .Values.studio.name }} + template: + metadata: + {{- with .Values.studio.deployment.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- with.Values.studio.deployment.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- include "langGraphCloud.labels" . | nindent 8 }} + app.kubernetes.io/component: {{ include "langGraphCloud.fullname" . }}-{{ .Values.studio.name }} + spec: + serviceAccountName: {{ include "studio.serviceAccountName" . }} + {{- with .Values.images.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.studio.deployment.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Values.studio.name }} + env: + - name: VITE_STUDIO_LOCAL_GRAPH_URL + value: {{ .Values.ingress.hostname }} + {{- with .Values.studio.deployment.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.images.studioImage.repository }}:{{ .Values.images.studioImage.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.images.studioImage.pullPolicy }} + ports: + - name: studio + containerPort: {{ .Values.studio.containerPort }} + protocol: TCP + startupProbe: + httpGet: + path: /health + port: {{ .Values.studio.containerPort }} + failureThreshold: 6 + periodSeconds: 10 + timeoutSeconds: 1 + readinessProbe: + httpGet: + path: /health + port: {{ .Values.studio.containerPort }} + failureThreshold: 3 + periodSeconds: 10 + timeoutSeconds: 1 + livenessProbe: + httpGet: + path: /health + port: {{ .Values.studio.containerPort }} + failureThreshold: 6 + periodSeconds: 10 + timeoutSeconds: 1 + resources: + {{- toYaml .Values.studio.deployment.resources | nindent 12 }} + securityContext: + {{- toYaml .Values.studio.deployment.securityContext | nindent 12 }} + {{- with .Values.studio.deployment.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.studio.deployment.sidecars }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.studio.deployment.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.studio.deployment.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.studio.deployment.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.studio.deployment.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/langgraph-cloud/templates/studio/hpa.yaml b/charts/langgraph-cloud/templates/studio/hpa.yaml new file mode 100644 index 0000000..841e243 --- /dev/null +++ b/charts/langgraph-cloud/templates/studio/hpa.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.studio.autoscaling.enabled .Values.studio.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "langGraphCloud.fullname" . }}-{{ .Values.studio.name }} + labels: + {{- include "langGraphCloud.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "langGraphCloud.fullname" . }}-{{ .Values.studio.name }} + minReplicas: {{ .Values.studio.autoscaling.minReplicas }} + maxReplicas: {{ .Values.studio.autoscaling.maxReplicas }} + metrics: + {{- if .Values.studio.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.studio.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.studio.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.studio.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/charts/langgraph-cloud/templates/studio/service-account.yaml b/charts/langgraph-cloud/templates/studio/service-account.yaml new file mode 100644 index 0000000..eaf6ebd --- /dev/null +++ b/charts/langgraph-cloud/templates/studio/service-account.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.studio.enabled .Values.studio.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "studio.serviceAccountName" . }} + labels: + {{- include "langGraphCloud.labels" . | nindent 4 }} + {{- with.Values.studio.deployment.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- include "langGraphCloud.annotations" . | nindent 4 }} + {{- with.Values.studio.serviceAccount.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/langgraph-cloud/templates/studio/service.yaml b/charts/langgraph-cloud/templates/studio/service.yaml new file mode 100644 index 0000000..ffa60bd --- /dev/null +++ b/charts/langgraph-cloud/templates/studio/service.yaml @@ -0,0 +1,35 @@ +{{- if .Values.studio.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "langGraphCloud.fullname" . }}-{{ .Values.studio.name }} + labels: + {{- include "langGraphCloud.labels" . | nindent 4 }} + {{- with.Values.studio.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- include "langGraphCloud.annotations" . | nindent 4 }} + {{- with.Values.studio.service.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.studio.service.type }} + {{- with .Values.studio.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml . | nindent 4 }} + {{- end }} + loadBalancerIP: {{ .Values.studio.service.loadBalancerIP }} + ports: + - name: http + port: {{ .Values.studio.service.httpPort }} + targetPort: studio + protocol: TCP + - name: https + port: {{ .Values.studio.service.httpsPort }} + targetPort: studio + protocol: TCP + selector: + {{- include "langGraphCloud.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: {{ include "langGraphCloud.fullname" . }}-{{ .Values.studio.name }} + {{- end }} diff --git a/charts/langgraph-cloud/values.yaml b/charts/langgraph-cloud/values.yaml index 58e5168..3c6a6b8 100644 --- a/charts/langgraph-cloud/values.yaml +++ b/charts/langgraph-cloud/values.yaml @@ -25,6 +25,10 @@ images: repository: "docker.io/redis" pullPolicy: IfNotPresent tag: "6" + studioImage: + repository: "docker.io/langchain/langgraph-debugger" + pullPolicy: Always + tag: "latest" config: existingSecretName: "" @@ -36,7 +40,8 @@ config: ingress: enabled: false - hostname: "" + hostname: "" # Set this to the hostname you want to use for the ingress. Also used as the base URL for studio + studioHostname: "" # Set this to the hostname you want to use for the studio ingress ingressClassName: "" annotations: {} labels: {} @@ -205,3 +210,46 @@ redis: name: "" labels: {} annotations: {} + +studio: + enabled: true + name: "studio" + containerPort: 3968 + deployment: + replicaCount: 1 + labels: {} + annotations: {} + podSecurityContext: {} + securityContext: {} + resources: + limits: + cpu: 1000m + memory: 2Gi + requests: + cpu: 500m + memory: 1Gi + extraEnv: [] + sidecars: [] + nodeSelector: {} + tolerations: [] + affinity: {} + volumes: [] + volumeMounts: [] + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + targetCPUUtilizationPercentage: 80 + service: + type: LoadBalancer + httpPort: 80 + httpsPort: 443 + labels: {} + annotations: {} + loadBalancerSourceRanges: [] + loadBalancerIP: "" + serviceAccount: + create: true + name: "" + labels: {} + annotations: {}