From 5b0ff2e4fa9e75073f0984e87d26bb2c08ea09fa Mon Sep 17 00:00:00 2001 From: Trayan Azarov Date: Tue, 3 Oct 2023 01:18:34 +0300 Subject: [PATCH] [ENH] Render.com Terraform Blueprint (#1176) ## Description of changes *Summarize the changes made by this PR.* - New functionality - New blueprint for render.com ## Test plan *How are these changes tested?* Manual testing ## Documentation Changes README part of the deployment --- .../deployments/render-terraform/README.md | 118 ++++++++++++++++++ .../deployments/render-terraform/chroma.tf | 88 +++++++++++++ .../render-terraform/sqlite_version.patch | 29 +++++ .../deployments/render-terraform/variables.tf | 70 +++++++++++ 4 files changed, 305 insertions(+) create mode 100644 examples/deployments/render-terraform/README.md create mode 100644 examples/deployments/render-terraform/chroma.tf create mode 100644 examples/deployments/render-terraform/sqlite_version.patch create mode 100644 examples/deployments/render-terraform/variables.tf diff --git a/examples/deployments/render-terraform/README.md b/examples/deployments/render-terraform/README.md new file mode 100644 index 00000000000..eab333cbeea --- /dev/null +++ b/examples/deployments/render-terraform/README.md @@ -0,0 +1,118 @@ +# Render.com Deployment + +This is an example deployment to Render.com using [terraform](https://www.terraform.io/) + +## Requirements + +- [Terraform CLI v1.3.4+](https://developer.hashicorp.com/terraform/tutorials/gcp-get-started/install-cli) +- [Terraform Render provider](https://registry.terraform.io/providers/jackall3n/render/latest/docs) + +## Deployment with terraform + +### 1. Init your terraform state + +```bash +terraform init +``` + +### 3. Deploy your application + +```bash +# Your Render.com API token. IMPORTANT: The API does not work with Free plan. +export TF_VAR_render_api_token= +# Your Render.com user email +export TF_VAR_render_user_email= +#set the chroma release to deploy +export TF_VAR_chroma_release="0.4.13" +# the region to deploy to. At the time of writing only oregon and frankfurt are available +export TF_VAR_region="oregon" +#enable basic auth for the chroma instance +export TF_VAR_enable_auth="true" +#The auth type to use for the chroma instance (token or basic) +export TF_VAR_auth_type="token" +terraform apply -auto-approve +``` + +### 4. Check your public IP and that Chroma is running + +> Note: It might take couple minutes for the instance to boot up + +Get the public IP of your instance (it should also be printed out after successful `terraform apply`): + +```bash +terraform output instance_url +``` + +Check that chroma is running: + +```bash +export instance_public_ip=$(terraform output instance_url | sed 's/"//g') +curl -v $instance_public_ip/api/v1/heartbeat +``` + +#### 4.1 Checking Auth + +##### Token + +When token auth is enabled (this is the default option) you can check the get the credentials from Terraform state by +running: + +```bash +terraform output chroma_auth_token +``` + +You should see something of the form: + +```bash +PVcQ4qUUnmahXwUgAf3UuYZoMlos6MnF +``` + +You can then export these credentials: + +```bash +export CHROMA_AUTH=$(terraform output chroma_auth_token | sed 's/"//g') +``` + +Using the credentials: + +```bash +curl -v $instance_public_ip/api/v1/collections -H "Authorization: Bearer ${CHROMA_AUTH}" +``` + +##### Basic + +When basic auth is enabled you can check the get the credentials from Terraform state by running: + +```bash +terraform output chroma_auth_basic +``` + +You should see something of the form: + +```bash +chroma:VuA8I}QyNrm0@QLq +``` + +You can then export these credentials: + +```bash +export CHROMA_AUTH=$(terraform output chroma_auth_basic | sed 's/"//g') +``` + +Using the credentials: + +```bash +curl -v https://$instance_public_ip:8000/api/v1/collections -u "${CHROMA_AUTH}" +``` + +> Note: Without `-u` you should be getting 401 Unauthorized response + +#### 4.2 SSH to your instance + +To connect to your instance via SSH you need to go to Render.com service dashboard. + +### 5. Destroy your application + +```bash +terraform destroy +``` diff --git a/examples/deployments/render-terraform/chroma.tf b/examples/deployments/render-terraform/chroma.tf new file mode 100644 index 00000000000..a6ef69113a5 --- /dev/null +++ b/examples/deployments/render-terraform/chroma.tf @@ -0,0 +1,88 @@ +terraform { + required_providers { + render = { + source = "jackall3n/render" + version = "~> 1.3.0" + } + } +} + +variable "render_api_token" { + sensitive = true +} + +variable "render_user_email" { + sensitive = true +} + +provider "render" { + api_key = var.render_api_token +} + +data "render_owner" "render_owner" { + email = var.render_user_email +} + +resource "render_service" "chroma" { + name = "chroma" + owner = data.render_owner.render_owner.id + type = "web_service" + auto_deploy = true + + env_vars = concat([{ + key = "IS_PERSISTENT" + value = "1" + }, + { + key = "PERSIST_DIRECTORY" + value = var.chroma_data_volume_mount_path + }, + ], + var.enable_auth? [{ + key = "CHROMA_SERVER_AUTH_CREDENTIALS_PROVIDER" + value = "chromadb.auth.token.TokenConfigServerAuthCredentialsProvider" + }, + { + key = "CHROMA_SERVER_AUTH_CREDENTIALS" + value = "${local.token_auth_credentials.token}" + }, + { + key = "CHROMA_SERVER_AUTH_PROVIDER" + value = var.auth_type + }] : [] + ) + + image = { + owner_id = data.render_owner.render_owner.id + image_path = "${var.chroma_image_reg_url}:${var.chroma_release}" + } + + web_service_details = { + env = "image" + plan = var.render_plan + region = var.region + health_check_path = "/api/v1/heartbeat" + disk = { + name = var.chroma_data_volume_device_name + mount_path = var.chroma_data_volume_mount_path + size_gb = var.chroma_data_volume_size + } + docker = { + command = "uvicorn chromadb.app:app --reload --workers 1 --host 0.0.0.0 --port 80 --log-config chromadb/log_config.yml" + path = "./Dockerfile" + } + } +} + +output "service_id" { + value = render_service.chroma.id +} + +output "instance_url" { + value = render_service.chroma.web_service_details.url +} + +output "chroma_auth_token" { + value = random_password.chroma_token.result + sensitive = true +} diff --git a/examples/deployments/render-terraform/sqlite_version.patch b/examples/deployments/render-terraform/sqlite_version.patch new file mode 100644 index 00000000000..aa19837a916 --- /dev/null +++ b/examples/deployments/render-terraform/sqlite_version.patch @@ -0,0 +1,29 @@ +diff --git a/chromadb/__init__.py b/chromadb/__init__.py +index 0ff5244a..450aaf0d 100644 +--- a/chromadb/__init__.py ++++ b/chromadb/__init__.py +@@ -55,21 +55,9 @@ except ImportError: + IN_COLAB = False + + if sqlite3.sqlite_version_info < (3, 35, 0): +- if IN_COLAB: +- # In Colab, hotswap to pysqlite-binary if it's too old +- import subprocess +- import sys +- +- subprocess.check_call( +- [sys.executable, "-m", "pip", "install", "pysqlite3-binary"] +- ) +- __import__("pysqlite3") +- sys.modules["sqlite3"] = sys.modules.pop("pysqlite3") +- else: +- raise RuntimeError( +- "\033[91mYour system has an unsupported version of sqlite3. Chroma requires sqlite3 >= 3.35.0.\033[0m\n" +- "\033[94mPlease visit https://docs.trychroma.com/troubleshooting#sqlite to learn how to upgrade.\033[0m" +- ) ++ __import__('pysqlite3') ++ import sys ++ sys.modules['sqlite3'] = sys.modules.pop('pysqlite3') + + + def configure(**kwargs) -> None: # type: ignore diff --git a/examples/deployments/render-terraform/variables.tf b/examples/deployments/render-terraform/variables.tf new file mode 100644 index 00000000000..2acde15274a --- /dev/null +++ b/examples/deployments/render-terraform/variables.tf @@ -0,0 +1,70 @@ +variable "chroma_image_reg_url" { + description = "The URL of the chroma-core image registry (e.g. docker.io/chromadb/chroma). The URL must also include the image itself without the tag." + type = string + default = "docker.io/chromadb/chroma" +} + +variable "chroma_release" { + description = "The chroma release to deploy" + type = string + default = "0.4.13" +} + +variable "region" { + type = string + default = "oregon" +} + +variable "render_plan" { + default = "starter" + description = "The Render plan to use. This determines the size of the machine. NOTE: Terraform Render provider uses Render's API which requires at least starter plan." + type = string +} + +variable "enable_auth" { + description = "Enable authentication" + type = bool + default = true // or false depending on your needs +} + +variable "auth_type" { + description = "Authentication type" + type = string + default = "token" // or token depending on your needs + validation { + condition = contains([ "token"], var.auth_type) + error_message = "Only token is supported as auth type" + } +} + +resource "random_password" "chroma_token" { + length = 32 + special = false + lower = true + upper = true +} + + +locals { + token_auth_credentials = { + token = random_password.chroma_token.result + } +} + +variable "chroma_data_volume_size" { + description = "The size of the attached data volume in GB." + type = number + default = 20 +} + +variable "chroma_data_volume_device_name" { + default = "chroma-disk-0" + description = "The device name of the chroma data volume" + type = string +} + +variable "chroma_data_volume_mount_path" { + default = "/chroma-data" + description = "The mount path of the chroma data volume" + type = string +}