From 816d0360be412693f687b6e0c227cdae3a7c7664 Mon Sep 17 00:00:00 2001 From: shaakirshah Date: Tue, 6 Oct 2026 13:01:37 -0400 Subject: [PATCH 1/2] PLATOPS-684 feat: add ignoredReplicaTables support for external replication denylist Add spec.replication.replicaFromExternal.ignoredReplicaTables, mirroring filteredReplicaTables. Entries are passed to the init container via MARIADB_EXTERNAL_REPL_IGNORED_TABLES and rendered as replicate_ignore_table in 0-replication.cnf. GTID strict mode defaults to off when set, as with filteredReplicaTables. Bump version to 26.6.0-bandwidth.9 and regenerate CRDs/docs. Co-Authored-By: Claude Sonnet 5.5 --- Makefile | 2 +- api/v1alpha1/mariadb_replication_types.go | 16 ++++++++++++++-- api/v1alpha1/zz_generated.deepcopy.go | 5 +++++ config/crd/bases/k8s.mariadb.com_mariadbs.yaml | 8 ++++++++ deploy/charts/mariadb-cluster/Chart.yaml | 2 +- deploy/charts/mariadb-cluster/README.md | 2 +- deploy/charts/mariadb-operator-crds/Chart.yaml | 2 +- .../mariadb-operator-crds/templates/crds.yaml | 8 ++++++++ deploy/charts/mariadb-operator/Chart.lock | 6 +++--- deploy/charts/mariadb-operator/Chart.yaml | 6 +++--- deploy/charts/mariadb-operator/README.md | 2 +- deploy/crds/crds.yaml | 8 ++++++++ docs/api_reference.md | 1 + docs/docker.md | 2 +- examples/manifests/mariadb_replication.yaml | 4 ++-- pkg/builder/container_builder.go | 6 ++++++ pkg/controller/replication/config.go | 6 ++++++ pkg/environment/environment.go | 10 ++++++++++ 18 files changed, 80 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 01e1b5f148..6cde9001bb 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ endif SHELL = /usr/bin/env bash -o pipefail .SHELLFLAGS = -ec -VERSION ?= 26.6.0-bandwidth.8 +VERSION ?= 26.6.0-bandwidth.9 # mariadb-operator IMG_NAME ?= ghcr.io/mariadb-operator/mariadb-operator diff --git a/api/v1alpha1/mariadb_replication_types.go b/api/v1alpha1/mariadb_replication_types.go index e5eda0246e..f842703f1f 100644 --- a/api/v1alpha1/mariadb_replication_types.go +++ b/api/v1alpha1/mariadb_replication_types.go @@ -255,6 +255,12 @@ type ReplicaFromExternal struct { // +optional // +operator-sdk:csv:customresourcedefinitions:type=spec FilteredReplicaTables []string `json:"filteredReplicaTables,omitempty"` + // IgnoredReplicaTables is an optional list of tables in "database.table" format to exclude from replication. + // When set, the replication will be configured with replicate_ignore_table for each entry. GTID strict mode + // is automatically disabled when this field is set, as partial replication is incompatible with it. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + IgnoredReplicaTables []string `json:"ignoredReplicaTables,omitempty"` } // HasFilteredTables returns true when at least one filtered table is defined. @@ -262,6 +268,11 @@ func (r *ReplicaFromExternal) HasFilteredTables() bool { return len(r.FilteredReplicaTables) > 0 } +// HasIgnoredTables returns true when at least one ignored table is defined. +func (r *ReplicaFromExternal) HasIgnoredTables() bool { + return len(r.IgnoredReplicaTables) > 0 +} + // SetDefaults fills the current ReplicaReplication object with DefaultReplicationSpec. // This enables having minimal ReplicaReplication objects and provides sensible defaults. func (r *ReplicaReplication) SetDefaults(mdb *MariaDB) { @@ -466,8 +477,9 @@ func (r *Replication) SetDefaults(mdb *MariaDB, env *environment.OperatorEnv) er } if r.GtidStrictMode == nil { - // Filtered replica is incompatible with GTID strict mode; disable it automatically. - if r.IsExternalReplication() && r.ReplicaFromExternal.HasFilteredTables() { + // Filtered/ignored replica is incompatible with GTID strict mode; disable it automatically. + if r.IsExternalReplication() && + (r.ReplicaFromExternal.HasFilteredTables() || r.ReplicaFromExternal.HasIgnoredTables()) { r.GtidStrictMode = ptr.To(false) } else { r.GtidStrictMode = ptr.To(true) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index ca4abcd7f5..d091e8a1a8 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -4315,6 +4315,11 @@ func (in *ReplicaFromExternal) DeepCopyInto(out *ReplicaFromExternal) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.IgnoredReplicaTables != nil { + in, out := &in.IgnoredReplicaTables, &out.IgnoredReplicaTables + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplicaFromExternal. diff --git a/config/crd/bases/k8s.mariadb.com_mariadbs.yaml b/config/crd/bases/k8s.mariadb.com_mariadbs.yaml index 12d1bd8215..bf01871cdb 100644 --- a/config/crd/bases/k8s.mariadb.com_mariadbs.yaml +++ b/config/crd/bases/k8s.mariadb.com_mariadbs.yaml @@ -5450,6 +5450,14 @@ spec: description: HealthCheckInterval to be used when the replica connects to the primary. type: string + ignoredReplicaTables: + description: |- + IgnoredReplicaTables is an optional list of tables in "database.table" format to exclude from replication. + When set, the replication will be configured with replicate_ignore_table for each entry. GTID strict mode + is automatically disabled when this field is set, as partial replication is incompatible with it. + items: + type: string + type: array mariaDbRef: description: MariaDBRef is a reference to a MariaDB object. properties: diff --git a/deploy/charts/mariadb-cluster/Chart.yaml b/deploy/charts/mariadb-cluster/Chart.yaml index a40ab0a18f..ef21d2afda 100644 --- a/deploy/charts/mariadb-cluster/Chart.yaml +++ b/deploy/charts/mariadb-cluster/Chart.yaml @@ -4,7 +4,7 @@ description: Create MariaDB cluster managed by mariadb-operator home: https://github.com/mariadb-operator/mariadb-operator icon: https://mariadb-operator.github.io/mariadb-operator/assets/mariadb_profile.svg type: application -version: 26.6.0-bandwidth.8 +version: 26.6.0-bandwidth.9 appVersion: "0.0.0" kubeVersion: ">=1.26.0-0" maintainers: diff --git a/deploy/charts/mariadb-cluster/README.md b/deploy/charts/mariadb-cluster/README.md index 21e93c1428..6bbdda9fc7 100644 --- a/deploy/charts/mariadb-cluster/README.md +++ b/deploy/charts/mariadb-cluster/README.md @@ -2,7 +2,7 @@ [//]: # (README.md generated by gotmpl. DO NOT EDIT.) -![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 26.6.0-bandwidth.8](https://img.shields.io/badge/Version-26.6.0--bandwidth.8-informational?style=flat-square) ![AppVersion: 0.0.0](https://img.shields.io/badge/AppVersion-0.0.0-informational?style=flat-square) +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 26.6.0-bandwidth.9](https://img.shields.io/badge/Version-26.6.0--bandwidth.9-informational?style=flat-square) ![AppVersion: 0.0.0](https://img.shields.io/badge/AppVersion-0.0.0-informational?style=flat-square) Create MariaDB cluster managed by mariadb-operator diff --git a/deploy/charts/mariadb-operator-crds/Chart.yaml b/deploy/charts/mariadb-operator-crds/Chart.yaml index 911dbce888..2ae74a9740 100644 --- a/deploy/charts/mariadb-operator-crds/Chart.yaml +++ b/deploy/charts/mariadb-operator-crds/Chart.yaml @@ -4,7 +4,7 @@ description: mariadb-operator CRDs home: https://github.com/mariadb-operator/mariadb-operator icon: https://mariadb-operator.github.io/mariadb-operator/assets/mariadb_profile.svg type: application -version: 26.6.0-bandwidth.8 +version: 26.6.0-bandwidth.9 appVersion: "0.0.0" kubeVersion: ">=1.26.0-0" maintainers: diff --git a/deploy/charts/mariadb-operator-crds/templates/crds.yaml b/deploy/charts/mariadb-operator-crds/templates/crds.yaml index eb85bb7186..c8366db0bc 100644 --- a/deploy/charts/mariadb-operator-crds/templates/crds.yaml +++ b/deploy/charts/mariadb-operator-crds/templates/crds.yaml @@ -7631,6 +7631,14 @@ spec: description: HealthCheckInterval to be used when the replica connects to the primary. type: string + ignoredReplicaTables: + description: |- + IgnoredReplicaTables is an optional list of tables in "database.table" format to exclude from replication. + When set, the replication will be configured with replicate_ignore_table for each entry. GTID strict mode + is automatically disabled when this field is set, as partial replication is incompatible with it. + items: + type: string + type: array mariaDbRef: description: MariaDBRef is a reference to a MariaDB object. properties: diff --git a/deploy/charts/mariadb-operator/Chart.lock b/deploy/charts/mariadb-operator/Chart.lock index ba6c698941..72ea733d54 100644 --- a/deploy/charts/mariadb-operator/Chart.lock +++ b/deploy/charts/mariadb-operator/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: mariadb-operator-crds repository: file://../mariadb-operator-crds - version: 26.6.0-bandwidth.8 -digest: sha256:b0951d96d44b099790a5d53d1b3a27ad7f331cd60749f40708e14250850607c5 -generated: "2026-09-18T17:14:32.642796078Z" + version: 26.6.0-bandwidth.9 +digest: sha256:a5ef40448b273ed42b39335d383c5a205224dc2562676789f744a846199d2606 +generated: "2026-10-06T12:59:27.219777751-04:00" diff --git a/deploy/charts/mariadb-operator/Chart.yaml b/deploy/charts/mariadb-operator/Chart.yaml index 93063cb9eb..c01d272c5b 100644 --- a/deploy/charts/mariadb-operator/Chart.yaml +++ b/deploy/charts/mariadb-operator/Chart.yaml @@ -4,8 +4,8 @@ description: Run and operate MariaDB in a cloud native way home: https://github.com/mariadb-operator/mariadb-operator icon: https://mariadb-operator.github.io/mariadb-operator/assets/mariadb_profile.svg type: application -version: 26.6.0-bandwidth.8 -appVersion: "26.6.0-bandwidth.8" +version: 26.6.0-bandwidth.9 +appVersion: "26.6.0-bandwidth.9" kubeVersion: ">=1.26.0-0" maintainers: - email: martin.montes@mariadb.com @@ -19,6 +19,6 @@ keywords: - maxscale dependencies: - name: mariadb-operator-crds - version: "26.6.0-bandwidth.8" + version: "26.6.0-bandwidth.9" condition: crds.enabled repository: file://../mariadb-operator-crds diff --git a/deploy/charts/mariadb-operator/README.md b/deploy/charts/mariadb-operator/README.md index b646f8f2a1..1270745cc8 100644 --- a/deploy/charts/mariadb-operator/README.md +++ b/deploy/charts/mariadb-operator/README.md @@ -2,7 +2,7 @@ [//]: # (README.md generated by gotmpl. DO NOT EDIT.) -![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 26.6.0-bandwidth.8](https://img.shields.io/badge/Version-26.6.0--bandwidth.8-informational?style=flat-square) ![AppVersion: 26.6.0-bandwidth.8](https://img.shields.io/badge/AppVersion-26.6.0--bandwidth.8-informational?style=flat-square) +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 26.6.0-bandwidth.9](https://img.shields.io/badge/Version-26.6.0--bandwidth.9-informational?style=flat-square) ![AppVersion: 26.6.0-bandwidth.9](https://img.shields.io/badge/AppVersion-26.6.0--bandwidth.9-informational?style=flat-square) Run and operate MariaDB in a cloud native way diff --git a/deploy/crds/crds.yaml b/deploy/crds/crds.yaml index eb85bb7186..c8366db0bc 100644 --- a/deploy/crds/crds.yaml +++ b/deploy/crds/crds.yaml @@ -7631,6 +7631,14 @@ spec: description: HealthCheckInterval to be used when the replica connects to the primary. type: string + ignoredReplicaTables: + description: |- + IgnoredReplicaTables is an optional list of tables in "database.table" format to exclude from replication. + When set, the replication will be configured with replicate_ignore_table for each entry. GTID strict mode + is automatically disabled when this field is set, as partial replication is incompatible with it. + items: + type: string + type: array mariaDbRef: description: MariaDBRef is a reference to a MariaDB object. properties: diff --git a/docs/api_reference.md b/docs/api_reference.md index 6f2f826be2..69dd173380 100644 --- a/docs/api_reference.md +++ b/docs/api_reference.md @@ -2644,6 +2644,7 @@ _Appears in:_ | `healthCheckInterval` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.36/#duration-v1-meta)_ | HealthCheckInterval to be used when the replica connects to the primary. | | | | `serverIdOffset` _integer_ | ServerIdOffset to be used on the replicas. Each replica gets server_id = podIndex + offset.
If not set, the operator auto-discovers a non-colliding offset by querying the external MariaDB
for the server ids already in use, leaving room above them for scale out and other clusters. The
discovered value is persisted to status.externalReplication.serverIdOffset and computed only once. | | | | `filteredReplicaTables` _string array_ | FilteredReplicaTables is an optional list of tables in "database.table" format to replicate.
When set, the logical backup will only include these tables and the replication will be
configured with replicate_do_table for each entry. GTID strict mode is automatically
disabled when this field is set, as partial replication is incompatible with it. | | | +| `ignoredReplicaTables` _string array_ | IgnoredReplicaTables is an optional list of tables in "database.table" format to exclude from replication.
When set, the replication will be configured with replicate_ignore_table for each entry. GTID strict mode
is automatically disabled when this field is set, as partial replication is incompatible with it. | | | #### ReplicaRecovery diff --git a/docs/docker.md b/docs/docker.md index af0d398003..5b8bd81a52 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -36,7 +36,7 @@ MariaDB Operator - ghcr.io/mariadb-operator/mariadb-operator:26.6.0-bandwidth.8 + ghcr.io/mariadb-operator/mariadb-operator:26.6.0-bandwidth.9 amd64 arm64 diff --git a/examples/manifests/mariadb_replication.yaml b/examples/manifests/mariadb_replication.yaml index 4ce288173d..0064f0406f 100644 --- a/examples/manifests/mariadb_replication.yaml +++ b/examples/manifests/mariadb_replication.yaml @@ -66,10 +66,10 @@ spec: # syncBinlog: 1 # Init container that cooperates with mariadb-operator. # initContainer: - # image: ghcr.io/mariadb-operator/mariadb-operator:26.6.0-bandwidth.8 + # image: ghcr.io/mariadb-operator/mariadb-operator:26.6.0-bandwidth.9 # Agent sidecar that cooperates with mariadb-operator. # agent: - # image: ghcr.io/mariadb-operator/mariadb-operator:26.6.0-bandwidth.8 + # image: ghcr.io/mariadb-operator/mariadb-operator:26.6.0-bandwidth.9 service: type: LoadBalancer diff --git a/pkg/builder/container_builder.go b/pkg/builder/container_builder.go index 696e957513..337bd8bcf6 100644 --- a/pkg/builder/container_builder.go +++ b/pkg/builder/container_builder.go @@ -659,6 +659,12 @@ func externalReplEnvVars(mariadb *mariadbv1alpha1.MariaDB) []corev1.EnvVar { Value: strings.Join(ext.FilteredReplicaTables, ","), }) } + if ext.HasIgnoredTables() { + env = append(env, corev1.EnvVar{ + Name: "MARIADB_EXTERNAL_REPL_IGNORED_TABLES", + Value: strings.Join(ext.IgnoredReplicaTables, ","), + }) + } return env } diff --git a/pkg/controller/replication/config.go b/pkg/controller/replication/config.go index b9d195bddd..58563a2db0 100644 --- a/pkg/controller/replication/config.go +++ b/pkg/controller/replication/config.go @@ -94,6 +94,7 @@ func NewReplicationConfig(env *env.PodEnvironment) ([]byte, error) { } filteredTables := env.ExternalReplFilteredTables() + ignoredTables := env.ExternalReplIgnoredTables() // To facilitate switchover/failover and avoid clashing with MaxScale, this configuration allows any Pod to act either as a primary or a replica. // See: https://mariadb.com/docs/server/ha-and-performance/standard-replication/semisynchronous-replication#enabling-semisynchronous-replication @@ -123,6 +124,9 @@ sync_binlog={{ . }} {{- range .ReplicateDoTables }} replicate_do_table={{ . }} {{- end }} +{{- range .IgnoredReplicaTables }} +replicate_ignore_table={{ . }} +{{- end }} `) buf := new(bytes.Buffer) err = tpl.Execute(buf, struct { @@ -135,6 +139,7 @@ replicate_do_table={{ . }} SyncBinlog *int ServerID int ReplicateDoTables []string + IgnoredReplicaTables []string }{ LogName: env.MariadbName, GtidStrictMode: gtidStrictMode, @@ -145,6 +150,7 @@ replicate_do_table={{ . }} ServerID: sId, SyncBinlog: syncBinlog, ReplicateDoTables: filteredTables, + IgnoredReplicaTables: ignoredTables, }) if err != nil { return nil, err diff --git a/pkg/environment/environment.go b/pkg/environment/environment.go index f19b322cba..d6f89213d6 100644 --- a/pkg/environment/environment.go +++ b/pkg/environment/environment.go @@ -72,6 +72,7 @@ type PodEnvironment struct { MariaDBExternalReplEnabled string `env:"MARIADB_EXTERNAL_REPL_ENABLED"` MariaDBExternalReplServerIdOffset string `env:"MARIADB_EXTERNAL_REPL_SERVER_ID_OFFSET"` MariaDBExternalReplFilteredTables string `env:"MARIADB_EXTERNAL_REPL_FILTERED_TABLES"` + MariaDBExternalReplIgnoredTables string `env:"MARIADB_EXTERNAL_REPL_IGNORED_TABLES"` MariaDBReplGtidStrictMode string `env:"MARIADB_REPL_GTID_STRICT_MODE"` MariaDBReplGtidDomainID string `env:"MARIADB_REPL_GTID_DOMAIN_ID"` MariaDBReplServerIDStartIndex string `env:"MARIADB_REPL_SERVER_ID_START_INDEX"` @@ -203,6 +204,15 @@ func (e *PodEnvironment) ExternalReplFilteredTables() []string { return strings.Split(e.MariaDBExternalReplFilteredTables, ",") } +// ExternalReplIgnoredTables returns the list of "database.table" entries to exclude from replication, +// or nil when ignored tables are not configured. +func (e *PodEnvironment) ExternalReplIgnoredTables() []string { + if e.MariaDBExternalReplIgnoredTables == "" { + return nil + } + return strings.Split(e.MariaDBExternalReplIgnoredTables, ",") +} + func GetPodEnv(ctx context.Context) (*PodEnvironment, error) { var env PodEnvironment if err := envconfig.Process(ctx, &env); err != nil { From a798687abaaa44e94fc5e95b68de18a0cf07dd0d Mon Sep 17 00:00:00 2001 From: Martin Montes Date: Thu, 24 Sep 2026 20:30:06 +0200 Subject: [PATCH 2/2] PLATOPS-684 ci: use pgsty MinIO images for integration tests Official MinIO images are no longer available on quay.io/docker.io, causing the minio helm post-install hook to time out in CI. Cherry-pick of upstream b04f95f3. Co-Authored-By: Claude Sonnet 5.5 --- hack/config/minio.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hack/config/minio.yaml b/hack/config/minio.yaml index 0ed867e30f..b7feb6bedb 100644 --- a/hack/config/minio.yaml +++ b/hack/config/minio.yaml @@ -1,3 +1,11 @@ +# Official MinIO images are no longer publicly available in quay.io nor docker.io. +image: + repository: docker.io/pgsty/minio + tag: RELEASE.2026-08-04T00-00-00Z +mcImage: + repository: docker.io/pgsty/mc + tag: RELEASE.2026-09-16T00-00-00Z + minioAPIPort: "9000" minioConsolePort: "9001"