Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d3ec2fd
feat(etcd)
yoav-katz Jun 18, 2026
a07a883
fix
yoav-katz Jun 18, 2026
3d26af1
Merge branch 'main' into etcd-dcs
yoav-katz Jun 18, 2026
e5ecd24
Self Code Review
yoav-katz Jun 18, 2026
fa46761
Merge branch 'etcd-dcs' of github.com:yoav-katz/percona-postgresql-op…
yoav-katz Jun 18, 2026
241cf08
feat(e2e_tests)
yoav-katz Jun 19, 2026
d34a071
Update run-pr.csv
yoav-katz Jun 19, 2026
f12b817
Update run-release.csv
yoav-katz Jun 19, 2026
3f1de89
fix(crd)
yoav-katz Jun 19, 2026
36094e3
Merge branch 'etcd-dcs' of github.com:yoav-katz/percona-postgresql-op…
yoav-katz Jun 19, 2026
2b0ac02
fix(bug)
yoav-katz Jun 20, 2026
48082f5
regenerate-crds
yoav-katz Jun 20, 2026
70d51b5
feat(e2e_tests): added check for immutable dcs after creation
yoav-katz Jun 20, 2026
05c0042
fix(tag)
yoav-katz Jun 20, 2026
8f26d3c
feat(patroni-role-change)
yoav-katz Jun 20, 2026
4168133
fix(patroni callbacks)
yoav-katz Jun 20, 2026
2466216
fix(patroni-role-change callback): added status too
yoav-katz Jun 20, 2026
4f19784
fix(service): using lables with role=primary instead of Endpoint
yoav-katz Jun 20, 2026
89e82d0
fix(cert-manager): fixed cert-manager tests
yoav-katz Jun 20, 2026
692e3e3
fix(tests)
yoav-katz Jun 21, 2026
67363a8
fix(MR comments)
yoav-katz Jun 24, 2026
92d684a
fix(pgcluster): added DCSType(): returns the type of the DCS
yoav-katz Jun 25, 2026
4bbcf67
Merge branch 'main' into etcd-dcs
yoav-katz Jun 25, 2026
6cb833e
Potential fix for pull request finding
yoav-katz Jun 25, 2026
9737acb
fix(lint errors)
yoav-katz Jul 7, 2026
e70a13c
fix(patroni_types)
yoav-katz Jul 8, 2026
08bb54c
fix(SystemIdentifier): added SystemIdentifier via api when not using …
yoav-katz Jul 8, 2026
cb68c63
feat(patroni-role-change.sh): added retries
yoav-katz Jul 8, 2026
f0d82ef
fix(duplicate validation)
yoav-katz Jul 8, 2026
689850f
fix(pgbackrest): clean Patroni DCS state via patronictl remove before…
yoav-katz Jul 8, 2026
f9e02f9
Merge branch 'main' into etcd-dcs
yoav-katz Jul 8, 2026
973f408
fix(bug): reach to patroni api requires full fqdn
yoav-katz Jul 8, 2026
c6620af
Merge branch 'etcd-dcs' of github.com:yoav-katz/percona-postgresql-op…
yoav-katz Jul 8, 2026
35ef794
fix(postgrescluster/cluster.go): use function cluster.UsesExternalDCS
yoav-katz Jul 9, 2026
3e8c575
fix(typo)
yoav-katz Jul 9, 2026
ee72659
Merge branch 'main' into etcd-dcs
yoav-katz Jul 11, 2026
2f836f1
Merge branch 'main' into etcd-dcs
yoav-katz Jul 14, 2026
e84a9b1
Merge branch 'percona:main' into etcd-dcs
yoav-katz Jul 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22038,6 +22038,66 @@ spec:
- pgbackrest
type: string
type: array
dcs:
description: |-
DCS configures the distributed configuration store backend.
Defaults to the Kubernetes-native backend (Endpoints).
N.B. Changing the DCS type causes downtime; all instances must restart simultaneously.
properties:
etcd:
description: |-
Etcd holds settings for the external etcd DCS backend.
Required when type is "etcd".
properties:
authSecret:
description: |-
AuthSecret is the name of a Secret in the same namespace with keys
username and password for etcd authentication.
type: string
endpoints:
description: |-
Endpoints is the list of etcd endpoints including scheme and port.
Example: ["https://etcd.etcd-cluster.svc:2379"]
The scheme of the first endpoint determines the protocol used.
All endpoints must use the same scheme.
items:
pattern: ^https?://[^/]
type: string
maxItems: 7
minItems: 1
type: array
x-kubernetes-validations:
- message: all endpoints must use the same scheme (http
or https)
rule: self.all(e, url(e).getScheme() == 'http') || self.all(e,
url(e).getScheme() == 'https')
tlsSecret:
description: |-
TLSSecret is the name of a Secret in the same namespace with keys
ca.crt, tls.crt, and tls.key for mutual TLS with etcd.
type: string
required:
- endpoints
type: object
type:
allOf:
- enum:
- kubernetes
- etcd
- enum:
- kubernetes
- etcd
default: kubernetes
description: PatroniDCSType identifies which DCS backend Patroni
should use.
type: string
type: object
x-kubernetes-validations:
- message: etcd.endpoints must be non-empty when type is etcd
rule: self.type != 'etcd' || (has(self.etcd) && size(self.etcd.endpoints)
> 0)
- message: DCS type is immutable after cluster creation
rule: '!has(oldSelf.type) || oldSelf.type == self.type'
dynamicConfiguration:
description: |-
Patroni dynamic configuration settings. Changes to this value will be
Expand Down
1 change: 1 addition & 0 deletions build/postgres-operator/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ COPY build/postgres-operator/postgres-entrypoint.sh /usr/local/bin
COPY build/postgres-operator/postgres-liveness-check.sh /usr/local/bin
COPY build/postgres-operator/postgres-readiness-check.sh /usr/local/bin
COPY build/postgres-operator/restore-command-wrapper.sh /usr/local/bin
COPY build/postgres-operator/patroni-role-change.sh /usr/local/bin
COPY hack/tools/queries /opt/crunchy/conf

