Skip to content

Commit 31a351f

Browse files
feat( cluster ): Add support for console stateful set (#782)
Signed-off-by: Philippe Noël <philippemnoel@gmail.com> Signed-off-by: Itay Grudev <itay@verito.digital> Co-authored-by: Itay Grudev <itay@verito.digital>
1 parent 6579321 commit 31a351f

9 files changed

Lines changed: 232 additions & 0 deletions

File tree

charts/cluster/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ refer to the [CloudNativePG Documentation](https://cloudnative-pg.io/documentat
153153
| cluster.affinity | object | `{"topologyKey":"topology.kubernetes.io/zone"}` | Affinity/Anti-affinity rules for Pods. See: https://cloudnative-pg.io/documentation/current/cloudnative-pg.v1/#postgresql-cnpg-io-v1-AffinityConfiguration |
154154
| cluster.annotations | object | `{}` | |
155155
| cluster.certificates | object | `{}` | The configuration for the CA and related certificates. See: https://cloudnative-pg.io/documentation/current/cloudnative-pg.v1/#postgresql-cnpg-io-v1-CertificatesConfiguration |
156+
| cluster.console.enabled | bool | `false` | Deploys a console StatefulSet to run long-running commands against the cluster (e.g. `CREATE INDEX`). |
156157
| cluster.enablePDB | bool | `true` | Allow to disable PDB, mainly useful for upgrade of single-instance clusters or development purposes See: https://cloudnative-pg.io/documentation/current/kubernetes_upgrade/#pod-disruption-budgets |
157158
| cluster.enableSuperuserAccess | bool | `true` | When this option is enabled, the operator will use the SuperuserSecret to update the postgres user password. If the secret is not present, the operator will automatically create one. When this option is disabled, the operator will ignore the SuperuserSecret content, delete it when automatically created, and then blank the password of the postgres user by setting it to NULL. |
158159
| cluster.env | list | `[]` | Env follows the Env format to pass environment variables to the pods created in the cluster |

charts/cluster/docs/Console.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Executing Long-running Tasks
2+
3+
By setting `cluster.console.enabled=true`, the chart deploys a StatefulSet with a console pod for executing long-running tasks. This is useful for tasks that need to run in the background or for batch processing, such as `CREATE INDEX`. The intent is to use this console pod to run commands in the background without maintaining a persistent client connection. Because the console pod is on the cluster, it is less susceptible to network issues.
4+
5+
> [!NOTE]
6+
> We don't provision a PodDisruption Budget (PDB) for the console StatefulSet. Node maintenance or other disruptions may cause the console pod to be evicted, killing your session.
7+
>
8+
> The console pod has `root` access so that you can use `apt install` to install any additional tools you may need. Keep in mind that while the root user home folder (`/root`) is persisted, any tools you install will not be persisted if the pod restarts.
9+
>
10+
> All the utilities in the pod are installed during the pod startup, so it may take a few seconds before they become available, after the pod has restarted.
11+
12+
## Connecting to the Console Pod
13+
14+
To use the console pod, you can run the following command:
15+
16+
```bash
17+
kubectl --namespace <namespace> exec --stdin --tty statefulset/<cluster-name>-console -- bash
18+
```
19+
20+
## Database credentials
21+
22+
We provide the database credentials as environment variables in the console pod. You can access them using:
23+
24+
* `$DB_APP_URI` - Connection URI for the default application user.
25+
* `$DB_SUPERUSER_URI` - Connection URI for the `postgres` superuser.
26+
27+
## Executing queries
28+
29+
To run a command in the background you can use the `nohup` command. For example, to create an index in the background:
30+
31+
```bash
32+
nohup psql "$DB_SUPERUSER_URI/<db-name>" -c "CREATE INDEX orders_idx ON orders USING bm25 (order_id, customer_name) WITH (key_field='order_id');" 2>&1 > command.log &
33+
```
34+
35+
To check on the status of the command, you can use the `tail` command:
36+
37+
```bash
38+
tail -f command.log
39+
```
40+
41+
## Advanced usage with `screen`
42+
43+
You can also use the `screen` utility to run commands in the background and keep them running even if you disconnect from the console pod. Here are some basic commands to get you started:
44+
45+
* Start a new screen session
46+
47+
```bash
48+
screen -S mysession
49+
```
50+
51+
* List all screen sessions
52+
53+
```bash
54+
screen -list
55+
```
56+
57+
* To detach from a screen session without stopping it, press `Ctrl + A`, then `D`.
58+
* You can reattach to a screen session with:
59+
60+
```bash
61+
screen -r mysession
62+
```

charts/cluster/templates/NOTES.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ Get a list of all base backups:
3434
Connect to the cluster's primary instance:
3535
{{ include "cluster.color-info" (printf "kubectl --namespace %s exec --stdin --tty services/%s-rw -- bash" .Release.Namespace (include "cluster.fullname" .)) }}
3636

37+
{{ if .Values.cluster.console.enabled -}}
38+
Connect to the console pod for executing long-running tasks (e.g. `CREATE INDEX`):
39+
{{ include "cluster.color-info" (printf "kubectl --namespace %s exec --stdin --tty statefulsets/%s-console -- bash" .Release.Namespace (include "cluster.fullname" .)) }}
40+
{{- end }}
41+
3742
Configuration
3843
-------------
3944

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
{{- if .Values.cluster.console.enabled }}
2+
apiVersion: apps/v1
3+
kind: StatefulSet
4+
metadata:
5+
name: {{ include "cluster.fullname" $ }}-console
6+
namespace: {{ include "cluster.namespace" $ }}
7+
{{- with .Values.cluster.annotations }}
8+
annotations:
9+
{{- toYaml . | nindent 8 }}
10+
{{- end }}
11+
labels:
12+
{{- include "cluster.labels" . | nindent 4 }}
13+
{{- with .Values.cluster.additionalLabels }}
14+
{{- toYaml . | nindent 4 }}
15+
{{- end }}
16+
app.kubernetes.io/component: console
17+
spec:
18+
replicas: 1
19+
selector:
20+
matchLabels:
21+
{{- include "cluster.selectorLabels" . | nindent 6 }}
22+
app.kubernetes.io/component: console
23+
serviceName: console
24+
volumeClaimTemplates:
25+
- metadata:
26+
name: console-home
27+
spec:
28+
accessModes: [ "ReadWriteOnce" ]
29+
resources:
30+
requests:
31+
storage: 1Gi
32+
template:
33+
metadata:
34+
{{- with .Values.cluster.annotations }}
35+
annotations:
36+
{{- toYaml . | nindent 8 }}
37+
{{- end }}
38+
labels:
39+
{{- include "cluster.labels" . | nindent 8 }}
40+
{{- with .Values.cluster.additionalLabels }}
41+
{{- toYaml . | nindent 8 }}
42+
{{- end }}
43+
app.kubernetes.io/component: console
44+
spec:
45+
terminationGracePeriodSeconds: 2
46+
containers:
47+
- name: console
48+
image: ubuntu:latest
49+
command: [ "sh" ]
50+
args:
51+
- "-c"
52+
- |
53+
apt update
54+
apt install -y postgresql-client
55+
apt install -y screen curl wget jq unzip gzip nano vim util-linux less htop
56+
cat <<EOF > /root/.bashrc
57+
echo -e "\nHere are some examples for connecting and running queries on the cluster:"
58+
echo ' nohup psql \$DB_SUPERUSER_URI"/DB_NAME" -c "SELECT 1;" 2>&1 > command.log &'
59+
echo -e "\nTo check up on the command, use:"
60+
echo " tail -f command.log"
61+
echo -e "\nYou can also use 'screen' for an interactive session. See https://github.com/paradedb/charts/blob/dev/charts/paradedb/docs/long-running-tasks.md for examples."
62+
echo -e "\n"
63+
EOF
64+
sleep infinity
65+
env:
66+
- name: DB_APP_URI
67+
valueFrom:
68+
secretKeyRef:
69+
name: {{ include "cluster.fullname" $ }}-app
70+
key: uri
71+
- name: DB_SUPERUSER_HOST
72+
valueFrom:
73+
secretKeyRef:
74+
name: {{ include "cluster.fullname" $ }}-superuser
75+
key: host
76+
- name: DB_SUPERUSER_PORT
77+
valueFrom:
78+
secretKeyRef:
79+
name: {{ include "cluster.fullname" $ }}-superuser
80+
key: port
81+
- name: DB_SUPERUSER_USER
82+
valueFrom:
83+
secretKeyRef:
84+
name: {{ include "cluster.fullname" $ }}-superuser
85+
key: user
86+
- name: DB_SUPERUSER_PASSWORD
87+
valueFrom:
88+
secretKeyRef:
89+
name: {{ include "cluster.fullname" $ }}-superuser
90+
key: password
91+
- name: DB_SUPERUSER_URI
92+
value: "postgresql://$(DB_SUPERUSER_USER):$(DB_SUPERUSER_PASSWORD)@$(DB_SUPERUSER_HOST):$(DB_SUPERUSER_PORT)"
93+
volumeMounts:
94+
- name: console-home
95+
mountPath: /root
96+
{{- end }}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: postgresql.cnpg.io/v1
2+
kind: Cluster
3+
metadata:
4+
name: console-test-cluster
5+
---
6+
apiVersion: apps/v1
7+
kind: StatefulSet
8+
metadata:
9+
name: console-test-cluster-console
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
type: postgresql
2+
mode: standalone
3+
cluster:
4+
instances: 1
5+
console:
6+
enabled: true
7+
backups:
8+
enabled: false
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
##
2+
# Tests the correct deployment of the console StatefulSet
3+
apiVersion: chainsaw.kyverno.io/v1alpha1
4+
kind: Test
5+
metadata:
6+
name: console-statefulset
7+
spec:
8+
timeouts:
9+
apply: 1s
10+
assert: 10s
11+
cleanup: 1m
12+
exec: 2m
13+
steps:
14+
- name: Install a cluster with a console enabled
15+
try:
16+
- script:
17+
content: |
18+
helm upgrade \
19+
--install \
20+
--namespace $NAMESPACE \
21+
--values ./01-console_test_cluster.yaml \
22+
--wait \
23+
console-test ../../
24+
- assert:
25+
file: ./01-console_test_cluster-assert.yaml
26+
- script:
27+
content: |
28+
kubectl --namespace $NAMESPACE wait --for=condition=ready clusters.postgresql.cnpg.io/console-test-cluster --timeout=60s
29+
kubectl --namespace $NAMESPACE wait --for=condition=ready pod/console-test-cluster-console-0 --timeout=60s
30+
kubectl --namespace $NAMESPACE exec pod/console-test-cluster-console-0 -- bash -c 'while true; do command -v psql && break || sleep 2; done'
31+
echo 'nohup psql $DB_SUPERUSER_URI -c "SELECT PG_SLEEP(120);" 2>&1 > command.log &' | kubectl --namespace $NAMESPACE exec --stdin pod/console-test-cluster-console-0 -- bash &
32+
sleep 60
33+
PSQL_RUNNING=$(kubectl --namespace $NAMESPACE exec statefulsets/console-test-cluster-console -- bash -c 'ps -ef | grep psql | wc -l')
34+
echo "PSQL_RUNNING: $PSQL_RUNNING"
35+
[ $PSQL_RUNNING -gt 3 ] || exit 1
36+
- name: Cleanup
37+
try:
38+
- script:
39+
content: |
40+
helm uninstall --namespace $NAMESPACE console-test

charts/cluster/values.schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,14 @@
187187
"certificates": {
188188
"type": "object"
189189
},
190+
"console": {
191+
"type": "object",
192+
"properties": {
193+
"enabled": {
194+
"type": "boolean"
195+
}
196+
}
197+
},
190198
"enablePDB": {
191199
"type": "boolean"
192200
},

charts/cluster/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,9 @@ cluster:
406406
additionalLabels: {}
407407
annotations: {}
408408

409+
console:
410+
# -- Deploys a console StatefulSet to run long-running commands against the cluster (e.g. `CREATE INDEX`).
411+
enabled: false
409412

410413
backups:
411414
# -- You need to configure backups manually, so backups are disabled by default.

0 commit comments

Comments
 (0)