From 6d67a6ef655f6d2a2913609884a188c73bb1492a Mon Sep 17 00:00:00 2001 From: Hiranmoy Das Chowdhury <49994927+HiranmoyChowdhury@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:14:20 +0600 Subject: [PATCH] Add Complete PgBouncer Docs (#718) * Signed-off-by: Hiranmoy Das Chowdhury * update-version Signed-off-by: Hiranmoy Das Chowdhury * scaling done Signed-off-by: Hiranmoy Das Chowdhury * autoScaler Signed-off-by: Hiranmoy Das Chowdhury * reconfiguration Signed-off-by: Hiranmoy Das Chowdhury * restart Signed-off-by: Hiranmoy Das Chowdhury * monitoring Signed-off-by: Hiranmoy Das Chowdhury * Signed-off-by: Hiranmoy Das Chowdhury * all completed until custom version Signed-off-by: Hiranmoy Das Chowdhury * update version svg Signed-off-by: Hiranmoy Das Chowdhury * completed till update-version Signed-off-by: Hiranmoy Das Chowdhury * Horizontal scaling done Signed-off-by: Hiranmoy Das Chowdhury * vertical scaling done fully Signed-off-by: Hiranmoy Das Chowdhury * autoscaling all done Signed-off-by: Hiranmoy Das Chowdhury * all done for reconfiguration Signed-off-by: Hiranmoy Das Chowdhury * restart done Signed-off-by: Hiranmoy Das Chowdhury * duplication removed Signed-off-by: Hiranmoy Das Chowdhury * build fixed Signed-off-by: Hiranmoy Das Chowdhury * remove reconfigure tls Signed-off-by: Hiranmoy Das Chowdhury * image added for monitoring Signed-off-by: Hiranmoy Das Chowdhury * pgbouncer wiki change Signed-off-by: Hiranmoy Das Chowdhury * autoscaling issue fixed Signed-off-by: Hiranmoy Das Chowdhury * test Signed-off-by: Hiranmoy Das Chowdhury * test 2 Signed-off-by: Hiranmoy Das Chowdhury * test 3 Signed-off-by: Hiranmoy Das Chowdhury * update version camel case removed Signed-off-by: Hiranmoy Das Chowdhury * monitoring part is done Signed-off-by: Hiranmoy Das Chowdhury * image changes for monitoring Signed-off-by: Hiranmoy Das Chowdhury * camecase solved Signed-off-by: Hiranmoy Das Chowdhury --------- Signed-off-by: Hiranmoy Das Chowdhury --- .../compute/pgbouncer-autoscale.yaml | 23 + .../compute/pgbouncer-autoscaler.yaml | 21 + .../reconfigure/pb-custom-config.yaml | 22 + .../reconfigure/pbops-reconfigure-apply.yaml | 17 + .../reconfigure/pbops-reconfigure.yaml | 15 + docs/examples/pgbouncer/restart/ops.yaml | 11 + .../examples/pgbouncer/restart/pgbouncer.yaml | 23 + .../scaling/horizontal-scaling-down-ops.yaml | 11 + .../scaling/horizontal-scaling-ops.yaml | 11 + .../pgbouncer/scaling/pb-horizontal.yaml | 23 + .../pgbouncer/scaling/pb-vertical-ops.yaml | 20 + .../pgbouncer/scaling/pb-vertical.yaml | 23 + .../pgbouncer/sync-users/pgbouncer-sync.yaml | 15 + .../examples/pgbouncer/sync-users/secret.yaml | 11 + .../pgbouncer/update-version/pb-update.yaml | 23 + .../update-version/pbops-update.yaml | 11 + docs/guides/pgbouncer/README.md | 23 +- docs/guides/pgbouncer/autoscaler/_index.md | 10 + .../pgbouncer/autoscaler/compute/_index.md | 10 + .../autoscaler/compute/compute-autoscale.md | 434 ++++++++++++++ .../pgbouncer/autoscaler/compute/overview.md | 55 ++ docs/guides/pgbouncer/concepts/appbinding.md | 4 +- docs/guides/pgbouncer/concepts/autoscaler.md | 73 +++ docs/guides/pgbouncer/concepts/opsrequest.md | 263 ++++++++ docs/guides/pgbouncer/concepts/pgbouncer.md | 2 +- .../guides/pgbouncer/custom-versions/setup.md | 12 +- docs/guides/pgbouncer/monitoring/_index.md | 2 +- docs/guides/pgbouncer/monitoring/overview.md | 54 +- .../monitoring/setup-grafana-dashboard.md | 117 ---- .../monitoring/using-builtin-prometheus.md | 115 ++-- .../monitoring/using-prometheus-operator.md | 321 ++++++---- .../guides/pgbouncer/quickstart/quickstart.md | 8 +- docs/guides/pgbouncer/reconfigure/_index.md | 10 + docs/guides/pgbouncer/reconfigure/overview.md | 54 ++ .../reconfigure/reconfigure-pgbouncer.md | 563 ++++++++++++++++++ docs/guides/pgbouncer/restart/_index.md | 10 + docs/guides/pgbouncer/restart/restart.md | 189 ++++++ docs/guides/pgbouncer/scaling/_index.md | 10 + .../scaling/horizontal-scaling/_index.md | 10 + .../horizontal-scaling/horizontal-ops.md | 396 ++++++++++++ .../scaling/horizontal-scaling/overview.md | 54 ++ .../scaling/vertical-scaling/_index.md | 10 + .../scaling/vertical-scaling/overview.md | 54 ++ .../scaling/vertical-scaling/vertical-ops.md | 304 ++++++++++ docs/guides/pgbouncer/sync-users/_index.md | 10 + .../sync-users/sync-users-pgbouncer.md | 195 ++++++ .../guides/pgbouncer/update-version/_index.md | 10 + .../pgbouncer/update-version/overview.md | 54 ++ .../update-version/update_version.md | 275 +++++++++ .../day-2-operation/pgbouncer/autoscaling.png | Bin 0 -> 49475 bytes .../pgbouncer/horizontal-scaling.png | Bin 0 -> 44824 bytes .../pgbouncer/prometheus-operator.png | Bin 0 -> 72921 bytes .../pgbouncer/reconfiguring.png | Bin 0 -> 43893 bytes .../pgbouncer/update-version.svg | 103 ++++ .../pgbouncer/vertical-scaling.svg | 104 ++++ .../monitoring/pb-builtin-prom-target.png | Bin 52431 -> 56304 bytes 56 files changed, 3850 insertions(+), 348 deletions(-) create mode 100644 docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscale.yaml create mode 100644 docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscaler.yaml create mode 100644 docs/examples/pgbouncer/reconfigure/pb-custom-config.yaml create mode 100644 docs/examples/pgbouncer/reconfigure/pbops-reconfigure-apply.yaml create mode 100644 docs/examples/pgbouncer/reconfigure/pbops-reconfigure.yaml create mode 100644 docs/examples/pgbouncer/restart/ops.yaml create mode 100644 docs/examples/pgbouncer/restart/pgbouncer.yaml create mode 100644 docs/examples/pgbouncer/scaling/horizontal-scaling-down-ops.yaml create mode 100644 docs/examples/pgbouncer/scaling/horizontal-scaling-ops.yaml create mode 100644 docs/examples/pgbouncer/scaling/pb-horizontal.yaml create mode 100644 docs/examples/pgbouncer/scaling/pb-vertical-ops.yaml create mode 100644 docs/examples/pgbouncer/scaling/pb-vertical.yaml create mode 100644 docs/examples/pgbouncer/sync-users/pgbouncer-sync.yaml create mode 100644 docs/examples/pgbouncer/sync-users/secret.yaml create mode 100644 docs/examples/pgbouncer/update-version/pb-update.yaml create mode 100644 docs/examples/pgbouncer/update-version/pbops-update.yaml create mode 100644 docs/guides/pgbouncer/autoscaler/_index.md create mode 100644 docs/guides/pgbouncer/autoscaler/compute/_index.md create mode 100644 docs/guides/pgbouncer/autoscaler/compute/compute-autoscale.md create mode 100644 docs/guides/pgbouncer/autoscaler/compute/overview.md create mode 100644 docs/guides/pgbouncer/concepts/autoscaler.md create mode 100644 docs/guides/pgbouncer/concepts/opsrequest.md delete mode 100644 docs/guides/pgbouncer/monitoring/setup-grafana-dashboard.md create mode 100644 docs/guides/pgbouncer/reconfigure/_index.md create mode 100644 docs/guides/pgbouncer/reconfigure/overview.md create mode 100644 docs/guides/pgbouncer/reconfigure/reconfigure-pgbouncer.md create mode 100644 docs/guides/pgbouncer/restart/_index.md create mode 100644 docs/guides/pgbouncer/restart/restart.md create mode 100644 docs/guides/pgbouncer/scaling/_index.md create mode 100644 docs/guides/pgbouncer/scaling/horizontal-scaling/_index.md create mode 100644 docs/guides/pgbouncer/scaling/horizontal-scaling/horizontal-ops.md create mode 100644 docs/guides/pgbouncer/scaling/horizontal-scaling/overview.md create mode 100644 docs/guides/pgbouncer/scaling/vertical-scaling/_index.md create mode 100644 docs/guides/pgbouncer/scaling/vertical-scaling/overview.md create mode 100644 docs/guides/pgbouncer/scaling/vertical-scaling/vertical-ops.md create mode 100755 docs/guides/pgbouncer/sync-users/_index.md create mode 100644 docs/guides/pgbouncer/sync-users/sync-users-pgbouncer.md create mode 100644 docs/guides/pgbouncer/update-version/_index.md create mode 100644 docs/guides/pgbouncer/update-version/overview.md create mode 100644 docs/guides/pgbouncer/update-version/update_version.md create mode 100644 docs/images/day-2-operation/pgbouncer/autoscaling.png create mode 100644 docs/images/day-2-operation/pgbouncer/horizontal-scaling.png create mode 100644 docs/images/day-2-operation/pgbouncer/prometheus-operator.png create mode 100644 docs/images/day-2-operation/pgbouncer/reconfiguring.png create mode 100644 docs/images/day-2-operation/pgbouncer/update-version.svg create mode 100644 docs/images/day-2-operation/pgbouncer/vertical-scaling.svg diff --git a/docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscale.yaml b/docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscale.yaml new file mode 100644 index 0000000000..d7cf7c1c11 --- /dev/null +++ b/docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscale.yaml @@ -0,0 +1,23 @@ +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pgbouncer-autoscale + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscaler.yaml b/docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscaler.yaml new file mode 100644 index 0000000000..37df8e5a77 --- /dev/null +++ b/docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscaler.yaml @@ -0,0 +1,21 @@ +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: PgBouncerAutoscaler +metadata: + name: pgbouncer-autoscale-ops + namespace: demo +spec: + databaseRef: + name: pgbouncer-autoscale + compute: + pgbouncer: + trigger: "On" + podLifeTimeThreshold: 5m + resourceDiffPercentage: 20 + minAllowed: + cpu: 400m + memory: 400Mi + maxAllowed: + cpu: 1 + memory: 1Gi + controlledResources: ["cpu", "memory"] + containerControlledValues: "RequestsAndLimits" \ No newline at end of file diff --git a/docs/examples/pgbouncer/reconfigure/pb-custom-config.yaml b/docs/examples/pgbouncer/reconfigure/pb-custom-config.yaml new file mode 100644 index 0000000000..1851b3492d --- /dev/null +++ b/docs/examples/pgbouncer/reconfigure/pb-custom-config.yaml @@ -0,0 +1,22 @@ +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pb-custom + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/pgbouncer/reconfigure/pbops-reconfigure-apply.yaml b/docs/examples/pgbouncer/reconfigure/pbops-reconfigure-apply.yaml new file mode 100644 index 0000000000..867d1a4393 --- /dev/null +++ b/docs/examples/pgbouncer/reconfigure/pbops-reconfigure-apply.yaml @@ -0,0 +1,17 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pbops-reconfigure-apply + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: pb-custom + configuration: + pgbouncer: + applyConfig: + pgbouncer.ini: |- + [pgbouncer] + auth_type=scram-sha-256 + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/pgbouncer/reconfigure/pbops-reconfigure.yaml b/docs/examples/pgbouncer/reconfigure/pbops-reconfigure.yaml new file mode 100644 index 0000000000..705f385a0f --- /dev/null +++ b/docs/examples/pgbouncer/reconfigure/pbops-reconfigure.yaml @@ -0,0 +1,15 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pbops-reconfigure + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: pb-custom + configuration: + pgbouncer: + configSecret: + name: new-custom-config + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/pgbouncer/restart/ops.yaml b/docs/examples/pgbouncer/restart/ops.yaml new file mode 100644 index 0000000000..cff7b49016 --- /dev/null +++ b/docs/examples/pgbouncer/restart/ops.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: restart-pgbouncer + namespace: demo +spec: + type: Restart + databaseRef: + name: pgbouncer + timeout: 3m + apply: Always \ No newline at end of file diff --git a/docs/examples/pgbouncer/restart/pgbouncer.yaml b/docs/examples/pgbouncer/restart/pgbouncer.yaml new file mode 100644 index 0000000000..30d3b3cfc4 --- /dev/null +++ b/docs/examples/pgbouncer/restart/pgbouncer.yaml @@ -0,0 +1,23 @@ +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pgbouncer + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/pgbouncer/scaling/horizontal-scaling-down-ops.yaml b/docs/examples/pgbouncer/scaling/horizontal-scaling-down-ops.yaml new file mode 100644 index 0000000000..7447bb29e8 --- /dev/null +++ b/docs/examples/pgbouncer/scaling/horizontal-scaling-down-ops.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-horizontal-scale-down + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: pb-horizontal + horizontalScaling: + replicas: 2 \ No newline at end of file diff --git a/docs/examples/pgbouncer/scaling/horizontal-scaling-ops.yaml b/docs/examples/pgbouncer/scaling/horizontal-scaling-ops.yaml new file mode 100644 index 0000000000..75dc3397f1 --- /dev/null +++ b/docs/examples/pgbouncer/scaling/horizontal-scaling-ops.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-horizontal-scale-up + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: pb-horizontal + horizontalScaling: + replicas: 3 \ No newline at end of file diff --git a/docs/examples/pgbouncer/scaling/pb-horizontal.yaml b/docs/examples/pgbouncer/scaling/pb-horizontal.yaml new file mode 100644 index 0000000000..512304f102 --- /dev/null +++ b/docs/examples/pgbouncer/scaling/pb-horizontal.yaml @@ -0,0 +1,23 @@ +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pb-horizontal + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/pgbouncer/scaling/pb-vertical-ops.yaml b/docs/examples/pgbouncer/scaling/pb-vertical-ops.yaml new file mode 100644 index 0000000000..cf24a4b110 --- /dev/null +++ b/docs/examples/pgbouncer/scaling/pb-vertical-ops.yaml @@ -0,0 +1,20 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-scale-vertical + namespace: demo +spec: + type: VerticalScaling + databaseRef: + name: pb-vertical + verticalScaling: + pgbouncer: + resources: + requests: + memory: "2Gi" + cpu: "1" + limits: + memory: "2Gi" + cpu: "1" + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/pgbouncer/scaling/pb-vertical.yaml b/docs/examples/pgbouncer/scaling/pb-vertical.yaml new file mode 100644 index 0000000000..97c25040b9 --- /dev/null +++ b/docs/examples/pgbouncer/scaling/pb-vertical.yaml @@ -0,0 +1,23 @@ +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pb-vertical + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/pgbouncer/sync-users/pgbouncer-sync.yaml b/docs/examples/pgbouncer/sync-users/pgbouncer-sync.yaml new file mode 100644 index 0000000000..8aae37078b --- /dev/null +++ b/docs/examples/pgbouncer/sync-users/pgbouncer-sync.yaml @@ -0,0 +1,15 @@ +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pgbouncer-sync + namespace: demo +spec: + version: "1.23.1" + replicas: 1 + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/pgbouncer/sync-users/secret.yaml b/docs/examples/pgbouncer/sync-users/secret.yaml new file mode 100644 index 0000000000..f4b0e86148 --- /dev/null +++ b/docs/examples/pgbouncer/sync-users/secret.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: ha-postgres + app.kubernetes.io/name: postgreses.kubedb.com + name: sync-secret + namespace: demo +stringData: + password: "12345" + username: "john" \ No newline at end of file diff --git a/docs/examples/pgbouncer/update-version/pb-update.yaml b/docs/examples/pgbouncer/update-version/pb-update.yaml new file mode 100644 index 0000000000..c5128d899d --- /dev/null +++ b/docs/examples/pgbouncer/update-version/pb-update.yaml @@ -0,0 +1,23 @@ +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pb-update + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/pgbouncer/update-version/pbops-update.yaml b/docs/examples/pgbouncer/update-version/pbops-update.yaml new file mode 100644 index 0000000000..aef1210119 --- /dev/null +++ b/docs/examples/pgbouncer/update-version/pbops-update.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-version-update + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: pb-update + updateVersion: + targetVersion: 1.23.1 \ No newline at end of file diff --git a/docs/guides/pgbouncer/README.md b/docs/guides/pgbouncer/README.md index c3ed534ed4..b64cf5f4bb 100644 --- a/docs/guides/pgbouncer/README.md +++ b/docs/guides/pgbouncer/README.md @@ -23,14 +23,21 @@ KubeDB operator now comes bundled with PgBouncer crd to handle connection poolin ## PgBouncer Features -| Features | Availability | -|------------------------------------|:------------:| -| Clustering | ✓ | -| Multiple PgBouncer Versions | ✓ | -| Customizable Pooling Configuration | ✓ | -| Custom docker images | ✓ | -| Builtin Prometheus Discovery | ✓ | -| Using Prometheus operator | ✓ | +| Features | Availability | +|-------------------------------------------------------------| :----------: | +| Multiple PgBouncer Versions | ✓ | +| Custom Configuration | ✓ | +| Externally manageable Auth Secret | ✓ | +| Reconfigurable Health Checker | ✓ | +| Integrate with externally managed PostgreSQL | ✓ | +| Sync Postgres Users to PgBouncer | ✓ | +| Custom docker images | ✓ | +| TLS: Add ( [Cert Manager]((https://cert-manager.io/docs/))) | ✓ | +| Monitoring with Prometheus & Grafana | ✓ | +| Builtin Prometheus Discovery | ✓ | +| Using Prometheus operator | ✓ | +| Alert Dashboard | ✓ | +| Grafana Dashboard | ✓ | ## User Guide diff --git a/docs/guides/pgbouncer/autoscaler/_index.md b/docs/guides/pgbouncer/autoscaler/_index.md new file mode 100644 index 0000000000..089e262d65 --- /dev/null +++ b/docs/guides/pgbouncer/autoscaler/_index.md @@ -0,0 +1,10 @@ +--- +title: Autoscaling +menu: + docs_{{ .version }}: + identifier: pb-auto-scaling + name: Autoscaling + parent: pb-pgbouncer-guides + weight: 46 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/pgbouncer/autoscaler/compute/_index.md b/docs/guides/pgbouncer/autoscaler/compute/_index.md new file mode 100644 index 0000000000..67db417dd2 --- /dev/null +++ b/docs/guides/pgbouncer/autoscaler/compute/_index.md @@ -0,0 +1,10 @@ +--- +title: Compute Autoscaling +menu: + docs_{{ .version }}: + identifier: pb-compute-auto-scaling + name: Compute Autoscaling + parent: pb-auto-scaling + weight: 10 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/pgbouncer/autoscaler/compute/compute-autoscale.md b/docs/guides/pgbouncer/autoscaler/compute/compute-autoscale.md new file mode 100644 index 0000000000..a137dfa447 --- /dev/null +++ b/docs/guides/pgbouncer/autoscaler/compute/compute-autoscale.md @@ -0,0 +1,434 @@ +--- +title: PgBouncer Autoscaling +menu: + docs_{{ .version }}: + identifier: pb-auto-scaling-pgbouncer + name: pgbouncerCompute + parent: pb-compute-auto-scaling + weight: 15 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Autoscaling the Compute Resource of a PgBouncer + +This guide will show you how to use `KubeDB` to autoscale compute resources i.e. cpu and memory of a PgBouncer. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. + +- Install `KubeDB` Provisioner, Ops-manager and Autoscaler operator in your cluster following the steps [here](/docs/setup/README.md). + +- Install `Metrics Server` from [here](https://github.com/kubernetes-sigs/metrics-server#installation) + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerAutoscaler](/docs/guides/pgbouncer/concepts/autoscaler.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + - [Compute Resource Autoscaling Overview](/docs/guides/pgbouncer/autoscaler/compute/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/pgbouncer](/docs/examples/pgbouncer) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Autoscaling of PgBouncer + +### Prepare Postgres +Prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. + +Here, we are going to deploy a `PgBouncer` standalone using a supported version by `KubeDB` operator. Then we are going to apply `PgBouncerAutoscaler` to set up autoscaling. + +#### Deploy PgBouncer + +In this section, we are going to deploy a PgBouncer with version `1.18.0` Then, in the next section we will set up autoscaling for this pgbouncer using `PgBouncerAutoscaler` CRD. Below is the YAML of the `PgBouncer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pgbouncer-autoscale + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut +``` + +Let's create the `PgBouncer` CRO we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscale.yaml +pgbouncer.kubedb.com/pgbouncer-autoscale created +``` + +Now, wait until `pgbouncer-autoscale` has status `Ready`. i.e, + +```bash +$ kubectl get pb -n demo +NAME TYPE VERSION STATUS AGE +pgbouncer-autoscale kubedb.com/v1 1.18.0 Ready 22s +``` + +Let's check the Pod containers resources, + +```bash +$ kubectl get pod -n demo pgbouncer-autoscale-0 -o json | jq '.spec.containers[].resources' +{ + "limits": { + "memory": "300Mi" + }, + "requests": { + "cpu": "200m", + "memory": "300Mi" + } +} +``` + +Let's check the PgBouncer resources, +```bash +$ kubectl get pgbouncer -n demo pgbouncer-autoscale -o json | jq '.spec.podTemplate.spec.containers[0].resources' +{ + "limits": { + "memory": "300Mi" + }, + "requests": { + "cpu": "200m", + "memory": "300Mi" + } +} +``` + +You can see from the above outputs that the resources are same as the one we have assigned while deploying the pgbouncer. + +We are now ready to apply the `PgBouncerAutoscaler` CRO to set up autoscaling for this database. + +### Compute Resource Autoscaling + +Here, we are going to set up compute (cpu and memory) autoscaling using a PgBouncerAutoscaler Object. + +#### Create PgBouncerAutoscaler Object + +In order to set up compute resource autoscaling for this pgbouncer, we have to create a `PgBouncerAutoscaler` CRO with our desired configuration. Below is the YAML of the `PgBouncerAutoscaler` object that we are going to create, + +```yaml +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: PgBouncerAutoscaler +metadata: + name: pgbouncer-autoscale-ops + namespace: demo +spec: + databaseRef: + name: pgbouncer-autoscale + compute: + pgbouncer: + trigger: "On" + podLifeTimeThreshold: 5m + resourceDiffPercentage: 20 + minAllowed: + cpu: 400m + memory: 400Mi + maxAllowed: + cpu: 1 + memory: 1Gi + controlledResources: ["cpu", "memory"] + containerControlledValues: "RequestsAndLimits" +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing compute resource autoscaling on `pgbouncer-autoscale`. +- `spec.compute.pgbouncer.trigger` specifies that compute resource autoscaling is enabled for this pgbouncer. +- `spec.compute.pgbouncer.podLifeTimeThreshold` specifies the minimum lifetime for at least one of the pod to initiate a vertical scaling. +- `spec.compute.replicaset.resourceDiffPercentage` specifies the minimum resource difference in percentage. The default is 10%. + If the difference between current & recommended resource is less than ResourceDiffPercentage, Autoscaler Operator will ignore the updating. +- `spec.compute.pgbouncer.minAllowed` specifies the minimum allowed resources for this pgbouncer. +- `spec.compute.pgbouncer.maxAllowed` specifies the maximum allowed resources for this pgbouncer. +- `spec.compute.pgbouncer.controlledResources` specifies the resources that are controlled by the autoscaler. +- `spec.compute.pgbouncer.containerControlledValues` specifies which resource values should be controlled. The default is "RequestsAndLimits". +- `spec.opsRequestOptions` contains the options to pass to the created OpsRequest. It has 2 fields. Know more about them here : [timeout](/docs/guides/pgbouncer/concepts/opsrequest.md#spectimeout), [apply](/docs/guides/pgbouncer/concepts/opsrequest.md#specapply). + +Let's create the `PgBouncerAutoscaler` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/autoscaling/compute/pgbouncer-autoscaler.yaml +pgbouncerautoscaler.autoscaling.kubedb.com/pgbouncer-autoscaler-ops created +``` + +#### Verify Autoscaling is set up successfully + +Let's check that the `pgbouncerautoscaler` resource is created successfully, + +```bash +$ kubectl get pgbouncerautoscaler -n demo +NAME AGE +pgbouncer-autoscale-ops 6m55s + +$ kubectl describe pgbouncerautoscaler pgbouncer-autoscale-ops -n demo +Name: pgbouncer-autoscale-ops +Namespace: demo +Labels: +Annotations: +API Version: autoscaling.kubedb.com/v1alpha1 +Kind: PgBouncerAutoscaler +Metadata: + Creation Timestamp: 2024-07-17T12:09:17Z + Generation: 1 + Resource Version: 81569 + UID: 3841c30b-3b19-4740-82f5-bf8e257ddc18 +Spec: + Compute: + PgBouncer: + Container Controlled Values: RequestsAndLimits + Controlled Resources: + cpu + memory + Max Allowed: + Cpu: 1 + Memory: 1Gi + Min Allowed: + Cpu: 400m + Memory: 400Mi + Pod Life Time Threshold: 5m0s + Resource Diff Percentage: 20 + Trigger: On + Database Ref: + Name: pgbouncer-autoscale + Ops Request Options: + Apply: IfReady +Status: + Checkpoints: + Cpu Histogram: + Bucket Weights: + Index: 0 + Weight: 10000 + Reference Timestamp: 2024-07-17T12:10:00Z + Total Weight: 0.8733542386168607 + First Sample Start: 2024-07-17T12:09:14Z + Last Sample Start: 2024-07-17T12:15:06Z + Last Update Time: 2024-07-17T12:15:38Z + Memory Histogram: + Bucket Weights: + Index: 11 + Weight: 10000 + Reference Timestamp: 2024-07-17T12:15:00Z + Total Weight: 0.7827734162991002 + Ref: + Container Name: pgbouncer + Vpa Object Name: pgbouncer-autoscale + Total Samples Count: 6 + Version: v3 + Conditions: + Last Transition Time: 2024-07-17T12:10:37Z + Message: Successfully created PgBouncerOpsRequest demo/pbops-pgbouncer-autoscale-zzell6 + Observed Generation: 1 + Reason: CreateOpsRequest + Status: True + Type: CreateOpsRequest + Vpas: + Conditions: + Last Transition Time: 2024-07-17T12:09:37Z + Status: True + Type: RecommendationProvided + Recommendation: + Container Recommendations: + Container Name: pgbouncer + Lower Bound: + Cpu: 400m + Memory: 400Mi + Target: + Cpu: 400m + Memory: 400Mi + Uncapped Target: + Cpu: 100m + Memory: 262144k + Upper Bound: + Cpu: 1 + Memory: 1Gi + Vpa Name: pgbouncer-autoscale +Events: +``` +So, the `pgbouncerautoscaler` resource is created successfully. + +you can see in the `Status.VPAs.Recommendation` section, that recommendation has been generated for our pgbouncer. Our autoscaler operator continuously watches the recommendation generated and creates an `pgbounceropsrequest` based on the recommendations, if the pgbouncer pods are needed to scaled up or down. + +Let's watch the `pgbounceropsrequest` in the demo namespace to see if any `pgbounceropsrequest` object is created. After some time you'll see that a `pgbounceropsrequest` will be created based on the recommendation. + +```bash +$ watch kubectl get pgbounceropsrequest -n demo +Every 2.0s: kubectl get pgbounceropsrequest -n demo +NAME TYPE STATUS AGE +pbops-pgbouncer-autoscale-zzell6 VerticalScaling Progressing 1m48s +``` + +Let's wait for the ops request to become successful. + +```bash +$ watch kubectl get pgbounceropsrequest -n demo +Every 2.0s: kubectl get pgbounceropsrequest -n demo +NAME TYPE STATUS AGE +pbops-pgbouncer-autoscale-zzell6 VerticalScaling Successful 3m40s +``` + +We can see from the above output that the `PgBouncerOpsRequest` has succeeded. If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed to scale the pgbouncer. + +```bash +$ kubectl describe pgbounceropsrequest -n demo pbops-pgbouncer-autoscale-zzell6 +Name: pbops-pgbouncer-autoscale-zzell6 +Namespace: demo +Labels: app.kubernetes.io/component=connection-pooler + app.kubernetes.io/instance=pgbouncer-autoscale + app.kubernetes.io/managed-by=kubedb.com + app.kubernetes.io/name=pgbouncers.kubedb.com +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2024-07-17T12:10:37Z + Generation: 1 + Owner References: + API Version: autoscaling.kubedb.com/v1alpha1 + Block Owner Deletion: true + Controller: true + Kind: PgBouncerAutoscaler + Name: pgbouncer-autoscale-ops + UID: 3841c30b-3b19-4740-82f5-bf8e257ddc18 + Resource Version: 81200 + UID: 57f99d31-af3d-4157-aa61-0f509ec89bbd +Spec: + Apply: IfReady + Database Ref: + Name: pgbouncer-autoscale + Type: VerticalScaling + Vertical Scaling: + Node: + Resources: + Limits: + Cpu: 400m + Memory: 400Mi + Requests: + Cpu: 400m + Memory: 400Mi +Status: + Conditions: + Last Transition Time: 2024-07-17T12:10:37Z + Message: PgBouncer ops-request has started to vertically scaling the PgBouncer nodes + Observed Generation: 1 + Reason: VerticalScaling + Status: True + Type: VerticalScaling + Last Transition Time: 2024-07-17T12:10:40Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2024-07-17T12:10:40Z + Message: Successfully updated PetSets Resources + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-07-17T12:11:25Z + Message: Successfully Restarted Pods With Resources + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2024-07-17T12:10:45Z + Message: get pod; ConditionStatus:True; PodName:pgbouncer-autoscale-0 + Observed Generation: 1 + Status: True + Type: GetPod--pgbouncer-autoscale-0 + Last Transition Time: 2024-07-17T12:10:45Z + Message: evict pod; ConditionStatus:True; PodName:pgbouncer-autoscale-0 + Observed Generation: 1 + Status: True + Type: EvictPod--pgbouncer-autoscale-0 + Last Transition Time: 2024-07-17T12:11:20Z + Message: check pod running; ConditionStatus:True; PodName:pgbouncer-autoscale-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--pgbouncer-autoscale-0 + Last Transition Time: 2024-07-17T12:11:26Z + Message: Successfully completed the vertical scaling for PgBouncer + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 8m19s KubeDB Ops-manager Operator Start processing for PgBouncerOpsRequest: demo/pbops-pgbouncer-autoscale-zzell6 + Normal Starting 8m19s KubeDB Ops-manager Operator Pausing PgBouncer databse: demo/pgbouncer-autoscale + Normal Successful 8m19s KubeDB Ops-manager Operator Successfully paused PgBouncer database: demo/pgbouncer-autoscale for PgBouncerOpsRequest: pbops-pgbouncer-autoscale-zzell6 + Normal UpdatePetSets 8m16s KubeDB Ops-manager Operator Successfully updated PetSets Resources + Warning get pod; ConditionStatus:True; PodName:pgbouncer-autoscale-0 8m11s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pgbouncer-autoscale-0 + Warning evict pod; ConditionStatus:True; PodName:pgbouncer-autoscale-0 8m11s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:pgbouncer-autoscale-0 + Warning check pod running; ConditionStatus:False; PodName:pgbouncer-autoscale-0 8m6s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:pgbouncer-autoscale-0 + Warning check pod running; ConditionStatus:True; PodName:pgbouncer-autoscale-0 7m36s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:pgbouncer-autoscale-0 + Normal RestartPods 7m31s KubeDB Ops-manager Operator Successfully Restarted Pods With Resources + Normal Starting 7m31s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pgbouncer-autoscale + Normal Successful 7m30s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pgbouncer-autoscale for PgBouncerOpsRequest: pbops-pgbouncer-autoscale-zzell6 +``` + +Now, we are going to verify from the Pod, and the PgBouncer yaml whether the resources of the pgbouncer has updated to meet up the desired state, Let's check, + +```bash +$ kubectl get pod -n demo pgbouncer-autoscale-0 -o json | jq '.spec.containers[].resources' +{ + "limits": { + "memory": "400Mi" + }, + "requests": { + "cpu": "400m", + "memory": "400Mi" + } +} + +$ kubectl get pgbouncer -n demo pgbouncer-autoscale -o json | jq '.spec.podTemplate.spec.containers[0].resources' +{ + "limits": { + "memory": "400Mi" + }, + "requests": { + "cpu": "400m", + "memory": "400Mi" + } +} +``` + + +The above output verifies that we have successfully auto-scaled the resources of the PgBouncer. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete pb -n demo pgbouncer-autoscale +kubectl delete pgbouncerautoscaler -n demo pgbouncer-autoscale-ops +``` \ No newline at end of file diff --git a/docs/guides/pgbouncer/autoscaler/compute/overview.md b/docs/guides/pgbouncer/autoscaler/compute/overview.md new file mode 100644 index 0000000000..ea2848cf82 --- /dev/null +++ b/docs/guides/pgbouncer/autoscaler/compute/overview.md @@ -0,0 +1,55 @@ +--- +title: PgBouncer Compute Autoscaling Overview +menu: + docs_{{ .version }}: + identifier: pb-auto-scaling-overview + name: Overview + parent: pb-compute-auto-scaling + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# PgBouncer Compute Resource Autoscaling + +This guide will give an overview on how KubeDB Autoscaler operator autoscales the database compute resources i.e. cpu and memory using `pgbouncerautoscaler` crd. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerAutoscaler](/docs/guides/pgbouncer/concepts/autoscaler.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + +## How Compute Autoscaling Works + +The following diagram shows how KubeDB Autoscaler operator autoscales the resources of `PgBouncer`. Open the image in a new tab to see the enlarged version. + +
+  Compute Auto Scaling process of PgBouncer +
Fig: Compute Auto Scaling process of PgBouncer
+
+ +The Auto Scaling process consists of the following steps: + +1. At first, a user creates a `PgBouncer` Custom Resource Object (CRO). + +2. `KubeDB` Provisioner operator watches the `PgBouncer` CRO. + +3. When the operator finds a `PgBouncer` CRO, it creates `PetSet` and related necessary stuff like secrets, services, etc. + +4. Then, in order to set up autoscaling of `PgBouncer`, the user creates a `PgBouncerAutoscaler` CRO with desired configuration. + +5. `KubeDB` Autoscaler operator watches the `PgBouncerAutoscaler` CRO. + +6. `KubeDB` Autoscaler operator generates recommendation using the modified version of kubernetes [official recommender](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler/pkg/recommender) for different components of the database, as specified in the `PgBouncerAutoscaler` CRO. + +7. If the generated recommendation doesn't match the current resources of the database, then `KubeDB` Autoscaler operator creates a `PgBouncerOpsRequest` CRO to scale the pgbouncer to match the recommendation generated. + +8. `KubeDB` Ops-manager operator watches the `PgBouncerOpsRequest` CRO. + +9. Then the `KubeDB` Ops-manager operator will scale the pgbouncer vertically as specified on the `PgBouncerOpsRequest` CRO. + +In the next docs, we are going to show a step-by-step guide on Autoscaling of PgBouncer using `PgBouncerAutoscaler` CRD. diff --git a/docs/guides/pgbouncer/concepts/appbinding.md b/docs/guides/pgbouncer/concepts/appbinding.md index 1e1fdb8c49..170a60250f 100644 --- a/docs/guides/pgbouncer/concepts/appbinding.md +++ b/docs/guides/pgbouncer/concepts/appbinding.md @@ -20,8 +20,6 @@ An `AppBinding` is a Kubernetes `CustomResourceDefinition`(CRD) which points to If you deploy a database using [KubeDB](https://kubedb.com/docs/latest/welcome/), `AppBinding` object will be created automatically for it. Otherwise, you have to create an `AppBinding` object manually pointing to your desired database. -KubeDB uses [Stash](https://appscode.com/products/stash/) to perform backup/recovery of databases. Stash needs to know how to connect with a target database and the credentials necessary to access it. This is done via an `AppBinding`. - ## AppBinding CRD Specification Like any official Kubernetes resource, an `AppBinding` has `TypeMeta`, `ObjectMeta` and `Spec` sections. However, unlike other Kubernetes resources, it does not have a `Status` section. @@ -71,7 +69,7 @@ An `AppBinding` object has the following fields in the `spec` section: #### spec.type -`spec.type` is an optional field that indicates the type of the app that this `AppBinding` is pointing to. Stash uses this field to resolve the values of `TARGET_APP_TYPE`, `TARGET_APP_GROUP` and `TARGET_APP_RESOURCE` variables of [BackupBlueprint](https://appscode.com/products/stash/latest/concepts/crds/backupblueprint/) object. +`spec.type` is an optional field that indicates the type of the app that this `AppBinding` is pointing to. PgBouncer operator uses this field to recognise the desired postgres database. This field follows the following format: `/`. The above AppBinding is pointing to a `postgres` resource under `kubedb.com` group. diff --git a/docs/guides/pgbouncer/concepts/autoscaler.md b/docs/guides/pgbouncer/concepts/autoscaler.md new file mode 100644 index 0000000000..6a4f144e37 --- /dev/null +++ b/docs/guides/pgbouncer/concepts/autoscaler.md @@ -0,0 +1,73 @@ +--- +title: PgBouncerAutoscaler CRD +menu: + docs_{{ .version }}: + identifier: pb-autoscaler-concepts + name: PgBouncerAutoscaler + parent: pb-concepts-pgbouncer + weight: 35 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# PgBouncerAutoscaler + +## What is PgBouncerAutoscaler + +`PgBouncerAutoscaler` is a Kubernetes `Custom Resource Definitions` (CRD). It provides a declarative configuration for autoscaling [PgBouncer](https://www.pgbouncer.org/usage.html) compute resources of PgBouncer components in a Kubernetes native way. + +## PgBouncerAutoscaler CRD Specifications + +Like any official Kubernetes resource, a `PgBouncerAutoscaler` has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections. + +Here, some sample `PgBouncerAutoscaler` CROs for autoscaling different components of pgbouncer is given below: + +**Sample `PgBouncerAutoscaler` for pgbouncer:** + +```yaml +apiVersion: autoscaling.kubedb.com/v1alpha1 +kind: PgBouncerAutoscaler +metadata: + name: pgbouncer-auto-scale + namespace: demo +spec: + databaseRef: + name: pgbouncer-server + compute: + pgbouncer: + trigger: "On" + podLifeTimeThreshold: 24h + minAllowed: + cpu: 250m + memory: 350Mi + maxAllowed: + cpu: 1 + memory: 1Gi + controlledResources: ["cpu", "memory"] + containerControlledValues: "RequestsAndLimits" + resourceDiffPercentage: 10 +``` + +Here, we are going to describe the various sections of a `PgBouncerAutoscaler` crd. + +A `PgBouncerAutoscaler` object has the following fields in the `spec` section. + +### spec.databaseRef + +`spec.databaseRef` is a required field that point to the [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) object for which the autoscaling will be performed. This field consists of the following sub-field: + +- **spec.databaseRef.name :** specifies the name of the [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) object. + +### spec.compute + +`spec.compute` specifies the autoscaling configuration for the compute resources i.e. cpu and memory of PgBouncer components. This field consists of the following sub-field: + +- `trigger` indicates if compute autoscaling is enabled for this component of the pgbouncer. If "On" then compute autoscaling is enabled. If "Off" then compute autoscaling is disabled. +- `minAllowed` specifies the minimal amount of resources that will be recommended, default is no minimum. +- `maxAllowed` specifies the maximum amount of resources that will be recommended, default is no maximum. +- `controlledResources` specifies which type of compute resources (cpu and memory) are allowed for autoscaling. Allowed values are "cpu" and "memory". +- `containerControlledValues` specifies which resource values should be controlled. Allowed values are "RequestsAndLimits" and "RequestsOnly". +- `resourceDiffPercentage` specifies the minimum resource difference between recommended value and the current value in percentage. If the difference percentage is greater than this value than autoscaling will be triggered. +- `podLifeTimeThreshold` specifies the minimum pod lifetime of at least one of the pods before triggering autoscaling. \ No newline at end of file diff --git a/docs/guides/pgbouncer/concepts/opsrequest.md b/docs/guides/pgbouncer/concepts/opsrequest.md new file mode 100644 index 0000000000..50430e0b38 --- /dev/null +++ b/docs/guides/pgbouncer/concepts/opsrequest.md @@ -0,0 +1,263 @@ +--- +title: PgBouncerOpsRequests CRD +menu: + docs_{{ .version }}: + identifier: pb-opsrequest-concepts + name: PgBouncerOpsRequest + parent: pb-concepts-pgbouncer + weight: 25 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# PgBouncerOpsRequest + +## What is PgBouncerOpsRequest + +`PgBouncerOpsRequest` is a Kubernetes `Custom Resource Definitions` (CRD). It provides a declarative configuration for [PgBouncer](https://www.pgbouncer.org/usage.html) administrative operations like version updating, horizontal scaling, vertical scaling etc. in a Kubernetes native way. + +## PgBouncerOpsRequest CRD Specifications + +Like any official Kubernetes resource, a `PgBouncerOpsRequest` has `TypeMeta`, `ObjectMeta`, `Spec` and `Status` sections. + +Here, some sample `PgBouncerOpsRequest` CRs for different administrative operations is given below: + +**Sample `PgBouncerOpsRequest` for updating version:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-version-update + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: pgbouncer-server + updateVersion: + targetVersion: 1.18.0 +``` + +**Sample `PgBouncerOpsRequest` Objects for Horizontal Scaling:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-horizontal-scale + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: pgbouncer-server + horizontalScaling: + replicas: 2 +``` + +**Sample `PgBouncerOpsRequest` Objects for Vertical Scaling:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-vertical-scale + namespace: demo +spec: + type: VerticalScaling + databaseRef: + name: pgbouncer-server + verticalScaling: + pgbouncer: + resources: + requests: + memory: "1200Mi" + cpu: "0.7" + limits: + memory: "1200Mi" + cpu: "0.7" +``` + +**Sample `PgBouncerOpsRequest` Objects for Reconfiguring:** + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-reconfigure + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: pgbouncer-server + configuration: + pgbouncer: + applyConfig: + pgbouncer.conf: |- + auth_type = scram-sh-256 +``` + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-reconfigure + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: pgbouncer-server + configuration: + pgbouncer: + removeCustomConfig: true +``` + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-reconfigure + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: pgbouncer-server + configuration: + pgbouncer: + configSecret: + name: new-custom-config +``` + +Here, we are going to describe the various sections of a `PgBouncerOpsRequest` crd. + +A `PgBouncerOpsRequest` object has the following fields in the `spec` section. + +### spec.databaseRef + +`spec.databaseRef` is a required field that point to the [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) object for which the administrative operations will be performed. This field consists of the following sub-field: + +- **spec.databaseRef.name :** specifies the name of the [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) object. + +### spec.type + +`spec.type` specifies the kind of operation that will be applied to the database. Currently, the following types of operations are allowed in `PgBouncerOpsRequest`. + +- `UpdateVersion` +- `HorizontalScaling` +- `VerticalScaling` +- `Reconfigure` +- `Restart` + +> You can perform only one type of operation on a single `PgBouncerOpsRequest` CR. For example, if you want to update your database and scale up its replica then you have to create two separate `PgBouncerOpsRequest`. At first, you have to create a `PgBouncerOpsRequest` for updating. Once it is completed, then you can create another `PgBouncerOpsRequest` for scaling. + +> Note: There is an exception to the above statement. It is possible to specify both `spec.configuration` & `spec.verticalScaling` in a OpsRequest of type `VerticalScaling`. + +### spec.updateVersion + +If you want to update your PgBouncer version, you have to specify the `spec.updateVersion` section that specifies the desired version information. This field consists of the following sub-field: + +- `spec.updateVersion.targetVersion` refers to a [PgBouncerVersion](/docs/guides/pgbouncer/concepts/catalog.md) CR that contains the PgBouncer version information where you want to update. + + +### spec.horizontalScaling + +If you want to scale-up or scale-down your PgBouncer cluster or different components of it, you have to specify `spec.horizontalScaling` section. This field consists of the following sub-field: + +- `spec.horizontalScaling.replicas` indicates the desired number of pods for PgBouncer cluster after scaling. For example, if your cluster currently has 4 pods, and you want to add additional 2 pods then you have to specify 6 in `spec.horizontalScaling.replicas` field. Similarly, if you want to remove one pod from the cluster, you have to specify 3 in `spec.horizontalScaling.replicas` field. + +### spec.verticalScaling + +`spec.verticalScaling` is a required field specifying the information of resources like `cpu`, `memory` etc. that will be scaled. This field consists of the following sub-fields: + +- `spec.verticalScaling.pgbouncer` indicates the desired resources for PetSet of PgBouncer after scaling. +- `spec.verticalScaling.exporter` indicates the desired resources for PetSet of PgBouncer Exporter after scaling. + +It has the below structure: + +```yaml +requests: + memory: "200Mi" + cpu: "0.1" +limits: + memory: "300Mi" + cpu: "0.2" +``` + +Here, when you specify the resource request, the scheduler uses this information to decide which node to place the container of the Pod on and when you specify a resource limit for the container, the `kubelet` enforces those limits so that the running container is not allowed to use more of that resource than the limit you set. You can found more details from [here](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/). + + +### spec.configuration + +If you want to reconfigure your Running PgBouncer cluster or different components of it with new custom configuration, you have to specify `spec.configuration` section. This field consists of the following sub-field: + +- `configSecret` points to a secret in the same namespace of a PgBouncer resource, which contains the new custom configurations. If there are any configSecret set before in the database, this secret will replace it. +- `applyConfig` contains the new custom config as a string which will be merged with the previous configuration. + +- `applyConfig` is a map where key supports 1 values, namely `pgbouncer.ini`. + +```yaml + applyConfig: + pgbouncer.conf: |- + max_pool = 30 +``` + +- `removeCustomConfig` is a boolean field. Specify this field to true if you want to remove all the custom configuration from the deployed pgbouncer server. + +### spec.timeout +As we internally retry the ops request steps multiple times, This `timeout` field helps the users to specify the timeout for those steps of the ops request (in second). +If a step doesn't finish within the specified timeout, the ops request will result in failure. + +### spec.apply +This field controls the execution of opsRequest depending on the database state. It has two supported values: `Always` & `IfReady`. +Use IfReady, if you want to process the opsRequest only when the database is Ready. And use Always, if you want to process the execution of opsReq irrespective of the Database state. + + +### PgBouncerOpsRequest `Status` + +`.status` describes the current state and progress of a `PgBouncerOpsRequest` operation. It has the following fields: + +### status.phase + +`status.phase` indicates the overall phase of the operation for this `PgBouncerOpsRequest`. It can have the following three values: + +| Phase | Meaning | +|-------------|------------------------------------------------------------------------------------| +| Successful | KubeDB has successfully performed the operation requested in the PgBouncerOpsRequest | +| Progressing | KubeDB has started the execution of the applied PgBouncerOpsRequest | +| Failed | KubeDB has failed the operation requested in the PgBouncerOpsRequest | +| Denied | KubeDB has denied the operation requested in the PgBouncerOpsRequest | +| Skipped | KubeDB has skipped the operation requested in the PgBouncerOpsRequest | + +Important: Ops-manager Operator can skip an opsRequest, only if its execution has not been started yet & there is a newer opsRequest applied in the cluster. `spec.type` has to be same as the skipped one, in this case. + +### status.observedGeneration + +`status.observedGeneration` shows the most recent generation observed by the `PgBouncerOpsRequest` controller. + +### status.conditions + +`status.conditions` is an array that specifies the conditions of different steps of `PgBouncerOpsRequest` processing. Each condition entry has the following fields: + +- `types` specifies the type of the condition. PgBouncerOpsRequest has the following types of conditions: + +| Type | Meaning | +|--------------------------------|---------------------------------------------------------------------------| +| `Progressing` | Specifies that the operation is now in the progressing state | +| `Successful` | Specifies such a state that the operation on the database was successful. | +| `DatabasePauseSucceeded` | Specifies such a state that the database is paused by the operator | +| `ResumeDatabase` | Specifies such a state that the database is resumed by the operator | +| `Failed` | Specifies such a state that the operation on the database failed. | +| `UpdatePetSetResources` | Specifies such a state that the PetSet resources has been updated | +| `UpdatePetSet` | Specifies such a state that the PetSet has been updated | +| `IssueCertificatesSucceeded` | Specifies such a state that the tls certificate issuing is successful | +| `UpdateDatabase` | Specifies such a state that the CR of PgBouncer is updated | + +- The `status` field is a string, with possible values `True`, `False`, and `Unknown`. + - `status` will be `True` if the current transition succeeded. + - `status` will be `False` if the current transition failed. + - `status` will be `Unknown` if the current transition was denied. +- The `message` field is a human-readable message indicating details about the condition. +- The `reason` field is a unique, one-word, CamelCase reason for the condition's last transition. +- The `lastTransitionTime` field provides a timestamp for when the operation last transitioned from one state to another. +- The `observedGeneration` shows the most recent condition transition generation observed by the controller. diff --git a/docs/guides/pgbouncer/concepts/pgbouncer.md b/docs/guides/pgbouncer/concepts/pgbouncer.md index 40802d1f2e..925b4bba12 100644 --- a/docs/guides/pgbouncer/concepts/pgbouncer.md +++ b/docs/guides/pgbouncer/concepts/pgbouncer.md @@ -32,7 +32,7 @@ metadata: namespace: demo spec: version: "1.18.0" - replicas: 2 + replicas: 1 database: syncUsers: true databaseName: "postgres" diff --git a/docs/guides/pgbouncer/custom-versions/setup.md b/docs/guides/pgbouncer/custom-versions/setup.md index 737b2684d3..3519ea56e1 100644 --- a/docs/guides/pgbouncer/custom-versions/setup.md +++ b/docs/guides/pgbouncer/custom-versions/setup.md @@ -21,7 +21,7 @@ PgBouncerVersions are KubeDB crds that define the docker images KubeDB will use If you want to create a custom image of pgbouncer with additional features, the best way is to build on top of the existing kubedb image. ```docker -FROM kubedb/pgbouncer:1.17.0 +FROM kubedb/pgbouncer:1.23.1 ENV SOME_VERSION_VAR 0.9.1 @@ -32,18 +32,18 @@ RUN set -ex \ bash ``` -From there, we would define a PgBouncerVersion that contains this new image. Let's say we tagged it as `myco/pgbouncer:custom-1.17.0`. You can also build exporter image yourself using [pgbouncer_exporter](https://github.com/kubedb/pgbouncer_exporter) repository. +From there, we would define a PgBouncerVersion that contains this new image. Let's say we tagged it as `myco/pgbouncer:custom-1.23.1`. You can also build exporter image yourself using [pgbouncer_exporter](https://github.com/kubedb/pgbouncer_exporter) repository. ```yaml apiVersion: catalog.kubedb.com/v1alpha1 kind: PgBouncerVersion metadata: - name: "1.17.0" + name: "1.23.1" spec: deprecated: false - version: "1.17.0" + version: "1.23.1" pgBouncer: - image: "myco/pgbouncer:custom-1.17.0" + image: "myco/pgbouncer:custom-1.23.1" exporter: image: "myco/pgbouncer_exporter:v0.1.1" ``` @@ -57,7 +57,7 @@ metadata: name: pgbouncer-server namespace: demo spec: - version: "1.17.0" + version: "1.23.1" replicas: 1 connectionPool: poolMode: session diff --git a/docs/guides/pgbouncer/monitoring/_index.md b/docs/guides/pgbouncer/monitoring/_index.md index dfd3aeaa86..2f5d8efa54 100755 --- a/docs/guides/pgbouncer/monitoring/_index.md +++ b/docs/guides/pgbouncer/monitoring/_index.md @@ -5,6 +5,6 @@ menu: identifier: pb-monitoring-pgbouncer name: Monitoring parent: pb-pgbouncer-guides - weight: 50 + weight: 100 menu_name: docs_{{ .version }} --- diff --git a/docs/guides/pgbouncer/monitoring/overview.md b/docs/guides/pgbouncer/monitoring/overview.md index 6230ab5b42..4f6d5247f8 100644 --- a/docs/guides/pgbouncer/monitoring/overview.md +++ b/docs/guides/pgbouncer/monitoring/overview.md @@ -44,27 +44,26 @@ In order to enable monitoring for a database, you have to configure `spec.monito ## Sample Configuration -A sample YAML for Redis crd with `spec.monitor` section configured to enable monitoring with [Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) is shown below. +A sample YAML for PgBouncer crd with `spec.monitor` section configured to enable monitoring with [Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) is shown below. ```yaml apiVersion: kubedb.com/v1 -kind: Redis +kind: PgBouncer metadata: - name: sample-redis - namespace: databases + name: pb + namespace: demo spec: - version: 6.0.20 - deletionPolicy: WipeOut - configSecret: # configure Redis to use password for authentication - name: redis-config - storageType: Durable - storage: - storageClassName: default - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi + replicas: 2 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "pg" + namespace: demo + connectionPool: + poolMode: session + port: 5432 monitor: agent: prometheus.io/operator prometheus: @@ -72,14 +71,6 @@ spec: labels: release: prometheus exporter: - args: - - --redis.password=$(REDIS_PASSWORD) - env: - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: _name_of_secret_with_redis_password - key: password # key with the password resources: requests: memory: 512Mi @@ -88,19 +79,14 @@ spec: memory: 512Mi cpu: 250m securityContext: - runAsUser: 2000 + runAsUser: 70 allowPrivilegeEscalation: false ``` -Assume that above Redis is configured to use basic authentication. So, exporter image also need to provide password to collect metrics. We have provided it through `spec.monitor.args` field. - -Here, we have specified that we are going to monitor this server using Prometheus operator through `spec.monitor.agent: prometheus.io/operator`. KubeDB will create a `ServiceMonitor` crd in `monitoring` namespace and this `ServiceMonitor` will have `release: prometheus` label. +Here, we have specified that we are going to monitor this server using Prometheus operator through `spec.monitor.agent: prometheus.io/operator`. KubeDB will create a `ServiceMonitor` crd in databases namespace and this `ServiceMonitor` will have `release: prometheus` label. ## Next Steps -- Learn how to monitor Elasticsearch database with KubeDB using [builtin-Prometheus](/docs/guides/elasticsearch/monitoring/using-builtin-prometheus.md) and using [Prometheus operator](/docs/guides/elasticsearch/monitoring/using-prometheus-operator.md). -- Learn how to monitor PostgreSQL database with KubeDB using [builtin-Prometheus](/docs/guides/postgres/monitoring/using-builtin-prometheus.md) and using [Prometheus operator](/docs/guides/postgres/monitoring/using-prometheus-operator.md). -- Learn how to monitor MySQL database with KubeDB using [builtin-Prometheus](/docs/guides/mysql/monitoring/builtin-prometheus/index.md) and using [Prometheus operator](/docs/guides/mysql/monitoring/prometheus-operator/index.md). -- Learn how to monitor MongoDB database with KubeDB using [builtin-Prometheus](/docs/guides/mongodb/monitoring/using-builtin-prometheus.md) and using [Prometheus operator](/docs/guides/mongodb/monitoring/using-prometheus-operator.md). -- Learn how to monitor Redis server with KubeDB using [builtin-Prometheus](/docs/guides/redis/monitoring/using-builtin-prometheus.md) and using [Prometheus operator](/docs/guides/redis/monitoring/using-prometheus-operator.md). -- Learn how to monitor Memcached server with KubeDB using [builtin-Prometheus](/docs/guides/memcached/monitoring/using-builtin-prometheus.md) and using [Prometheus operator](/docs/guides/memcached/monitoring/using-prometheus-operator.md). +- Learn how to monitor PgBouncer database with KubeDB using [builtin-Prometheus](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md) +- Learn how to monitor PgBouncer database with KubeDB using [Prometheus operator](/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md). + diff --git a/docs/guides/pgbouncer/monitoring/setup-grafana-dashboard.md b/docs/guides/pgbouncer/monitoring/setup-grafana-dashboard.md deleted file mode 100644 index 911ba4b220..0000000000 --- a/docs/guides/pgbouncer/monitoring/setup-grafana-dashboard.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: Monitor PgBouncer using Prometheus Operator -menu: - docs_{{ .version }}: - identifier: pb-setup-grafana-dashboard-monitoring - name: Setup Grafana Dashboard - parent: pb-monitoring-pgbouncer - weight: 25 -menu_name: docs_{{ .version }} -section_menu_id: guides ---- - -> New to KubeDB? Please start [here](/docs/README.md). - -# Visualize PgBouncer Using Grafana Dashboard - -[Grafana](https://github.com/grafana/grafana) is an open source, feature rich metrics dashboard and graph editor for Graphite, Elasticsearch, OpenTSDB, Prometheus and InfluxDB. PgBouncer comes with a Grafana dashboard designed to monitor real-time updates of PgBouncer servers using Prometheus metrics. - -This tutorial will show you how to import our dashboard on Grafana to monitor PgBouncer deployed with KubeDB. - -## Before You Begin - -- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). - -- To learn how Prometheus monitoring works with KubeDB in general, please visit [here](/docs/guides/pgbouncer/monitoring/overview.md). - -- You need to have monitoring enabled using either [Builtin Prometheus](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md) or [Prometheus operator](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md). - -- To keep everything isolated, we are going to use a separate namespace called `monitoring` to deploy respective monitoring resources. We are going to deploy database in `demo` namespace. - - ```bash - $ kubectl create ns monitoring - namespace/monitoring created - - $ kubectl create ns demo - namespace/demo created - ``` - -> Note: YAML files used in this tutorial are stored in [docs/examples/pgbouncer](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/pgbouncer) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). - -## Deploy Grafana - -After you have made sure that you have a PgBouncer server running with Monitoring enabled, you're ready to deploy your very own Grafana server. If you still have not deployed PgBouncer server with monitoring enabled, then do so using [Builtin Prometheus](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md) or [Prometheus operator](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md). - -However, if you already have a Grafana server running in your cluster, feel free to skip this part. Otherwise, create one using: - -```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/monitoring/grafana.yaml -deployment.apps/grafana created -``` - -Let's get the name of the pod created by this deployment: - -```bash -$ kubectl get pod -n monitoring -l "app=grafana" - -NAME READY STATUS RESTARTS AGE -grafana-7cbd6b6f87-w9dkh 1/1 Running 0 57s -``` - -## View Dashboard - -Now, we have to expose the Grafana pod so that we can access it from a browser. - -```bash -$ kubectl port-forward -n monitoring grafana-7cbd6b6f87-w9dkh 3000 -Forwarding from 127.0.0.1:3000 -> 3000 -Forwarding from [::1]:3000 -> 3000 -``` - -Grafana should now be available on [localhost](http://localhost:3000/). Use default credentials `(username: admin, password: admin)` to login to Grafana Dashboard. - -## Add Data Source - -First, we need to know the name of the service that exposes our prometheus server pods. In this tutorial, we have used a service named `prometheus-operated` that exposes our prometheus metrics on port 9090. - -```bash -$ kubectl get service -n monitoring -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -prometheus-operated ClusterIP 10.111.246.229 9090/TCP 38m -``` - -We will use this service to point Grafana to our desired data source. - -From Home Dashboard, go to [Configuration > Data Sources](http://localhost:3000/datasources), and select `Add data source`. Select `Prometheus` as the `data source type`. - -In the following screen, add `http://prometheus-operated.monitoring.svc:9090` as the data source `URL`, give it a name `PGBOUNCER_PROMETHEUS`, and press the `Save and Test` button. You should get a message confirming that the `Data source is working`. - -

-  Data Target -

- -## Import Dashboard - -Now, go to [http://localhost:3000/dashboard/import](http://localhost:3000/dashboard/import) to import our PgBouncer Dashboard. Put `10945` as the grafana dashboard id. Select `PGBOUNCER_PROMETHEUS` as the data source, and press `import`. You will now be directed to your PgBouncer dashboard. - -

-  Data Target -

- -## Cleaning up - -To cleanup the Kubernetes resources created by this tutorial, run the following commands - -```bash -# cleanup prometheus resources -kubectl delete -n monitoring deployment grafana - -# delete namespace -kubectl delete ns monitoring -``` - -## Next Steps - -- Monitor your PgBouncer with KubeDB using [built-in Prometheus](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md). -- Monitor your PgBouncer with KubeDB using [Prometheus operator](/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md). -- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md b/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md index f747fc248e..ef1e0bb17a 100644 --- a/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md +++ b/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md @@ -14,7 +14,7 @@ section_menu_id: guides # Monitoring PgBouncer with builtin Prometheus -This tutorial will show you how to monitor PgBouncer using builtin [Prometheus](https://github.com/prometheus/prometheus) scraper. +This tutorial will show you how to monitor PgBouncer database using builtin [Prometheus](https://github.com/prometheus/prometheus) scraper. ## Before You Begin @@ -38,28 +38,31 @@ This tutorial will show you how to monitor PgBouncer using builtin [Prometheus]( > Note: YAML files used in this tutorial are stored in [docs/examples/pgbouncer](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/pgbouncer) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). +## Prepare Postgres +Prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. + ## Deploy PgBouncer with Monitoring Enabled -At first, we will need a PgBouncer with monitoring enabled. This PgBouncer needs to be connected to PostgreSQL database(s). You can get a PgBouncer setup with active connection(s) to PostgreSQL by following the [quickstart](/docs/guides/pgbouncer/quickstart/quickstart.md) guide. PgBouncer object in that guide didn't come with monitoring. So we are going to enable monitoring in it. Below is the PgBouncer object that contains built-in monitoring: +At first, let's deploy a PgBouncer with monitoring enabled. Below is the PgBouncer object that we are going to create. ```yaml apiVersion: kubedb.com/v1 kind: PgBouncer metadata: - name: pgbouncer-server + name: builtin-prom-pb namespace: demo spec: - version: "1.17.0" replicas: 1 + version: "1.18.0" database: syncUsers: true databaseName: "postgres" databaseRef: - name: "quick-postgres" + name: "ha-postgres" namespace: demo connectionPool: - maxClientConnections: 20 - reservePoolSize: 5 + poolMode: session + port: 5432 monitor: agent: prometheus.io/builtin ``` @@ -68,49 +71,55 @@ Here, - `spec.monitor.agent: prometheus.io/builtin` specifies that we are going to monitor this server using builtin Prometheus scraper. -Let's patch the existing PgBouncer with the crd we have shown above. +Let's create the PgBouncer crd we have shown above. ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/monitoring/builtin-prom-pgbouncer.yaml -pgbouncer.kubedb.com/pgbouncer-server configured +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/monitoring/builtin-prom-pb.yaml +pgbouncer.kubedb.com/builtin-prom-pb created ``` -PgBouncer should still be in `Running` state. +Now, wait for the database to go into `Running` state. ```bash -$ kubectl get pb -n demo pgbouncer-server -NAME VERSION STATUS AGE -pgbouncer-server 1.17.0 Running 13s +$ kubectl get pb -n demo builtin-prom-pb +NAME TYPE VERSION STATUS AGE +builtin-prom-pb kubedb.com/v1 1.18.0 Ready 65s ``` -KubeDB will create a separate stats service with name `{PgBouncer crd name}-stats` for monitoring purpose. +KubeDB will create a separate stats service with name `{PgBouncer cr name}-stats` for monitoring purpose. ```bash -$ kubectl get svc -n demo --selector="app.kubernetes.io/instance=pgbouncer-server" -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -pgbouncer-server ClusterIP 10.108.152.208 5432/TCP 16m -pgbouncer-server-stats ClusterIP 10.111.194.83 56790/TCP 16m +$ kubectl get svc -n demo --selector="app.kubernetes.io/instance=builtin-prom-pb" +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +builtin-prom-pb ClusterIP 10.96.210.2 5432/TCP 86s +builtin-prom-pb-pods ClusterIP None 5432/TCP 86s +builtin-prom-pb-stats ClusterIP 10.96.215.193 56790/TCP 74s ``` -Here, `pgbouncer-server-stats` service has been created for monitoring purpose. Let's describe the service. +Here, `builtin-prom-pb-stats` service has been created for monitoring purpose. Let's describe the service. ```bash -$ kubectl describe svc -n demo pgbouncer-server-stats -Name: pgbouncer-server-stats +$ kubectl describe svc -n demo builtin-prom-pb-stats +Name: builtin-prom-pb-stats Namespace: demo -Labels: app.kubernetes.io/name=pgbouncers.kubedb.com - app.kubernetes.io/instance=pgbouncer-server +Labels: app.kubernetes.io/component=connection-pooler + app.kubernetes.io/instance=builtin-prom-pb + app.kubernetes.io/managed-by=kubedb.com + app.kubernetes.io/name=pgbouncers.kubedb.com kubedb.com/role=stats Annotations: monitoring.appscode.com/agent: prometheus.io/builtin prometheus.io/path: /metrics prometheus.io/port: 56790 prometheus.io/scrape: true -Selector: app.kubernetes.io/name=pgbouncers.kubedb.com,app.kubernetes.io/instance=pgbouncer-server +Selector: app.kubernetes.io/instance=builtin-prom-pb,app.kubernetes.io/managed-by=kubedb.com,app.kubernetes.io/name=pgbouncers.kubedb.com Type: ClusterIP -IP: 10.110.56.149 -Port: prom-http 56790/TCP -TargetPort: prom-http/TCP -Endpoints: 172.17.0.7:56790 +IP Family Policy: SingleStack +IP Families: IPv4 +IP: 10.96.215.193 +IPs: 10.96.215.193 +Port: metrics 56790/TCP +TargetPort: metrics/TCP +Endpoints: 10.244.0.28:56790 Session Affinity: None Events: ``` @@ -193,7 +202,7 @@ Let's configure a Prometheus scraping job to collect metrics from this service. If you already have a Prometheus server running, you have to add above scraping job in the `ConfigMap` used to configure the Prometheus server. Then, you have to restart it for the updated configuration to take effect. -> If you don't use a persistent volume for Prometheus storage, you will lose your previously scraped data on restart. +>If you don't use a persistent volume for Prometheus storage, you will lose your previously scraped data on restart. ### Deploy New Prometheus Server @@ -305,15 +314,6 @@ $ kubectl apply -f https://github.com/appscode/third-party-tools/raw/master/moni deployment.apps/prometheus created ``` -**Prometheus Service:** - -We will use a service for the Prometheus server. We can use this to look up metrics from within the cluster as well as outside of the cluster. - -```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/monitoring/builtin-prom-service.yaml -service/prometheus-operated created -``` - ### Verify Monitoring Metrics Prometheus server is listening to port `9090`. We are going to use [port forwarding](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) to access Prometheus dashboard. @@ -321,26 +321,26 @@ Prometheus server is listening to port `9090`. We are going to use [port forward At first, let's check if the Prometheus pod is in `Running` state. ```bash -kubectl get pod -n monitoring -l=app=prometheus -NAME READY STATUS RESTARTS AGE -prometheus-789c9695fc-7rjzf 1/1 Running 0 27s +$ kubectl get pod -n monitoring -l=app=prometheus +NAME READY STATUS RESTARTS AGE +prometheus-d64b668fb-4khbg 1/1 Running 0 21s ``` -Now, run following command on a separate terminal to forward 9090 port of `prometheus-8568c86d86-95zhn` pod, +Now, run following command on a separate terminal to forward 9090 port of `prometheus-d64b668fb-4khbg` pod, ```bash -$ kubectl port-forward -n monitoring svc/prometheus-operated 9090 +$ kubectl port-forward -n monitoring prometheus-d64b668fb-4khbg 9090 Forwarding from 127.0.0.1:9090 -> 9090 Forwarding from [::1]:9090 -> 9090 ``` -Now, we can access the dashboard at `localhost:9090`. Open [http://localhost:9090/targets](http://localhost:9090/targets) in your browser. You should see the endpoint of `pgbouncer-server-stats` service as one of the targets. +Now, we can access the dashboard at `localhost:9090`. Open [http://localhost:9090](http://localhost:9090) in your browser. You should see the endpoint of `builtin-prom-pb-stats` service as one of the targets.

-  Prometheus Target +  Prometheus Target

-Check the labels which confirm that the metrics are coming from `pgbouncer-server` through stats service `pgbouncer-server-stats`. +Check the labels marked with red rectangle. These labels confirm that the metrics are coming from `PgBouncer` database `builtin-prom-pb` through stats service `builtin-prom-pb-stats`. Now, you can view the collected metrics and create a graph from homepage of this Prometheus dashboard. You can also use this Prometheus server as data source for [Grafana](https://grafana.com/) and create beautiful dashboard with collected metrics. @@ -349,19 +349,22 @@ Now, you can view the collected metrics and create a graph from homepage of this To cleanup the Kubernetes resources created by this tutorial, run following commands ```bash -$ kubectl delete -n demo pb/pgbouncer-server +kubectl delete -n demo pb/builtin-prom-pb -$ kubectl delete -n monitoring deployment.apps/prometheus +kubectl delete -n monitoring deployment.apps/prometheus -$ kubectl delete -n monitoring clusterrole.rbac.authorization.k8s.io/prometheus -$ kubectl delete -n monitoring serviceaccount/prometheus -$ kubectl delete -n monitoring clusterrolebinding.rbac.authorization.k8s.io/prometheus +kubectl delete -n monitoring clusterrole.rbac.authorization.k8s.io/prometheus +kubectl delete -n monitoring serviceaccount/prometheus +kubectl delete -n monitoring clusterrolebinding.rbac.authorization.k8s.io/prometheus -$ kubectl delete ns demo -$ kubectl delete ns monitoring +kubectl delete ns demo +kubectl delete ns monitoring ``` ## Next Steps -- Monitor your PgBouncer with KubeDB using [`out-of-the-box` Prometheus operator](/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md). -- Use [private Docker registry](/docs/guides/pgbouncer/private-registry/using-private-registry.md) to deploy PgBouncer with KubeDB. + + +- Monitor your PgBouncer database with KubeDB using [out-of-the-box prometheus-Operator](/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md). +- Detail concepts of [PgBouncer object](/docs/guides/pgbouncer/concepts/pgbouncer.md). +- Detail concepts of [PgBouncerVersion object](/docs/guides/pgbouncer/concepts/catalog.md). - Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md b/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md index bc8d5f8fd7..a12813466a 100644 --- a/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md +++ b/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md @@ -12,9 +12,16 @@ section_menu_id: guides > New to KubeDB? Please start [here](/docs/README.md). -# Monitoring PgBouncer using Prometheus operator +# Monitoring PgBouncer Using Prometheus operator -[Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) provides simple and Kubernetes native way to deploy and configure Prometheus server. This tutorial will show you how to use Prometheus operator to monitor PgBouncer deployed with KubeDB. +[Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) provides simple and Kubernetes native way to deploy and configure Prometheus server. This tutorial will show you how to use Prometheus operator to monitor PgBouncer database deployed with KubeDB. + +The following diagram shows how KubeDB Provisioner operator monitor `PgBouncer` using Prometheus Operator. Open the image in a new tab to see the enlarged version. + +
+  Monitoring process of PgBouncer using Prometheus Operator +
Fig: Monitoring process of PgBouncer
+
## Before You Begin @@ -22,104 +29,175 @@ section_menu_id: guides - To learn how Prometheus monitoring works with KubeDB in general, please visit [here](/docs/guides/pgbouncer/monitoring/overview.md). -- To keep Prometheus resources isolated, we are going to use a separate namespace called `monitoring` to deploy respective monitoring resources. We are going to deploy database in `demo` namespace. +- We need a [Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) instance running. If you don't already have a running instance, you can deploy one using this helm chart [here](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack). + +- To keep Prometheus resources isolated, we are going to use a separate namespace called `monitoring` to deploy the prometheus operator helm chart. We are going to deploy database in `demo` namespace. ```bash $ kubectl create ns monitoring namespace/monitoring created + + $ kubectl create ns demo + namespace/demo created ``` -- We need a [Prometheus operator](https://github.com/prometheus-operator/prometheus-operator) instance running. If you don't already have a running instance, deploy one following the docs from [here](https://github.com/appscode/third-party-tools/blob/master/monitoring/prometheus/operator/README.md). -- If you already don't have a Prometheus server running, deploy one following tutorial from [here](https://github.com/appscode/third-party-tools/blob/master/monitoring/prometheus/operator/README.md#deploy-prometheus-server). > Note: YAML files used in this tutorial are stored in [docs/examples/pgbouncer](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/pgbouncer) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). ## Find out required labels for ServiceMonitor -We need to know the labels used to select `ServiceMonitor` by a `Prometheus` crd. We are going to provide these labels in `spec.monitor.prometheus.labels` field of PgBouncer crd so that KubeDB creates `ServiceMonitor` object accordingly. +We need to know the labels used to select `ServiceMonitor` by a `Prometheus` crd. We are going to provide these labels in `spec.monitor.prometheus.serviceMonitor.labels` field of PgBouncer crd so that KubeDB creates `ServiceMonitor` object accordingly. -As a prerequisite, we need to have Prometheus operator running, and a prometheus server created to monitor PgBouncer exporter. In this tutorial we are going to use a prometheus server named `promethus` in `monitoring` namespace. You can use the following to install `Prometheus operator`. +At first, let's find out the available Prometheus server in our cluster. ```bash -$ kubectl apply -f https://raw.githubusercontent.com/appscode/third-party-tools/master/monitoring/prometheus/coreos-operator/artifacts/operator.yaml -``` - -Now, get a prometheus server up and running. - -```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/monitoring/coreos-prom-server.yaml - -clusterrole.rbac.authorization.k8s.io/prometheus created -serviceaccount/prometheus created -clusterrolebinding.rbac.authorization.k8s.io/prometheus created -prometheus.monitoring.coreos.com/prometheus created +$ kubectl get prometheus --all-namespaces +NAMESPACE NAME VERSION REPLICAS AGE +monitoring prometheus-kube-prometheus-prometheus v2.39.0 1 13d ``` -Now, let's find out the available Prometheus server in our cluster. +> If you don't have any Prometheus server running in your cluster, deploy one following the guide specified in **Before You Begin** section. +Now, let's view the YAML of the available Prometheus server `prometheus` in `monitoring` namespace. ```bash - -$ kubectl get prometheus --all-namespaces -NAMESPACE NAME AGE -default tufted-rodent-prometheus-o-prometheus 3h42m -monitoring prometheus 18m +$ kubectl get prometheus -n monitoring prometheus-kube-prometheus-prometheus -o yaml ``` - -Now, let's view the YAML of the available Prometheus server `prometheus` in `monitoring` namespace. - ```yaml -$ kubectl get prometheus -n monitoring prometheus -o yaml apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: annotations: - kubectl.kubernetes.io/last-applied-configuration: | - {"apiVersion":"monitoring.coreos.com/v1","kind":"Prometheus","metadata":{"annotations":{},"labels":{"prometheus":"prometheus"},"name":"prometheus","namespace":"monitoring"},"spec":{"replicas":1,"resources":{"requests":{"memory":"400Mi"}},"serviceAccountName":"prometheus","serviceMonitorSelector":{"matchLabels":{"release":"prometheus"}}}} - creationTimestamp: "2019-09-19T09:32:12Z" + meta.helm.sh/release-name: prometheus + meta.helm.sh/release-namespace: monitoring + creationTimestamp: "2024-07-15T09:54:08Z" generation: 1 labels: - prometheus: prometheus - name: prometheus + app: kube-prometheus-stack-prometheus + app.kubernetes.io/instance: prometheus + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/part-of: kube-prometheus-stack + app.kubernetes.io/version: 61.2.0 + chart: kube-prometheus-stack-61.2.0 + heritage: Helm + release: prometheus + name: prometheus-kube-prometheus-prometheus namespace: monitoring - resourceVersion: "38348" - selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/prometheuses/prometheus - uid: f9285974-3349-40e8-815a-8f50c3a8a4f5 + resourceVersion: "83770" + uid: 7144c771-beff-4285-b7a4-bc105c408bd2 spec: + alerting: + alertmanagers: + - apiVersion: v2 + name: prometheus-kube-prometheus-alertmanager + namespace: monitoring + pathPrefix: / + port: http-web + automountServiceAccountToken: true + enableAdminAPI: false + evaluationInterval: 30s + externalUrl: http://prometheus-kube-prometheus-prometheus.monitoring:9090 + hostNetwork: false + image: quay.io/prometheus/prometheus:v2.53.0 + listenLocal: false + logFormat: logfmt + logLevel: info + paused: false + podMonitorNamespaceSelector: {} + podMonitorSelector: + matchLabels: + release: prometheus + portName: http-web + probeNamespaceSelector: {} + probeSelector: + matchLabels: + release: prometheus replicas: 1 - resources: - requests: - memory: 400Mi - serviceAccountName: prometheus + retention: 10d + routePrefix: / + ruleNamespaceSelector: {} + ruleSelector: + matchLabels: + release: prometheus + scrapeConfigNamespaceSelector: {} + scrapeConfigSelector: + matchLabels: + release: prometheus + scrapeInterval: 30s + securityContext: + fsGroup: 2000 + runAsGroup: 2000 + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + serviceAccountName: prometheus-kube-prometheus-prometheus + serviceMonitorNamespaceSelector: {} serviceMonitorSelector: matchLabels: release: prometheus + shards: 1 + tsdb: + outOfOrderTimeWindow: 0s + version: v2.53.0 + walCompression: true +status: + availableReplicas: 1 + conditions: + - lastTransitionTime: "2024-07-15T09:56:09Z" + message: "" + observedGeneration: 1 + reason: "" + status: "True" + type: Available + - lastTransitionTime: "2024-07-15T09:56:09Z" + message: "" + observedGeneration: 1 + reason: "" + status: "True" + type: Reconciled + paused: false + replicas: 1 + selector: app.kubernetes.io/instance=prometheus-kube-prometheus-prometheus,app.kubernetes.io/managed-by=prometheus-operator,app.kubernetes.io/name=prometheus,operator.prometheus.io/name=prometheus-kube-prometheus-prometheus,prometheus=prometheus-kube-prometheus-prometheus + shardStatuses: + - availableReplicas: 1 + replicas: 1 + shardID: "0" + unavailableReplicas: 0 + updatedReplicas: 1 + shards: 1 + unavailableReplicas: 0 + updatedReplicas: 1 ``` -Notice the `spec.serviceMonitorSelector` section. Here, `release: prometheus` label is used to select `ServiceMonitor` crd. So, we are going to use this label in `spec.monitor.prometheus.labels` field of PgBouncer crd. +Notice the `spec.serviceMonitorSelector` section. Here, `release: prometheus` label is used to select `ServiceMonitor` crd. So, we are going to use this label in `spec.monitor.prometheus.serviceMonitor.labels` field of PgBouncer crd. + +## Prepare Postgres +Prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. ## Deploy PgBouncer with Monitoring Enabled -We will need a PgBouncer with monitoring enabled. This PgBouncer needs to be connected to PostgreSQL database(s). You can get a PgBouncer setup with active connection(s) to PostgreSQL by following the [quickstart](/docs/guides/pgbouncer/quickstart/quickstart.md) guide. PgBouncer object in that guide didn't come with monitoring. So we are going to enable monitoring in it. Below is the PgBouncer object that contains Prometheus operator based monitoring: +At first, let's deploy an PgBouncer database with monitoring enabled. Below is the PgBouncer object that we are going to create. ```yaml apiVersion: kubedb.com/v1 kind: PgBouncer metadata: - name: pgbouncer-server + name: coreos-prom-pb namespace: demo spec: - version: "1.17.0" replicas: 1 + version: "1.18.0" database: syncUsers: true databaseName: "postgres" databaseRef: - name: "quick-postgres" + name: "ha-postgres" namespace: demo connectionPool: - maxClientConnections: 20 - reservePoolSize: 5 + poolMode: session + port: 5432 + deletionPolicy: WipeOut monitor: agent: prometheus.io/operator prometheus: @@ -132,155 +210,162 @@ spec: Here, - `monitor.agent: prometheus.io/operator` indicates that we are going to monitor this server using Prometheus operator. -- `monitor.prometheus.namespace: monitoring` specifies that KubeDB should create `ServiceMonitor` in `monitoring` namespace. - -- `monitor.prometheus.labels` specifies that KubeDB should create `ServiceMonitor` with these labels. - +- `monitor.prometheus.serviceMonitor.labels` specifies that KubeDB should create `ServiceMonitor` with these labels. - `monitor.prometheus.interval` indicates that the Prometheus server should scrape metrics from this database with 10 seconds interval. Let's create the PgBouncer object that we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/monitoring/coreos-prom-pgbouncer.yaml -pgbouncer.kubedb.com/pgbouncer-server configured +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/monitoring/coreos-prom-pb.yaml +pgbouncer.kubedb.com/coreos-prom-pb created ``` Now, wait for the database to go into `Running` state. ```bash -$ kubectl get pb -n demo pgbouncer-server -NAME VERSION STATUS AGE -pgbouncer-server 1.17.0 Running 10s +$ kubectl get pb -n demo coreos-prom-pb +NAME TYPE VERSION STATUS AGE +coreos-prom-pb kubedb.com/v1 1.18.0 Ready 65s ``` KubeDB will create a separate stats service with name `{PgBouncer crd name}-stats` for monitoring purpose. ```bash -$ kubectl get svc -n demo --selector="app.kubernetes.io/instance=pgbouncer-server" -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -pgbouncer-server ClusterIP 10.104.83.201 5432/TCP 52s -pgbouncer-server-stats ClusterIP 10.101.214.117 56790/TCP 50s +$ kubectl get svc -n demo --selector="app.kubernetes.io/instance=coreos-prom-pb" +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +coreos-prom-pb ClusterIP 10.96.201.180 9999/TCP,9595/TCP 4m3s +coreos-prom-pb-pods ClusterIP None 9999/TCP 4m3s +coreos-prom-pb-stats ClusterIP 10.96.73.22 9719/TCP 4m3s ``` -Here, `pgbouncer-server-stats` service has been created for monitoring purpose. +Here, `coreos-prom-pb-stats` service has been created for monitoring purpose. Let's describe this stats service. +```bash +$ kubectl describe svc -n demo coreos-prom-pb-stats +``` ```yaml -$ kubectl describe svc -n demo pgbouncer-server-stats -Name: pgbouncer-server-stats +Name: coreos-prom-pb-stats Namespace: demo -Labels: app.kubernetes.io/name=pgbouncers.kubedb.com - app.kubernetes.io/instance=pgbouncer-server - kubedb.com/role=stats -Annotations: monitoring.appscode.com/agent:prometheus.io/operator -Selector: app.kubernetes.io/name=pgbouncers.kubedb.com,app.kubernetes.io/instance=pgbouncer-server +Labels: app.kubernetes.io/component=connection-pooler + app.kubernetes.io/instance=coreos-prom-pb + app.kubernetes.io/managed-by=kubedb.com + app.kubernetes.io/name=pgbouncers.kubedb.com +Annotations: monitoring.appscode.com/agent: prometheus.io/operator +Selector: app.kubernetes.io/instance=coreos-prom-pb,app.kubernetes.io/managed-by=kubedb.com,app.kubernetes.io/name=pgbouncers.kubedb.com Type: ClusterIP -IP: 10.101.214.117 -Port: prom-http 56790/TCP -TargetPort: prom-http/TCP -Endpoints: 172.17.0.7:56790 +IP Family Policy: SingleStack +IP Families: IPv4 +IP: 10.96.73.22 +IPs: 10.96.73.22 +Port: metrics 9719/TCP +TargetPort: metrics/TCP +Endpoints: 10.244.0.26:9719 Session Affinity: None +Events: ``` -Notice the `Labels` and `Port` fields. `ServiceMonitor` will use these information to target its endpoints. +Notice the `Labels` and `Port` fields. `ServiceMonitor` will use this information to target its endpoints. -KubeDB will also create a `ServiceMonitor` crd in `monitoring` namespace that select the endpoints of `pgbouncer-server-stats` service. Verify that the `ServiceMonitor` crd has been created. +KubeDB will also create a `ServiceMonitor` crd in `demo` namespace that select the endpoints of `coreos-prom-pb-stats` service. Verify that the `ServiceMonitor` crd has been created. ```bash -$ kubectl get servicemonitor -n monitoring -NAME AGE -kubedb-demo-pgbouncer-server 3m4s +$ kubectl get servicemonitor -n demo +NAME AGE +coreos-prom-pb-stats 2m40s ``` Let's verify that the `ServiceMonitor` has the label that we had specified in `spec.monitor` section of PgBouncer crd. +```bash +$ kubectl get servicemonitor -n demo coreos-prom-pb-stats -o yaml +``` ```yaml -$ kubectl get servicemonitor -n monitoring kubedb-demo-pgbouncer-server -o yaml apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: - creationTimestamp: "2019-09-19T10:03:24Z" + creationTimestamp: "2024-07-15T10:42:35Z" generation: 1 labels: + app.kubernetes.io/component: connection-pooler + app.kubernetes.io/instance: coreos-prom-pb + app.kubernetes.io/managed-by: kubedb.com + app.kubernetes.io/name: pgbouncers.kubedb.com release: prometheus - monitoring.appscode.com/service: pgbouncer-server-stats.demo - name: kubedb-demo-pgbouncer-server - namespace: monitoring + name: coreos-prom-pb-stats + namespace: demo ownerReferences: - - apiVersion: v1 - blockOwnerDeletion: true - kind: Service - name: pgbouncer-server-stats - uid: 749bc2ed-e14c-4a9e-9688-9d319af2b902 - resourceVersion: "41639" - selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/servicemonitors/kubedb-demo-pgbouncer-server - uid: 4a68d942-a003-4b47-a8cb-f20e526e9748 + - apiVersion: v1 + blockOwnerDeletion: true + controller: true + kind: Service + name: coreos-prom-pb-stats + uid: 844d49bc-dfe4-4ab7-a2dc-b5ec43c3b63e + resourceVersion: "87651" + uid: a7b859d8-306e-4061-9f70-4b57c4b784f7 spec: endpoints: - - honorLabels: true - interval: 5s - path: /metrics - port: prom-http + - honorLabels: true + interval: 10s + path: /metrics + port: metrics namespaceSelector: matchNames: - - demo + - demo selector: matchLabels: + app.kubernetes.io/component: connection-pooler + app.kubernetes.io/instance: coreos-prom-pb + app.kubernetes.io/managed-by: kubedb.com app.kubernetes.io/name: pgbouncers.kubedb.com - app.kubernetes.io/instance: pgbouncer-server - kubedb.com/role: stats ``` Notice that the `ServiceMonitor` has label `release: prometheus` that we had specified in PgBouncer crd. -Also notice that the `ServiceMonitor` has selector which match the labels we have seen in the `pgbouncer-server-stats` service. It also, target the `prom-http` port that we have seen in the stats service. +Also notice that the `ServiceMonitor` has selector which match the labels we have seen in the `coreos-prom-pb-stats` service. It also, target the `metrics` port that we have seen in the stats service. ## Verify Monitoring Metrics At first, let's find out the respective Prometheus pod for `prometheus` Prometheus server. ```bash -$ kubectl get pod -n monitoring -l=app=prometheus -NAME READY STATUS RESTARTS AGE -prometheus-prometheus-0 3/3 Running 1 35m +$ kubectl get pod -n monitoring -l=app.kubernetes.io/name=prometheus +NAME READY STATUS RESTARTS AGE +prometheus-prometheus-kube-prometheus-prometheus-0 2/2 Running 1 13d ``` -Prometheus server is listening to port `9090` of `prometheus-prometheus-0` pod. We are going to use [port forwarding](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) to access Prometheus dashboard. +Prometheus server is listening to port `9090` of `prometheus-prometheus-kube-prometheus-prometheus-0` pod. We are going to use [port forwarding](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) to access Prometheus dashboard. -Run following command on a separate terminal to forward the port 9090 of `prometheus-prometheus-0` pod, +Run following command on a separate terminal to forward the port 9090 of `prometheus-prometheus-kube-prometheus-prometheus-0` pod, ```bash -$ kubectl port-forward -n monitoring prometheus-prometheus-0 9090 +$ kubectl port-forward -n monitoring prometheus-prometheus-kube-prometheus-prometheus-0 9090 Forwarding from 127.0.0.1:9090 -> 9090 Forwarding from [::1]:9090 -> 9090 ``` -Now, we can access the dashboard at `localhost:9090`. Open [http://localhost:9090/targets](http://localhost:9090/targets) in your browser. You should see `prom-http` endpoint of `pgbouncer-server-stats` service as one of the targets. +Now, we can access the dashboard at `localhost:9090`. Open [http://localhost:9090](http://localhost:9090) in your browser. You should see `metrics` endpoint of `coreos-prom-pb-stats` service as one of the targets.

  Prometheus Target

-Check the `endpoint` and `service` labels which verify that the target is our expected database. Now, you can view the collected metrics and create a graph from homepage of this Prometheus dashboard. You can also use this Prometheus server as data source for [Grafana](https://grafana.com/) and create beautiful dashboard with collected metrics. +Check the `endpoint` and `service` labels marked by the red rectangles. It verifies that the target is our expected database. Now, you can view the collected metrics and create a graph from homepage of this Prometheus dashboard. You can also use this Prometheus server as data source for [Grafana](https://grafana.com/) and create a beautiful dashboard with collected metrics. ## Cleaning up -To cleanup the Kubernetes resources created by this tutorial, run the following commands +To clean up the Kubernetes resources created by this tutorial, run following commands ```bash -# cleanup prometheus resources -kubectl delete -n monitoring prometheus prometheus -kubectl delete -n monitoring clusterrolebinding prometheus -kubectl delete -n monitoring clusterrole prometheus -kubectl delete -n monitoring serviceaccount prometheus -kubectl delete -n monitoring service prometheus-operated - -# delete namespace -kubectl delete ns monitoring +kubectl delete -n demo pb/coreos-prom-pb +kubectl delete -n demo pg/ha-postgres +kubectl delete ns demo ``` ## Next Steps -- Monitor your PgBouncer with KubeDB using [built-in Prometheus](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md). +- Monitor your PgBouncer database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md). +- Detail concepts of [PgBouncer object](/docs/guides/pgbouncer/concepts/pgbouncer.md). +- Detail concepts of [PgBouncerVersion object](/docs/guides/pgbouncer/concepts/catalog.md). - Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/pgbouncer/quickstart/quickstart.md b/docs/guides/pgbouncer/quickstart/quickstart.md index 5a366ced90..187e9ad530 100644 --- a/docs/guides/pgbouncer/quickstart/quickstart.md +++ b/docs/guides/pgbouncer/quickstart/quickstart.md @@ -47,6 +47,7 @@ $ kubectl get pgbouncerversions NAME VERSION PGBOUNCER_IMAGE DEPRECATED AGE 1.17.0 1.17.0 ghcr.io/kubedb/pgbouncer:1.17.0 22h 1.18.0 1.18.0 ghcr.io/kubedb/pgbouncer:1.18.0 22h + 1.23.1 1.23.1 ghcr.io/kubedb/pgbouncer:1.23.1 22h ``` @@ -156,7 +157,7 @@ KubeDB implements a PgBouncer crd to define the specifications of a PgBouncer. Below is the PgBouncer object created in this tutorial. -`Note`: If your `KubeDB version` is less or equal to `v2024.6.4`, You have to use `v1alpha2` apiVersion. +`Note`: If your `KubeDB version` is less or equal to `v2024.6.4`, You have to use `v1` apiVersion. ```yaml apiVersion: kubedb.com/v1 @@ -208,7 +209,7 @@ spec: ``` ```bash -$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/quickstart/pgbouncer-server-v1alpha2.yaml +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/quickstart/pgbouncer-server-v1.yaml pgbouncer.kubedb.com/pgbouncer-server created ``` @@ -258,9 +259,8 @@ Following table show what KubeDB does when you delete Postgres crd for different | Behavior | DoNotTerminate | Delete | WipeOut | |---------------------------| :------------: | :------: | :------: | | 1. Block Delete operation | ✓ | ✗ | ✗ | -| 2. Delete PetSet | ✗ | ✓ | ✓ | +| 2. Delete PetSet | ✗ | ✓ | ✓ | | 3. Delete Services | ✗ | ✓ | ✓ | -| 4. Delete PVCs | ✗ | ✓ | ✓ | | 5. Delete Secrets | ✗ | ✗ | ✓ | diff --git a/docs/guides/pgbouncer/reconfigure/_index.md b/docs/guides/pgbouncer/reconfigure/_index.md new file mode 100644 index 0000000000..9f613fd9a8 --- /dev/null +++ b/docs/guides/pgbouncer/reconfigure/_index.md @@ -0,0 +1,10 @@ +--- +title: Reconfigure +menu: + docs_{{ .version }}: + identifier: pb-reconfigure + name: Reconfigure + parent: pb-pgbouncer-guides + weight: 48 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/pgbouncer/reconfigure/overview.md b/docs/guides/pgbouncer/reconfigure/overview.md new file mode 100644 index 0000000000..d926ecaeb5 --- /dev/null +++ b/docs/guides/pgbouncer/reconfigure/overview.md @@ -0,0 +1,54 @@ +--- +title: Reconfiguring PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-reconfigure-overview + name: Overview + parent: pb-reconfigure + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfiguring PgBouncer + +This guide will give an overview on how KubeDB Ops-manager operator reconfigures `PgBouncer`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + +## How Reconfiguring PgBouncer Process Works + +The following diagram shows how KubeDB Ops-manager operator reconfigures `PgBouncer`. Open the image in a new tab to see the enlarged version. + +
+  Reconfiguring process of PgBouncer +
Fig: Reconfiguring process of PgBouncer
+
+ +The Reconfiguring PgBouncer process consists of the following steps: + +1. At first, a user creates a `PgBouncer` Custom Resource (CR). + +2. `KubeDB` Provisioner operator watches the `PgBouncer` CR. + +3. When the operator finds a `PgBouncer` CR, it creates `PetSet` and related necessary stuff like secrets, services, etc. + +4. Then, in order to reconfigure of the `PgBouncer`, the user creates a `PgBouncerOpsRequest` CR with desired information. + +5. `KubeDB` Ops-manager operator watches the `PgBouncerOpsRequest` CR. + +6. When it finds a `PgBouncerOpsRequest` CR, it pauses the `PgBouncer` object which is referred from the `PgBouncerOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `PgBouncer` object during the reconfiguring process. + +7. Then the `KubeDB` Ops-manager operator will replace the existing configuration with the new configuration provided or merge the new configuration with the existing configuration according to the `PgBouncerOpsRequest` CR. + +8. Then the `KubeDB` Ops-manager operator will perform reload operation in each Pod so that the desired configuration will replace the old configuration. + +9. After the successful reconfiguring of the `PgBouncer`, the `KubeDB` Ops-manager operator resumes the `PgBouncer` object so that the `KubeDB` Provisioner operator resumes its usual operations. + +In the next docs, we are going to show a step-by-step guide on reconfiguring PgBouncer database components using `PgBouncerOpsRequest` CRD. \ No newline at end of file diff --git a/docs/guides/pgbouncer/reconfigure/reconfigure-pgbouncer.md b/docs/guides/pgbouncer/reconfigure/reconfigure-pgbouncer.md new file mode 100644 index 0000000000..4e0e3c4f5d --- /dev/null +++ b/docs/guides/pgbouncer/reconfigure/reconfigure-pgbouncer.md @@ -0,0 +1,563 @@ +--- +title: Reconfigure Standalone PgBouncer Database +menu: + docs_{{ .version }}: + identifier: pb-reconfigure-pgbouncer + name: PgBouncer Reconfigure + parent: pb-reconfigure + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfigure PgBouncer + +This guide will show you how to use `KubeDB` Ops-manager operator to reconfigure a PgBouncer. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. + +- Install `KubeDB` Provisioner and Ops-manager operator in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + - [Reconfigure Overview](/docs/guides/pgbouncer/reconfigure/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/pgbouncer](/docs/examples/pgbouncer) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +### Prepare Postgres +For a PgBouncer surely we will need a Postgres server so, prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. + +Now, we are going to deploy a `PgBouncer` using a supported version by `KubeDB` operator. Then we are going to apply `PgBouncerOpsRequest` to reconfigure its configuration. + +### Prepare PgBouncer + +Now, we are going to deploy a `PgBouncer` with version `1.18.0`. + +### Deploy PgBouncer + +At first, we will create `pgbouncer.ini` file containing required configuration settings. + +```ini +$ cat pgbouncer.ini +[pgbouncer] +auth_type = scram-sha-256 +``` +Here, `auth_type` is set to `scram-sha-256`, whereas the default value is `md5`. + +Now, we will create a secret with this configuration file. + +```bash +$ kubectl create secret generic -n demo pb-custom-config --from-file=./pgbouncer.ini +secret/pb-custom-config created +``` + +In this section, we are going to create a PgBouncer object specifying `spec.configSecret` field to apply this custom configuration. Below is the YAML of the `PgBouncer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pb-custom + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + deletionPolicy: WipeOut +``` + +Let's create the `PgBouncer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/reconfigure/pb-custom-config.yaml +pgbouncer.kubedb.com/pb-custom created +``` + +Now, wait until `pb-custom` has status `Ready`. i.e, + +```bash +$ kubectl get pb -n demo +NAME TYPE VERSION STATUS AGE +pb-custom kubedb.com/v1 1.18.0 Ready 112s +``` + +Now, we will check if the pgbouncer has started with the custom configuration we have provided. + +Now, you can exec into the pgbouncer pod and find if the custom configuration is there, + +```bash +$ kubectl exec -it -n demo pb-custom-0 -- /bin/sh +pb-custom-0:/$ cat etc/config/pgbouncer.ini +[databases] +postgres= host=ha-postgres.demo.svc port=5432 dbname=postgres + +[pgbouncer] +max_client_conn = 87 +default_pool_size = 2 +min_pool_size = 1 +max_db_connections = 1 +logfile = /tmp/pgbouncer.log +listen_port = 5432 +ignore_startup_parameters = extra_float_digits +pidfile = /tmp/pgbouncer.pid +listen_addr = * +reserve_pool_size = 5 +reserve_pool_timeout = 5 +auth_type = scram-sha-256 +auth_file = /var/run/pgbouncer/secret/userlist +admin_users = pgbouncer +pool_mode = session +max_user_connections = 2 +stats_period = 60 +pb-custom-0:/$ exit +exit +``` + +As we can see from the configuration of running pgbouncer, the value of `auth_type` has been set to `scram-sha-256`. + +### Reconfigure using new secret + +Now we will reconfigure this pgbouncer to set `auth_type` to `md5`. + +Now, we will edit the `pgbouncer.ini` file containing required configuration settings. + +```ini +$ cat pgbouncer.ini +auth_type=md5 +``` + +Then, we will create a new secret with this configuration file. + +```bash +$ kubectl create secret generic -n demo new-custom-config --from-file=./pgbouncer.ini +secret/new-custom-config created +``` + +#### Create PgBouncerOpsRequest + +Now, we will use this secret to replace the previous secret using a `PgBouncerOpsRequest` CR. The `PgBouncerOpsRequest` yaml is given below, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pbops-reconfigure + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: pb-custom + configuration: + pgbouncer: + configSecret: + name: new-custom-config + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are reconfiguring `pb-csutom` pgbouncer. +- `spec.type` specifies that we are performing `Reconfigure` on our pgbouncer. +- `spec.configuration.pgbouncer.configSecret.name` specifies the name of the new secret. +- Have a look [here](/docs/guides/pgbouncer/concepts/opsrequest.md#spectimeout) on the respective sections to understand the `timeout` & `apply` fields. + +Let's create the `PgBouncerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/reconfigure/pbops-reconfigure.yaml +pgbounceropsrequest.ops.kubedb.com/pbops-reconfigure created +``` + +#### Verify the new configuration is working + +If everything goes well, `KubeDB` Ops-manager operator will update the `configSecret` of `PgBouncer` object. + +Let's wait for `PgBouncerOpsRequest` to be `Successful`. Run the following command to watch `PgBouncerOpsRequest` CR, + +```bash +$ watch kubectl get pgbounceropsrequest -n demo +Every 2.0s: kubectl get pgbounceropsrequest -n demo +NAME TYPE STATUS AGE +pbops-reconfigure Reconfigure Successful 63s +``` + +We can see from the above output that the `PgBouncerOpsRequest` has succeeded. If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed to reconfigure the pgbouncer. + +```bash +$ kubectl describe pgbounceropsrequest -n demo pbops-reconfigure +Name: pbops-reconfigure +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2024-11-28T10:06:23Z + Generation: 1 + Resource Version: 86377 + UID: f96d088e-a32b-40eb-bd9b-ca15a8370548 +Spec: + Apply: IfReady + Configuration: + Pgbouncer: + Config Secret: + Name: new-custom-config + Database Ref: + Name: pb-custom + Timeout: 5m + Type: Reconfigure +Status: + Conditions: + Last Transition Time: 2024-11-28T10:06:23Z + Message: Controller has started to Progress with Reconfigure of PgBouncerOpsRequest: demo/pbops-reconfigure + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2024-11-28T10:06:26Z + Message: paused pgbouncer database + Observed Generation: 1 + Reason: Paused + Status: True + Type: Paused + Last Transition Time: 2024-11-28T10:06:36Z + Message: Successfully updated PgBouncer + Observed Generation: 1 + Reason: UpdateDatabase + Status: True + Type: UpdateDatabase + Last Transition Time: 2024-11-28T10:06:36Z + Message: Successfully updated PgBouncer backend secret + Observed Generation: 1 + Reason: UpdateBackendSecret + Status: True + Type: UpdateBackendSecret + Last Transition Time: 2024-11-28T10:06:41Z + Message: get pod; ConditionStatus:True; PodName:pb-custom-0 + Observed Generation: 1 + Status: True + Type: GetPod--pb-custom-0 + Last Transition Time: 2024-11-28T10:07:16Z + Message: volume mount check; ConditionStatus:True; PodName:pb-custom-0 + Observed Generation: 1 + Status: True + Type: VolumeMountCheck--pb-custom-0 + Last Transition Time: 2024-11-28T10:07:21Z + Message: reload config; ConditionStatus:True; PodName:pb-custom-0 + Observed Generation: 1 + Status: True + Type: ReloadConfig--pb-custom-0 + Last Transition Time: 2024-11-28T10:07:21Z + Message: Reloading performed successfully in PgBouncer: demo/pb-custom for PgBouncerOpsRequest: pbops-reconfigure + Observed Generation: 1 + Reason: ReloadPodsSucceeded + Status: True + Type: ReloadPods + Last Transition Time: 2024-11-28T10:07:21Z + Message: Successfully Reconfigured + Observed Generation: 1 + Reason: Reconfigure + Status: True + Type: Reconfigure + Last Transition Time: 2024-11-28T10:07:21Z + Message: Controller has successfully completed with Reconfigure of PgBouncerOpsRequest: demo/pbops-reconfigure + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 70s KubeDB Ops-manager Operator Start processing for PgBouncerOpsRequest: demo/pbops-reconfigure + Normal Starting 70s KubeDB Ops-manager Operator Pausing PgBouncer databse: demo/pb-custom + Normal Successful 70s KubeDB Ops-manager Operator Successfully paused PgBouncer database: demo/pb-custom for PgBouncerOpsRequest: pbops-reconfigure + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 52s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning volume mount check; ConditionStatus:False; PodName:pb-custom-0 52s KubeDB Ops-manager Operator volume mount check; ConditionStatus:False; PodName:pb-custom-0 + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 47s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 42s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 37s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 32s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 27s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 22s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 17s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning volume mount check; ConditionStatus:True; PodName:pb-custom-0 17s KubeDB Ops-manager Operator volume mount check; ConditionStatus:True; PodName:pb-custom-0 + Warning reload config; ConditionStatus:True; PodName:pb-custom-0 12s KubeDB Ops-manager Operator reload config; ConditionStatus:True; PodName:pb-custom-0 + Warning reload config; ConditionStatus:True; PodName:pb-custom-0 12s KubeDB Ops-manager Operator reload config; ConditionStatus:True; PodName:pb-custom-0 + Normal Successful 12s KubeDB Ops-manager Operator Reloading performed successfully in PgBouncer: demo/pb-custom for PgBouncerOpsRequest: pbops-reconfigure + Normal Starting 12s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pb-custom + Normal Successful 12s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pb-custom + Normal Successful 12s KubeDB Ops-manager Operator Controller has Successfully Reconfigured PgBouncer databases: demo/pb-custom +``` + +Now let's exec into the pgbouncer pod and check the new configuration we have provided. + +```bash +$ kubectl exec -it -n demo pb-custom-0 -- /bin/sh +pb-custom-0:/$ cat etc/config/pgbouncer.ini +[databases] +postgres= host=ha-postgres.demo.svc port=5432 dbname=postgres + +[pgbouncer] +max_db_connections = 1 +logfile = /tmp/pgbouncer.log +listen_addr = * +admin_users = pgbouncer +pool_mode = session +max_client_conn = 87 +listen_port = 5432 +ignore_startup_parameters = extra_float_digits +auth_file = /var/run/pgbouncer/secret/userlist +default_pool_size = 2 +min_pool_size = 1 +max_user_connections = 2 +stats_period = 60 +auth_type = md5 +pidfile = /tmp/pgbouncer.pid +reserve_pool_size = 5 +reserve_pool_timeout = 5 +pb-custom-0:/$ exit +exit +``` + +As we can see from the configuration of running pgbouncer, the value of `auth_type` has been changed from `scram-sha-256` to `md5`. So the reconfiguration of the pgbouncer is successful. + + +### Reconfigure using apply config + +Now we will reconfigure this pgbouncer again to set `auth_type` to `scram-sha-256`. This time we won't use a new secret. We will use the `applyConfig` field of the `PgBouncerOpsRequest`. This will merge the new config in the existing secret. + +#### Create PgBouncerOpsRequest + +Now, we will use the new configuration in the `data` field in the `PgBouncerOpsRequest` CR. The `PgBouncerOpsRequest` yaml is given below, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pbops-reconfigure-apply + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: pb-custom + configuration: + pgbouncer: + applyConfig: + pgbouncer.ini: |- + [pgbouncer] + auth_type=scram-sha-256 + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are reconfiguring `pb-custom` pgbouncer. +- `spec.type` specifies that we are performing `Reconfigure` on our pgbouncer. +- `spec.configuration.pgbouncer.applyConfig` specifies the new configuration that will be merged in the existing secret. + +Let's create the `PgBouncerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/reconfigure/pbops-reconfigure-apply.yaml +pgbounceropsrequest.ops.kubedb.com/pbops-reconfigure-apply created +``` + +#### Verify the new configuration is working + +If everything goes well, `KubeDB` Ops-manager operator will merge this new config with the existing configuration. + +Let's wait for `PgBouncerOpsRequest` to be `Successful`. Run the following command to watch `PgBouncerOpsRequest` CR, + +```bash +$ watch kubectl get pgbounceropsrequest -n demo +Every 2.0s: kubectl get pgbounceropsrequest -n demo +NAME TYPE STATUS AGE +pbops-reconfigure Reconfigure Successful 9m15s +pbops-reconfigure-apply Reconfigure Successful 53s +``` + +We can see from the above output that the `PgBouncerOpsRequest` has succeeded. If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed to reconfigure the pgbouncer. + +```bash +$ kubectl describe pgbounceropsrequest -n demo pbops-reconfigure-apply +Name: pbops-reconfigure-apply +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2024-11-28T10:11:52Z + Generation: 1 + Resource Version: 86774 + UID: a4b8e8b5-0b82-4391-a8fe-66911aa5bee6 +Spec: + Apply: IfReady + Configuration: + Pgbouncer: + Apply Config: + pgbouncer.ini: [pgbouncer] +auth_type=scram-sha-256 + Database Ref: + Name: pb-custom + Timeout: 5m + Type: Reconfigure +Status: + Conditions: + Last Transition Time: 2024-11-28T10:11:52Z + Message: Controller has started to Progress with Reconfigure of PgBouncerOpsRequest: demo/pbops-reconfigure-apply + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2024-11-28T10:11:55Z + Message: paused pgbouncer database + Observed Generation: 1 + Reason: Paused + Status: True + Type: Paused + Last Transition Time: 2024-11-28T10:11:55Z + Message: Successfully updated PgBouncer + Observed Generation: 1 + Reason: UpdateDatabase + Status: True + Type: UpdateDatabase + Last Transition Time: 2024-11-28T10:11:55Z + Message: Successfully updated PgBouncer backend secret + Observed Generation: 1 + Reason: UpdateBackendSecret + Status: True + Type: UpdateBackendSecret + Last Transition Time: 2024-11-28T10:12:00Z + Message: get pod; ConditionStatus:True; PodName:pb-custom-0 + Observed Generation: 1 + Status: True + Type: GetPod--pb-custom-0 + Last Transition Time: 2024-11-28T10:12:00Z + Message: volume mount check; ConditionStatus:True; PodName:pb-custom-0 + Observed Generation: 1 + Status: True + Type: VolumeMountCheck--pb-custom-0 + Last Transition Time: 2024-11-28T10:12:05Z + Message: reload config; ConditionStatus:True; PodName:pb-custom-0 + Observed Generation: 1 + Status: True + Type: ReloadConfig--pb-custom-0 + Last Transition Time: 2024-11-28T10:12:05Z + Message: Reloading performed successfully in PgBouncer: demo/pb-custom for PgBouncerOpsRequest: pbops-reconfigure-apply + Observed Generation: 1 + Reason: ReloadPodsSucceeded + Status: True + Type: ReloadPods + Last Transition Time: 2024-11-28T10:12:05Z + Message: Successfully Reconfigured + Observed Generation: 1 + Reason: Reconfigure + Status: True + Type: Reconfigure + Last Transition Time: 2024-11-28T10:12:05Z + Message: Controller has successfully completed with Reconfigure of PgBouncerOpsRequest: demo/pbops-reconfigure-apply + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 54s KubeDB Ops-manager Operator Start processing for PgBouncerOpsRequest: demo/pbops-reconfigure-apply + Normal Starting 54s KubeDB Ops-manager Operator Pausing PgBouncer databse: demo/pb-custom + Normal Successful 54s KubeDB Ops-manager Operator Successfully paused PgBouncer database: demo/pb-custom for PgBouncerOpsRequest: pbops-reconfigure-apply + Warning get pod; ConditionStatus:True; PodName:pb-custom-0 46s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-custom-0 + Warning volume mount check; ConditionStatus:True; PodName:pb-custom-0 46s KubeDB Ops-manager Operator volume mount check; ConditionStatus:True; PodName:pb-custom-0 + Warning reload config; ConditionStatus:True; PodName:pb-custom-0 41s KubeDB Ops-manager Operator reload config; ConditionStatus:True; PodName:pb-custom-0 + Warning reload config; ConditionStatus:True; PodName:pb-custom-0 41s KubeDB Ops-manager Operator reload config; ConditionStatus:True; PodName:pb-custom-0 + Normal Successful 41s KubeDB Ops-manager Operator Reloading performed successfully in PgBouncer: demo/pb-custom for PgBouncerOpsRequest: pbops-reconfigure-apply + Normal Starting 41s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pb-custom + Normal Successful 41s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pb-custom + Normal Successful 41s KubeDB Ops-manager Operator Controller has Successfully Reconfigured PgBouncer databases: demo/pb-custom + Normal Starting 41s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pb-custom + Normal Successful 41s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pb-custom + Normal Successful 41s KubeDB Ops-manager Operator Controller has Successfully Reconfigured PgBouncer databases: demo/pb-custom +``` + +Now let's exec into the pgbouncer pod and check the new configuration we have provided. + +```bash +$ kubectl exec -it -n demo pb-custom-0 -- /bin/sh +pb-custom-0:/$ cat etc/config/pgbouncer.ini +[databases] +postgres= host=ha-postgres.demo.svc port=5432 dbname=postgres + +[pgbouncer] +stats_period = 60 +pidfile = /tmp/pgbouncer.pid +pool_mode = session +reserve_pool_timeout = 5 +max_client_conn = 87 +min_pool_size = 1 +default_pool_size = 2 +listen_addr = * +max_db_connections = 1 +max_user_connections = 2 +auth_type=scram-sha-256 +ignore_startup_parameters = extra_float_digits +admin_users = pgbouncer +auth_file = /var/run/pgbouncer/secret/userlist +logfile = /tmp/pgbouncer.log +listen_port = 5432 +reserve_pool_size = 5 +pb-custom-0:/$ exit +exit +``` + +As we can see from the configuration of running pgbouncer, the value of `auth_type` has been changed from `md5` to `scram-sha-256`. So the reconfiguration of the pgbouncer using the `applyConfig` field is successful. + +### Remove config + +This will remove all the custom config previously provided. After this Ops-manager operator will merge the new given config with the default config and apply this. + +- `spec.databaseRef.name` specifies that we are reconfiguring `pb-custom` pgbouncer. +- `spec.type` specifies that we are performing `Reconfigure` on our pgbouncer. +- `spec.configuration.pgbouncer.removeCustomConfig` specifies for boolean values to remove previous custom configuration. + + + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: +```bash +kubectl delete -n demo pb/pb-custom +kubectl delete pgbounceropsrequest -n demo pbops-reconfigure pbops-reconfigure-apply +kubectl delete pg -n demo ha-postgres +kubectl delete ns demo +``` \ No newline at end of file diff --git a/docs/guides/pgbouncer/restart/_index.md b/docs/guides/pgbouncer/restart/_index.md new file mode 100644 index 0000000000..9b528e5b81 --- /dev/null +++ b/docs/guides/pgbouncer/restart/_index.md @@ -0,0 +1,10 @@ +--- +title: Restart PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-restart + name: Restart + parent: pb-pgbouncer-guides + weight: 50 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/pgbouncer/restart/restart.md b/docs/guides/pgbouncer/restart/restart.md new file mode 100644 index 0000000000..688411ccd4 --- /dev/null +++ b/docs/guides/pgbouncer/restart/restart.md @@ -0,0 +1,189 @@ +--- +title: Restart PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-restart-details + name: Restart PgBouncer + parent: pb-restart + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Restart PgBouncer + +KubeDB supports restarting the PgBouncer via a PgBouncerOpsRequest. Restarting is useful if some pods are got stuck in some phase, or they are not working correctly. This tutorial will show you how to use that. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash + $ kubectl create ns demo + namespace/demo created + ``` + +> Note: YAML files used in this tutorial are stored in [docs/examples/pgbouncer](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/pgbouncer) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Prepare Postgres +Prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. + +## Deploy PgBouncer + +In this section, we are going to deploy a PgBouncer using KubeDB. + +```yaml +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pgbouncer + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut +``` + +Let's create the `PgBouncer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/restart/pgbouncer.yaml +pgbouncer.kubedb.com/pgbouncer created +``` + +## Apply Restart opsRequest + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: restart-pgbouncer + namespace: demo +spec: + type: Restart + databaseRef: + name: pgbouncer + timeout: 3m + apply: Always +``` + +- `spec.type` specifies the Type of the ops Request +- `spec.databaseRef` holds the name of the PgBouncer. The pgbouncer should be available in the same namespace as the opsRequest +- The meaning of `spec.timeout` & `spec.apply` fields will be found [here](/docs/guides/pgbouncer/concepts/opsrequest.md#spectimeout) + +Let's create the `PgBouncerOpsRequest` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/restart/ops.yaml +pgbounceropsrequest.ops.kubedb.com/restart-pgbouncer created +``` + +Now the Ops-manager operator will restart the pods one by one. + +```shell +$ kubectl get pbops -n demo +NAME TYPE STATUS AGE +restart-pgbouncer Restart Successful 79s + +$ kubectl get pbops -n demo -oyaml restart-pgbouncer +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"apiVersion":"ops.kubedb.com/v1alpha1","kind":"PgBouncerOpsRequest","metadata":{"annotations":{},"name":"restart-pgbouncer","namespace":"demo"},"spec":{"apply":"Always","databaseRef":{"name":"pgbouncer"},"timeout":"3m","type":"Restart"}} + creationTimestamp: "2024-07-18T06:49:50Z" + generation: 1 + name: restart-pgbouncer + namespace: demo + resourceVersion: "94394" + uid: 8d3387fc-0c21-4e14-8bed-857a7cdf5423 +spec: + apply: Always + databaseRef: + name: pgbouncer + timeout: 3m + type: Restart +status: + conditions: + - lastTransitionTime: "2024-07-18T06:49:50Z" + message: PgBouncer ops-request has started to restart pgbouncer nodes + observedGeneration: 1 + reason: Restart + status: "True" + type: Restart + - lastTransitionTime: "2024-07-18T06:49:53Z" + message: Successfully paused database + observedGeneration: 1 + reason: DatabasePauseSucceeded + status: "True" + type: DatabasePauseSucceeded + - lastTransitionTime: "2024-07-18T06:50:38Z" + message: Successfully Restarted PgBouncer nodes + observedGeneration: 1 + reason: RestartNodes + status: "True" + type: RestartNodes + - lastTransitionTime: "2024-07-18T06:49:58Z" + message: get pod; ConditionStatus:True; PodName:pgbouncer-0 + observedGeneration: 1 + status: "True" + type: GetPod--pgbouncer-0 + - lastTransitionTime: "2024-07-18T06:49:58Z" + message: evict pod; ConditionStatus:True; PodName:pgbouncer-0 + observedGeneration: 1 + status: "True" + type: EvictPod--pgbouncer-0 + - lastTransitionTime: "2024-07-18T06:50:33Z" + message: check pod running; ConditionStatus:True; PodName:pgbouncer-0 + observedGeneration: 1 + status: "True" + type: CheckPodRunning--pgbouncer-0 + - lastTransitionTime: "2024-07-18T06:50:38Z" + message: Controller has successfully restart the PgBouncer replicas + observedGeneration: 1 + reason: Successful + status: "True" + type: Successful + observedGeneration: 1 + phase: Successful +``` + + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete pgbounceropsrequest -n demo restart-pgbouncer +kubectl delete pgbouncer -n demo pgbouncer +kubectl delete ns demo +``` + +## Next Steps + +- Detail concepts of [PgBouncer object](/docs/guides/pgbouncer/concepts/pgbouncer.md). +- Monitor your PgBouncer database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md). +- Monitor your PgBouncer database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md). +- Detail concepts of [PgBouncer object](/docs/guides/pgbouncer/concepts/pgbouncer.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/pgbouncer/scaling/_index.md b/docs/guides/pgbouncer/scaling/_index.md new file mode 100644 index 0000000000..dd2566b603 --- /dev/null +++ b/docs/guides/pgbouncer/scaling/_index.md @@ -0,0 +1,10 @@ +--- +title: Scaling PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-scaling + name: Scaling + parent: pb-pgbouncer-guides + weight: 43 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/pgbouncer/scaling/horizontal-scaling/_index.md b/docs/guides/pgbouncer/scaling/horizontal-scaling/_index.md new file mode 100644 index 0000000000..96af9d6773 --- /dev/null +++ b/docs/guides/pgbouncer/scaling/horizontal-scaling/_index.md @@ -0,0 +1,10 @@ +--- +title: Horizontal Scaling +menu: + docs_{{ .version }}: + identifier: pb-horizontal-scaling + name: Horizontal Scaling + parent: pb-scaling + weight: 10 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/pgbouncer/scaling/horizontal-scaling/horizontal-ops.md b/docs/guides/pgbouncer/scaling/horizontal-scaling/horizontal-ops.md new file mode 100644 index 0000000000..f11927fc8b --- /dev/null +++ b/docs/guides/pgbouncer/scaling/horizontal-scaling/horizontal-ops.md @@ -0,0 +1,396 @@ +--- +title: Horizontal Scaling PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-horizontal-scaling-ops + name: HorizontalScaling OpsRequest + parent: pb-horizontal-scaling + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Horizontal Scale PgBouncer + +This guide will show you how to use `KubeDB` Ops-manager operator to scale the replicaset of a PgBouncer. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `KubeDB` Provisioner and Ops-manager operator in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + - [Horizontal Scaling Overview](/docs/guides/pgbouncer/scaling/horizontal-scaling/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/pgbouncer](/docs/examples/pgbouncer) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Apply Horizontal Scaling on pgbouncer + +Here, we are going to deploy a `PgBouncer` using a supported version by `KubeDB` operator. Then we are going to apply horizontal scaling on it. + +### Prepare Postgres +Prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. + +### Prepare PgBouncer + +Now, we are going to deploy a `PgBouncer` with version `1.23.1`. + +### Deploy PgBouncer + +In this section, we are going to deploy a PgBouncer. Then, in the next section we will scale the pgbouncer using `PgBouncerOpsRequest` CRD. Below is the YAML of the `PgBouncer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pb-horizontal + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut +``` +Let's create the `PgBouncer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/scaling/pb-horizontal.yaml +pgbouncer.kubedb.com/pb-horizontal created +``` + +Now, wait until `pb-horizontal ` has status `Ready`. i.e, + +```bash +$ kubectl get pb -n demo +NAME VERSION STATUS AGE +pb-horizontal 1.18.0 Ready 2m19s +``` + +Let's check the number of replicas this pgbouncer has from the PgBouncer object, number of pods the petset have, + +```bash +$ kubectl get pgbouncer -n demo pb-horizontal -o json | jq '.spec.replicas' +1 + +$ kubectl get petset -n demo pb-horizontal -o json | jq '.spec.replicas' +1 +``` + +We can see from both command that the pgbouncer has 1 replicas. + +We are now ready to apply the `PgBouncerOpsRequest` CR to scale this pgbouncer. + +## Scale Up Replicas + +Here, we are going to scale up the replicas of the pgbouncer to meet the desired number of replicas after scaling. + +#### Create PgBouncerOpsRequest + +In order to scale up the replicas of the pgbouncer, we have to create a `PgBouncerOpsRequest` CR with our desired replicas. Below is the YAML of the `PgBouncerOpsRequest` CR that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-horizontal-scale-up + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: pb-horizontal + horizontalScaling: + replicas: 3 +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing horizontal scaling operation on `pb-horizontal` pgbouncer. +- `spec.type` specifies that we are performing `HorizontalScaling` on our pgbouncer. +- `spec.horizontalScaling.replicas` specifies the desired replicas after scaling. + +Let's create the `PgBouncerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/scaling/horizontal-scaling-ops.yaml +pgbounceropsrequest.ops.kubedb.com/pgbouncer-horizontal-scale-up created +``` + +#### Verify replicas scaled up successfully + +If everything goes well, `KubeDB` Ops-manager operator will update the replicas of `PgBouncer` object and related `PetSet`. + +Let's wait for `PgBouncerOpsRequest` to be `Successful`. Run the following command to watch `PgBouncerOpsRequest` CR, + +```bash +$ watch kubectl get pgbounceropsrequest -n demo +Every 2.0s: kubectl get pgbounceropsrequest -n demo +NAME TYPE STATUS AGE +pgbouncer-horizontal-scale-up HorizontalScaling Successful 2m49s +``` + +We can see from the above output that the `PgBouncerOpsRequest` has succeeded. If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed to scale the pgbouncer. + +```bash +$ kubectl describe pgbounceropsrequest -n demo pgbouncer-horizontal-scale-up +Name: pgbouncer-horizontal-scale-up +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2024-11-27T11:12:29Z + Generation: 1 + Resource Version: 49162 + UID: ce390f66-e10f-490f-ad47-f28894d0569a +Spec: + Apply: IfReady + Database Ref: + Name: pb-horizontal + Horizontal Scaling: + Replicas: 3 + Type: HorizontalScaling +Status: + Conditions: + Last Transition Time: 2024-11-27T11:12:29Z + Message: Controller has started to Progress with HorizontalScaling of PgBouncerOpsRequest: demo/pgbouncer-horizontal-scale-up + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2024-11-27T11:12:32Z + Message: Horizontal scaling started in PgBouncer: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-up + Observed Generation: 1 + Reason: HorizontalScaleStarted + Status: True + Type: HorizontalScale + Last Transition Time: 2024-11-27T11:12:37Z + Message: patch p s; ConditionStatus:True; PodName:pb-horizontal-1 + Observed Generation: 1 + Status: True + Type: PatchPS--pb-horizontal-1 + Last Transition Time: 2024-11-27T11:12:42Z + Message: is pg bouncer running; ConditionStatus:True; PodName:pb-horizontal-1 + Observed Generation: 1 + Status: True + Type: IsPgBouncerRunning--pb-horizontal-1 + Last Transition Time: 2024-11-27T11:12:47Z + Message: patch p s; ConditionStatus:True; PodName:pb-horizontal-2 + Observed Generation: 1 + Status: True + Type: PatchPS--pb-horizontal-2 + Last Transition Time: 2024-11-27T11:12:52Z + Message: is pg bouncer running; ConditionStatus:True; PodName:pb-horizontal-2 + Observed Generation: 1 + Status: True + Type: IsPgBouncerRunning--pb-horizontal-2 + Last Transition Time: 2024-11-27T11:12:57Z + Message: Horizontal scaling Up performed successfully in PgBouncer: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-up + Observed Generation: 1 + Reason: HorizontalScaleSucceeded + Status: True + Type: HorizontalScaleUp + Last Transition Time: 2024-11-27T11:13:07Z + Message: Controller has successfully completed with HorizontalScaling of PgBouncerOpsRequest: demo/pgbouncer-horizontal-scale-up + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 2m13s KubeDB Ops-manager Operator Start processing for PgBouncerOpsRequest: demo/pgbouncer-horizontal-scale-up + Normal Starting 2m13s KubeDB Ops-manager Operator Pausing PgBouncer databse: demo/pb-horizontal + Normal Successful 2m13s KubeDB Ops-manager Operator Successfully paused PgBouncer database: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-up + Normal Starting 2m10s KubeDB Ops-manager Operator Horizontal scaling started in PgBouncer: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-up + Warning patch p s; ConditionStatus:True; PodName:pb-horizontal-1 2m5s KubeDB Ops-manager Operator patch p s; ConditionStatus:True; PodName:pb-horizontal-1 + Warning is pg bouncer running; ConditionStatus:True; PodName:pb-horizontal-1 2m KubeDB Ops-manager Operator is pg bouncer running; ConditionStatus:True; PodName:pb-horizontal-1 + Warning patch p s; ConditionStatus:True; PodName:pb-horizontal-2 115s KubeDB Ops-manager Operator patch p s; ConditionStatus:True; PodName:pb-horizontal-2 + Warning is pg bouncer running; ConditionStatus:True; PodName:pb-horizontal-2 110s KubeDB Ops-manager Operator is pg bouncer running; ConditionStatus:True; PodName:pb-horizontal-2 + Normal Successful 105s KubeDB Ops-manager Operator Horizontal scaling Up performed successfully in PgBouncer: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-up + Normal Starting 95s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pb-horizontal + Normal Successful 95s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pb-horizontal + Normal Successful 95s KubeDB Ops-manager Operator Controller has Successfully scaled the PgBouncer database: demo/pb-horizontal +``` + +Now, we are going to verify the number of replicas this pgbouncer has from the PgBouncer object, number of pods the petset have, + +```bash +$ kubectl get pb -n demo pb-horizontal -o json | jq '.spec.replicas' +3 + +$ kubectl get petset -n demo pb-horizontal -o json | jq '.spec.replicas' +3 +``` +From all the above outputs we can see that the replicas of the pgbouncer is `3`. That means we have successfully scaled up the replicas of the PgBouncer. + + +### Scale Down Replicas + +Here, we are going to scale down the replicas of the pgbouncer to meet the desired number of replicas after scaling. + +#### Create PgBouncerOpsRequest + +In order to scale down the replicas of the pgbouncer, we have to create a `PgBouncerOpsRequest` CR with our desired replicas. Below is the YAML of the `PgBouncerOpsRequest` CR that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-horizontal-scale-down + namespace: demo +spec: + type: HorizontalScaling + databaseRef: + name: pb-horizontal + horizontalScaling: + replicas: 2 +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing horizontal scaling down operation on `pb-horizontal` pgbouncer. +- `spec.type` specifies that we are performing `HorizontalScaling` on our pgbouncer. +- `spec.horizontalScaling.replicas` specifies the desired replicas after scaling. + +Let's create the `PgBouncerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/scaling/horizontal-scaling-down-ops.yaml +pgbounceropsrequest.ops.kubedb.com/pgbouncer-horizontal-scale-down created +``` + +#### Verify replicas scaled down successfully + +If everything goes well, `KubeDB` Ops-manager operator will update the replicas of `PgBouncer` object and related `PetSet`. + +Let's wait for `PgBouncerOpsRequest` to be `Successful`. Run the following command to watch `PgBouncerOpsRequest` CR, + +```bash +$ watch kubectl get pgbounceropsrequest -n demo +Every 2.0s: kubectl get pgbounceropsrequest -n demo +NAME TYPE STATUS AGE +pgbouncer-horizontal-scale-down HorizontalScaling Successful 75s +``` + +We can see from the above output that the `PgBouncerOpsRequest` has succeeded. If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed to scale the pgbouncer. + +```bash +$ kubectl describe pgbounceropsrequest -n demo pgbouncer-horizontal-scale-down +Name: pgbouncer-horizontal-scale-down +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2024-11-27T11:16:05Z + Generation: 1 + Resource Version: 49481 + UID: cf4bc042-8316-4dce-b6a2-60981af7f4db +Spec: + Apply: IfReady + Database Ref: + Name: pb-horizontal + Horizontal Scaling: + Replicas: 2 + Type: HorizontalScaling +Status: + Conditions: + Last Transition Time: 2024-11-27T11:16:05Z + Message: Controller has started to Progress with HorizontalScaling of PgBouncerOpsRequest: demo/pgbouncer-horizontal-scale-down + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2024-11-27T11:16:08Z + Message: Horizontal scaling started in PgBouncer: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-down + Observed Generation: 1 + Reason: HorizontalScaleStarted + Status: True + Type: HorizontalScale + Last Transition Time: 2024-11-27T11:16:13Z + Message: patch p s; ConditionStatus:True; PodName:pb-horizontal-3 + Observed Generation: 1 + Status: True + Type: PatchPS--pb-horizontal-3 + Last Transition Time: 2024-11-27T11:16:18Z + Message: get pod; ConditionStatus:True; PodName:pb-horizontal-2 + Observed Generation: 1 + Status: True + Type: GetPod--pb-horizontal-2 + Last Transition Time: 2024-11-27T11:16:23Z + Message: Horizontal scaling down performed successfully in PgBouncer: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-down + Observed Generation: 1 + Reason: HorizontalScaleSucceeded + Status: True + Type: HorizontalScaleDown + Last Transition Time: 2024-11-27T11:16:33Z + Message: Controller has successfully completed with HorizontalScaling of PgBouncerOpsRequest: demo/pgbouncer-horizontal-scale-down + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 2m38s KubeDB Ops-manager Operator Start processing for PgBouncerOpsRequest: demo/pgbouncer-horizontal-scale-down + Normal Starting 2m38s KubeDB Ops-manager Operator Pausing PgBouncer databse: demo/pb-horizontal + Normal Successful 2m38s KubeDB Ops-manager Operator Successfully paused PgBouncer database: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-down + Normal Starting 2m35s KubeDB Ops-manager Operator Horizontal scaling started in PgBouncer: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-down + Warning patch p s; ConditionStatus:True; PodName:pb-horizontal-3 2m30s KubeDB Ops-manager Operator patch p s; ConditionStatus:True; PodName:pb-horizontal-3 + Warning get pod; ConditionStatus:True; PodName:pb-horizontal-2 2m25s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-horizontal-2 + Normal Successful 2m20s KubeDB Ops-manager Operator Horizontal scaling down performed successfully in PgBouncer: demo/pb-horizontal for PgBouncerOpsRequest: pgbouncer-horizontal-scale-down + Normal Starting 2m10s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pb-horizontal + Normal Successful 2m10s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pb-horizontal + Normal Successful 2m10s KubeDB Ops-manager Operator Controller has Successfully scaled the PgBouncer database: demo/pb-horizontal +``` + +Now, we are going to verify the number of replicas this pgbouncer has from the PgBouncer object, number of pods the petset have, + +```bash +$ kubectl get pb -n demo pb-horizontal -o json | jq '.spec.replicas' +2 + +$ kubectl get petset -n demo pb-horizontal -o json | jq '.spec.replicas' +2 +``` +From all the above outputs we can see that the replicas of the pgbouncer is `2`. That means we have successfully scaled down the replicas of the PgBouncer. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete pb -n demo pb-horizontal +kubectl delete pgbounceropsrequest -n demo pgbouncer-horizontal-scale-down +``` \ No newline at end of file diff --git a/docs/guides/pgbouncer/scaling/horizontal-scaling/overview.md b/docs/guides/pgbouncer/scaling/horizontal-scaling/overview.md new file mode 100644 index 0000000000..44681355b9 --- /dev/null +++ b/docs/guides/pgbouncer/scaling/horizontal-scaling/overview.md @@ -0,0 +1,54 @@ +--- +title: PgBouncer Horizontal Scaling Overview +menu: + docs_{{ .version }}: + identifier: pb-horizontal-scaling-overview + name: Overview + parent: pb-horizontal-scaling + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# PgBouncer Horizontal Scaling + +This guide will give an overview on how KubeDB Ops-manager operator scales up or down `PgBouncer` replicas of PetSet. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + +## How Horizontal Scaling Process Works + +The following diagram shows how KubeDB Ops-manager operator scales up or down `PgBouncer` database components. Open the image in a new tab to see the enlarged version. + +
+  Horizontal scaling process of PgBouncer +
Fig: Horizontal scaling process of PgBouncer
+
+ +The Horizontal scaling process consists of the following steps: + +1. At first, a user creates a `PgBouncer` Custom Resource (CR). + +2. `KubeDB` Provisioner operator watches the `PgBouncer` CR. + +3. When the operator finds a `PgBouncer` CR, it creates `PetSet` and related necessary stuff like secrets, services, etc. + +4. Then, in order to scale the `PetSet` of the `PgBouncer` database the user creates a `PgBouncerOpsRequest` CR with desired information. + +5. `KubeDB` Ops-manager operator watches the `PgBouncerOpsRequest` CR. + +6. When it finds a `PgBouncerOpsRequest` CR, it pauses the `PgBouncer` object which is referred from the `PgBouncerOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `PgBouncer` object during the horizontal scaling process. + +7. Then the `KubeDB` Ops-manager operator will scale the related PetSet Pods to reach the expected number of replicas defined in the `PgBouncerOpsRequest` CR. + +8. After the successfully scaling the replicas of the related PetSet Pods, the `KubeDB` Ops-manager operator updates the number of replicas in the `PgBouncer` object to reflect the updated state. + +9. After the successful scaling of the `PgBouncer` replicas, the `KubeDB` Ops-manager operator resumes the `PgBouncer` object so that the `KubeDB` Provisioner operator resumes its usual operations. + +In the next docs, we are going to show a step-by-step guide on horizontal scaling of PgBouncer using `PgBouncerOpsRequest` CRD. \ No newline at end of file diff --git a/docs/guides/pgbouncer/scaling/vertical-scaling/_index.md b/docs/guides/pgbouncer/scaling/vertical-scaling/_index.md new file mode 100644 index 0000000000..da67c6d842 --- /dev/null +++ b/docs/guides/pgbouncer/scaling/vertical-scaling/_index.md @@ -0,0 +1,10 @@ +--- +title: Vertical Scaling +menu: + docs_{{ .version }}: + identifier: pb-vertical-scaling + name: Vertical Scaling + parent: pb-scaling + weight: 20 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/pgbouncer/scaling/vertical-scaling/overview.md b/docs/guides/pgbouncer/scaling/vertical-scaling/overview.md new file mode 100644 index 0000000000..77839a6144 --- /dev/null +++ b/docs/guides/pgbouncer/scaling/vertical-scaling/overview.md @@ -0,0 +1,54 @@ +--- +title: PgBouncer Vertical Scaling Overview +menu: + docs_{{ .version }}: + identifier: pb-vertical-scaling-overview + name: Overview + parent: pb-vertical-scaling + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# PgBouncer Vertical Scaling + +This guide will give an overview on how KubeDB Ops-manager operator updates the resources(for example CPU and Memory etc.) of the `PgBouncer`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + +## How Vertical Scaling Process Works + +The following diagram shows how KubeDB Ops-manager operator updates the resources of the `PgBouncer`. Open the image in a new tab to see the enlarged version. + +
+  Vertical scaling process of PgBouncer +
Fig: Vertical scaling process of PgBouncer
+
+ +The vertical scaling process consists of the following steps: + +1. At first, a user creates a `PgBouncer` Custom Resource (CR). + +2. `KubeDB` Provisioner operator watches the `PgBouncer` CR. + +3. When the operator finds a `PgBouncer` CR, it creates `PetSet` and related necessary stuff like secrets, services, etc. + +4. Then, in order to update the resources(for example `CPU`, `Memory` etc.) of the `PgBouncer`, the user creates a `PgBouncerOpsRequest` CR with desired information. + +5. `KubeDB` Ops-manager operator watches the `PgBouncerOpsRequest` CR. + +6. When it finds a `PgBouncerOpsRequest` CR, it pauses the `PgBouncer` object which is referred from the `PgBouncerOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `PgBouncer` object during the vertical scaling process. + +7. Then the `KubeDB` Ops-manager operator will update resources of the PetSet to reach desired state. + +8. After the successful update of the resources of the PetSet's replica, the `KubeDB` Ops-manager operator updates the `PgBouncer` object to reflect the updated state. + +9. After the successful update of the `PgBouncer` resources, the `KubeDB` Ops-manager operator resumes the `PgBouncer` object so that the `KubeDB` Provisioner operator resumes its usual operations. + +In the next docs, we are going to show a step-by-step guide on updating resources of PgBouncer `PgBouncerOpsRequest` CRD. \ No newline at end of file diff --git a/docs/guides/pgbouncer/scaling/vertical-scaling/vertical-ops.md b/docs/guides/pgbouncer/scaling/vertical-scaling/vertical-ops.md new file mode 100644 index 0000000000..eb3bb8da08 --- /dev/null +++ b/docs/guides/pgbouncer/scaling/vertical-scaling/vertical-ops.md @@ -0,0 +1,304 @@ +--- +title: Vertical Scaling PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-vertical-scaling-ops + name: VerticalScaling OpsRequest + parent: pb-vertical-scaling + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Vertical Scale PgBouncer + +This guide will show you how to use `KubeDB` Ops-manager operator to update the resources of a PgBouncer. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `KubeDB` Provisioner and Ops-manager operator in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + - [Vertical Scaling Overview](/docs/guides/pgbouncer/scaling/vertical-scaling/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/pgbouncer](/docs/examples/pgbouncer) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +## Apply Vertical Scaling on PgBouncer + +Here, we are going to deploy a `PgBouncer` using a supported version by `KubeDB` operator. Then we are going to apply vertical scaling on it. + +### Prepare Postgres +Prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. + +### Prepare PgBouncer + +Now, we are going to deploy a `PgBouncer` with version `1.18.0`. + +### Deploy PgBouncer + +In this section, we are going to deploy a PgBouncer. Then, in the next section we will update the resources using `PgBouncerOpsRequest` CRD. Below is the YAML of the `PgBouncer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pb-vertical + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut +``` + +Let's create the `PgBouncer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/scaling/pb-vertical.yaml +pgbouncer.kubedb.com/pb-vertical created +``` + +Now, wait until `pb-vertical` has status `Ready`. i.e, + +```bash +$ kubectl get pb -n demo +NAME TYPE VERSION STATUS AGE +pb-vertical kubedb.com/v1 1.18.0 Ready 17s +``` + +Let's check the Pod containers resources, + +```bash +$ kubectl get pod -n demo pb-vertical-0 -o json | jq '.spec.containers[].resources' +{ + "limits": { + "memory": "1Gi" + }, + "requests": { + "cpu": "500m", + "memory": "1Gi" + } +} +``` + +You can see the Pod has default resources which is assigned by the KubeDB operator. + +We are now ready to apply the `PgBouncerOpsRequest` CR to update the resources of this pgbouncer. + +### Vertical Scaling + +Here, we are going to update the resources of the pgbouncer to meet the desired resources after scaling. + +#### Create PgBouncerOpsRequest + +In order to update the resources of the pgbouncer, we have to create a `PgBouncerOpsRequest` CR with our desired resources. Below is the YAML of the `PgBouncerOpsRequest` CR that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-scale-vertical + namespace: demo +spec: + type: VerticalScaling + databaseRef: + name: pb-vertical + verticalScaling: + pgbouncer: + resources: + requests: + memory: "2Gi" + cpu: "1" + limits: + memory: "2Gi" + cpu: "1" + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing vertical scaling operation on `pb-vertical` pgbouncer. +- `spec.type` specifies that we are performing `VerticalScaling` on our database. +- `spec.VerticalScaling.pgbouncer` specifies the desired resources after scaling. +- Have a look [here](/docs/guides/pgbouncer/concepts/opsrequest.md) on the respective sections to understand the `timeout` & `apply` fields. + +Let's create the `PgBouncerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/scaling/pb-vertical-ops.yaml +pgbounceropsrequest.ops.kubedb.com/pgbouncer-scale-vertical created +``` + +#### Verify PgBouncer resources updated successfully + +If everything goes well, `KubeDB` Ops-manager operator will update the resources of `PgBouncer` object and related `PetSet` and `Pods`. + +Let's wait for `PgBouncerOpsRequest` to be `Successful`. Run the following command to watch `PgBouncerOpsRequest` CR, + +```bash +$ kubectl get pgbounceropsrequest -n demo +Every 2.0s: kubectl get pgbounceropsrequest -n demo +NAME TYPE STATUS AGE +pgbouncer-scale-vertical VerticalScaling Successful 3m42s +``` + +We can see from the above output that the `PgBouncerOpsRequest` has succeeded. If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed to scale the pgbouncer. + +```bash +$ kubectl describe pgbounceropsrequest -n demo pgbouncer-scale-vertical +Name: pgbouncer-scale-vertical +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2024-11-27T12:35:02Z + Generation: 1 + Resource Version: 55854 + UID: 567e12f9-b561-4fea-af91-1ed9412a0d74 +Spec: + Apply: IfReady + Database Ref: + Name: pb-vertical + Timeout: 5m + Type: VerticalScaling + Vertical Scaling: + Pgbouncer: + Resources: + Limits: + Cpu: 1 + Memory: 2Gi + Requests: + Cpu: 1 + Memory: 2Gi +Status: + Conditions: + Last Transition Time: 2024-11-27T12:35:02Z + Message: Controller has started to Progress with VerticalScaling of PgBouncerOpsRequest: demo/pgbouncer-scale-vertical + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2024-11-27T12:35:08Z + Message: Successfully updated Petset resource + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-27T12:35:13Z + Message: get pod; ConditionStatus:True; PodName:pb-vertical-0 + Observed Generation: 1 + Status: True + Type: GetPod--pb-vertical-0 + Last Transition Time: 2024-11-27T12:35:13Z + Message: evict pod; ConditionStatus:True; PodName:pb-vertical-0 + Observed Generation: 1 + Status: True + Type: EvictPod--pb-vertical-0 + Last Transition Time: 2024-11-27T12:35:18Z + Message: check replica func; ConditionStatus:True; PodName:pb-vertical-0 + Observed Generation: 1 + Status: True + Type: CheckReplicaFunc--pb-vertical-0 + Last Transition Time: 2024-11-27T12:35:18Z + Message: check pod ready; ConditionStatus:True; PodName:pb-vertical-0 + Observed Generation: 1 + Status: True + Type: CheckPodReady--pb-vertical-0 + Last Transition Time: 2024-11-27T12:35:38Z + Message: check pg bouncer running; ConditionStatus:True; PodName:pb-vertical-0 + Observed Generation: 1 + Status: True + Type: CheckPgBouncerRunning--pb-vertical-0 + Last Transition Time: 2024-11-27T12:35:43Z + Message: Vertical scaling Up performed successfully in PgBouncer: demo/pb-vertical for PgBouncerOpsRequest: pgbouncer-scale-vertical + Observed Generation: 1 + Reason: VerticalScaleSucceeded + Status: True + Type: VerticalScale + Last Transition Time: 2024-11-27T12:35:53Z + Message: Controller has successfully completed with VerticalScaling of PgBouncerOpsRequest: demo/pgbouncer-scale-vertical + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 81s KubeDB Ops-manager Operator Start processing for PgBouncerOpsRequest: demo/pgbouncer-scale-vertical + Normal Starting 81s KubeDB Ops-manager Operator Pausing PgBouncer databse: demo/pb-vertical + Normal Successful 81s KubeDB Ops-manager Operator Successfully paused PgBouncer database: demo/pb-vertical for PgBouncerOpsRequest: pgbouncer-scale-vertical + Warning get pod; ConditionStatus:True; PodName:pb-vertical-0 70s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-vertical-0 + Warning evict pod; ConditionStatus:True; PodName:pb-vertical-0 70s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:pb-vertical-0 + Warning check replica func; ConditionStatus:True; PodName:pb-vertical-0 65s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pb-vertical-0 + Warning check pod ready; ConditionStatus:True; PodName:pb-vertical-0 65s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pb-vertical-0 + Warning check pg bouncer running; ConditionStatus:False; PodName:pb-vertical-0 55s KubeDB Ops-manager Operator check pg bouncer running; ConditionStatus:False; PodName:pb-vertical-0 + Warning check replica func; ConditionStatus:True; PodName:pb-vertical-0 55s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pb-vertical-0 + Warning check pod ready; ConditionStatus:True; PodName:pb-vertical-0 55s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pb-vertical-0 + Warning check replica func; ConditionStatus:True; PodName:pb-vertical-0 45s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pb-vertical-0 + Warning check pod ready; ConditionStatus:True; PodName:pb-vertical-0 45s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pb-vertical-0 + Warning check pg bouncer running; ConditionStatus:True; PodName:pb-vertical-0 45s KubeDB Ops-manager Operator check pg bouncer running; ConditionStatus:True; PodName:pb-vertical-0 + Normal Successful 40s KubeDB Ops-manager Operator Vertical scaling Up performed successfully in PgBouncer: demo/pb-vertical for PgBouncerOpsRequest: pgbouncer-scale-vertical + Normal Starting 30s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pb-vertical + Normal Successful 30s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pb-vertical + Normal Starting 30s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pb-vertical + Normal Successful 30s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pb-vertical + Normal Successful 30s KubeDB Ops-manager Operator Controller has Successfully scaled the PgBouncer database: demo/pb-vertical +``` + +Now, we are going to verify from the Pod yaml whether the resources of the pgbouncer has updated to meet up the desired state, Let's check, + +```bash +$ kubectl get pod -n demo pb-vertical-0 -o json | jq '.spec.containers[].resources' +{ + "limits": { + "cpu": "1", + "memory": "2Gi" + }, + "requests": { + "cpu": "1", + "memory": "2Gi" + } +} +``` + +The above output verifies that we have successfully scaled up the resources of the PgBouncer. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete pb -n demo pb-vertical +kubectl delete pgbounceropsrequest -n demo pgbouncer-scale-vertical +``` \ No newline at end of file diff --git a/docs/guides/pgbouncer/sync-users/_index.md b/docs/guides/pgbouncer/sync-users/_index.md new file mode 100755 index 0000000000..43e4e2a7a8 --- /dev/null +++ b/docs/guides/pgbouncer/sync-users/_index.md @@ -0,0 +1,10 @@ +--- +title: Runtime users sync to PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-sync-users + name: Sync Users + parent: pb-pgbouncer-guides + weight: 30 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/pgbouncer/sync-users/sync-users-pgbouncer.md b/docs/guides/pgbouncer/sync-users/sync-users-pgbouncer.md new file mode 100644 index 0000000000..8184e0bc8a --- /dev/null +++ b/docs/guides/pgbouncer/sync-users/sync-users-pgbouncer.md @@ -0,0 +1,195 @@ +--- +title: Runtime users sync to PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-sync-users-pgbouncer + name: Sync users pgbouncer + parent: pb-sync-users + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Using Sync Users + +KubeDB supports providing a way to add/update users to PgBouncer in runtime simply by creating secret with defined keys and labels. This tutorial will show you how to use KubeDB to sync a user to PgBouncer on runtime. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. Run the following command to prepare your cluster for this tutorial: + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +> Note: The yaml files used in this tutorial are stored in [docs/examples/pgbouncer](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/pgbouncer) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Overview + +KubeDB operator allows us to sync additional Postgres users to PgBouncer on runtime by setting `spec.syncUsers` to `true`, if this option is true KubeDB operator searches for secrets in the namespace of the Postgres mentioned with some certain labels. Then if the secret have username and password as key KubeDB operator will sync the username and password to PgBouncer. Again not only to add a user but also this feature can also be used for updating a user's password. + +At first, we need to create a secret that contains a `user` key and a `password` key which contains the `username` and `password` respectively. Also, we need to add two labels `` and `postgreses.kubedb.com`. The namespace must be ``. Below given a sample structure of the secret. + +Example: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: ha-postgres + app.kubernetes.io/name: postgreses.kubedb.com + name: pg-user + namespace: demo +stringData: + password: "12345" + username: "alice" +``` +- `app.kubernetes.io/instance` should be same as`appbinding name mentioned in .spec.postgresRef.name`. +- `app.kubernetes.io/name` should be `postgreses.kubedb.com`. +- `namespace` should be same as `namespace mentioned in .spec.postgresRef.namespace`. + +In every `20 seconds` KubeDB operator will sync all the users to PgBouncer. + +Secrets provided by users are not managed by KubeDB, and therefore, won't be modified or garbage collected by the KubeDB operator (version 0.13.0 and higher). + +### Prepare Postgres +For a PgBouncer surely we will need a Postgres server so, prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. + +### Prepare PgBouncer + +Now, we are going to deploy a `PgBouncer` with version `1.23.1`. + +### Deploy PgBouncer + +Below is the YAML of the `PgBouncer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pgbouncer-sync + namespace: demo +spec: + version: "1.23.1" + replicas: 1 + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + deletionPolicy: WipeOut +``` + +Let's create the `PgBouncer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/sync-users/pgbouncer-sync.yaml +pgbouncer.kubedb.com/pgbouncer-sync created +``` + +Now, wait until `pgbouncer-sync` has status `Ready`. i.e, + +```bash +$ kubectl get pb -n demo +NAME TYPE VERSION STATUS AGE +pgbouncer-sync kubedb.com/v1 1.18.0 Ready 41s +``` + +### Sync Users + +Now, create a secret with structure defined [here](/docs/guides/pgbouncer/concepts/pgbouncer.md#specsyncusers). Below is the YAML of the `secret` that we are going to create, + +```yaml +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/instance: ha-postgres + app.kubernetes.io/name: postgreses.kubedb.com + name: sync-secret + namespace: demo +stringData: + password: "12345" + username: "john" +``` + +Now, create the secret by applying the yaml above. + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/sync-users/secret.yaml +secret/sync-secret created +``` + +Now, after `20 seconds` you can exec into the pgbouncer pod and find if the new user is there, + +```bash +$ kubectl exec -it -n demo pgbouncer-sync-0 -- /bin/sh +/$ cat /var/run/pgbouncer/secret/userlist +"postgres" "md5AESOmAkfj+zX8zXLm92d6Vup6a5yASiiGScoHNDTIgBwH8=" +"john" "md5AEScbLKDSMb+KVrILhh7XEmyQ==" +"pgbouncer" "md5AESOmAkfj+zX8zXLm92d6Vup6a5yASiiGScoHNDTIgBwH8=" +/$ exit +exit +``` +We can see that the user is there in PgBouncer. So, now let's create this user and try to use this user through PgBouncer. +Now, you can connect to this pgbouncer through [psql](https://www.postgresql.org/docs/current/app-psql.html). Before that we need to port-forward to the primary service of pgbouncer. + +```bash +$ kubectl port-forward svc/pgbouncer-sync -n demo 9999:5432 +Forwarding from 127.0.0.1:9999 -> 5432 +Forwarding from [::1]:9999 -> 5432 +``` +We will use the root Postgres user to create the user, so let's get the password for the root user, so that we can use it. +```bash +$ kubectl get secrets -n demo ha-postgres-auth -o jsonpath='{.data.\password}' | base64 -d +qEeuU6cu5aH!O9CI⏎ +``` +We can use this password now, +```bash +$ export PGPASSWORD='qEeuU6cu5aH!O9CI' +$ psql --host=localhost --port=9999 --username=postgres postgres +psql (16.3 (Ubuntu 16.3-1.pgdg22.04+1), server 16.1) +Type "help" for help. + +postgres=# CREATE USER john WITH PASSWORD '12345'; +CREATE ROLE +postgres=# exit +``` +Now, let's use this john user. +```bash +$ export PGPASSWORD='12345' +$ psql --host=localhost --port=9999 --username=john postgres +psql (16.3 (Ubuntu 16.3-1.pgdg22.04+1), server 16.1) +Type "help" for help. + +postgres=> exit +``` +So, we can successfully verify that the user is registered in PgBouncer and also we can use it. + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete -n demo pb/pgbouncer-sync +kubectl delete -n demo secret/sync-secret +kubectl delete pg -n demo ha-postgres +kubectl delete ns demo +``` + +## Next Steps + +- Monitor your PgBouncer database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/pgbouncer/monitoring/using-prometheus-operator.md). +- Monitor your PgBouncer database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/pgbouncer/monitoring/using-builtin-prometheus.md). +- Detail concepts of [PgBouncer object](/docs/guides/pgbouncer/concepts/pgbouncer.md). +- Detail concepts of [PgBouncerVersion object](/docs/guides/pgbouncer/concepts/catalog.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/pgbouncer/update-version/_index.md b/docs/guides/pgbouncer/update-version/_index.md new file mode 100644 index 0000000000..98ba265037 --- /dev/null +++ b/docs/guides/pgbouncer/update-version/_index.md @@ -0,0 +1,10 @@ +--- +title: Updating PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-updating + name: Update Version + parent: pb-pgbouncer-guides + weight: 40 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/pgbouncer/update-version/overview.md b/docs/guides/pgbouncer/update-version/overview.md new file mode 100644 index 0000000000..5c6a208dc1 --- /dev/null +++ b/docs/guides/pgbouncer/update-version/overview.md @@ -0,0 +1,54 @@ +--- +title: Updating PgBouncer Overview +menu: + docs_{{ .version }}: + identifier: pb-updating-overview + name: Overview + parent: pb-updating + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# updating PgBouncer version Overview + +This guide will give you an overview on how KubeDB Ops-manager operator update the version of `PgBouncer`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + +## How update version Process Works + +The following diagram shows how KubeDB Ops-manager operator used to update the version of `PgBouncer`. Open the image in a new tab to see the enlarged version. + +
+  updating Process of Kafka +
Fig: updating Process of Kafka
+
+ +The updating process consists of the following steps: + +1. At first, a user creates a `PgBouncer` Custom Resource (CR). + +2. `KubeDB` Provisioner operator watches the `PgBouncer` CR. + +3. When the operator finds a `PgBouncer` CR, it creates required number of `PetSets` and related necessary stuff like secrets, services, etc. + +4. Then, in order to update the version of the `PgBouncer` the user creates a `PgBouncerOpsRequest` CR with the desired version. + +5. `KubeDB` Ops-manager operator watches the `PgBouncerOpsRequest` CR. + +6. When it finds a `PgBouncerOpsRequest` CR, it halts the `PgBouncer` object which is referred from the `PgBouncerOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `PgBouncer` object during the updating process. + +7. By looking at the target version from `PgBouncerOpsRequest` CR, `KubeDB` Ops-manager operator updates the image of the `PetSet`. + +8. After successfully updating the `PetSet` and their `Pods` images, the `KubeDB` Ops-manager operator updates the image of the `PgBouncer` object to reflect the updated state of the database. + +9. After successfully updating of `PgBouncer` object, the `KubeDB` Ops-manager operator resumes the `PgBouncer` object so that the `KubeDB` Provisioner operator can resume its usual operations. + +In the next doc, we are going to show a step-by-step guide on updating of a PgBouncer using updateVersion operation. \ No newline at end of file diff --git a/docs/guides/pgbouncer/update-version/update_version.md b/docs/guides/pgbouncer/update-version/update_version.md new file mode 100644 index 0000000000..a408d09694 --- /dev/null +++ b/docs/guides/pgbouncer/update-version/update_version.md @@ -0,0 +1,275 @@ +--- +title: Updating PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-updating-pgbouncer + name: Updating PgBouncer + parent: pb-updating + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# update version of PgBouncer + +This guide will show you how to use `KubeDB` Ops-manager operator to update the version of `PgBouncer`. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install `KubeDB` Provisioner and Ops-manager operator in your cluster following the steps [here](/docs/setup/README.md). + +- You should be familiar with the following `KubeDB` concepts: + - [PgBouncer](/docs/guides/pgbouncer/concepts/pgbouncer.md) + - [PgBouncerOpsRequest](/docs/guides/pgbouncer/concepts/opsrequest.md) + - [Updating Overview](/docs/guides/pgbouncer/update-version/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/pgbouncer](/docs/examples/pgbouncer) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +### Prepare Postgres +Prepare a KubeDB Postgres cluster using this [tutorial](/docs/guides/postgres/clustering/streaming_replication.md), or you can use any externally managed postgres but in that case you need to create an [appbinding](/docs/guides/pgbouncer/concepts/appbinding.md) yourself. In this tutorial we will use 3 node Postgres cluster named `ha-postgres`. + +### Prepare PgBouncer + +Now, we are going to deploy a `PgBouncer` with version `1.18.0`. + +### Deploy PgBouncer: + +In this section, we are going to deploy a PgBouncer. Then, in the next section we will update the version using `PgBouncerOpsRequest` CRD. Below is the YAML of the `PgBouncer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1 +kind: PgBouncer +metadata: + name: pb-update + namespace: demo +spec: + replicas: 1 + version: "1.18.0" + database: + syncUsers: true + databaseName: "postgres" + databaseRef: + name: "ha-postgres" + namespace: demo + connectionPool: + poolMode: session + port: 5432 + reservePoolSize: 5 + maxClientConnections: 87 + defaultPoolSize: 2 + minPoolSize: 1 + authType: md5 + deletionPolicy: WipeOut +``` + +Let's create the `PgBouncer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/update-version/pb-update.yaml +pgbouncer.kubedb.com/pb-update created +``` + +Now, wait until `pb-update` created has status `Ready`. i.e, + +```bash +$ kubectl get pb -n demo + NAME TYPE VERSION STATUS AGE + pb-update kubedb.com/v1 1.18.0 Ready 26s +``` + +We are now ready to apply the `PgBouncerOpsRequest` CR to update this PgBouncer. + +### update PgBouncer Version + +Here, we are going to update `PgBouncer` from `1.18.0` to `1.23.1`. + +#### Create PgBouncerOpsRequest: + +In order to update the PgBouncer, we have to create a `PgBouncerOpsRequest` CR with your desired version that is supported by `KubeDB`. Below is the YAML of the `PgBouncerOpsRequest` CR that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pgbouncer-version-update + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: pb-update + updateVersion: + targetVersion: 1.23.1 +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing operation on `pb-update` PgBouncer. +- `spec.type` specifies that we are going to perform `UpdateVersion` on our PgBouncer. +- `spec.updateVersion.targetVersion` specifies the expected version of the PgBouncer `1.23.1`. + + +Let's create the `PgBouncerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/update-version/pbops-update.yaml +pgbounceropsrequest.ops.kubedb.com/pgbouncer-version-update created +``` + +#### Verify PgBouncer version updated successfully : + +If everything goes well, `KubeDB` Ops-manager operator will update the image of `PgBouncer` object and related `PetSets` and `Pods`. + +Let's wait for `PgBouncerOpsRequest` to be `Successful`. Run the following command to watch `PgBouncerOpsRequest` CR, + +```bash +$ watch kubectl get pgbounceropsrequest -n demo +Every 2.0s: kubectl get pgbounceropsrequest -n demo +NAME TYPE STATUS AGE +pgbouncer-version-update UpdateVersion Successful 93s +``` + +We can see from the above output that the `PgBouncerOpsRequest` has succeeded. If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed to update the PgBouncer. + +```bash +$ kubectl describe pgbounceropsrequest -n demo pgbouncer-version-update +Name: pgbouncer-version-update +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2024-11-27T09:40:03Z + Generation: 1 + Resource Version: 41823 + UID: a53940fd-4d2d-4b4b-8ef1-0419dfbce660 +Spec: + Apply: IfReady + Database Ref: + Name: pb-update + Type: UpdateVersion + Update Version: + Target Version: 1.23.1 +Status: + Conditions: + Last Transition Time: 2024-11-27T09:40:03Z + Message: Controller has started to Progress with UpdateVersion of PgBouncerOpsRequest: demo/pgbouncer-version-update + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2024-11-27T09:40:08Z + Message: Successfully updated Petset resource + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-27T09:40:13Z + Message: get pod; ConditionStatus:True; PodName:pb-update-0 + Observed Generation: 1 + Status: True + Type: GetPod--pb-update-0 + Last Transition Time: 2024-11-27T09:40:13Z + Message: evict pod; ConditionStatus:True; PodName:pb-update-0 + Observed Generation: 1 + Status: True + Type: EvictPod--pb-update-0 + Last Transition Time: 2024-11-27T09:40:18Z + Message: check replica func; ConditionStatus:True; PodName:pb-update-0 + Observed Generation: 1 + Status: True + Type: CheckReplicaFunc--pb-update-0 + Last Transition Time: 2024-11-27T09:40:18Z + Message: check pod ready; ConditionStatus:True; PodName:pb-update-0 + Observed Generation: 1 + Status: True + Type: CheckPodReady--pb-update-0 + Last Transition Time: 2024-11-27T09:40:48Z + Message: check pg bouncer running; ConditionStatus:True; PodName:pb-update-0 + Observed Generation: 1 + Status: True + Type: CheckPgBouncerRunning--pb-update-0 + Last Transition Time: 2024-11-27T09:40:53Z + Message: Restarting all pods performed successfully in PgBouncer: demo/pb-update for PgBouncerOpsRequest: pgbouncer-version-update + Observed Generation: 1 + Reason: RestartPodsSucceeded + Status: True + Type: RestartPods + Last Transition Time: 2024-11-27T09:41:04Z + Message: Successfully updated PgBouncer + Observed Generation: 1 + Reason: UpdateDatabase + Status: True + Type: UpdateDatabase + Last Transition Time: 2024-11-27T09:41:04Z + Message: Successfully version updated + Observed Generation: 1 + Reason: VersionUpdate + Status: True + Type: VersionUpdate + Last Transition Time: 2024-11-27T09:41:04Z + Message: Controller has successfully completed with UpdateVersion of PgBouncerOpsRequest: demo/pgbouncer-version-update + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 114s KubeDB Ops-manager Operator Start processing for PgBouncerOpsRequest: demo/pgbouncer-version-update + Normal Starting 114s KubeDB Ops-manager Operator Pausing PgBouncer databse: demo/pb-update + Normal Successful 114s KubeDB Ops-manager Operator Successfully paused PgBouncer database: demo/pb-update for PgBouncerOpsRequest: pgbouncer-version-update + Warning get pod; ConditionStatus:True; PodName:pb-update-0 104s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pb-update-0 + Warning evict pod; ConditionStatus:True; PodName:pb-update-0 104s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:pb-update-0 + Warning check replica func; ConditionStatus:True; PodName:pb-update-0 99s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pb-update-0 + Warning check pod ready; ConditionStatus:True; PodName:pb-update-0 99s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pb-update-0 + Warning check pg bouncer running; ConditionStatus:False; PodName:pb-update-0 89s KubeDB Ops-manager Operator check pg bouncer running; ConditionStatus:False; PodName:pb-update-0 + Warning check replica func; ConditionStatus:True; PodName:pb-update-0 89s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pb-update-0 + Warning check pod ready; ConditionStatus:True; PodName:pb-update-0 89s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pb-update-0 + Warning check replica func; ConditionStatus:True; PodName:pb-update-0 79s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pb-update-0 + Warning check pod ready; ConditionStatus:True; PodName:pb-update-0 79s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pb-update-0 + Warning check replica func; ConditionStatus:True; PodName:pb-update-0 69s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pb-update-0 + Warning check pod ready; ConditionStatus:True; PodName:pb-update-0 69s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pb-update-0 + Warning check pg bouncer running; ConditionStatus:True; PodName:pb-update-0 69s KubeDB Ops-manager Operator check pg bouncer running; ConditionStatus:True; PodName:pb-update-0 + Normal Successful 64s KubeDB Ops-manager Operator Restarting all pods performed successfully in PgBouncer: demo/pb-update for PgBouncerOpsRequest: pgbouncer-version-update + Normal Starting 53s KubeDB Ops-manager Operator Resuming PgBouncer database: demo/pb-update + Normal Successful 53s KubeDB Ops-manager Operator Successfully resumed PgBouncer database: demo/pb-update + Normal Successful 53s KubeDB Ops-manager Operator Controller has Successfully updated the version of PgBouncer database: demo/pb-update +``` + +Now, we are going to verify whether the `PgBouncer` and the related `PetSets` their `Pods` have the new version image. Let's check, + +```bash +$ kubectl get pb -n demo pb-update -o=jsonpath='{.spec.version}{"\n"}' +1.23.1 + +$ kubectl get petset -n demo pb-update -o=jsonpath='{.spec.template.spec.containers[0].image}{"\n"}' +ghcr.io/kubedb/pgbouncer:1.23.1@sha256:9829a24c60938ab709fe9e039fecd9f0019354edf4e74bfd9e62bb2203e945ee + +$ kubectl get pods -n demo pb-update-0 -o=jsonpath='{.spec.containers[0].image}{"\n"}' +ghcr.io/kubedb/pgbouncer:1.23.1@sha256:9829a24c60938ab709fe9e039fecd9f0019354edf4e74bfd9e62bb2203e945ee +``` + +You can see from above, our `PgBouncer` has been updated with the new version. So, the update process is successfully completed. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete pb -n demo pb-update +kubectl delete pgbounceropsrequest -n demo pgbouncer-version-update +``` \ No newline at end of file diff --git a/docs/images/day-2-operation/pgbouncer/autoscaling.png b/docs/images/day-2-operation/pgbouncer/autoscaling.png new file mode 100644 index 0000000000000000000000000000000000000000..f1b2ba2f1becc15d66242d08cafa7396b6222c17 GIT binary patch literal 49475 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 G2L2zK{AE}G literal 0 HcmV?d00001 diff --git a/docs/images/day-2-operation/pgbouncer/horizontal-scaling.png b/docs/images/day-2-operation/pgbouncer/horizontal-scaling.png new file mode 100644 index 0000000000000000000000000000000000000000..9ae39092c6f7ddcc2a4d68280446fc7fe8d223e9 GIT binary patch literal 44824 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 i(?8PO3BZ93CsN-cM5|pABohHol08tTxz|4+97 literal 0 HcmV?d00001 diff --git a/docs/images/day-2-operation/pgbouncer/prometheus-operator.png b/docs/images/day-2-operation/pgbouncer/prometheus-operator.png new file mode 100644 index 0000000000000000000000000000000000000000..abcb7e8fb6fe1edf88851d6bf2e3af73c025de33 GIT binary patch literal 72921 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
+^c-Ql6c}wSX4VjOwYX_sE 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 literal 0 HcmV?d00001 diff --git a/docs/images/day-2-operation/pgbouncer/reconfiguring.png b/docs/images/day-2-operation/pgbouncer/reconfiguring.png new file mode 100644 index 0000000000000000000000000000000000000000..11c617da0c94f81a1badec0aefe3eec877787069 GIT binary patch literal 43893 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/day-2-operation/pgbouncer/vertical-scaling.svg b/docs/images/day-2-operation/pgbouncer/vertical-scaling.svg new file mode 100644 index 0000000000..e8effa6bdf --- /dev/null +++ b/docs/images/day-2-operation/pgbouncer/vertical-scaling.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/pgbouncer/monitoring/pb-builtin-prom-target.png b/docs/images/pgbouncer/monitoring/pb-builtin-prom-target.png index c7f19ea488629a871ecbda0738ae1504b73c1fe8..882e0b29ceeccc311b06709e8504b51c01ad6808 100644 GIT binary patch literal 56304 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 cwD|!s`w-4#$(KzA26{<|$bPT