Add a shard¶
Adding capacity is a reviewed change in the landscape repository; there is no code change and no API call.
The provider needs, per shard: a Percona PG cluster, a provisioner role, and a Shard object.
1. Prepare the Percona PG cluster¶
- Create the cluster with your usual Percona PG definition, with a pgBouncer behind the private load balancer consumers connect to.
- Declare a role named
provisionerwith the attributesLOGIN CREATEDB CREATEROLEand no superuser (inPerconaPGCluster.spec.users, with the same options the other shards use). Tenant roles and databases are created by the provider itself and are deliberately not declared inspec.users. - Make the provisioner credential available as a Secret with the keys
userandpassword(other key names can be configured withsecretRef.userKey/passwordKey), in the release namespace or listed by name in the chart valueshardSecrets(add{namespace, names}and upgrade the release before creating theShard: the chart grantsgeton exactly these Secrets, never list/watch on the namespace, which also holds replication certificates and backup keys). Unlisted, the Shard reportsAdminSecretInvalid. -
Recommended hardening (shard bootstrap): PostgreSQL grants
CONNECTandTEMPon every database toPUBLIC. The provider revokes this on each tenant database it creates, but not on databases it does not own. Run once per shard as a superuser:Otherwise every tenant role can log in to
postgres. Verify that your own monitoring and Percona's system users still connect afterwards (they connect as roles with their own grants).
2. Create the Shard¶
apiVersion: db.bnerd.com/v1alpha1
kind: Shard
metadata:
name: shard02
spec:
accepting: false # start closed until the checks below pass
maxDatabases: 200
perconaCluster: {namespace: databases, name: pg-shard02}
admin:
serviceName: pg-shard02-primary
secretRef: {namespace: databases, name: pg-shard02-pguser-provisioner}
client: {host: 192.0.2.201, port: 5432, sslmode: require}
(Field reference and the admin versus client endpoint distinction: Configure shards and consumers.)
3. Check¶
kubectl get shard shard02
kubectl get shard shard02 -o jsonpath='{range .status.conditions[*]}{.type}={.status} {.reason}{"\n"}{end}'
Expect Ready=True Ok. Otherwise: AdminSecretInvalid (Secret or keys), AdminAuthFailed (wrong
password or the role is not allowed to log in via the primary Service), Unreachable (Service name, port,
TLS sslmode, the chart's NetworkPolicy: add the shard's namespace to networkPolicy.shardNamespaces and its
admin port to networkPolicy.shardPorts).
4. Open it¶
Set accepting: true. New databases are placed on the accepting, ready shard with the fewest databases
(so a fresh shard receives new placements until it catches up); existing databases are never moved.
Retiring a shard¶
Set accepting: false, wait until its databases are deleted (kubectl get shard shows Databases going to 0),
then remove the Shard object, and its admin Secret entry from shardSecrets. Do not remove a Shard that
still has databases: they would report ShardNotFound and could not be disabled or dropped. With
deletionProtection.enabled (default) the admission policy refuses that delete while
status.databaseCount > 0.