diff --git a/deployment/docker/datamate/docker-compose.yml b/deployment/docker/datamate/docker-compose.yml index 9f3ec006..9d9e0fec 100644 --- a/deployment/docker/datamate/docker-compose.yml +++ b/deployment/docker/datamate/docker-compose.yml @@ -199,6 +199,26 @@ services: # ============================== # Optional: Label Studio (profile: label-studio) # ============================== + label-studio-pgbouncer: + container_name: label-studio-pgbouncer + image: pgbouncer/pgbouncer:latest + restart: on-failure + ports: + - "6432:6432" + environment: + - DATABASES_HOST=datamate-database + - DATABASES_PORT=5432 + - DATABASES_NAME=labelstudio + - DATABASES_USER=postgres + - DATABASES_PASSWORD=${DB_PASSWORD:-password} + - POOL_MODE=transaction + - MAX_CLIENT_CONN=100 + - DEFAULT_POOL_SIZE=20 + - MAX_DB_CONNECTIONS=20 + networks: + - datamate + profiles: [ label-studio ] + label-studio: container_name: label-studio stdin_open: true @@ -212,14 +232,14 @@ services: ports: - "30001:8000" depends_on: - - datamate-database + - label-studio-pgbouncer environment: - DJANGO_DB=default - POSTGRE_NAME=labelstudio - POSTGRE_USER=postgres - POSTGRE_PASSWORD=${DB_PASSWORD:-password} - - POSTGRE_PORT=5432 - - POSTGRE_HOST=datamate-database + - POSTGRE_PORT=6432 + - POSTGRE_HOST=label-studio-pgbouncer - LABEL_STUDIO_HOST=${LABEL_STUDIO_HOST:-} - LOCAL_FILES_SERVING_ENABLED=true - LOCAL_FILES_DOCUMENT_ROOT=/label-studio/local diff --git a/deployment/helm/label-studio/templates/deployment.yaml b/deployment/helm/label-studio/templates/deployment.yaml index 5ef7ec3a..1cbb9029 100644 --- a/deployment/helm/label-studio/templates/deployment.yaml +++ b/deployment/helm/label-studio/templates/deployment.yaml @@ -38,9 +38,9 @@ spec: - name: POSTGRE_PASSWORD value: {{ .Values.env.POSTGRE_PASSWORD | quote }} - name: POSTGRE_PORT - value: {{ .Values.env.POSTGRE_PORT | quote }} + value: {{ if .Values.pgbouncer.enabled }}{{ "6432" | quote }}{{ else }}{{ .Values.env.POSTGRE_PORT | quote }}{{ end }} - name: POSTGRE_HOST - value: {{ .Values.env.POSTGRE_HOST | quote }} + value: {{ if .Values.pgbouncer.enabled }}{{ printf "%s-pgbouncer" (include "label-studio.fullname" .) | quote }}{{ else }}{{ .Values.env.POSTGRE_HOST | quote }}{{ end }} - name: LABEL_STUDIO_HOST value: {{ .Values.env.LABEL_STUDIO_HOST | quote }} - name: LOCAL_FILES_SERVING_ENABLED diff --git a/deployment/helm/label-studio/templates/pgbouncer-deployment.yaml b/deployment/helm/label-studio/templates/pgbouncer-deployment.yaml new file mode 100644 index 00000000..a00aba8b --- /dev/null +++ b/deployment/helm/label-studio/templates/pgbouncer-deployment.yaml @@ -0,0 +1,78 @@ +{{- if .Values.pgbouncer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "label-studio.fullname" . }}-pgbouncer + labels: + app.kubernetes.io/name: {{ include "label-studio.name" .}}-pgbouncer + helm.sh/chart: {{ include "label-studio.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + replicas: {{ .Values.pgbouncer.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "label-studio.name" . }}-pgbouncer + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "label-studio.name" . }}-pgbouncer + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: pgbouncer + {{- if .Values.global.imageRegistry }} + image: "{{ .Values.global.imageRegistry | trimSuffix "/" }}/{{ .Values.pgbouncer.image.repository }}:{{ .Values.pgbouncer.image.tag }}" + {{- else }} + image: "{{ .Values.pgbouncer.image.repository }}:{{ .Values.pgbouncer.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.pgbouncer.image.pullPolicy }} + ports: + - name: pgbouncer + containerPort: 6432 + protocol: TCP + env: + - name: DATABASES_HOST + value: {{ .Values.env.POSTGRE_HOST | quote }} + - name: DATABASES_PORT + value: {{ .Values.env.POSTGRE_PORT | quote }} + - name: DATABASES_NAME + value: {{ .Values.env.POSTGRE_NAME | quote }} + - name: DATABASES_USER + value: {{ .Values.env.POSTGRE_USER | quote }} + - name: DATABASES_PASSWORD + value: {{ .Values.env.POSTGRE_PASSWORD | quote }} + - name: POOL_MODE + value: {{ .Values.pgbouncer.poolMode | quote }} + - name: MAX_CLIENT_CONN + value: {{ .Values.pgbouncer.maxClientConn | quote }} + - name: DEFAULT_POOL_SIZE + value: {{ .Values.pgbouncer.defaultPoolSize | quote }} + - name: MAX_DB_CONNECTIONS + value: {{ .Values.pgbouncer.maxDbConnections | quote }} + livenessProbe: + tcpSocket: + port: 6432 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + tcpSocket: + port: 6432 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + {{- toYaml .Values.pgbouncer.resources | nindent 12 }} + {{- with .Values.pgbouncer.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.pgbouncer.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.pgbouncer.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/deployment/helm/label-studio/templates/pgbouncer-service.yaml b/deployment/helm/label-studio/templates/pgbouncer-service.yaml new file mode 100644 index 00000000..77f1e743 --- /dev/null +++ b/deployment/helm/label-studio/templates/pgbouncer-service.yaml @@ -0,0 +1,21 @@ +{{- if .Values.pgbouncer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "label-studio.fullname" . }}-pgbouncer + labels: + app.kubernetes.io/name: {{ include "label-studio.name" . }}-pgbouncer + helm.sh/chart: {{ include "label-studio.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + type: ClusterIP + ports: + - port: 6432 + targetPort: pgbouncer + protocol: TCP + name: pgbouncer + selector: + app.kubernetes.io/name: {{ include "label-studio.name" . }}-pgbouncer + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/deployment/helm/label-studio/values.yaml b/deployment/helm/label-studio/values.yaml index 08c0ccd2..10b53012 100644 --- a/deployment/helm/label-studio/values.yaml +++ b/deployment/helm/label-studio/values.yaml @@ -66,4 +66,27 @@ datasetVolume: enabled: true claimName: datamate-dataset-pvc # if empty, uses same PVC as persistence or creates a dedicated one +# PgBouncer configuration for connection pooling +pgbouncer: + enabled: true + replicaCount: 1 + + image: + repository: pgbouncer/pgbouncer + tag: "latest" + pullPolicy: IfNotPresent + + # Connection pool settings + poolMode: transaction # transaction, session, or statement + maxClientConn: 100 # Maximum number of client connections + defaultPoolSize: 20 # Default pool size per database (max connections to PostgreSQL) + maxDbConnections: 20 # Maximum database connections (hard limit) + + resources: {} + + nodeSelector: {} + + tolerations: [] + + affinity: {}