RUN chgrp -R 0 /opt/crunchy/conf && chmod -R g=u opt/crunchy/conf
Expand Down
1 change: 1 addition & 0 deletions build/postgres-operator/init-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/postgres-liveness
install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/postgres-readiness-check.sh" "${CRUNCHY_BINDIR}/bin/postgres-readiness-check.sh"
install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/relocate-extensions.sh" "${CRUNCHY_BINDIR}/bin/relocate-extensions.sh"
install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/restore-command-wrapper.sh" "${CRUNCHY_BINDIR}/bin/restore-command-wrapper.sh"
install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "/usr/local/bin/patroni-role-change.sh" "${CRUNCHY_BINDIR}/bin/patroni-role-change.sh"
30 changes: 30 additions & 0 deletions build/postgres-operator/patroni-role-change.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash
# Patroni on_role_change / on_start callback.
# Called by Patroni as: <script> <event> <role> <scope>
# With etcd DCS, Patroni does not update pod labels or annotations.
# This script patches both so that:
# - Service selectors work (role label)
# - IsWritable() works (status annotation read by the operator)

ROLE=${2}

NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
POD=${HOSTNAME}

case "${ROLE}" in
master|primary) LABEL="primary" ;;
replica) LABEL="replica" ;;
*) LABEL="${ROLE}" ;;
esac

PATCH_BODY="{\"metadata\":{\"labels\":{\"postgres-operator.crunchydata.com/role\":\"${LABEL}\"},\"annotations\":{\"status\":\"{\\\"role\\\":\\\"${LABEL}\\\"}\"}}}"
Comment thread
yoav-katz marked this conversation as resolved.

curl -sf -X PATCH \
Comment thread
yoav-katz marked this conversation as resolved.
--retry 3 --retry-delay 1 --retry-connrefused \
--cacert "${CA}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/strategic-merge-patch+json" \
"https://kubernetes.default.svc/api/v1/namespaces/${NAMESPACE}/pods/${POD}" \
-d "${PATCH_BODY}"
9 changes: 9 additions & 0 deletions cmd/postgres-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error {
return err
}

if err := mgr.GetFieldIndexer().IndexField(
context.Background(),
&v2.PerconaPGCluster{},
v2.IndexFieldPatroniEtcdSecrets,
v2.PatroniEtcdSecretsIndexerFunc,
); err != nil {
return err
}

