While I was preparing to deploy PostgreSQL for Firefly III, I was thinking it would be a neat idea to write an operator that uses custom resources to manage PostgreSQL roles and databases. Then I though, surely something like that must exist already. As it turns out, the [Postgres Operator][0] does exactly that, and a whole lot more. The *Postgres Operator* handles deploying PostgreSQL server instances, including primary/standby replication with load balancers. It uses custom resources to manage the databases and users (roles) in an instance, and stores role passwords in Secret resources. It supports backing up instances using `pg_basebackup` and WAL archives (i.e. physical backups) via [WAL-E][1]/[WAL-G][2]. While various backup storage targets are supported, *Postgres Operator* really only works well with the cloud storage services like S3, Azure, and Google Cloud Platform. Fortunately, S3-compatible on-premises solutions like MinIO are just fine. I think for my use cases, a single PostgreSQL cluster with multiple databases will be sufficient. I know *Firefly III* will need a PostgreSQL database, and I will likely want to migrate *Paperless-ngx* to PostgreSQL eventually too. Having a single instance will save on memory resources, at the cost of per-application point-in-time recovery. For now, just one server in the cluster is probably sufficient, but luckily adding standby servers appears to be really easy should the need arise. [0]: https://postgres-operator.readthedocs.io/en/latest/ [1]: https://github.com/wal-e/wal-e [2]: https://github.com/wal-g/wal-g
291 lines
4.6 KiB
YAML
291 lines
4.6 KiB
YAML
apiVersion: v1
|
|
kind: ServiceAccount
|
|
metadata:
|
|
name: postgres-operator
|
|
namespace: default
|
|
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRole
|
|
metadata:
|
|
name: postgres-operator
|
|
rules:
|
|
# all verbs allowed for custom operator resources
|
|
- apiGroups:
|
|
- acid.zalan.do
|
|
resources:
|
|
- postgresqls
|
|
- postgresqls/status
|
|
- operatorconfigurations
|
|
verbs:
|
|
- create
|
|
- delete
|
|
- deletecollection
|
|
- get
|
|
- list
|
|
- patch
|
|
- update
|
|
- watch
|
|
# operator only reads PostgresTeams
|
|
- apiGroups:
|
|
- acid.zalan.do
|
|
resources:
|
|
- postgresteams
|
|
verbs:
|
|
- get
|
|
- list
|
|
- watch
|
|
# all verbs allowed for event streams (Zalando-internal feature)
|
|
# - apiGroups:
|
|
# - zalando.org
|
|
# resources:
|
|
# - fabriceventstreams
|
|
# verbs:
|
|
# - create
|
|
# - delete
|
|
# - deletecollection
|
|
# - get
|
|
# - list
|
|
# - patch
|
|
# - update
|
|
# - watch
|
|
# to create or get/update CRDs when starting up
|
|
- apiGroups:
|
|
- apiextensions.k8s.io
|
|
resources:
|
|
- customresourcedefinitions
|
|
verbs:
|
|
- create
|
|
- get
|
|
- patch
|
|
- update
|
|
# to read configuration from ConfigMaps
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- configmaps
|
|
verbs:
|
|
- get
|
|
# to send events to the CRs
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- events
|
|
verbs:
|
|
- create
|
|
- get
|
|
- list
|
|
- patch
|
|
- update
|
|
- watch
|
|
# to manage endpoints which are also used by Patroni
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- endpoints
|
|
verbs:
|
|
- create
|
|
- delete
|
|
- deletecollection
|
|
- get
|
|
- list
|
|
- patch
|
|
- update
|
|
- watch
|
|
# to CRUD secrets for database access
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- secrets
|
|
verbs:
|
|
- create
|
|
- delete
|
|
- get
|
|
- update
|
|
# to check nodes for node readiness label
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- nodes
|
|
verbs:
|
|
- get
|
|
- list
|
|
- watch
|
|
# to read or delete existing PVCs. Creation via StatefulSet
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- persistentvolumeclaims
|
|
verbs:
|
|
- delete
|
|
- get
|
|
- list
|
|
- patch
|
|
- update
|
|
# to read existing PVs. Creation should be done via dynamic provisioning
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- persistentvolumes
|
|
verbs:
|
|
- get
|
|
- list
|
|
- update # only for resizing AWS volumes
|
|
# to watch Spilo pods and do rolling updates. Creation via StatefulSet
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- pods
|
|
verbs:
|
|
- delete
|
|
- get
|
|
- list
|
|
- patch
|
|
- update
|
|
- watch
|
|
# to resize the filesystem in Spilo pods when increasing volume size
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- pods/exec
|
|
verbs:
|
|
- create
|
|
# to CRUD services to point to Postgres cluster instances
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- services
|
|
verbs:
|
|
- create
|
|
- delete
|
|
- get
|
|
- patch
|
|
- update
|
|
# to CRUD the StatefulSet which controls the Postgres cluster instances
|
|
- apiGroups:
|
|
- apps
|
|
resources:
|
|
- statefulsets
|
|
- deployments
|
|
verbs:
|
|
- create
|
|
- delete
|
|
- get
|
|
- list
|
|
- patch
|
|
# to CRUD cron jobs for logical backups
|
|
- apiGroups:
|
|
- batch
|
|
resources:
|
|
- cronjobs
|
|
verbs:
|
|
- create
|
|
- delete
|
|
- get
|
|
- list
|
|
- patch
|
|
- update
|
|
# to get namespaces operator resources can run in
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- namespaces
|
|
verbs:
|
|
- get
|
|
# to define PDBs. Update happens via delete/create
|
|
- apiGroups:
|
|
- policy
|
|
resources:
|
|
- poddisruptionbudgets
|
|
verbs:
|
|
- create
|
|
- delete
|
|
- get
|
|
# to create ServiceAccounts in each namespace the operator watches
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- serviceaccounts
|
|
verbs:
|
|
- get
|
|
- create
|
|
# to create role bindings to the postgres-pod service account
|
|
- apiGroups:
|
|
- rbac.authorization.k8s.io
|
|
resources:
|
|
- rolebindings
|
|
verbs:
|
|
- get
|
|
- create
|
|
# to grant privilege to run privileged pods (not needed by default)
|
|
#- apiGroups:
|
|
# - extensions
|
|
# resources:
|
|
# - podsecuritypolicies
|
|
# resourceNames:
|
|
# - privileged
|
|
# verbs:
|
|
# - use
|
|
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRoleBinding
|
|
metadata:
|
|
name: postgres-operator
|
|
roleRef:
|
|
apiGroup: rbac.authorization.k8s.io
|
|
kind: ClusterRole
|
|
name: postgres-operator
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: postgres-operator
|
|
namespace: default
|
|
|
|
---
|
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRole
|
|
metadata:
|
|
name: postgres-pod
|
|
rules:
|
|
# Patroni needs to watch and manage endpoints
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- endpoints
|
|
verbs:
|
|
- create
|
|
- delete
|
|
- deletecollection
|
|
- get
|
|
- list
|
|
- patch
|
|
- update
|
|
- watch
|
|
# Patroni needs to watch pods
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- pods
|
|
verbs:
|
|
- get
|
|
- list
|
|
- patch
|
|
- update
|
|
- watch
|
|
# to let Patroni create a headless service
|
|
- apiGroups:
|
|
- ""
|
|
resources:
|
|
- services
|
|
verbs:
|
|
- create
|
|
# to grant privilege to run privileged pods (not needed by default)
|
|
#- apiGroups:
|
|
# - extensions
|
|
# resources:
|
|
# - podsecuritypolicies
|
|
# resourceNames:
|
|
# - privileged
|
|
# verbs:
|
|
# - use
|