StackGres implements the Service Binding specification for provisioned services, making it easy to connect applications to PostgreSQL clusters using a standardized approach.
Service Binding is a Kubernetes specification that standardizes how applications discover and connect to backing services like databases. Instead of manually configuring connection details, applications can automatically bind to services that implement the specification.
Key benefits:
When you create an SGCluster, StackGres automatically creates a binding Secret that conforms to the Service Binding specification.
The binding Secret is referenced in the cluster’s status:
status:
binding:
name: my-cluster-binding
The binding Secret contains all connection information:
| Key | Description | Example |
|---|---|---|
type |
Service type | postgresql |
provider |
Provider name | stackgres |
host |
Database hostname | my-cluster |
port |
Database port | 5432 |
database |
Database name | postgres |
username |
Username | postgres |
password |
Password | <password> |
uri |
Connection URI | postgresql://postgres:pass@my-cluster:5432/postgres |
The Service Binding Operator automatically projects binding information into your application pods.
# Using OperatorHub (OpenShift)
# Or install manually
kubectl apply -f https://github.com/servicebinding/service-binding-controller/releases/latest/download/service-binding-controller.yaml
apiVersion: servicebinding.io/v1beta1
kind: ServiceBinding
metadata:
name: myapp-postgres-binding
spec:
service:
apiVersion: stackgres.io/v1
kind: SGCluster
name: my-cluster
workload:
apiVersion: apps/v1
kind: Deployment
name: myapp
The operator will automatically inject binding information as files in /bindings/<binding-name>/:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
# Bindings are automatically mounted at /bindings/myapp-postgres-binding/
Your application can read connection details from files:
/bindings/myapp-postgres-binding/host/bindings/myapp-postgres-binding/port/bindings/myapp-postgres-binding/username/bindings/myapp-postgres-binding/password/bindings/myapp-postgres-binding/database/bindings/myapp-postgres-binding/uriYou can manually project the binding Secret into your application:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
env:
- name: SERVICE_BINDING_ROOT
value: /bindings
volumeMounts:
- name: postgres-binding
mountPath: /bindings/postgres
readOnly: true
volumes:
- name: postgres-binding
secret:
secretName: my-cluster-binding
Or as environment variables:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DATABASE_HOST
valueFrom:
secretKeyRef:
name: my-cluster-binding
key: host
- name: DATABASE_PORT
valueFrom:
secretKeyRef:
name: my-cluster-binding
key: port
- name: DATABASE_NAME
valueFrom:
secretKeyRef:
name: my-cluster-binding
key: database
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: my-cluster-binding
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: my-cluster-binding
key: password
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: my-cluster-binding
key: uri
You can customize the binding configuration in the SGCluster spec:
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
name: my-cluster
spec:
configurations:
binding:
provider: my-company # Custom provider name (default: stackgres)
database: myappdb # Specific database (default: postgres)
username: myapp # Specific username (default: superuser)
password: # Custom password secret
name: myapp-credentials
key: password
To bind with a non-superuser account:
kubectl exec my-cluster-0 -c postgres-util -- psql << EOF
CREATE USER myapp WITH PASSWORD 'secure_password';
CREATE DATABASE myappdb OWNER myapp;
EOF
apiVersion: v1
kind: Secret
metadata:
name: myapp-credentials
type: Opaque
stringData:
password: secure_password
apiVersion: stackgres.io/v1
kind: SGCluster
metadata:
name: my-cluster
spec:
configurations:
binding:
database: myappdb
username: myapp
password:
name: myapp-credentials
key: password
Many application frameworks support Service Binding natively.
Spring Cloud Bindings automatically detects PostgreSQL bindings:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bindings</artifactId>
</dependency>
No additional configuration needed - Spring Boot will automatically configure the DataSource.
Quarkus supports Service Binding via the quarkus-kubernetes-service-binding extension:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kubernetes-service-binding</artifactId>
</dependency>
Use the kube-service-bindings library:
const { getBinding } = require('kube-service-bindings');
const binding = getBinding('POSTGRESQL');
const connectionString = binding.uri;
Read bindings from the file system:
import os
binding_root = os.environ.get('SERVICE_BINDING_ROOT', '/bindings')
binding_name = 'postgres'
def read_binding(key):
with open(f'{binding_root}/{binding_name}/{key}') as f:
return f.read().strip()
host = read_binding('host')
port = read_binding('port')
database = read_binding('database')
username = read_binding('username')
password = read_binding('password')
connection_string = f"postgresql://{username}:{password}@{host}:{port}/{database}"
View the binding information:
# Get the binding secret name from cluster status
kubectl get sgcluster my-cluster -o jsonpath='{.status.binding.name}'
# View binding contents
kubectl get secret my-cluster-binding -o json | jq -r '.data | to_entries[] | "\(.key): \(.value | @base64d)"'
For applications that need different access levels, create multiple SGClusters or use custom bindings:
# Read-write binding (default)
apiVersion: servicebinding.io/v1beta1
kind: ServiceBinding
metadata:
name: myapp-postgres-rw
spec:
service:
apiVersion: stackgres.io/v1
kind: SGCluster
name: my-cluster
workload:
apiVersion: apps/v1
kind: Deployment
name: myapp
---
# Read-only binding (using replicas service)
apiVersion: v1
kind: Secret
metadata:
name: my-cluster-readonly-binding
type: servicebinding.io/postgresql
stringData:
type: postgresql
provider: stackgres
host: my-cluster-replicas
port: "5432"
database: postgres
username: readonly_user
password: readonly_password