externalEvents := make(chan event.GenericEvent)
stopChan := make(chan event.DeleteEvent)

Expand Down
60 changes: 60 additions & 0 deletions config/crd/bases/pgv2.percona.com_perconapgclusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22736,6 +22736,66 @@ spec:
- pgbackrest
type: string
type: array
dcs:
description: |-
DCS configures the distributed configuration store backend.
Defaults to the Kubernetes-native backend (Endpoints).
N.B. Changing the DCS type causes downtime; all instances must restart simultaneously.
properties:
etcd:
description: |-
Etcd holds settings for the external etcd DCS backend.
Required when type is "etcd".
properties:
authSecret:
description: |-
AuthSecret is the name of a Secret in the same namespace with keys
username and password for etcd authentication.
type: string
endpoints:
description: |-
Endpoints is the list of etcd endpoints including scheme and port.
Example: ["https://etcd.etcd-cluster.svc:2379"]
The scheme of the first endpoint determines the protocol used.
All endpoints must use the same scheme.
items:
pattern: ^https?://[^/]
type: string
maxItems: 7
minItems: 1
type: array
x-kubernetes-validations:
- message: all endpoints must use the same scheme (http
or https)
rule: self.all(e, url(e).getScheme() == 'http') || self.all(e,
url(e).getScheme() == 'https')
tlsSecret:
description: |-
TLSSecret is the name of a Secret in the same namespace with keys
ca.crt, tls.crt, and tls.key for mutual TLS with etcd.
type: string
required:
- endpoints
type: object
type:
allOf:
- enum:
- kubernetes
- etcd
- enum:
- kubernetes
- etcd
default: kubernetes
description: PatroniDCSType identifies which DCS backend Patroni
should use.
type: string
type: object
x-kubernetes-validations:
- message: etcd.endpoints must be non-empty when type is etcd
rule: self.type != 'etcd' || (has(self.etcd) && size(self.etcd.endpoints)
> 0)
- message: DCS type is immutable after cluster creation
rule: '!has(oldSelf.type) || oldSelf.type == self.type'
dynamicConfiguration:
description: |-
Patroni dynamic configuration settings. Changes to this value will be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22382,6 +22382,66 @@ spec:
- pgbackrest
type: string
type: array
dcs:
description: |-
DCS configures the distributed configuration store backend.
Defaults to the Kubernetes-native backend (Endpoints).
N.B. Changing the DCS type causes downtime; all instances must restart simultaneously.
properties:
etcd:
description: |-
Etcd holds settings for the external etcd DCS backend.
Required when type is "etcd".
properties:
authSecret:
description: |-
AuthSecret is the name of a Secret in the same namespace with keys
username and password for etcd authentication.
type: string
endpoints:
description: |-
Endpoints is the list of etcd endpoints including scheme and port.
Example: ["https://etcd.etcd-cluster.svc:2379"]
The scheme of the first endpoint determines the protocol used.
All endpoints must use the same scheme.
items:
pattern: ^https?://[^/]
type: string
maxItems: 7
minItems: 1
type: array
x-kubernetes-validations:
- message: all endpoints must use the same scheme (http
or https)
rule: self.all(e, url(e).getScheme() == 'http') || self.all(e,
url(e).getScheme() == 'https')
tlsSecret:
description: |-
TLSSecret is the name of a Secret in the same namespace with keys
ca.crt, tls.crt, and tls.key for mutual TLS with etcd.
type: string
required:
- endpoints
type: object
type:
allOf:
- enum:
- kubernetes
- etcd
- enum:
- kubernetes
- etcd
default: kubernetes
description: PatroniDCSType identifies which DCS backend Patroni
should use.
type: string
type: object
x-kubernetes-validations:
- message: etcd.endpoints must be non-empty when type is etcd
rule: self.type != 'etcd' || (has(self.etcd) && size(self.etcd.endpoints)
> 0)
- message: DCS type is immutable after cluster creation
rule: '!has(oldSelf.type) || oldSelf.type == self.type'
dynamicConfiguration:
description: |-
Patroni dynamic configuration settings. Changes to this value will be
Expand Down
Loading
Loading