From ccd6e59a8a43c59ed645eb0b11d9717f89db6b24 Mon Sep 17 00:00:00 2001 From: mtrujillo <42344046+trujillm@users.noreply.github.com> Date: Thu, 15 Jan 2026 10:06:39 -0500 Subject: [PATCH 1/8] add logic for edb pull secret --- Makefile | 14 ++- README.md | 15 +++ ansible/playbooks/create-edb-pull-secret.yaml | 109 ++++++++++++++++++ values-secret.yaml.template | 9 ++ 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 ansible/playbooks/create-edb-pull-secret.yaml diff --git a/Makefile b/Makefile index bd6c0aa9..6df26765 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,17 @@ -include Makefile-common - # Azure gpu vars GPU_VM_SIZE ?= Standard_NC8as_T4_v3 GPU_REPLICAS ?= 1 OVERRIDE_ZONE ?= +# Override the install target to include EDB pull secret creation +.PHONY: install +install: create-edb-pull-secret pattern-install ## Installs the pattern onto a cluster (creates EDB pull secret first, then loads secrets) + +.PHONY: create-edb-pull-secret +create-edb-pull-secret: ## Creates the EDB operator pull secret from values-secret.yaml + @echo "Creating EDB Postgres Operator pull secret..." + @ansible-playbook ansible/playbooks/create-edb-pull-secret.yaml + .PHONY: create-gpu-machineset create-gpu-machineset: ## Creates a gpu machineset for AWS ansible-playbook ansible/playbooks/create-gpu-machineset.yaml @@ -13,3 +20,6 @@ create-gpu-machineset: ## Creates a gpu machineset for AWS create-gpu-machineset-azure: ## Creates an Azure GPU machineset (overrides: GPU_VM_SIZE, GPU_REPLICAS, OVERRIDE_ZONE) ansible-playbook ansible/playbooks/create-gpu-machineset-azure.yaml \ -e "gpu_vm_size=$(GPU_VM_SIZE) gpu_replicas=$(GPU_REPLICAS) override_zone=$(OVERRIDE_ZONE)" + +# Include common Makefile targets (after our overrides) +include Makefile-common diff --git a/README.md b/README.md index 00747910..c8d974fc 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,12 @@ OpenShift to generate project proposals for specific Red Hat products. - Red Hat Openshift cluster running in AWS. Supported regions are : us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 sa-east-1 eu-west-1 eu-west-2 eu-west-3 eu-central-1 eu-north-1 ap-northeast-1 ap-northeast-2 ap-northeast-3 ap-southeast-1 ap-southeast-2 ap-south-1. - GPU Node to run Hugging Face Text Generation Inference server on Red Hat OpenShift cluster. - Create a fork of the [rag-llm-gitops](https://github.com/validatedpatterns/rag-llm-gitops.git) Git repository. +- **EDB Postgres Operator Credentials** (Required for default database): The pattern uses the EDB Postgres for Kubernetes operator from the certified-operators catalog by default. This operator requires authentication to pull images from `docker.enterprisedb.com`. You will need to: + 1. Register for a free trial account at [EDB Registration](https://www.enterprisedb.com/accounts/register) + 2. Obtain your subscription token from [EDB Repos Downloads](https://www.enterprisedb.com/repos-downloads) + 3. Add the token to your `values-secret.yaml` file during configuration (see below) + + For more details, see the [EDB Installation Documentation](https://www.enterprisedb.com/docs/postgres_for_kubernetes/latest/installation_upgrade/). ## Demo Description & Architecture @@ -116,6 +122,8 @@ cp values-secret.yaml.template ~/values-secret-rag-llm-gitops.yaml To deploy a model that can requires an Hugging Face token, grab the [Hugging Face token](https://huggingface.co/settings/tokens) and accept the terms and conditions on the model page. Edit ~/values-secret-rag-llm-gitops.yaml to replace the `model Id` and the `Hugging Face` token. +**IMPORTANT**: If you are using the default EDB Postgres database (recommended), you must add your EDB subscription token to the `values-secret.yaml` file: + ```sh secrets: - name: hfmodel @@ -124,6 +132,11 @@ secrets: value: null - name: modelId value: "ibm-granite/granite-3.1-8b-instruct" + - name: edb + fields: + - name: token + value: "YOUR_EDB_TOKEN_HERE" # Replace with your EDB subscription token + description: EDB subscription token for pulling certified operator images - name: minio fields: - name: MINIO_ROOT_USER @@ -133,6 +146,8 @@ secrets: onMissingValue: generate ``` +The EDB token is automatically used during installation to create the required pull secret for the EDB Postgres operator. Without this token, the operator will fail to pull its container image and the database will not be created. + ### Provision GPU MachineSet As a pre-requisite to deploy the application using the validated pattern, GPU nodes should be provisioned along with Node Feature Discovery Operator and NVIDIA GPU operator. To provision GPU Nodes diff --git a/ansible/playbooks/create-edb-pull-secret.yaml b/ansible/playbooks/create-edb-pull-secret.yaml new file mode 100644 index 00000000..c37a22db --- /dev/null +++ b/ansible/playbooks/create-edb-pull-secret.yaml @@ -0,0 +1,109 @@ +--- +- name: Create EDB Postgres Operator Pull Secret + hosts: localhost + connection: local + gather_facts: false + vars: + edb_operator_namespace: openshift-operators + edb_secret_name: postgresql-operator-pull-secret + tasks: + - name: Find values-secret file in home directory + ansible.builtin.find: + paths: "{{ lookup('env', 'HOME') }}" + patterns: "values-secret-*.yaml" + recurse: no + register: values_secret_files + + - name: Set values-secret file path + ansible.builtin.set_fact: + values_secret_file: "{{ values_secret_files.files[0].path }}" + when: values_secret_files.matched > 0 + + - name: Load values-secret.yaml if it exists + ansible.builtin.include_vars: + file: "{{ values_secret_file }}" + name: values_secret_data + when: values_secret_files.matched > 0 + + - name: Extract EDB token from values-secret + ansible.builtin.set_fact: + edb_token: "{{ values_secret_data.secrets | selectattr('name', 'equalto', 'edb') | map(attribute='fields') | flatten | selectattr('name', 'equalto', 'token') | map(attribute='value') | first | default('') }}" + when: + - values_secret_files.matched > 0 + - values_secret_data.secrets is defined + + - name: Check if EDB token is provided + ansible.builtin.debug: + msg: "EDB token is {{ 'configured (' + (edb_token | length | string) + ' chars)' if edb_token and edb_token != 'null' else 'NOT configured' }}" + + - name: Skip secret creation if no token provided + ansible.builtin.debug: + msg: "Skipping EDB pull secret creation - no token configured in values-secret.yaml" + when: not edb_token or edb_token == 'null' or edb_token == '' + + - name: End play if no token + ansible.builtin.meta: end_play + when: not edb_token or edb_token == 'null' or edb_token == '' + + - name: Check if EDB pull secret already exists + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "{{ edb_secret_name }}" + namespace: "{{ edb_operator_namespace }}" + register: existing_secret + + - name: Create EDB pull secret + kubernetes.core.k8s: + state: present + definition: + apiVersion: v1 + kind: Secret + metadata: + name: "{{ edb_secret_name }}" + namespace: "{{ edb_operator_namespace }}" + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: "{{ docker_config | to_json | b64encode }}" + vars: + docker_config: + auths: + docker.enterprisedb.com: + username: "k8s" + password: "{{ edb_token }}" + auth: "{{ ('k8s:' + edb_token) | b64encode }}" + when: existing_secret.resources | length == 0 + + - name: Update existing EDB pull secret if token changed + kubernetes.core.k8s: + state: present + definition: + apiVersion: v1 + kind: Secret + metadata: + name: "{{ edb_secret_name }}" + namespace: "{{ edb_operator_namespace }}" + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: "{{ docker_config | to_json | b64encode }}" + vars: + docker_config: + auths: + docker.enterprisedb.com: + username: "k8s" + password: "{{ edb_token }}" + auth: "{{ ('k8s:' + edb_token) | b64encode }}" + when: existing_secret.resources | length > 0 + + - name: Verify secret was created + kubernetes.core.k8s_info: + api_version: v1 + kind: Secret + name: "{{ edb_secret_name }}" + namespace: "{{ edb_operator_namespace }}" + register: final_secret + + - name: Display success message + ansible.builtin.debug: + msg: "EDB pull secret '{{ edb_secret_name }}' successfully {{ 'created' if existing_secret.resources | length == 0 else 'updated' }} in namespace '{{ edb_operator_namespace }}'" + when: final_secret.resources | length > 0 diff --git a/values-secret.yaml.template b/values-secret.yaml.template index aa526f1b..0007f3ee 100644 --- a/values-secret.yaml.template +++ b/values-secret.yaml.template @@ -10,11 +10,20 @@ version: "2.0" # provide your token as a value for hftoken # NOTE: you need to add value in values-global.yaml as well +# EDB Postgres Operator requires authentication to pull images from docker.enterprisedb.com +# Register for a free trial at: https://www.enterprisedb.com/accounts/register +# Get your token from: https://www.enterprisedb.com/repos-downloads + secrets: - name: hfmodel fields: - name: hftoken value: null + - name: edb + fields: + - name: token + value: null + description: EDB subscription token for pulling certified operator images - name: mssql fields: - name: sa-pass From a3605a0d72487d40de960de2ec1a383fb7cfb7d1 Mon Sep 17 00:00:00 2001 From: mtrujillo <42344046+trujillm@users.noreply.github.com> Date: Thu, 15 Jan 2026 12:33:23 -0500 Subject: [PATCH 2/8] adjusting to use vault logic for edb --- Makefile | 14 +-- README.md | 2 +- ansible/playbooks/create-edb-pull-secret.yaml | 109 ------------------ .../rag-llm/templates/edb-pull-secret.yaml | 25 ++++ charts/all/rag-llm/values.yaml | 3 + 5 files changed, 31 insertions(+), 122 deletions(-) delete mode 100644 ansible/playbooks/create-edb-pull-secret.yaml create mode 100644 charts/all/rag-llm/templates/edb-pull-secret.yaml diff --git a/Makefile b/Makefile index 6df26765..bd6c0aa9 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,10 @@ +include Makefile-common + # Azure gpu vars GPU_VM_SIZE ?= Standard_NC8as_T4_v3 GPU_REPLICAS ?= 1 OVERRIDE_ZONE ?= -# Override the install target to include EDB pull secret creation -.PHONY: install -install: create-edb-pull-secret pattern-install ## Installs the pattern onto a cluster (creates EDB pull secret first, then loads secrets) - -.PHONY: create-edb-pull-secret -create-edb-pull-secret: ## Creates the EDB operator pull secret from values-secret.yaml - @echo "Creating EDB Postgres Operator pull secret..." - @ansible-playbook ansible/playbooks/create-edb-pull-secret.yaml - .PHONY: create-gpu-machineset create-gpu-machineset: ## Creates a gpu machineset for AWS ansible-playbook ansible/playbooks/create-gpu-machineset.yaml @@ -20,6 +13,3 @@ create-gpu-machineset: ## Creates a gpu machineset for AWS create-gpu-machineset-azure: ## Creates an Azure GPU machineset (overrides: GPU_VM_SIZE, GPU_REPLICAS, OVERRIDE_ZONE) ansible-playbook ansible/playbooks/create-gpu-machineset-azure.yaml \ -e "gpu_vm_size=$(GPU_VM_SIZE) gpu_replicas=$(GPU_REPLICAS) override_zone=$(OVERRIDE_ZONE)" - -# Include common Makefile targets (after our overrides) -include Makefile-common diff --git a/README.md b/README.md index c8d974fc..6c38a5dc 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ secrets: onMissingValue: generate ``` -The EDB token is automatically used during installation to create the required pull secret for the EDB Postgres operator. Without this token, the operator will fail to pull its container image and the database will not be created. +The EDB token is synced into Vault and then used by External Secrets to create the required pull secret (`postgresql-operator-pull-secret`) in `openshift-operators`. Without this token, the EDB operator will fail to pull its container image and the database will not be created. ### Provision GPU MachineSet diff --git a/ansible/playbooks/create-edb-pull-secret.yaml b/ansible/playbooks/create-edb-pull-secret.yaml deleted file mode 100644 index c37a22db..00000000 --- a/ansible/playbooks/create-edb-pull-secret.yaml +++ /dev/null @@ -1,109 +0,0 @@ ---- -- name: Create EDB Postgres Operator Pull Secret - hosts: localhost - connection: local - gather_facts: false - vars: - edb_operator_namespace: openshift-operators - edb_secret_name: postgresql-operator-pull-secret - tasks: - - name: Find values-secret file in home directory - ansible.builtin.find: - paths: "{{ lookup('env', 'HOME') }}" - patterns: "values-secret-*.yaml" - recurse: no - register: values_secret_files - - - name: Set values-secret file path - ansible.builtin.set_fact: - values_secret_file: "{{ values_secret_files.files[0].path }}" - when: values_secret_files.matched > 0 - - - name: Load values-secret.yaml if it exists - ansible.builtin.include_vars: - file: "{{ values_secret_file }}" - name: values_secret_data - when: values_secret_files.matched > 0 - - - name: Extract EDB token from values-secret - ansible.builtin.set_fact: - edb_token: "{{ values_secret_data.secrets | selectattr('name', 'equalto', 'edb') | map(attribute='fields') | flatten | selectattr('name', 'equalto', 'token') | map(attribute='value') | first | default('') }}" - when: - - values_secret_files.matched > 0 - - values_secret_data.secrets is defined - - - name: Check if EDB token is provided - ansible.builtin.debug: - msg: "EDB token is {{ 'configured (' + (edb_token | length | string) + ' chars)' if edb_token and edb_token != 'null' else 'NOT configured' }}" - - - name: Skip secret creation if no token provided - ansible.builtin.debug: - msg: "Skipping EDB pull secret creation - no token configured in values-secret.yaml" - when: not edb_token or edb_token == 'null' or edb_token == '' - - - name: End play if no token - ansible.builtin.meta: end_play - when: not edb_token or edb_token == 'null' or edb_token == '' - - - name: Check if EDB pull secret already exists - kubernetes.core.k8s_info: - api_version: v1 - kind: Secret - name: "{{ edb_secret_name }}" - namespace: "{{ edb_operator_namespace }}" - register: existing_secret - - - name: Create EDB pull secret - kubernetes.core.k8s: - state: present - definition: - apiVersion: v1 - kind: Secret - metadata: - name: "{{ edb_secret_name }}" - namespace: "{{ edb_operator_namespace }}" - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: "{{ docker_config | to_json | b64encode }}" - vars: - docker_config: - auths: - docker.enterprisedb.com: - username: "k8s" - password: "{{ edb_token }}" - auth: "{{ ('k8s:' + edb_token) | b64encode }}" - when: existing_secret.resources | length == 0 - - - name: Update existing EDB pull secret if token changed - kubernetes.core.k8s: - state: present - definition: - apiVersion: v1 - kind: Secret - metadata: - name: "{{ edb_secret_name }}" - namespace: "{{ edb_operator_namespace }}" - type: kubernetes.io/dockerconfigjson - data: - .dockerconfigjson: "{{ docker_config | to_json | b64encode }}" - vars: - docker_config: - auths: - docker.enterprisedb.com: - username: "k8s" - password: "{{ edb_token }}" - auth: "{{ ('k8s:' + edb_token) | b64encode }}" - when: existing_secret.resources | length > 0 - - - name: Verify secret was created - kubernetes.core.k8s_info: - api_version: v1 - kind: Secret - name: "{{ edb_secret_name }}" - namespace: "{{ edb_operator_namespace }}" - register: final_secret - - - name: Display success message - ansible.builtin.debug: - msg: "EDB pull secret '{{ edb_secret_name }}' successfully {{ 'created' if existing_secret.resources | length == 0 else 'updated' }} in namespace '{{ edb_operator_namespace }}'" - when: final_secret.resources | length > 0 diff --git a/charts/all/rag-llm/templates/edb-pull-secret.yaml b/charts/all/rag-llm/templates/edb-pull-secret.yaml new file mode 100644 index 00000000..b62d8937 --- /dev/null +++ b/charts/all/rag-llm/templates/edb-pull-secret.yaml @@ -0,0 +1,25 @@ +{{- if eq .Values.global.db.type "EDB" }} +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: edb-operator-pull-secret + namespace: openshift-operators +spec: + refreshInterval: 15s + secretStoreRef: + name: {{ .Values.secretStore.name }} + kind: {{ .Values.secretStore.kind }} + target: + name: postgresql-operator-pull-secret + template: + type: kubernetes.io/dockerconfigjson + engineVersion: v2 + data: + .dockerconfigjson: | + {"auths":{"docker.enterprisedb.com":{"username":"k8s","password":"{{ `{{ .token }}` }}","auth":"{{ `{{ printf \"k8s:%s\" .token | b64enc }}` }}"}}} + data: + - secretKey: token + remoteRef: + key: {{ .Values.edb.key }} + property: token +{{- end }} diff --git a/charts/all/rag-llm/values.yaml b/charts/all/rag-llm/values.yaml index e20629ad..75e21035 100644 --- a/charts/all/rag-llm/values.yaml +++ b/charts/all/rag-llm/values.yaml @@ -240,6 +240,9 @@ secretStore: hfmodel: key: secret/data/hub/hfmodel +edb: + key: secret/data/hub/edb + # Create NetworkPolicy to allow traffic from all namespaces to allow monitoring. Set to false if monitoring is not needed customnetworkpolicy: enabled: true From e13457a05cf2064b79e4e93b5bef74734779f30d Mon Sep 17 00:00:00 2001 From: mtrujillo <42344046+trujillm@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:16:17 -0500 Subject: [PATCH 3/8] Fix edb pull secret template quoting --- charts/all/rag-llm/templates/edb-pull-secret.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/all/rag-llm/templates/edb-pull-secret.yaml b/charts/all/rag-llm/templates/edb-pull-secret.yaml index b62d8937..aa96b574 100644 --- a/charts/all/rag-llm/templates/edb-pull-secret.yaml +++ b/charts/all/rag-llm/templates/edb-pull-secret.yaml @@ -16,7 +16,7 @@ spec: engineVersion: v2 data: .dockerconfigjson: | - {"auths":{"docker.enterprisedb.com":{"username":"k8s","password":"{{ `{{ .token }}` }}","auth":"{{ `{{ printf \"k8s:%s\" .token | b64enc }}` }}"}}} + {"auths":{"docker.enterprisedb.com":{"username":"k8s","password":"{{ `{{ .token }}` }}","auth":"{{ `{{ printf "k8s:%s" .token | b64enc }}` }}"}}} data: - secretKey: token remoteRef: From 7af05bd506ced6057eeabcaed8cb4a929ae3ca10 Mon Sep 17 00:00:00 2001 From: mtrujillo <42344046+trujillm@users.noreply.github.com> Date: Mon, 19 Jan 2026 12:30:50 -0500 Subject: [PATCH 4/8] add update pgvector set as default --- README.md | 6 +- charts/all/rag-llm/charts/pgvector/Chart.yaml | 24 +++++ .../charts/pgvector/templates/_helpers.tpl | 62 +++++++++++++ .../charts/pgvector/templates/configmap.yaml | 20 ++++ .../charts/pgvector/templates/secret.yaml | 15 +++ .../charts/pgvector/templates/service.yaml | 17 ++++ .../pgvector/templates/statefulset.yaml | 93 +++++++++++++++++++ .../all/rag-llm/charts/pgvector/values.yaml | 91 ++++++++++++++++++ charts/all/rag-llm/templates/deployment.yaml | 2 +- .../templates/populate-vectordb-job.yaml | 2 +- values-global.yaml | 5 +- 11 files changed, 330 insertions(+), 7 deletions(-) create mode 100644 charts/all/rag-llm/charts/pgvector/Chart.yaml create mode 100644 charts/all/rag-llm/charts/pgvector/templates/_helpers.tpl create mode 100644 charts/all/rag-llm/charts/pgvector/templates/configmap.yaml create mode 100644 charts/all/rag-llm/charts/pgvector/templates/secret.yaml create mode 100644 charts/all/rag-llm/charts/pgvector/templates/service.yaml create mode 100644 charts/all/rag-llm/charts/pgvector/templates/statefulset.yaml create mode 100644 charts/all/rag-llm/charts/pgvector/values.yaml diff --git a/README.md b/README.md index 6c38a5dc..8f1294b3 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ Alternatiely, follow the [instructions](./GPU_provisioning.md) to manually insta ### Deploy application -***Note:**: This pattern supports three types of vector databases, EDB Postgres for Kubernetes, Elasticsearch and Redis. By default the pattern will deploy EDB Postgres for Kubernetes as a vector DB. To deploy Redis, change the global.db.type to REDIS in [values-global.yaml](./values-global.yaml). +***Note:**: This pattern supports four types of vector databases: EDB Postgres for Kubernetes, PGVector (local chart), Elasticsearch, and Redis. By default the pattern will deploy EDB Postgres for Kubernetes as a vector DB. To deploy PGVector locally, set `global.db.type` to `pgvector` in [values-global.yaml](./values-global.yaml). ```yaml --- @@ -176,10 +176,10 @@ global: useCSV: false syncPolicy: Automatic installPlanApproval: Automatic -# Possible value for db.type = [REDIS, EDB, ELASTIC] +# Possible value for db.type = [REDIS, EDB, ELASTIC, pgvector] db: index: docs - type: EDB # <--- Default is EDB, Change the db type to REDIS for Redis deployment or ELASTIC for Elasticsearch + type: EDB # <--- Default is EDB. Use REDIS, ELASTIC, or pgvector as needed. main: clusterGroupName: hub multiSourceConfig: diff --git a/charts/all/rag-llm/charts/pgvector/Chart.yaml b/charts/all/rag-llm/charts/pgvector/Chart.yaml new file mode 100644 index 00000000..d3e5923e --- /dev/null +++ b/charts/all/rag-llm/charts/pgvector/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: pgvector +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.5.2 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "0.5.2" diff --git a/charts/all/rag-llm/charts/pgvector/templates/_helpers.tpl b/charts/all/rag-llm/charts/pgvector/templates/_helpers.tpl new file mode 100644 index 00000000..64934e6d --- /dev/null +++ b/charts/all/rag-llm/charts/pgvector/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "pgvector.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 "pgvector.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 "pgvector.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "pgvector.labels" -}} +helm.sh/chart: {{ include "pgvector.chart" . }} +{{ include "pgvector.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "pgvector.selectorLabels" -}} +app.kubernetes.io/name: {{ include "pgvector.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "pgvector.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "pgvector.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/all/rag-llm/charts/pgvector/templates/configmap.yaml b/charts/all/rag-llm/charts/pgvector/templates/configmap.yaml new file mode 100644 index 00000000..f6806484 --- /dev/null +++ b/charts/all/rag-llm/charts/pgvector/templates/configmap.yaml @@ -0,0 +1,20 @@ +{{- if eq .Values.global.db.type "pgvector" }} +kind: ConfigMap +apiVersion: v1 +metadata: + name: pgvector-initsql + labels: + {{- include "pgvector.labels" . | nindent 4 }} +data: + init-db.sh: | + #!/bin/bash + set -e + psql -U postgres -c "CREATE DATABASE ${POSTGRES_DBNAME};" + psql -U postgres -d ${POSTGRES_DBNAME} -c "CREATE EXTENSION VECTOR;" + {{- range .Values.extraDatabases }} + psql -U postgres -c "CREATE DATABASE {{ .name }};" + {{- if .vectordb }} + psql -U postgres -d {{ .name }} -c "CREATE EXTENSION VECTOR;" + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/all/rag-llm/charts/pgvector/templates/secret.yaml b/charts/all/rag-llm/charts/pgvector/templates/secret.yaml new file mode 100644 index 00000000..4b761d7e --- /dev/null +++ b/charts/all/rag-llm/charts/pgvector/templates/secret.yaml @@ -0,0 +1,15 @@ +{{- if and (eq .Values.global.db.type "pgvector") .Values.secret.create }} +kind: Secret +apiVersion: v1 +metadata: + name: vectordb-app + labels: + {{- include "pgvector.labels" . | nindent 4 }} +data: + username: {{ .Values.secret.user | b64enc | quote }} + password: {{ .Values.secret.password | b64enc | quote }} + host: {{ default (include "pgvector.fullname" .) .Values.secret.host | b64enc | quote }} + port: {{ .Values.secret.port | b64enc | quote }} + dbname: {{ .Values.secret.dbname | b64enc | quote }} +type: Opaque +{{- end }} diff --git a/charts/all/rag-llm/charts/pgvector/templates/service.yaml b/charts/all/rag-llm/charts/pgvector/templates/service.yaml new file mode 100644 index 00000000..6b6d0e9c --- /dev/null +++ b/charts/all/rag-llm/charts/pgvector/templates/service.yaml @@ -0,0 +1,17 @@ +{{- if eq .Values.global.db.type "pgvector" }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "pgvector.fullname" . }} + labels: + {{- include "pgvector.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "pgvector.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/all/rag-llm/charts/pgvector/templates/statefulset.yaml b/charts/all/rag-llm/charts/pgvector/templates/statefulset.yaml new file mode 100644 index 00000000..6ed9bb85 --- /dev/null +++ b/charts/all/rag-llm/charts/pgvector/templates/statefulset.yaml @@ -0,0 +1,93 @@ +{{- if eq .Values.global.db.type "pgvector" }} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "pgvector.fullname" . }} + labels: + {{- include "pgvector.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "pgvector.selectorLabels" . | nindent 6 }} + {{- with .Values.volumeClaimTemplates }} + volumeClaimTemplates: + {{- toYaml . | nindent 4 }} + {{- end }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "pgvector.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "pgvector.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- with .Values.args }} + args: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + {{- toYaml .Values.env | nindent 12 }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + readinessProbe: + exec: + command: + - /bin/sh + - -c + - | + for db in "$POSTGRES_DBNAME" {{- range .Values.extraDatabases }} "{{ .name }}"{{- end }}; do + pg_isready -U "$POSTGRES_USER" -d "$db" -h 127.0.0.1 -p "$POSTGRES_PORT" || exit 1 + done + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: initdb-volume + configMap: + name: pgvector-initsql +{{- end }} \ No newline at end of file diff --git a/charts/all/rag-llm/charts/pgvector/values.yaml b/charts/all/rag-llm/charts/pgvector/values.yaml new file mode 100644 index 00000000..afa168c1 --- /dev/null +++ b/charts/all/rag-llm/charts/pgvector/values.yaml @@ -0,0 +1,91 @@ +# Default values for pgvector. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: docker.io/pgvector/pgvector + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: pg17 + +imagePullSecrets: [] + +nameOverride: "pgvector" +fullnameOverride: "pgvector" + +serviceAccount: + create: false + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} +securityContext: {} + +service: + type: ClusterIP + port: 5432 + +env: + - name: POSTGRES_USER + valueFrom: + secretKeyRef: + key: username + name: vectordb-app + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + key: password + name: vectordb-app + - name: POSTGRES_PORT + valueFrom: + secretKeyRef: + key: port + name: vectordb-app + - name: POSTGRES_DBNAME + valueFrom: + secretKeyRef: + key: dbname + name: vectordb-app + +resources: {} + +autoscaling: + enabled: false + +volumeClaimTemplates: + - metadata: + name: pg-data + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 5Gi + +volumeMounts: + - mountPath: /docker-entrypoint-initdb.d + name: initdb-volume + - mountPath: /var/lib/postgresql + name: pg-data + +nodeSelector: {} +affinity: {} + +# Secret configuration for pgvector +# These values can be overridden from a parent chart or via --set flags +# Example: helm install ... +# --set pgvector.secret.user=myuser - +# --set pgvector.secret.password=mypass +secret: + create: true + user: postgres + password: rag_password + dbname: rag_blueprint + host: pgvector + port: "5432" + +extraDatabases: [] + #- name: test_db + # vectordb: false diff --git a/charts/all/rag-llm/templates/deployment.yaml b/charts/all/rag-llm/templates/deployment.yaml index 1534476b..6a5ec8ae 100644 --- a/charts/all/rag-llm/templates/deployment.yaml +++ b/charts/all/rag-llm/templates/deployment.yaml @@ -56,7 +56,7 @@ spec: - name: REDIS_SCHEMA value: redis_schema.yaml {{- end }} - {{- if eq .Values.global.db.type "EDB" }} + {{- if or (eq .Values.global.db.type "EDB") (eq .Values.global.db.type "pgvector") }} - name: DB_TYPE value: PGVECTOR - name: DB_USERNAME diff --git a/charts/all/rag-llm/templates/populate-vectordb-job.yaml b/charts/all/rag-llm/templates/populate-vectordb-job.yaml index 46b0813d..b8b074b0 100644 --- a/charts/all/rag-llm/templates/populate-vectordb-job.yaml +++ b/charts/all/rag-llm/templates/populate-vectordb-job.yaml @@ -50,7 +50,7 @@ spec: - name: REDIS_SCHEMA value: redis_schema.yaml {{- end }} - {{- if eq .Values.global.db.type "EDB" }} + {{- if or (eq .Values.global.db.type "EDB") (eq .Values.global.db.type "pgvector") }} - name: DB_TYPE value: "PGVECTOR" - name: DB_USERNAME diff --git a/values-global.yaml b/values-global.yaml index 8943afab..a0823a54 100644 --- a/values-global.yaml +++ b/values-global.yaml @@ -7,13 +7,14 @@ global: installPlanApproval: Automatic # Possible values for RAG vector DB db.type: # REDIS -> Redis (Local chart deploy) - # EDB -> PGVector (Local chart deploy) + # EDB -> PGVector via EDB operator (Local chart deploy) + # pgvector -> PGVector (Local Postgres chart deploy) # ELASTIC -> Elasticsearch (Local chart deploy) # MSSQL -> MS SQL Server (Local chart deploy) # AZURESQL -> Azure SQL (Pre-existing in Azure) db: index: docs - type: EDB + type: pgvector # Models used by the inference service (should be a HuggingFace model ID) model: vllm: ibm-granite/granite-3.3-8b-instruct From eda8effcb030c9c822da1c75ec583f4bf9be7d3c Mon Sep 17 00:00:00 2001 From: mtrujillo <42344046+trujillm@users.noreply.github.com> Date: Mon, 19 Jan 2026 14:16:40 -0500 Subject: [PATCH 5/8] Set db type to EDB for test --- values-global.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/values-global.yaml b/values-global.yaml index a0823a54..3a639a7f 100644 --- a/values-global.yaml +++ b/values-global.yaml @@ -14,7 +14,7 @@ global: # AZURESQL -> Azure SQL (Pre-existing in Azure) db: index: docs - type: pgvector + type: EDB # Models used by the inference service (should be a HuggingFace model ID) model: vllm: ibm-granite/granite-3.3-8b-instruct From 5c27329fbd1567d503bb6571064428a5cfda21c9 Mon Sep 17 00:00:00 2001 From: mtrujillo <42344046+trujillm@users.noreply.github.com> Date: Mon, 19 Jan 2026 16:25:47 -0500 Subject: [PATCH 6/8] adjust to use pgvector default --- values-global.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/values-global.yaml b/values-global.yaml index 3a639a7f..a0823a54 100644 --- a/values-global.yaml +++ b/values-global.yaml @@ -14,7 +14,7 @@ global: # AZURESQL -> Azure SQL (Pre-existing in Azure) db: index: docs - type: EDB + type: pgvector # Models used by the inference service (should be a HuggingFace model ID) model: vllm: ibm-granite/granite-3.3-8b-instruct From 38f05ce35b4eb539e6c91f4ed8300f6edabac0d8 Mon Sep 17 00:00:00 2001 From: mtrujillo <42344046+trujillm@users.noreply.github.com> Date: Mon, 19 Jan 2026 16:30:37 -0500 Subject: [PATCH 7/8] adjust document for pgvector default --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8f1294b3..002db6eb 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ OpenShift to generate project proposals for specific Red Hat products. - Red Hat Openshift cluster running in AWS. Supported regions are : us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 sa-east-1 eu-west-1 eu-west-2 eu-west-3 eu-central-1 eu-north-1 ap-northeast-1 ap-northeast-2 ap-northeast-3 ap-southeast-1 ap-southeast-2 ap-south-1. - GPU Node to run Hugging Face Text Generation Inference server on Red Hat OpenShift cluster. - Create a fork of the [rag-llm-gitops](https://github.com/validatedpatterns/rag-llm-gitops.git) Git repository. -- **EDB Postgres Operator Credentials** (Required for default database): The pattern uses the EDB Postgres for Kubernetes operator from the certified-operators catalog by default. This operator requires authentication to pull images from `docker.enterprisedb.com`. You will need to: +- **EDB Postgres Operator Credentials** (Required only if you select EDB): The EDB Postgres for Kubernetes operator from the certified-operators catalog requires authentication to pull images from `docker.enterprisedb.com`. You will need to: 1. Register for a free trial account at [EDB Registration](https://www.enterprisedb.com/accounts/register) 2. Obtain your subscription token from [EDB Repos Downloads](https://www.enterprisedb.com/repos-downloads) 3. Add the token to your `values-secret.yaml` file during configuration (see below) @@ -122,7 +122,7 @@ cp values-secret.yaml.template ~/values-secret-rag-llm-gitops.yaml To deploy a model that can requires an Hugging Face token, grab the [Hugging Face token](https://huggingface.co/settings/tokens) and accept the terms and conditions on the model page. Edit ~/values-secret-rag-llm-gitops.yaml to replace the `model Id` and the `Hugging Face` token. -**IMPORTANT**: If you are using the default EDB Postgres database (recommended), you must add your EDB subscription token to the `values-secret.yaml` file: +**IMPORTANT**: If you are using EDB Postgres for Kubernetes, you must add your EDB subscription token to the `values-secret.yaml` file: ```sh secrets: @@ -166,7 +166,7 @@ Alternatiely, follow the [instructions](./GPU_provisioning.md) to manually insta ### Deploy application -***Note:**: This pattern supports four types of vector databases: EDB Postgres for Kubernetes, PGVector (local chart), Elasticsearch, and Redis. By default the pattern will deploy EDB Postgres for Kubernetes as a vector DB. To deploy PGVector locally, set `global.db.type` to `pgvector` in [values-global.yaml](./values-global.yaml). +***Note:**: This pattern supports four types of vector databases: PGVector (local chart), EDB Postgres for Kubernetes, Elasticsearch, and Redis. By default the pattern will deploy PGVector as a vector DB. To deploy EDB, set `global.db.type` to `EDB` in [values-global.yaml](./values-global.yaml). ```yaml --- @@ -179,7 +179,7 @@ global: # Possible value for db.type = [REDIS, EDB, ELASTIC, pgvector] db: index: docs - type: EDB # <--- Default is EDB. Use REDIS, ELASTIC, or pgvector as needed. + type: pgvector # <--- Default is pgvector. Use EDB, REDIS, or ELASTIC as needed. main: clusterGroupName: hub multiSourceConfig: From 328f50069860b4aa7640ea39706aa4d3740f4650 Mon Sep 17 00:00:00 2001 From: mtrujillo <42344046+trujillm@users.noreply.github.com> Date: Mon, 19 Jan 2026 16:37:33 -0500 Subject: [PATCH 8/8] update pgvector to uppercase to match others --- README.md | 6 +++--- charts/all/rag-llm/charts/pgvector/templates/configmap.yaml | 2 +- charts/all/rag-llm/charts/pgvector/templates/secret.yaml | 2 +- charts/all/rag-llm/charts/pgvector/templates/service.yaml | 2 +- .../all/rag-llm/charts/pgvector/templates/statefulset.yaml | 2 +- charts/all/rag-llm/templates/deployment.yaml | 2 +- charts/all/rag-llm/templates/populate-vectordb-job.yaml | 2 +- values-global.yaml | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 002db6eb..382a6a72 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ Alternatiely, follow the [instructions](./GPU_provisioning.md) to manually insta ### Deploy application -***Note:**: This pattern supports four types of vector databases: PGVector (local chart), EDB Postgres for Kubernetes, Elasticsearch, and Redis. By default the pattern will deploy PGVector as a vector DB. To deploy EDB, set `global.db.type` to `EDB` in [values-global.yaml](./values-global.yaml). +***Note:**: This pattern supports four types of vector databases: PGVECTOR (local chart), EDB Postgres for Kubernetes, Elasticsearch, and Redis. By default the pattern will deploy PGVECTOR as a vector DB. To deploy EDB, set `global.db.type` to `EDB` in [values-global.yaml](./values-global.yaml). ```yaml --- @@ -176,10 +176,10 @@ global: useCSV: false syncPolicy: Automatic installPlanApproval: Automatic -# Possible value for db.type = [REDIS, EDB, ELASTIC, pgvector] +# Possible value for db.type = [REDIS, EDB, ELASTIC, PGVECTOR] db: index: docs - type: pgvector # <--- Default is pgvector. Use EDB, REDIS, or ELASTIC as needed. + type: PGVECTOR # <--- Default is PGVECTOR. Use EDB, REDIS, or ELASTIC as needed. main: clusterGroupName: hub multiSourceConfig: diff --git a/charts/all/rag-llm/charts/pgvector/templates/configmap.yaml b/charts/all/rag-llm/charts/pgvector/templates/configmap.yaml index f6806484..0ebac895 100644 --- a/charts/all/rag-llm/charts/pgvector/templates/configmap.yaml +++ b/charts/all/rag-llm/charts/pgvector/templates/configmap.yaml @@ -1,4 +1,4 @@ -{{- if eq .Values.global.db.type "pgvector" }} +{{- if eq .Values.global.db.type "PGVECTOR" }} kind: ConfigMap apiVersion: v1 metadata: diff --git a/charts/all/rag-llm/charts/pgvector/templates/secret.yaml b/charts/all/rag-llm/charts/pgvector/templates/secret.yaml index 4b761d7e..d0a92934 100644 --- a/charts/all/rag-llm/charts/pgvector/templates/secret.yaml +++ b/charts/all/rag-llm/charts/pgvector/templates/secret.yaml @@ -1,4 +1,4 @@ -{{- if and (eq .Values.global.db.type "pgvector") .Values.secret.create }} +{{- if and (eq .Values.global.db.type "PGVECTOR") .Values.secret.create }} kind: Secret apiVersion: v1 metadata: diff --git a/charts/all/rag-llm/charts/pgvector/templates/service.yaml b/charts/all/rag-llm/charts/pgvector/templates/service.yaml index 6b6d0e9c..1eed6d7f 100644 --- a/charts/all/rag-llm/charts/pgvector/templates/service.yaml +++ b/charts/all/rag-llm/charts/pgvector/templates/service.yaml @@ -1,4 +1,4 @@ -{{- if eq .Values.global.db.type "pgvector" }} +{{- if eq .Values.global.db.type "PGVECTOR" }} apiVersion: v1 kind: Service metadata: diff --git a/charts/all/rag-llm/charts/pgvector/templates/statefulset.yaml b/charts/all/rag-llm/charts/pgvector/templates/statefulset.yaml index 6ed9bb85..07ae7ace 100644 --- a/charts/all/rag-llm/charts/pgvector/templates/statefulset.yaml +++ b/charts/all/rag-llm/charts/pgvector/templates/statefulset.yaml @@ -1,4 +1,4 @@ -{{- if eq .Values.global.db.type "pgvector" }} +{{- if eq .Values.global.db.type "PGVECTOR" }} apiVersion: apps/v1 kind: StatefulSet metadata: diff --git a/charts/all/rag-llm/templates/deployment.yaml b/charts/all/rag-llm/templates/deployment.yaml index 6a5ec8ae..adaa158d 100644 --- a/charts/all/rag-llm/templates/deployment.yaml +++ b/charts/all/rag-llm/templates/deployment.yaml @@ -56,7 +56,7 @@ spec: - name: REDIS_SCHEMA value: redis_schema.yaml {{- end }} - {{- if or (eq .Values.global.db.type "EDB") (eq .Values.global.db.type "pgvector") }} + {{- if or (eq .Values.global.db.type "EDB") (eq .Values.global.db.type "PGVECTOR") }} - name: DB_TYPE value: PGVECTOR - name: DB_USERNAME diff --git a/charts/all/rag-llm/templates/populate-vectordb-job.yaml b/charts/all/rag-llm/templates/populate-vectordb-job.yaml index b8b074b0..fed9aa0a 100644 --- a/charts/all/rag-llm/templates/populate-vectordb-job.yaml +++ b/charts/all/rag-llm/templates/populate-vectordb-job.yaml @@ -50,7 +50,7 @@ spec: - name: REDIS_SCHEMA value: redis_schema.yaml {{- end }} - {{- if or (eq .Values.global.db.type "EDB") (eq .Values.global.db.type "pgvector") }} + {{- if or (eq .Values.global.db.type "EDB") (eq .Values.global.db.type "PGVECTOR") }} - name: DB_TYPE value: "PGVECTOR" - name: DB_USERNAME diff --git a/values-global.yaml b/values-global.yaml index a0823a54..3f10827b 100644 --- a/values-global.yaml +++ b/values-global.yaml @@ -8,13 +8,13 @@ global: # Possible values for RAG vector DB db.type: # REDIS -> Redis (Local chart deploy) # EDB -> PGVector via EDB operator (Local chart deploy) - # pgvector -> PGVector (Local Postgres chart deploy) + # PGVECTOR -> PGVector (Local Postgres chart deploy) # ELASTIC -> Elasticsearch (Local chart deploy) # MSSQL -> MS SQL Server (Local chart deploy) # AZURESQL -> Azure SQL (Pre-existing in Azure) db: index: docs - type: pgvector + type: PGVECTOR # Models used by the inference service (should be a HuggingFace model ID) model: vllm: ibm-granite/granite-3.3-8b-instruct