diff --git a/README.md b/README.md index 324f1f2b..ff1b86f7 100644 --- a/README.md +++ b/README.md @@ -27,3 +27,25 @@ For information regarding the software versions of the components included and K The examples provided in this project repository are available subject to the [Apache 2.0](https://github.com/CrunchyData/postgres-operator-examples/blob/-/LICENSE.md) license with the PGO logo and branding assets covered by our [trademark guidelines](https://github.com/CrunchyData/postgres-operator/blob/-/docs/static/logos/TRADEMARKS.md). The examples as provided in this repo are designed for the use of PGO along with Crunchy Data's Postgres distribution, Crunchy Postgres, as Crunchy Postgres for Kubernetes. The unmodified use of these examples will result in downloading container images from Crunchy Data repositories - specifically the Crunchy Data Developer Portal. The use of container images downloaded from the Crunchy Data Developer Portal are subject to the [Crunchy Data Developer Program terms](https://www.crunchydata.com/developers/terms-of-use). + + +$RHINO_USER_PASSWORD='wq/etO{sk9ulgIqBGz/29.lD' + +kubectl create secret generic pgadmin-password-secret -n postgres-operator --from-literal=rhino-password=wq/etO{sk9ulgIqBGz/29.lD + + +kubectl get crd --selector postgres-operator.crunchydata.com/control-plane=postgres-operator + +NAME CREATED AT +pgadmins.postgres-operator.crunchydata.com ... + + +PG_CLUSTER_USER_SECRET_NAME=hippo-pguser-rhino + +PGPASSWORD=$(kubectl get secrets -n postgres-operator "${PG_CLUSTER_USER_SECRET_NAME}" -o go-template='{{.data.password | base64decode}}') \ e=) +PGUSER=$(kubectl get secrets -n postgres-operator "${PG_CLUSTER_USER_SECRET_NAME}" -o go-template='{{.data.user | base64decode}}') \ rhino +PGDATABASE=$(kubectl get secrets -n postgres-operator "${PG_CLUSTER_USER_SECRET_NAME}" -o go-template='{{.data.dbname | base64decode}}') \ +psql -h localhost + +kubectl create secret generic pgadmin-password-secret -n postgres-operator --from-literal=rhino-password='e=)w@qst83|l7X} + diff --git a/docs_latest.pdf b/docs_latest.pdf new file mode 100644 index 00000000..340884cf Binary files /dev/null and b/docs_latest.pdf differ diff --git a/helm/install/values.yaml b/helm/install/values.yaml index c4b491f5..83c9279e 100644 --- a/helm/install/values.yaml +++ b/helm/install/values.yaml @@ -49,7 +49,7 @@ pgoControllerLeaseName: cpk-leader-election-lease # replicas sets the number of PGO instances. # Warning: This should only be greater than 1 if pgoControllerLeaseName is set! -replicas: 1 +replicas: 2 # imagePullSecretNames is a list of secret names to use for pulling controller images. # More info: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod diff --git a/kustomize/certmanager/certman/selfsigned-issuer.yaml b/kustomize/certmanager/certman/selfsigned-issuer.yaml index ec7ac02c..660027ab 100644 --- a/kustomize/certmanager/certman/selfsigned-issuer.yaml +++ b/kustomize/certmanager/certman/selfsigned-issuer.yaml @@ -3,5 +3,6 @@ apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: selfsigned-issuer + namespace: cert-manager spec: selfSigned: {} diff --git a/kustomize/high-availability/ha-postgres.yaml b/kustomize/high-availability/ha-postgres.yaml index db69d156..d7861e75 100644 --- a/kustomize/high-availability/ha-postgres.yaml +++ b/kustomize/high-availability/ha-postgres.yaml @@ -5,14 +5,16 @@ metadata: spec: postgresVersion: 16 instances: - - name: pgha1 - replicas: 2 + - name: instance1 + replicas: 3 dataVolumeClaimSpec: accessModes: - "ReadWriteOnce" resources: requests: storage: 1Gi + limits: + storage: 25Gi affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: @@ -22,7 +24,7 @@ spec: labelSelector: matchLabels: postgres-operator.crunchydata.com/cluster: hippo-ha - postgres-operator.crunchydata.com/instance-set: pgha1 + postgres-operator.crunchydata.com/instance-set: instance1 backups: pgbackrest: repos: @@ -36,7 +38,7 @@ spec: storage: 1Gi proxy: pgBouncer: - replicas: 2 + replicas: 3 affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: diff --git a/kustomize/install/default/kustomization.yaml b/kustomize/install/default/kustomization.yaml index d3b8b978..f0ea5885 100644 --- a/kustomize/install/default/kustomization.yaml +++ b/kustomize/install/default/kustomization.yaml @@ -34,4 +34,4 @@ patches: - name: operator env: - name: PGO_FEATURE_GATES - value: "" + value: "AutoGrowVolumes=true" diff --git a/kustomize/install/manager/manager.yaml b/kustomize/install/manager/manager.yaml index f4fbb352..0d8c10de 100644 --- a/kustomize/install/manager/manager.yaml +++ b/kustomize/install/manager/manager.yaml @@ -4,7 +4,7 @@ kind: Deployment metadata: name: pgo spec: - replicas: 1 + replicas: 2 strategy: { type: Recreate } template: spec: diff --git a/kustomize/keycloak/keycloak.yaml b/kustomize/keycloak/keycloak.yaml index bfa66376..92d1c488 100644 --- a/kustomize/keycloak/keycloak.yaml +++ b/kustomize/keycloak/keycloak.yaml @@ -22,15 +22,15 @@ spec: - name: DB_VENDOR value: "postgres" - name: DB_ADDR - valueFrom: { secretKeyRef: { name: keycloakdb-pguser-keycloakdb, key: host } } + valueFrom: { secretKeyRef: { name: hippo-pguser-rhino, key: pgbouncer-host } } - name: DB_PORT - valueFrom: { secretKeyRef: { name: keycloakdb-pguser-keycloakdb, key: port } } + valueFrom: { secretKeyRef: { name: hippo-pguser-rhino, key: pgbouncer-port } } - name: DB_DATABASE - valueFrom: { secretKeyRef: { name: keycloakdb-pguser-keycloakdb, key: dbname } } + valueFrom: { secretKeyRef: { name: hippo-pguser-rhino, key: dbname } } - name: DB_USER - valueFrom: { secretKeyRef: { name: keycloakdb-pguser-keycloakdb, key: user } } + valueFrom: { secretKeyRef: { name: hippo-pguser-rhino, key: user } } - name: DB_PASSWORD - valueFrom: { secretKeyRef: { name: keycloakdb-pguser-keycloakdb, key: password } } + valueFrom: { secretKeyRef: { name: hippo-pguser-rhino, key: password } } - name: KEYCLOAK_ADMIN value: "admin" - name: KEYCLOAK_ADMIN_PASSWORD @@ -47,3 +47,5 @@ spec: path: /realms/master port: 8080 restartPolicy: Always + + Solution: \ No newline at end of file diff --git a/kustomize/keycloak/postgres.yaml b/kustomize/keycloak/postgres.yaml index 221ecde2..1b15050a 100644 --- a/kustomize/keycloak/postgres.yaml +++ b/kustomize/keycloak/postgres.yaml @@ -3,6 +3,8 @@ kind: PostgresCluster metadata: name: keycloakdb spec: + proxy: + pgBouncer: {} postgresVersion: 16 instances: - replicas: 2 @@ -32,4 +34,4 @@ spec: - "ReadWriteOnce" resources: requests: - storage: 1Gi + storage: 1Gi \ No newline at end of file diff --git a/kustomize/pgadmin/kustomization.yaml b/kustomize/pgadmin/kustomization.yaml index 629978c1..2fa9d1e2 100644 --- a/kustomize/pgadmin/kustomization.yaml +++ b/kustomize/pgadmin/kustomization.yaml @@ -9,8 +9,8 @@ resources: secretGenerator: - name: pgadmin-password-secret literals: - - rhino-password=pgadmin + - rhino-password="x|9[iMoBy8[^","tls.crt":"","tls.key":""} +``` + +### 2. Extract and Decode the Data +Use the following commands to decode each part of the secret: + +#### Decode `ca.crt` (CA Certificate): +```bash +kubectl get secret hippo-tls -n postgres-operator -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt +``` + +#### Decode `tls.crt` (Server Certificate): +```bash +kubectl get secret hippo-tls -n postgres-operator -o jsonpath='{.data.tls\.crt}' | base64 -d > tls.crt +``` + +#### Decode `tls.key` (Server Private Key): +```bash +kubectl get secret hippo-tls -n postgres-operator -o jsonpath='{.data.tls\.key}' | base64 -d > tls.key +``` + +### 3. View the Decoded Contents +After decoding, you can view the contents of the files using the following commands: + +#### View `ca.crt`: +```bash +cat ca.crt +``` + +#### View `tls.crt`: +```bash +cat tls.crt +``` + +#### View `tls.key`: +```bash +cat tls.key +``` + +### Example Outputs + +#### `ca.crt` (Certificate Authority Certificate): +``` +-----BEGIN CERTIFICATE----- +[Base64 encoded certificate] +-----END CERTIFICATE----- +``` + +#### `tls.crt` (Server Certificate): +``` +-----BEGIN CERTIFICATE----- +[Base64 encoded certificate] +-----END CERTIFICATE----- +``` + +#### `tls.key` (Server Private Key): +``` +-----BEGIN PRIVATE KEY----- +[Base64 encoded private key] +-----END PRIVATE KEY----- +``` + +### 4. Verify the Decoded Files +You can use the `openssl` tool to verify the decoded files: + +#### Verify the Certificate: +```bash +openssl x509 -in tls.crt -text -noout +``` + +#### Verify the Private Key: +```bash +openssl rsa -in tls.key -check +``` + +### Use Cases +- The decoded files (`ca.crt`, `tls.crt`, and `tls.key`) can now be used for: + - Configuring TLS for `pgBouncer` or `PostgreSQL`. + - Testing and debugging certificate and key configurations. + +By following these steps, you can successfully decode and retrieve the contents of your certificates and private key from the Kubernetes secret. \ No newline at end of file diff --git a/kustomize/postgres/kustomization.yaml b/kustomize/postgres/kustomization.yaml index e3b72752..74474c67 100644 --- a/kustomize/postgres/kustomization.yaml +++ b/kustomize/postgres/kustomization.yaml @@ -4,4 +4,6 @@ kind: Kustomization namespace: postgres-operator resources: +- cert.yaml +- cert-repl.yaml - postgres.yaml diff --git a/kustomize/postgres/lb-pgbouncer.yaml b/kustomize/postgres/lb-pgbouncer.yaml new file mode 100644 index 00000000..8c78c209 --- /dev/null +++ b/kustomize/postgres/lb-pgbouncer.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgres-cluster-pgbouncer-loadbalancer + namespace: postgres-operator + labels: + app: postgres-cluster + annotations: + io.cilium/lb-ipam-ips: "10.1.80.156" +spec: + type: LoadBalancer + selector: + postgres-operator.crunchydata.com/cluster: hippo + postgres-operator.crunchydata.com/role: pgbouncer + ports: + - name: postgres + protocol: TCP + port: 5432 + targetPort: 5432 + externalTrafficPolicy: Local \ No newline at end of file diff --git a/kustomize/postgres/lb.yaml b/kustomize/postgres/lb.yaml new file mode 100644 index 00000000..41173471 --- /dev/null +++ b/kustomize/postgres/lb.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgres-cluster-loadbalancer + namespace: postgres-operator + labels: + app: postgres-cluster + annotations: + io.cilium/lb-ipam-ips: "10.1.80.155" +spec: + type: LoadBalancer + selector: + postgres-operator.crunchydata.com/role: master + postgres-operator.crunchydata.com/cluster: hippo + ports: + - name: postgres + protocol: TCP + port: 5432 + targetPort: 5432 + externalTrafficPolicy: Local \ No newline at end of file diff --git a/kustomize/postgres/postgres.yaml b/kustomize/postgres/postgres.yaml index 91186b13..bf83448c 100644 --- a/kustomize/postgres/postgres.yaml +++ b/kustomize/postgres/postgres.yaml @@ -4,22 +4,80 @@ metadata: name: hippo spec: postgresVersion: 16 + customReplicationTLSSecret: + name: hippo-repl-tls + customTLSSecret: + name: hippo-tls users: - name: rhino databases: - zoo + options: 'SUPERUSER' + - name: llama + databases: + - zoo + patroni: + dynamicConfiguration: + failsafe_mode: true + synchronous_mode: true + postgresql: + parameters: + synchronous_commit: 'on' + max_parallel_workers: 2 + max_worker_processes: 2 + shared_buffers: 1GB + work_mem: 2MB + pg_hba: + - "hostssl all all all scram-sha-256" instances: - name: instance1 + replicas: 3 dataVolumeClaimSpec: accessModes: - "ReadWriteOnce" resources: requests: - storage: 1Gi + storage: 10Gi + walVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 10Gi + limits: + storage: 25Gi + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: hippo + postgres-operator.crunchydata.com/instance-set: instance1 + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/instance-set: instance backups: pgbackrest: + repoHost: + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: topology.csi.vmware.com/k8s-zone + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/pgbackrest: "" repos: - name: repo1 + schedules: + full: "0 1 * * 0" + differential: "0 1 * * 1-6" volume: volumeClaimSpec: accessModes: @@ -27,3 +85,47 @@ spec: resources: requests: storage: 1Gi + limits: + storage: 25Gi + global: + repo1-retention-full: "14" + repo1-retention-full-type: time + # manual: + # repoName: repo1 + # options: + # - --type=full + # This does not trigger the one-off backup -- you have to do that by adding the postgres-operator.crunchydata.com/pgbackrest-backup annotation to your custom resource. The best way to set this annotation is with a timestamp, so you know when you initialized the backup. + # For example, for our hippo cluster, we can run the following command to trigger the one-off backup: + # kubectl annotate -n postgres-operator postgrescluster hippo postgres-operator.crunchydata.com/pgbackrest-backup="$(date)" + # PGO will detect this annotation and create a new, one-off backup Job! + # If you intend to take one-off backups with similar settings in the future, you can leave those in the spec; just update the annotation to a different value the next time you are taking a backup. + # To re-run the command above, you will need to add the --overwrite flag so the annotation's value can be updated, i.e. + # kubectl annotate -n postgres-operator postgrescluster hippo --overwrite postgres-operator.crunchydata.com/pgbackrest-backup="$(date)" + + proxy: + pgBouncer: + # customTLSSecret: + # name: hippo-tls + # config: + # databases: + # '*': host=hippo-primary port=5432 #change this port if you're not using default + # global: + # pool_mode: transaction + # query_wait_timeout: "240" + # default_pool_size: "100" + # max_client_conn: "1000" #change depending on your app requirement + # # server_tls_sslmode: verify-ca + replicas: 3 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: topology.csi.vmware.com/k8s-zone + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: hippo + postgres-operator.crunchydata.com/role: pgbouncer + monitoring: + pgmonitor: + exporter: {} \ No newline at end of file diff --git a/kustomize/postgres/sidecart-container.example.md b/kustomize/postgres/sidecart-container.example.md new file mode 100644 index 00000000..09da0920 --- /dev/null +++ b/kustomize/postgres/sidecart-container.example.md @@ -0,0 +1,35 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: sidecar-hippo +spec: + postgresVersion: 16 + instances: + - name: instance1 + containers: + - name: testcontainer + image: mycontainer1:latest + - name: testcontainer2 + image: mycontainer1:latest + dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + repos: + - name: repo1 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + proxy: + pgBouncer: + containers: + - name: bouncertestcontainer1 + image: mycontainer1:latest diff --git a/temp.json b/temp.json new file mode 100644 index 00000000..e4efe6a3 --- /dev/null +++ b/temp.json @@ -0,0 +1,62 @@ +{ + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "cattle.io/status": "{\"Conditions\":[{\"Type\":\"ResourceQuotaInit\",\"Status\":\"True\",\"Message\":\"\",\"LastUpdateTime\":\"2024-12-11T22:09:14Z\"},{\"Type\":\"InitialRolesPopulated\",\"Status\":\"True\",\"Message\":\"\",\"LastUpdateTime\":\"2024-12-11T22:09:14Z\"}]}", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"postgres-operator\"}}\n", + "lifecycle.cattle.io/create.namespace-auth": "true" + }, + "creationTimestamp": "2024-12-11T22:09:18Z", + "deletionTimestamp": "2024-12-12T00:06:35Z", + "labels": { + "kubernetes.io/metadata.name": "postgres-operator" + }, + "name": "postgres-operator", + "resourceVersion": "745358", + "uid": "917b5f7a-db1c-41c3-9db1-c884cf217011" + }, + "spec": { + "finalizers": [] + }, + "status": { + "conditions": [ + { + "lastTransitionTime": "2024-12-12T00:06:43Z", + "message": "All resources successfully discovered", + "reason": "ResourcesDiscovered", + "status": "False", + "type": "NamespaceDeletionDiscoveryFailure" + }, + { + "lastTransitionTime": "2024-12-12T00:06:43Z", + "message": "All legacy kube types successfully parsed", + "reason": "ParsedGroupVersions", + "status": "False", + "type": "NamespaceDeletionGroupVersionParsingFailure" + }, + { + "lastTransitionTime": "2024-12-12T00:07:14Z", + "message": "All content successfully deleted, may be waiting on finalization", + "reason": "ContentDeleted", + "status": "False", + "type": "NamespaceDeletionContentFailure" + }, + { + "lastTransitionTime": "2024-12-12T00:06:43Z", + "message": "Some resources are remaining: postgresclusters.postgres-operator.crunchydata.com has 1 resource instances", + "reason": "SomeResourcesRemain", + "status": "True", + "type": "NamespaceContentRemaining" + }, + { + "lastTransitionTime": "2024-12-12T00:06:43Z", + "message": "Some content in the namespace has finalizers remaining: postgres-operator.crunchydata.com/finalizer in 1 resource instances", + "reason": "SomeFinalizersRemain", + "status": "True", + "type": "NamespaceFinalizersRemaining" + } + ], + "phase": "Terminating" + } +}