Merge branch 'master' into validate-resources
This commit is contained in:
commit
25ab3d0df6
2
Makefile
2
Makefile
|
|
@ -88,7 +88,7 @@ vet:
|
||||||
@go vet $(PKG)
|
@go vet $(PKG)
|
||||||
@staticcheck $(PKG)
|
@staticcheck $(PKG)
|
||||||
|
|
||||||
deps:
|
deps: tools
|
||||||
GO111MODULE=on go mod vendor
|
GO111MODULE=on go mod vendor
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,300 @@
|
||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: operatorconfigurations.acid.zalan.do
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: postgres-operator
|
||||||
|
annotations:
|
||||||
|
"helm.sh/hook": crd-install
|
||||||
|
spec:
|
||||||
|
group: acid.zalan.do
|
||||||
|
names:
|
||||||
|
kind: OperatorConfiguration
|
||||||
|
listKind: OperatorConfigurationList
|
||||||
|
plural: operatorconfigurations
|
||||||
|
singular: operatorconfiguration
|
||||||
|
shortNames:
|
||||||
|
- opconfig
|
||||||
|
additionalPrinterColumns:
|
||||||
|
- name: Image
|
||||||
|
type: string
|
||||||
|
description: Spilo image to be used for Pods
|
||||||
|
JSONPath: .configuration.docker_image
|
||||||
|
- name: Cluster-Label
|
||||||
|
type: string
|
||||||
|
description: Label for K8s resources created by operator
|
||||||
|
JSONPath: .configuration.kubernetes.cluster_name_label
|
||||||
|
- name: Service-Account
|
||||||
|
type: string
|
||||||
|
description: Name of service account to be used
|
||||||
|
JSONPath: .configuration.kubernetes.pod_service_account_name
|
||||||
|
- name: Min-Instances
|
||||||
|
type: integer
|
||||||
|
description: Minimum number of instances per Postgres cluster
|
||||||
|
JSONPath: .configuration.min_instances
|
||||||
|
- name: Age
|
||||||
|
type: date
|
||||||
|
JSONPath: .metadata.creationTimestamp
|
||||||
|
scope: Namespaced
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
version: v1
|
||||||
|
validation:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- kind
|
||||||
|
- apiVersion
|
||||||
|
- configuration
|
||||||
|
properties:
|
||||||
|
kind:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- OperatorConfiguration
|
||||||
|
apiVersion:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- acid.zalan.do/v1
|
||||||
|
configuration:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
docker_image:
|
||||||
|
type: string
|
||||||
|
enable_crd_validation:
|
||||||
|
type: boolean
|
||||||
|
enable_shm_volume:
|
||||||
|
type: boolean
|
||||||
|
etcd_host:
|
||||||
|
type: string
|
||||||
|
max_instances:
|
||||||
|
type: integer
|
||||||
|
minimum: -1 # -1 = disabled
|
||||||
|
min_instances:
|
||||||
|
type: integer
|
||||||
|
minimum: -1 # -1 = disabled
|
||||||
|
resync_period:
|
||||||
|
type: string
|
||||||
|
repair_period:
|
||||||
|
type: string
|
||||||
|
set_memory_request_to_limit:
|
||||||
|
type: boolean
|
||||||
|
sidecar_docker_images:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
workers:
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
users:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
replication_username:
|
||||||
|
type: string
|
||||||
|
super_username:
|
||||||
|
type: string
|
||||||
|
kubernetes:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
cluster_domain:
|
||||||
|
type: string
|
||||||
|
cluster_labels:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
cluster_name_label:
|
||||||
|
type: string
|
||||||
|
custom_pod_annotations:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
enable_pod_antiaffinity:
|
||||||
|
type: boolean
|
||||||
|
enable_pod_disruption_budget:
|
||||||
|
type: boolean
|
||||||
|
infrastructure_roles_secret_name:
|
||||||
|
type: string
|
||||||
|
inherited_labels:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
node_readiness_label:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
oauth_token_secret_name:
|
||||||
|
type: string
|
||||||
|
pdb_name_format:
|
||||||
|
type: string
|
||||||
|
pod_antiaffinity_topology_key:
|
||||||
|
type: string
|
||||||
|
pod_environment_configmap:
|
||||||
|
type: string
|
||||||
|
pod_management_policy:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "ordered_ready"
|
||||||
|
- "parallel"
|
||||||
|
pod_role_label:
|
||||||
|
type: string
|
||||||
|
pod_service_account_name:
|
||||||
|
type: string
|
||||||
|
pod_terminate_grace_period:
|
||||||
|
type: string
|
||||||
|
secret_name_template:
|
||||||
|
type: string
|
||||||
|
spilo_fsgroup:
|
||||||
|
type: integer
|
||||||
|
spilo_privileged:
|
||||||
|
type: boolean
|
||||||
|
toleration:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
watched_namespace:
|
||||||
|
type: string
|
||||||
|
postgres_pod_resources:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
default_cpu_limit:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+m|\d+(\.\d{1,3})?)$'
|
||||||
|
default_cpu_request:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+m|\d+(\.\d{1,3})?)$'
|
||||||
|
default_memory_limit:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
default_memory_request:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
timeouts:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
pod_label_wait_timeout:
|
||||||
|
type: string
|
||||||
|
pod_deletion_wait_timeout:
|
||||||
|
type: string
|
||||||
|
ready_wait_interval:
|
||||||
|
type: string
|
||||||
|
ready_wait_timeout:
|
||||||
|
type: string
|
||||||
|
resource_check_interval:
|
||||||
|
type: string
|
||||||
|
resource_check_timeout:
|
||||||
|
type: string
|
||||||
|
load_balancer:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
db_hosted_zone:
|
||||||
|
type: string
|
||||||
|
enable_master_load_balancer:
|
||||||
|
type: boolean
|
||||||
|
enable_replica_load_balancer:
|
||||||
|
type: boolean
|
||||||
|
custom_service_annotations:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
master_dns_name_format:
|
||||||
|
type: string
|
||||||
|
replica_dns_name_format:
|
||||||
|
type: string
|
||||||
|
aws_or_gcp:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
additional_secret_mount:
|
||||||
|
type: string
|
||||||
|
additional_secret_mount_path:
|
||||||
|
type: string
|
||||||
|
aws_region:
|
||||||
|
type: string
|
||||||
|
kube_iam_role:
|
||||||
|
type: string
|
||||||
|
log_s3_bucket:
|
||||||
|
type: string
|
||||||
|
wal_s3_bucket:
|
||||||
|
type: string
|
||||||
|
logical_backup:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
logical_backup_schedule:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
|
||||||
|
logical_backup_docker_image:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_bucket:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_endpoint:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_sse:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_access_key_id:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_secret_access_key:
|
||||||
|
type: string
|
||||||
|
debug:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
debug_logging:
|
||||||
|
type: boolean
|
||||||
|
enable_database_access:
|
||||||
|
type: boolean
|
||||||
|
teams_api:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
enable_admin_role_for_users:
|
||||||
|
type: boolean
|
||||||
|
enable_team_superuser:
|
||||||
|
type: boolean
|
||||||
|
enable_teams_api:
|
||||||
|
type: boolean
|
||||||
|
pam_configuration:
|
||||||
|
type: string
|
||||||
|
pam_role_name:
|
||||||
|
type: string
|
||||||
|
postgres_superuser_teams:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
protected_role_names:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
team_admin_role:
|
||||||
|
type: string
|
||||||
|
team_api_role_configuration:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
teams_api_url:
|
||||||
|
type: string
|
||||||
|
logging_rest_api:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
api_port:
|
||||||
|
type: integer
|
||||||
|
cluster_history_entries:
|
||||||
|
type: integer
|
||||||
|
ring_log_lines:
|
||||||
|
type: integer
|
||||||
|
scalyr:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
scalyr_api_key:
|
||||||
|
type: string
|
||||||
|
scalyr_cpu_limit:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+m|\d+(\.\d{1,3})?)$'
|
||||||
|
scalyr_cpu_request:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+m|\d+(\.\d{1,3})?)$'
|
||||||
|
scalyr_image:
|
||||||
|
type: string
|
||||||
|
scalyr_memory_limit:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
scalyr_memory_request:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
scalyr_server_url:
|
||||||
|
type: string
|
||||||
|
|
@ -0,0 +1,363 @@
|
||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: postgresqls.acid.zalan.do
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: postgres-operator
|
||||||
|
annotations:
|
||||||
|
"helm.sh/hook": crd-install
|
||||||
|
spec:
|
||||||
|
group: acid.zalan.do
|
||||||
|
names:
|
||||||
|
kind: postgresql
|
||||||
|
listKind: postgresqlList
|
||||||
|
plural: postgresqls
|
||||||
|
singular: postgresql
|
||||||
|
shortNames:
|
||||||
|
- pg
|
||||||
|
additionalPrinterColumns:
|
||||||
|
- name: Team
|
||||||
|
type: string
|
||||||
|
description: Team responsible for Postgres CLuster
|
||||||
|
JSONPath: .spec.teamId
|
||||||
|
- name: Version
|
||||||
|
type: string
|
||||||
|
description: PostgreSQL version
|
||||||
|
JSONPath: .spec.postgresql.version
|
||||||
|
- name: Pods
|
||||||
|
type: integer
|
||||||
|
description: Number of Pods per Postgres cluster
|
||||||
|
JSONPath: .spec.numberOfInstances
|
||||||
|
- name: Volume
|
||||||
|
type: string
|
||||||
|
description: Size of the bound volume
|
||||||
|
JSONPath: .spec.volume.size
|
||||||
|
- name: CPU-Request
|
||||||
|
type: string
|
||||||
|
description: Requested CPU for Postgres containers
|
||||||
|
JSONPath: .spec.resources.requests.cpu
|
||||||
|
- name: Memory-Request
|
||||||
|
type: string
|
||||||
|
description: Requested memory for Postgres containers
|
||||||
|
JSONPath: .spec.resources.requests.memory
|
||||||
|
- name: Age
|
||||||
|
type: date
|
||||||
|
JSONPath: .metadata.creationTimestamp
|
||||||
|
- name: Status
|
||||||
|
type: string
|
||||||
|
description: Current sync status of postgresql resource
|
||||||
|
JSONPath: .status.PostgresClusterStatus
|
||||||
|
scope: Namespaced
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
version: v1
|
||||||
|
validation:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- kind
|
||||||
|
- apiVersion
|
||||||
|
- spec
|
||||||
|
properties:
|
||||||
|
kind:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- postgresql
|
||||||
|
apiVersion:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- acid.zalan.do/v1
|
||||||
|
spec:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- numberOfInstances
|
||||||
|
- teamId
|
||||||
|
- postgresql
|
||||||
|
properties:
|
||||||
|
allowedSourceRanges:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\/(\d|[1-2]\d|3[0-2])$'
|
||||||
|
clone:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- cluster
|
||||||
|
properties:
|
||||||
|
cluster:
|
||||||
|
type: string
|
||||||
|
s3_endpoint:
|
||||||
|
type: string
|
||||||
|
s3_access_key_id:
|
||||||
|
type: string
|
||||||
|
s3_secret_access_key:
|
||||||
|
type: string
|
||||||
|
s3_force_path_style:
|
||||||
|
type: string
|
||||||
|
s3_wal_path:
|
||||||
|
type: string
|
||||||
|
timestamp:
|
||||||
|
type: string
|
||||||
|
pattern: '^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([+-]([01][0-9]|2[0-3]):[0-5][0-9]))$'
|
||||||
|
# The regexp matches the date-time format (RFC 3339 Section 5.6) that specifies a timezone as an offset relative to UTC
|
||||||
|
# Example: 1996-12-19T16:39:57-08:00
|
||||||
|
# Note: this field requires a timezone
|
||||||
|
uid:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
databases:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
# Note: usernames specified here as database owners must be declared in the users key of the spec key.
|
||||||
|
dockerImage:
|
||||||
|
type: string
|
||||||
|
enableLogicalBackup:
|
||||||
|
type: boolean
|
||||||
|
enableMasterLoadBalancer:
|
||||||
|
type: boolean
|
||||||
|
enableReplicaLoadBalancer:
|
||||||
|
type: boolean
|
||||||
|
enableShmVolume:
|
||||||
|
type: boolean
|
||||||
|
init_containers: # deprecated
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
initContainers:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
logicalBackupSchedule:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
|
||||||
|
maintenanceWindows:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
pattern: '^\ *((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))-((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))\ *$'
|
||||||
|
numberOfInstances:
|
||||||
|
type: integer
|
||||||
|
minimum: 0
|
||||||
|
patroni:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
initdb:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
pg_hba:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
slots:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
ttl:
|
||||||
|
type: integer
|
||||||
|
loop_wait:
|
||||||
|
type: integer
|
||||||
|
retry_timeout:
|
||||||
|
type: integer
|
||||||
|
maximum_lag_on_failover:
|
||||||
|
type: integer
|
||||||
|
podAnnotations:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
pod_priority_class_name: # deprecated
|
||||||
|
type: string
|
||||||
|
podPriorityClassName:
|
||||||
|
type: string
|
||||||
|
postgresql:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- version
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "9.3"
|
||||||
|
- "9.4"
|
||||||
|
- "9.5"
|
||||||
|
- "9.6"
|
||||||
|
- "10"
|
||||||
|
- "11"
|
||||||
|
- "12"
|
||||||
|
parameters:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
replicaLoadBalancer: # deprecated
|
||||||
|
type: boolean
|
||||||
|
resources:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- requests
|
||||||
|
- limits
|
||||||
|
properties:
|
||||||
|
limits:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- cpu
|
||||||
|
- memory
|
||||||
|
properties:
|
||||||
|
cpu:
|
||||||
|
type: string
|
||||||
|
# Decimal natural followed by m, or decimal natural followed by
|
||||||
|
# dot followed by up to three decimal digits.
|
||||||
|
#
|
||||||
|
# This is because the Kubernetes CPU resource has millis as the
|
||||||
|
# maximum precision. The actual values are checked in code
|
||||||
|
# because the regular expression would be huge and horrible and
|
||||||
|
# not very helpful in validation error messages; this one checks
|
||||||
|
# only the format of the given number.
|
||||||
|
#
|
||||||
|
# https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu
|
||||||
|
pattern: '^(\d+m|\d+\.\d{1,3})$'
|
||||||
|
# Note: the value specified here must not be zero or be lower
|
||||||
|
# than the corresponding request.
|
||||||
|
memory:
|
||||||
|
type: string
|
||||||
|
# You can express memory as a plain integer or as a fixed-point
|
||||||
|
# integer using one of these suffixes: E, P, T, G, M, k. You can
|
||||||
|
# also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki
|
||||||
|
#
|
||||||
|
# https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
# Note: the value specified here must not be zero or be lower
|
||||||
|
# than the corresponding request.
|
||||||
|
requests:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- cpu
|
||||||
|
- memory
|
||||||
|
properties:
|
||||||
|
cpu:
|
||||||
|
type: string
|
||||||
|
# Decimal natural followed by m, or decimal natural followed by
|
||||||
|
# dot followed by up to three decimal digits.
|
||||||
|
#
|
||||||
|
# This is because the Kubernetes CPU resource has millis as the
|
||||||
|
# maximum precision. The actual values are checked in code
|
||||||
|
# because the regular expression would be huge and horrible and
|
||||||
|
# not very helpful in validation error messages; this one checks
|
||||||
|
# only the format of the given number.
|
||||||
|
#
|
||||||
|
# https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu
|
||||||
|
pattern: '^(\d+m|\d+\.\d{1,3})$'
|
||||||
|
# Note: the value specified here must not be zero or be higher
|
||||||
|
# than the corresponding limit.
|
||||||
|
memory:
|
||||||
|
type: string
|
||||||
|
# You can express memory as a plain integer or as a fixed-point
|
||||||
|
# integer using one of these suffixes: E, P, T, G, M, k. You can
|
||||||
|
# also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki
|
||||||
|
#
|
||||||
|
# https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
# Note: the value specified here must not be zero or be higher
|
||||||
|
# than the corresponding limit.
|
||||||
|
sidecars:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
spiloFSGroup:
|
||||||
|
type: integer
|
||||||
|
standby:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- s3_wal_path
|
||||||
|
properties:
|
||||||
|
s3_wal_path:
|
||||||
|
type: string
|
||||||
|
teamId:
|
||||||
|
type: string
|
||||||
|
tolerations:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
- operator
|
||||||
|
- effect
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
operator:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- Equal
|
||||||
|
- Exists
|
||||||
|
value:
|
||||||
|
type: string
|
||||||
|
effect:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- NoExecute
|
||||||
|
- NoSchedule
|
||||||
|
- PreferNoSchedule
|
||||||
|
tolerationSeconds:
|
||||||
|
type: integer
|
||||||
|
useLoadBalancer: # deprecated
|
||||||
|
type: boolean
|
||||||
|
users:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
description: "Role flags specified here must not contradict each other"
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- bypassrls
|
||||||
|
- BYPASSRLS
|
||||||
|
- nobypassrls
|
||||||
|
- NOBYPASSRLS
|
||||||
|
- createdb
|
||||||
|
- CREATEDB
|
||||||
|
- nocreatedb
|
||||||
|
- NOCREATEDB
|
||||||
|
- createrole
|
||||||
|
- CREATEROLE
|
||||||
|
- nocreaterole
|
||||||
|
- NOCREATEROLE
|
||||||
|
- inherit
|
||||||
|
- INHERIT
|
||||||
|
- noinherit
|
||||||
|
- NOINHERIT
|
||||||
|
- login
|
||||||
|
- LOGIN
|
||||||
|
- nologin
|
||||||
|
- NOLOGIN
|
||||||
|
- replication
|
||||||
|
- REPLICATION
|
||||||
|
- noreplication
|
||||||
|
- NOREPLICATION
|
||||||
|
- superuser
|
||||||
|
- SUPERUSER
|
||||||
|
- nosuperuser
|
||||||
|
- NOSUPERUSER
|
||||||
|
volume:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- size
|
||||||
|
properties:
|
||||||
|
size:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
# Note: the value specified here must not be zero.
|
||||||
|
storageClass:
|
||||||
|
type: string
|
||||||
|
subPath:
|
||||||
|
type: string
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{{ if .Values.crd.create }}
|
||||||
|
{{- range $path, $bytes := .Files.Glob "crds/*.yaml" }}
|
||||||
|
{{ $.Files.Get $path }}
|
||||||
|
---
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
{{ if .Values.crd.create }}
|
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
|
||||||
kind: CustomResourceDefinition
|
|
||||||
metadata:
|
|
||||||
name: postgresqls.acid.zalan.do
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ template "postgres-operator.name" . }}
|
|
||||||
helm.sh/chart: {{ template "postgres-operator.chart" . }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": crd-install
|
|
||||||
spec:
|
|
||||||
group: acid.zalan.do
|
|
||||||
names:
|
|
||||||
kind: postgresql
|
|
||||||
listKind: postgresqlList
|
|
||||||
plural: postgresqls
|
|
||||||
singular: postgresql
|
|
||||||
shortNames:
|
|
||||||
- pg
|
|
||||||
additionalPrinterColumns:
|
|
||||||
- name: Team
|
|
||||||
type: string
|
|
||||||
description: Team responsible for Postgres CLuster
|
|
||||||
JSONPath: .spec.teamId
|
|
||||||
- name: Version
|
|
||||||
type: string
|
|
||||||
description: PostgreSQL version
|
|
||||||
JSONPath: .spec.postgresql.version
|
|
||||||
- name: Pods
|
|
||||||
type: integer
|
|
||||||
description: Number of Pods per Postgres cluster
|
|
||||||
JSONPath: .spec.numberOfInstances
|
|
||||||
- name: Volume
|
|
||||||
type: string
|
|
||||||
description: Size of the bound volume
|
|
||||||
JSONPath: .spec.volume.size
|
|
||||||
- name: CPU-Request
|
|
||||||
type: string
|
|
||||||
description: Requested CPU for Postgres containers
|
|
||||||
JSONPath: .spec.resources.requests.cpu
|
|
||||||
- name: Memory-Request
|
|
||||||
type: string
|
|
||||||
description: Requested memory for Postgres containers
|
|
||||||
JSONPath: .spec.resources.requests.memory
|
|
||||||
- name: Age
|
|
||||||
type: date
|
|
||||||
JSONPath: .metadata.creationTimestamp
|
|
||||||
- name: Status
|
|
||||||
type: string
|
|
||||||
description: Current sync status of postgresql resource
|
|
||||||
JSONPath: .status.PostgresClusterStatus
|
|
||||||
scope: Namespaced
|
|
||||||
subresources:
|
|
||||||
status: {}
|
|
||||||
version: v1
|
|
||||||
---
|
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
|
||||||
kind: CustomResourceDefinition
|
|
||||||
metadata:
|
|
||||||
name: operatorconfigurations.acid.zalan.do
|
|
||||||
labels:
|
|
||||||
app.kubernetes.io/name: {{ template "postgres-operator.name" . }}
|
|
||||||
helm.sh/chart: {{ template "postgres-operator.chart" . }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": crd-install
|
|
||||||
spec:
|
|
||||||
group: acid.zalan.do
|
|
||||||
names:
|
|
||||||
kind: OperatorConfiguration
|
|
||||||
listKind: OperatorConfigurationList
|
|
||||||
plural: operatorconfigurations
|
|
||||||
singular: operatorconfiguration
|
|
||||||
shortNames:
|
|
||||||
- opconfig
|
|
||||||
additionalPrinterColumns:
|
|
||||||
- name: Image
|
|
||||||
type: string
|
|
||||||
description: Spilo image to be used for Pods
|
|
||||||
JSONPath: .configuration.docker_image
|
|
||||||
- name: Cluster-Label
|
|
||||||
type: string
|
|
||||||
description: Label for K8s resources created by operator
|
|
||||||
JSONPath: .configuration.kubernetes.cluster_name_label
|
|
||||||
- name: Service-Account
|
|
||||||
type: string
|
|
||||||
description: Name of service account to be used
|
|
||||||
JSONPath: .configuration.kubernetes.pod_service_account_name
|
|
||||||
- name: Min-Instances
|
|
||||||
type: integer
|
|
||||||
description: Minimum number of instances per Postgres cluster
|
|
||||||
JSONPath: .configuration.min_instances
|
|
||||||
- name: Age
|
|
||||||
type: date
|
|
||||||
JSONPath: .metadata.creationTimestamp
|
|
||||||
scope: Namespaced
|
|
||||||
subresources:
|
|
||||||
status: {}
|
|
||||||
version: v1
|
|
||||||
{{ end }}
|
|
||||||
|
|
@ -14,7 +14,7 @@ configuration:
|
||||||
{{ toYaml .Values.configUsers | indent 4 }}
|
{{ toYaml .Values.configUsers | indent 4 }}
|
||||||
kubernetes:
|
kubernetes:
|
||||||
oauth_token_secret_name: {{ template "postgres-operator.fullname" . }}
|
oauth_token_secret_name: {{ template "postgres-operator.fullname" . }}
|
||||||
pod_service_account_name: operator
|
pod_service_account_name: {{ include "postgres-operator.serviceAccountName" . }}
|
||||||
{{ toYaml .Values.configKubernetes | indent 4 }}
|
{{ toYaml .Values.configKubernetes | indent 4 }}
|
||||||
postgres_pod_resources:
|
postgres_pod_resources:
|
||||||
{{ toYaml .Values.configPostgresPodResources | indent 4 }}
|
{{ toYaml .Values.configPostgresPodResources | indent 4 }}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ configTarget: "OperatorConfigurationCRD"
|
||||||
|
|
||||||
# general top-level configuration parameters
|
# general top-level configuration parameters
|
||||||
configGeneral:
|
configGeneral:
|
||||||
|
# choose if deployment creates/updates CRDs with OpenAPIV3Validation
|
||||||
|
enable_crd_validation: true
|
||||||
# start any new database pod without limitations on shm memory
|
# start any new database pod without limitations on shm memory
|
||||||
enable_shm_volume: true
|
enable_shm_volume: true
|
||||||
# etcd connection string for Patroni. Empty uses K8s-native DCS.
|
# etcd connection string for Patroni. Empty uses K8s-native DCS.
|
||||||
|
|
@ -57,7 +59,10 @@ configKubernetes:
|
||||||
# label assigned to Kubernetes objects created by the operator
|
# label assigned to Kubernetes objects created by the operator
|
||||||
cluster_name_label: cluster-name
|
cluster_name_label: cluster-name
|
||||||
# additional annotations to add to every database pod
|
# additional annotations to add to every database pod
|
||||||
custom_pod_annotations:
|
# custom_pod_annotations:
|
||||||
|
# keya: valuea
|
||||||
|
# keyb: valueb
|
||||||
|
|
||||||
# toggles pod anti affinity on the Postgres pods
|
# toggles pod anti affinity on the Postgres pods
|
||||||
enable_pod_antiaffinity: false
|
enable_pod_antiaffinity: false
|
||||||
# toggles PDB to set to MinAvailabe 0 or 1
|
# toggles PDB to set to MinAvailabe 0 or 1
|
||||||
|
|
@ -74,7 +79,8 @@ configKubernetes:
|
||||||
# master_pod_move_timeout: 20m
|
# master_pod_move_timeout: 20m
|
||||||
|
|
||||||
# set of labels that a running and active node should possess to be considered ready
|
# set of labels that a running and active node should possess to be considered ready
|
||||||
# node_readiness_label: ""
|
# node_readiness_label:
|
||||||
|
# status: ready
|
||||||
|
|
||||||
# name of the secret containing the OAuth2 token to pass to the teams API
|
# name of the secret containing the OAuth2 token to pass to the teams API
|
||||||
# oauth_token_secret_name: postgresql-operator
|
# oauth_token_secret_name: postgresql-operator
|
||||||
|
|
@ -184,12 +190,20 @@ configAwsOrGcp:
|
||||||
|
|
||||||
# configure K8s cron job managed by the operator
|
# configure K8s cron job managed by the operator
|
||||||
configLogicalBackup:
|
configLogicalBackup:
|
||||||
# backup schedule in the cron format
|
|
||||||
logical_backup_schedule: "30 00 * * *"
|
|
||||||
# image for pods of the logical backup job (example runs pg_dumpall)
|
# image for pods of the logical backup job (example runs pg_dumpall)
|
||||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
|
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
|
||||||
|
# S3 Access Key ID
|
||||||
|
logical_backup_s3_access_key_id: ""
|
||||||
# S3 bucket to store backup results
|
# S3 bucket to store backup results
|
||||||
logical_backup_s3_bucket: "my-bucket-url"
|
logical_backup_s3_bucket: "my-bucket-url"
|
||||||
|
# S3 endpoint url when not using AWS
|
||||||
|
logical_backup_s3_endpoint: ""
|
||||||
|
# S3 Secret Access Key
|
||||||
|
logical_backup_s3_secret_access_key: ""
|
||||||
|
# S3 server side encription
|
||||||
|
logical_backup_s3_sse: "AES256"
|
||||||
|
# backup schedule in the cron format
|
||||||
|
logical_backup_schedule: "30 00 * * *"
|
||||||
|
|
||||||
# automate creation of human users with teams API service
|
# automate creation of human users with teams API service
|
||||||
configTeamsApi:
|
configTeamsApi:
|
||||||
|
|
@ -206,7 +220,8 @@ configTeamsApi:
|
||||||
# operator will add all team member roles to this group and add a pg_hba line
|
# operator will add all team member roles to this group and add a pg_hba line
|
||||||
pam_role_name: zalandos
|
pam_role_name: zalandos
|
||||||
# List of teams which members need the superuser role in each Postgres cluster
|
# List of teams which members need the superuser role in each Postgres cluster
|
||||||
# postgres_superuser_teams: "postgres_superusers"
|
# postgres_superuser_teams:
|
||||||
|
# - postgres_superusers
|
||||||
|
|
||||||
# List of roles that cannot be overwritten by an application, team or infrastructure role
|
# List of roles that cannot be overwritten by an application, team or infrastructure role
|
||||||
protected_role_names:
|
protected_role_names:
|
||||||
|
|
@ -220,7 +235,7 @@ configTeamsApi:
|
||||||
# teams_api_url: http://fake-teams-api.default.svc.cluster.local
|
# teams_api_url: http://fake-teams-api.default.svc.cluster.local
|
||||||
|
|
||||||
# Scalyr is a log management tool that Zalando uses as a sidecar
|
# Scalyr is a log management tool that Zalando uses as a sidecar
|
||||||
scalyr:
|
configScalyr:
|
||||||
# API key for the Scalyr sidecar
|
# API key for the Scalyr sidecar
|
||||||
# scalyr_api_key: ""
|
# scalyr_api_key: ""
|
||||||
|
|
||||||
|
|
@ -249,9 +264,7 @@ serviceAccount:
|
||||||
create: true
|
create: true
|
||||||
# The name of the ServiceAccount to use.
|
# The name of the ServiceAccount to use.
|
||||||
# If not set and create is true, a name is generated using the fullname template
|
# If not set and create is true, a name is generated using the fullname template
|
||||||
# When relying solely on the OperatorConfiguration CRD, this value has to be "operator"
|
name:
|
||||||
# Otherwise, the operator tries to use the "default" service account which is forbidden
|
|
||||||
name: operator
|
|
||||||
|
|
||||||
priorityClassName: ""
|
priorityClassName: ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ configTarget: "ConfigMap"
|
||||||
|
|
||||||
# general configuration parameters
|
# general configuration parameters
|
||||||
configGeneral:
|
configGeneral:
|
||||||
|
# choose if deployment creates/updates CRDs with OpenAPIV3Validation
|
||||||
|
enable_crd_validation: "true"
|
||||||
# start any new database pod without limitations on shm memory
|
# start any new database pod without limitations on shm memory
|
||||||
enable_shm_volume: "true"
|
enable_shm_volume: "true"
|
||||||
# etcd connection string for Patroni. Empty uses K8s-native DCS.
|
# etcd connection string for Patroni. Empty uses K8s-native DCS.
|
||||||
|
|
@ -55,7 +57,8 @@ configKubernetes:
|
||||||
# label assigned to Kubernetes objects created by the operator
|
# label assigned to Kubernetes objects created by the operator
|
||||||
cluster_name_label: version
|
cluster_name_label: version
|
||||||
# annotations attached to each database pod
|
# annotations attached to each database pod
|
||||||
# custom_pod_annotations: keya:valuea
|
# custom_pod_annotations: keya:valuea,keyb:valueb
|
||||||
|
|
||||||
# toggles pod anti affinity on the Postgres pods
|
# toggles pod anti affinity on the Postgres pods
|
||||||
enable_pod_antiaffinity: "false"
|
enable_pod_antiaffinity: "false"
|
||||||
# toggles PDB to set to MinAvailabe 0 or 1
|
# toggles PDB to set to MinAvailabe 0 or 1
|
||||||
|
|
@ -136,9 +139,9 @@ configLoadBalancer:
|
||||||
# toggles service type load balancer pointing to the replica pod of the cluster
|
# toggles service type load balancer pointing to the replica pod of the cluster
|
||||||
enable_replica_load_balancer: "false"
|
enable_replica_load_balancer: "false"
|
||||||
# defines the DNS name string template for the master load balancer cluster
|
# defines the DNS name string template for the master load balancer cluster
|
||||||
master_dns_name_format: '{cluster}.{team}.staging.{hostedzone}'
|
master_dns_name_format: '{cluster}.{team}.{hostedzone}'
|
||||||
# defines the DNS name string template for the replica load balancer cluster
|
# defines the DNS name string template for the replica load balancer cluster
|
||||||
replica_dns_name_format: '{cluster}-repl.{team}.staging.{hostedzone}'
|
replica_dns_name_format: '{cluster}-repl.{team}.{hostedzone}'
|
||||||
|
|
||||||
# options to aid debugging of the operator itself
|
# options to aid debugging of the operator itself
|
||||||
configDebug:
|
configDebug:
|
||||||
|
|
@ -178,12 +181,20 @@ configAwsOrGcp:
|
||||||
|
|
||||||
# configure K8s cron job managed by the operator
|
# configure K8s cron job managed by the operator
|
||||||
configLogicalBackup:
|
configLogicalBackup:
|
||||||
# backup schedule in the cron format
|
|
||||||
logical_backup_schedule: "30 00 * * *"
|
|
||||||
# image for pods of the logical backup job (example runs pg_dumpall)
|
# image for pods of the logical backup job (example runs pg_dumpall)
|
||||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
|
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
|
||||||
|
# S3 Access Key ID
|
||||||
|
logical_backup_s3_access_key_id: ""
|
||||||
# S3 bucket to store backup results
|
# S3 bucket to store backup results
|
||||||
logical_backup_s3_bucket: "my-bucket-url"
|
logical_backup_s3_bucket: "my-bucket-url"
|
||||||
|
# S3 endpoint url when not using AWS
|
||||||
|
logical_backup_s3_endpoint: ""
|
||||||
|
# S3 Secret Access Key
|
||||||
|
logical_backup_s3_secret_access_key: ""
|
||||||
|
# S3 server side encription
|
||||||
|
logical_backup_s3_sse: "AES256"
|
||||||
|
# backup schedule in the cron format
|
||||||
|
logical_backup_schedule: "30 00 * * *"
|
||||||
|
|
||||||
# automate creation of human users with teams API service
|
# automate creation of human users with teams API service
|
||||||
configTeamsApi:
|
configTeamsApi:
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ pipeline:
|
||||||
IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test
|
IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test
|
||||||
fi
|
fi
|
||||||
export IMAGE
|
export IMAGE
|
||||||
make tools deps docker
|
make deps docker
|
||||||
- desc: 'Run unit tests'
|
- desc: 'Run unit tests'
|
||||||
cmd: |
|
cmd: |
|
||||||
export PATH=$PATH:$HOME/go/bin
|
export PATH=$PATH:$HOME/go/bin
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,13 @@ function aws_upload {
|
||||||
# NB: $LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX already contains the leading "/" when set by the Postgres Operator
|
# NB: $LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX already contains the leading "/" when set by the Postgres Operator
|
||||||
PATH_TO_BACKUP=s3://$LOGICAL_BACKUP_S3_BUCKET"/spilo/"$SCOPE$LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX"/logical_backups/"$(date +%s).sql.gz
|
PATH_TO_BACKUP=s3://$LOGICAL_BACKUP_S3_BUCKET"/spilo/"$SCOPE$LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX"/logical_backups/"$(date +%s).sql.gz
|
||||||
|
|
||||||
if [ -z "$EXPECTED_SIZE" ]; then
|
args=()
|
||||||
aws s3 cp - "$PATH_TO_BACKUP" --debug --sse="AES256"
|
|
||||||
else
|
[[ ! -z "$EXPECTED_SIZE" ]] && args+=("--expected-size=$EXPECTED_SIZE")
|
||||||
aws s3 cp - "$PATH_TO_BACKUP" --debug --expected-size "$EXPECTED_SIZE" --sse="AES256"
|
[[ ! -z "$LOGICAL_BACKUP_S3_ENDPOINT" ]] && args+=("--endpoint-url=\"$LOGICAL_BACKUP_S3_ENDPOINT\"")
|
||||||
fi;
|
[[ ! "$LOGICAL_BACKUP_S3_SSE" == "" ]] && args+=("--sse=\"$LOGICAL_BACKUP_S3_SSE\"")
|
||||||
|
|
||||||
|
aws s3 cp - "$PATH_TO_BACKUP" "${args[@]//\'/}" --debug
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_pods {
|
function get_pods {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,30 @@
|
||||||
Learn how to configure and manage the Postgres Operator in your Kubernetes (K8s)
|
Learn how to configure and manage the Postgres Operator in your Kubernetes (K8s)
|
||||||
environment.
|
environment.
|
||||||
|
|
||||||
|
## CRD Validation
|
||||||
|
|
||||||
|
[CustomResourceDefinitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions)
|
||||||
|
will be registered with schema validation by default when the operator is
|
||||||
|
deployed. The `OperatorConfiguration` CRD will only get created if the
|
||||||
|
`POSTGRES_OPERATOR_CONFIGURATION_OBJECT` [environment variable](../manifests/postgres-operator.yaml#L36)
|
||||||
|
in the deployment yaml is set and not empty.
|
||||||
|
|
||||||
|
When submitting manifests of [`postgresql`](../manifests/postgresql.crd.yaml) or
|
||||||
|
[`OperatorConfiguration`](../manifests/operatorconfiguration.crd.yaml) custom
|
||||||
|
resources with kubectl, validation can be bypassed with `--validate=false`. The
|
||||||
|
operator can also be configured to not register CRDs with validation on `ADD` or
|
||||||
|
`UPDATE` events. Running instances are not affected when enabling the validation
|
||||||
|
afterwards unless the manifests is not changed then. Note, that the provided CRD
|
||||||
|
manifests contain the validation for users to understand what schema is
|
||||||
|
enforced.
|
||||||
|
|
||||||
|
Once the validation is enabled it can only be disabled manually by editing or
|
||||||
|
patching the CRD manifest:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zk8 patch crd postgresqls.acid.zalan.do -p '{"spec":{"validation": null}}'
|
||||||
|
```
|
||||||
|
|
||||||
## Namespaces
|
## Namespaces
|
||||||
|
|
||||||
### Select the namespace to deploy to
|
### Select the namespace to deploy to
|
||||||
|
|
@ -32,7 +56,7 @@ By default, the operator watches the namespace it is deployed to. You can
|
||||||
change this by setting the `WATCHED_NAMESPACE` var in the `env` section of the
|
change this by setting the `WATCHED_NAMESPACE` var in the `env` section of the
|
||||||
[operator deployment](../manifests/postgres-operator.yaml) manifest or by
|
[operator deployment](../manifests/postgres-operator.yaml) manifest or by
|
||||||
altering the `watched_namespace` field in the operator
|
altering the `watched_namespace` field in the operator
|
||||||
[ConfigMap](../manifests/configmap.yaml#L79).
|
[configuration](../manifests/postgresql-operator-default-configuration.yaml#L49).
|
||||||
In the case both are set, the env var takes the precedence. To make the
|
In the case both are set, the env var takes the precedence. To make the
|
||||||
operator listen to all namespaces, explicitly set the field/env var to "`*`".
|
operator listen to all namespaces, explicitly set the field/env var to "`*`".
|
||||||
|
|
||||||
|
|
@ -115,7 +139,7 @@ that are aggregated into the K8s [default roles](https://kubernetes.io/docs/refe
|
||||||
|
|
||||||
To ensure Postgres pods are running on nodes without any other application pods,
|
To ensure Postgres pods are running on nodes without any other application pods,
|
||||||
you can use [taints and tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/)
|
you can use [taints and tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/)
|
||||||
and configure the required toleration in the operator ConfigMap.
|
and configure the required toleration in the operator configuration.
|
||||||
|
|
||||||
As an example you can set following node taint:
|
As an example you can set following node taint:
|
||||||
|
|
||||||
|
|
@ -136,6 +160,21 @@ data:
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For an OperatorConfiguration resource the toleration should be defined like
|
||||||
|
this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: "acid.zalan.do/v1"
|
||||||
|
kind: OperatorConfiguration
|
||||||
|
metadata:
|
||||||
|
name: postgresql-configuration
|
||||||
|
configuration:
|
||||||
|
kubernetes:
|
||||||
|
toleration:
|
||||||
|
postgres: "key:postgres,operator:Exists,effect:NoSchedule"
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
Note that the K8s version 1.13 brings [taint-based eviction](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/#taint-based-evictions)
|
Note that the K8s version 1.13 brings [taint-based eviction](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/#taint-based-evictions)
|
||||||
to the beta stage and enables it by default. Postgres pods by default receive
|
to the beta stage and enables it by default. Postgres pods by default receive
|
||||||
tolerations for `unreachable` and `noExecute` taints with the timeout of `5m`.
|
tolerations for `unreachable` and `noExecute` taints with the timeout of `5m`.
|
||||||
|
|
@ -148,7 +187,7 @@ completely, specify the toleration by leaving out the `tolerationSeconds` value
|
||||||
|
|
||||||
To ensure Postgres pods are running on different topologies, you can use
|
To ensure Postgres pods are running on different topologies, you can use
|
||||||
[pod anti affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/)
|
[pod anti affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/)
|
||||||
and configure the required topology in the operator ConfigMap.
|
and configure the required topology in the operator configuration.
|
||||||
|
|
||||||
Enable pod anti affinity by adding following line to the operator ConfigMap:
|
Enable pod anti affinity by adding following line to the operator ConfigMap:
|
||||||
|
|
||||||
|
|
@ -161,21 +200,22 @@ data:
|
||||||
enable_pod_antiaffinity: "true"
|
enable_pod_antiaffinity: "true"
|
||||||
```
|
```
|
||||||
|
|
||||||
By default the topology key for the pod anti affinity is set to
|
Likewise, when using an OperatorConfiguration resource add:
|
||||||
`kubernetes.io/hostname`, you can set another topology key e.g.
|
|
||||||
`failure-domain.beta.kubernetes.io/zone` by adding following line to the
|
|
||||||
operator ConfigMap, see [built-in node labels](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#interlude-built-in-node-labels) for available topology keys:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: v1
|
apiVersion: "acid.zalan.do/v1"
|
||||||
kind: ConfigMap
|
kind: OperatorConfiguration
|
||||||
metadata:
|
metadata:
|
||||||
name: postgres-operator
|
name: postgresql-configuration
|
||||||
data:
|
configuration:
|
||||||
enable_pod_antiaffinity: "true"
|
kubernetes:
|
||||||
pod_antiaffinity_topology_key: "failure-domain.beta.kubernetes.io/zone"
|
enable_pod_antiaffinity: true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default the topology key for the pod anti affinity is set to
|
||||||
|
`kubernetes.io/hostname`, you can set another topology key e.g.
|
||||||
|
`failure-domain.beta.kubernetes.io/zone`. See [built-in node labels](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#interlude-built-in-node-labels) for available topology keys.
|
||||||
|
|
||||||
## Pod Disruption Budget
|
## Pod Disruption Budget
|
||||||
|
|
||||||
By default the operator uses a PodDisruptionBudget (PDB) to protect the cluster
|
By default the operator uses a PodDisruptionBudget (PDB) to protect the cluster
|
||||||
|
|
@ -280,6 +320,20 @@ data:
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**OperatorConfiguration**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: "acid.zalan.do/v1"
|
||||||
|
kind: OperatorConfiguration
|
||||||
|
metadata:
|
||||||
|
name: postgresql-operator-configuration
|
||||||
|
configuration:
|
||||||
|
kubernetes:
|
||||||
|
# referencing config map with custom settings
|
||||||
|
pod_environment_configmap: postgres-pod-config
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
**referenced ConfigMap `postgres-pod-config`**
|
**referenced ConfigMap `postgres-pod-config`**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|
@ -312,7 +366,7 @@ services: one for the master pod and one for replica pods. To expose these
|
||||||
services to an outer network, one can attach load balancers to them by setting
|
services to an outer network, one can attach load balancers to them by setting
|
||||||
`enableMasterLoadBalancer` and/or `enableReplicaLoadBalancer` to `true` in the
|
`enableMasterLoadBalancer` and/or `enableReplicaLoadBalancer` to `true` in the
|
||||||
cluster manifest. In the case any of these variables are omitted from the
|
cluster manifest. In the case any of these variables are omitted from the
|
||||||
manifest, the operator configmap's settings `enable_master_load_balancer` and
|
manifest, the operator configuration settings `enable_master_load_balancer` and
|
||||||
`enable_replica_load_balancer` apply. Note that the operator settings affect
|
`enable_replica_load_balancer` apply. Note that the operator settings affect
|
||||||
all Postgresql services running in all namespaces watched by the operator.
|
all Postgresql services running in all namespaces watched by the operator.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ by setting the `GO111MODULE` environment variable to `on`. The make targets do
|
||||||
this for you, so simply run
|
this for you, so simply run
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make tools deps
|
make deps
|
||||||
```
|
```
|
||||||
|
|
||||||
This would take a while to complete. You have to redo `make deps` every time
|
This would take a while to complete. You have to redo `make deps` every time
|
||||||
|
|
@ -284,6 +284,7 @@ manifest files:
|
||||||
|
|
||||||
Postgres manifest parameters are defined in the [api package](../pkg/apis/acid.zalan.do/v1/postgresql_type.go).
|
Postgres manifest parameters are defined in the [api package](../pkg/apis/acid.zalan.do/v1/postgresql_type.go).
|
||||||
The operator behavior has to be implemented at least in [k8sres.go](../pkg/cluster/k8sres.go).
|
The operator behavior has to be implemented at least in [k8sres.go](../pkg/cluster/k8sres.go).
|
||||||
|
Validation of CRD parameters is controlled in [crd.go](../pkg/apis/acid.zalan.do/v1/crds.go).
|
||||||
Please, reflect your changes in tests, for example in:
|
Please, reflect your changes in tests, for example in:
|
||||||
* [config_test.go](../pkg/util/config/config_test.go)
|
* [config_test.go](../pkg/util/config/config_test.go)
|
||||||
* [k8sres_test.go](../pkg/cluster/k8sres_test.go)
|
* [k8sres_test.go](../pkg/cluster/k8sres_test.go)
|
||||||
|
|
@ -294,6 +295,7 @@ Please, reflect your changes in tests, for example in:
|
||||||
For the CRD-based configuration, please update the following files:
|
For the CRD-based configuration, please update the following files:
|
||||||
* the default [OperatorConfiguration](../manifests/postgresql-operator-default-configuration.yaml)
|
* the default [OperatorConfiguration](../manifests/postgresql-operator-default-configuration.yaml)
|
||||||
* the Helm chart's [values-crd file](../charts/postgres-operator/values.yaml)
|
* the Helm chart's [values-crd file](../charts/postgres-operator/values.yaml)
|
||||||
|
* the CRD's [validation](../manifests/operatorconfiguration.crd.yaml)
|
||||||
|
|
||||||
Reflect the changes in the ConfigMap configuration as well (note that numeric
|
Reflect the changes in the ConfigMap configuration as well (note that numeric
|
||||||
and boolean parameters have to use double quotes here):
|
and boolean parameters have to use double quotes here):
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,8 @@ kubectl create -f manifests/postgres-operator.yaml # deployment
|
||||||
```
|
```
|
||||||
|
|
||||||
There is a [Kustomization](https://github.com/kubernetes-sigs/kustomize)
|
There is a [Kustomization](https://github.com/kubernetes-sigs/kustomize)
|
||||||
manifest that [combines the mentioned resources](../manifests/kustomization.yaml) -
|
manifest that [combines the mentioned resources](../manifests/kustomization.yaml)
|
||||||
it can be used with kubectl 1.14 or newer as easy as:
|
(except for the CRD) - it can be used with kubectl 1.14 or newer as easy as:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubectl apply -k github.com/zalando/postgres-operator/manifests
|
kubectl apply -k github.com/zalando/postgres-operator/manifests
|
||||||
|
|
@ -73,22 +73,23 @@ manifest.
|
||||||
### Helm chart
|
### Helm chart
|
||||||
|
|
||||||
Alternatively, the operator can be installed by using the provided [Helm](https://helm.sh/)
|
Alternatively, the operator can be installed by using the provided [Helm](https://helm.sh/)
|
||||||
chart which saves you the manual steps. Therefore, install the helm CLI on your
|
chart which saves you the manual steps. Clone this repo and change directory to
|
||||||
machine. After initializing helm (and its server component Tiller) in your local
|
the repo root. With Helm v3 installed you should be able to run:
|
||||||
cluster you can install the operator chart. You can define a release name that
|
|
||||||
is prepended to the operator resource's names.
|
|
||||||
|
|
||||||
Use `--name zalando` to match with the default service account name as older
|
|
||||||
operator versions do not support custom names for service accounts. To use
|
|
||||||
CRD-based configuration you need to specify the [values-crd yaml file](../charts/postgres-operator/values-crd.yaml).
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1) initialize helm
|
helm install postgres-operator ./charts/postgres-operator
|
||||||
helm init
|
|
||||||
# 2) install postgres-operator chart
|
|
||||||
helm install --name zalando ./charts/postgres-operator
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To use CRD-based configuration you need to specify the [values-crd yaml file](../charts/postgres-operator/values-crd.yaml).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install postgres-operator ./charts/postgres-operator -f ./charts/postgres-operator/values-crd.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
The chart works with both Helm 2 and Helm 3. The `crd-install` hook from v2 will
|
||||||
|
be skipped with warning when using v3. Documentation for installing applications
|
||||||
|
with Helm 2 can be found in the [v2 docs](https://v2.helm.sh/docs/).
|
||||||
|
|
||||||
### Operator Lifecycle Manager (OLM)
|
### Operator Lifecycle Manager (OLM)
|
||||||
|
|
||||||
The [Operator Lifecycle Manager (OLM)](https://github.com/operator-framework/operator-lifecycle-manager)
|
The [Operator Lifecycle Manager (OLM)](https://github.com/operator-framework/operator-lifecycle-manager)
|
||||||
|
|
@ -119,15 +120,15 @@ kubectl get pod -l app.kubernetes.io/name=postgres-operator
|
||||||
kubectl create -f manifests/minimal-postgres-manifest.yaml
|
kubectl create -f manifests/minimal-postgres-manifest.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
After the cluster manifest is submitted the operator will create Service and
|
After the cluster manifest is submitted and passed the validation the operator
|
||||||
Endpoint resources and a StatefulSet which spins up new Pod(s) given the number
|
will create Service and Endpoint resources and a StatefulSet which spins up new
|
||||||
of instances specified in the manifest. All resources are named like the
|
Pod(s) given the number of instances specified in the manifest. All resources
|
||||||
cluster. The database pods can be identified by their number suffix, starting
|
are named like the cluster. The database pods can be identified by their number
|
||||||
from `-0`. They run the [Spilo](https://github.com/zalando/spilo) container
|
suffix, starting from `-0`. They run the [Spilo](https://github.com/zalando/spilo)
|
||||||
image by Zalando. As for the services and endpoints, there will be one for the
|
container image by Zalando. As for the services and endpoints, there will be one
|
||||||
master pod and another one for all the replicas (`-repl` suffix). Check if all
|
for the master pod and another one for all the replicas (`-repl` suffix). Check
|
||||||
components are coming up. Use the label `application=spilo` to filter and list
|
if all components are coming up. Use the label `application=spilo` to filter and
|
||||||
the label `spilo-role` to see who is currently the master.
|
list the label `spilo-role` to see who is currently the master.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# check the deployed cluster
|
# check the deployed cluster
|
||||||
|
|
|
||||||
|
|
@ -29,21 +29,20 @@ configuration.
|
||||||
|
|
||||||
To test the CRD-based configuration locally, use the following
|
To test the CRD-based configuration locally, use the following
|
||||||
```bash
|
```bash
|
||||||
|
kubectl create -f manifests/operatorconfiguration.crd.yaml # registers the CRD
|
||||||
|
kubectl create -f manifests/postgresql-operator-default-configuration.yaml
|
||||||
|
|
||||||
kubectl create -f manifests/operator-service-account-rbac.yaml
|
kubectl create -f manifests/operator-service-account-rbac.yaml
|
||||||
kubectl create -f manifests/postgres-operator.yaml # set the env var as mentioned above
|
kubectl create -f manifests/postgres-operator.yaml # set the env var as mentioned above
|
||||||
kubectl create -f manifests/postgresql-operator-default-configuration.yaml
|
|
||||||
kubectl get operatorconfigurations postgresql-operator-default-configuration -o yaml
|
kubectl get operatorconfigurations postgresql-operator-default-configuration -o yaml
|
||||||
```
|
```
|
||||||
Note that the operator first attempts to register the CRD of the
|
|
||||||
`OperatorConfiguration` and then waits for an instance to be created. In
|
|
||||||
between these two event the operator pod may be failing since it cannot fetch
|
|
||||||
the not-yet-existing `OperatorConfiguration` instance.
|
|
||||||
|
|
||||||
The CRD-based configuration is more powerful than the one based on ConfigMaps
|
The CRD-based configuration is more powerful than the one based on ConfigMaps
|
||||||
and should be used unless there is a compatibility requirement to use an already
|
and should be used unless there is a compatibility requirement to use an already
|
||||||
existing configuration. Even in that case, it should be rather straightforward
|
existing configuration. Even in that case, it should be rather straightforward
|
||||||
to convert the configmap based configuration into the CRD-based one and restart
|
to convert the ConfigMap-based configuration into the CRD-based one and restart
|
||||||
the operator. The ConfigMaps-based configuration will be deprecated and
|
the operator. The ConfigMap-based configuration will be deprecated and
|
||||||
subsequently removed in future releases.
|
subsequently removed in future releases.
|
||||||
|
|
||||||
Note that for the CRD-based configuration groups of configuration options below
|
Note that for the CRD-based configuration groups of configuration options below
|
||||||
|
|
@ -71,6 +70,11 @@ Variable names are underscore-separated words.
|
||||||
|
|
||||||
Those are top-level keys, containing both leaf keys and groups.
|
Those are top-level keys, containing both leaf keys and groups.
|
||||||
|
|
||||||
|
* **enable_crd_validation**
|
||||||
|
toggles if the operator will create or update CRDs with
|
||||||
|
[OpenAPI v3 schema validation](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#validation)
|
||||||
|
The default is `true`.
|
||||||
|
|
||||||
* **etcd_host**
|
* **etcd_host**
|
||||||
Etcd connection string for Patroni defined as `host:port`. Not required when
|
Etcd connection string for Patroni defined as `host:port`. Not required when
|
||||||
Patroni native Kubernetes support is used. The default is empty (use
|
Patroni native Kubernetes support is used. The default is empty (use
|
||||||
|
|
@ -441,6 +445,19 @@ grouped under the `logical_backup` key.
|
||||||
S3 bucket to store backup results. The bucket has to be present and
|
S3 bucket to store backup results. The bucket has to be present and
|
||||||
accessible by Postgres pods. Default: empty.
|
accessible by Postgres pods. Default: empty.
|
||||||
|
|
||||||
|
* **logical_backup_s3_endpoint**
|
||||||
|
When using non-AWS S3 storage, endpoint can be set as a ENV variable.
|
||||||
|
|
||||||
|
* **logical_backup_s3_sse**
|
||||||
|
Specify server side encription that S3 storage is using. If empty string
|
||||||
|
is specified, no argument will be passed to `aws s3` command. Default: "AES256".
|
||||||
|
|
||||||
|
* **logical_backup_s3_access_key_id**
|
||||||
|
When set, value will be in AWS_ACCESS_KEY_ID env variable. The Default is empty.
|
||||||
|
|
||||||
|
* **logical_backup_s3_secret_access_key**
|
||||||
|
When set, value will be in AWS_SECRET_ACCESS_KEY env variable. The Default is empty.
|
||||||
|
|
||||||
## Debugging the operator
|
## Debugging the operator
|
||||||
|
|
||||||
Options to aid debugging of the operator itself. Grouped under the `debug` key.
|
Options to aid debugging of the operator itself. Grouped under the `debug` key.
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,9 @@ spec:
|
||||||
- hostssl all all 0.0.0.0/0 md5
|
- hostssl all all 0.0.0.0/0 md5
|
||||||
- host all all 0.0.0.0/0 md5
|
- host all all 0.0.0.0/0 md5
|
||||||
# slots:
|
# slots:
|
||||||
# - permanent_physical_1:
|
# permanent_physical_1:
|
||||||
# type: physical
|
# type: physical
|
||||||
# - permanent_logical_1:
|
# permanent_logical_1:
|
||||||
# type: logical
|
# type: logical
|
||||||
# database: foo
|
# database: foo
|
||||||
# plugin: pgoutput
|
# plugin: pgoutput
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ data:
|
||||||
cluster_labels: application:spilo
|
cluster_labels: application:spilo
|
||||||
cluster_name_label: version
|
cluster_name_label: version
|
||||||
# custom_service_annotations: "keyx:valuez,keya:valuea"
|
# custom_service_annotations: "keyx:valuez,keya:valuea"
|
||||||
# custom_pod_annotations: "keya:valuea"
|
# custom_pod_annotations: "keya:valuea,keyb:valueb"
|
||||||
db_hosted_zone: db.example.com
|
db_hosted_zone: db.example.com
|
||||||
debug_logging: "true"
|
debug_logging: "true"
|
||||||
# default_cpu_limit: "3"
|
# default_cpu_limit: "3"
|
||||||
|
|
@ -21,6 +21,7 @@ data:
|
||||||
# default_memory_request: 100Mi
|
# default_memory_request: 100Mi
|
||||||
docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
|
docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
|
||||||
# enable_admin_role_for_users: "true"
|
# enable_admin_role_for_users: "true"
|
||||||
|
# enable_crd_validation: "true"
|
||||||
# enable_database_access: "true"
|
# enable_database_access: "true"
|
||||||
enable_master_load_balancer: "false"
|
enable_master_load_balancer: "false"
|
||||||
# enable_pod_antiaffinity: "false"
|
# enable_pod_antiaffinity: "false"
|
||||||
|
|
@ -35,9 +36,13 @@ data:
|
||||||
# kube_iam_role: ""
|
# kube_iam_role: ""
|
||||||
# log_s3_bucket: ""
|
# log_s3_bucket: ""
|
||||||
# logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
|
# logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
|
||||||
|
# logical_backup_s3_access_key_id: ""
|
||||||
# logical_backup_s3_bucket: "my-bucket-url"
|
# logical_backup_s3_bucket: "my-bucket-url"
|
||||||
|
# logical_backup_s3_endpoint: ""
|
||||||
|
# logical_backup_s3_secret_access_key: ""
|
||||||
|
# logical_backup_s3_sse: "AES256"
|
||||||
# logical_backup_schedule: "30 00 * * *"
|
# logical_backup_schedule: "30 00 * * *"
|
||||||
master_dns_name_format: "{cluster}.{team}.staging.{hostedzone}"
|
master_dns_name_format: "{cluster}.{team}.{hostedzone}"
|
||||||
# master_pod_move_timeout: 10m
|
# master_pod_move_timeout: 10m
|
||||||
# max_instances: "-1"
|
# max_instances: "-1"
|
||||||
# min_instances: "-1"
|
# min_instances: "-1"
|
||||||
|
|
@ -60,11 +65,11 @@ data:
|
||||||
ready_wait_interval: 3s
|
ready_wait_interval: 3s
|
||||||
ready_wait_timeout: 30s
|
ready_wait_timeout: 30s
|
||||||
repair_period: 5m
|
repair_period: 5m
|
||||||
replica_dns_name_format: "{cluster}-repl.{team}.staging.{hostedzone}"
|
replica_dns_name_format: "{cluster}-repl.{team}.{hostedzone}"
|
||||||
replication_username: standby
|
replication_username: standby
|
||||||
resource_check_interval: 3s
|
resource_check_interval: 3s
|
||||||
resource_check_timeout: 10m
|
resource_check_timeout: 10m
|
||||||
resync_period: 5m
|
resync_period: 30m
|
||||||
ring_log_lines: "100"
|
ring_log_lines: "100"
|
||||||
secret_name_template: "{username}.{cluster}.credentials"
|
secret_name_template: "{username}.{cluster}.credentials"
|
||||||
# sidecar_docker_images: ""
|
# sidecar_docker_images: ""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,276 @@
|
||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: operatorconfigurations.acid.zalan.do
|
||||||
|
spec:
|
||||||
|
group: acid.zalan.do
|
||||||
|
names:
|
||||||
|
kind: OperatorConfiguration
|
||||||
|
listKind: OperatorConfigurationList
|
||||||
|
plural: operatorconfigurations
|
||||||
|
singular: operatorconfiguration
|
||||||
|
shortNames:
|
||||||
|
- opconfig
|
||||||
|
scope: Namespaced
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
version: v1
|
||||||
|
validation:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- kind
|
||||||
|
- apiVersion
|
||||||
|
- configuration
|
||||||
|
properties:
|
||||||
|
kind:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- OperatorConfiguration
|
||||||
|
apiVersion:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- acid.zalan.do/v1
|
||||||
|
configuration:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
docker_image:
|
||||||
|
type: string
|
||||||
|
enable_crd_validation:
|
||||||
|
type: boolean
|
||||||
|
enable_shm_volume:
|
||||||
|
type: boolean
|
||||||
|
etcd_host:
|
||||||
|
type: string
|
||||||
|
max_instances:
|
||||||
|
type: integer
|
||||||
|
minimum: -1 # -1 = disabled
|
||||||
|
min_instances:
|
||||||
|
type: integer
|
||||||
|
minimum: -1 # -1 = disabled
|
||||||
|
resync_period:
|
||||||
|
type: string
|
||||||
|
repair_period:
|
||||||
|
type: string
|
||||||
|
set_memory_request_to_limit:
|
||||||
|
type: boolean
|
||||||
|
sidecar_docker_images:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
workers:
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
users:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
replication_username:
|
||||||
|
type: string
|
||||||
|
super_username:
|
||||||
|
type: string
|
||||||
|
kubernetes:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
cluster_domain:
|
||||||
|
type: string
|
||||||
|
cluster_labels:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
cluster_name_label:
|
||||||
|
type: string
|
||||||
|
custom_pod_annotations:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
enable_pod_antiaffinity:
|
||||||
|
type: boolean
|
||||||
|
enable_pod_disruption_budget:
|
||||||
|
type: boolean
|
||||||
|
infrastructure_roles_secret_name:
|
||||||
|
type: string
|
||||||
|
inherited_labels:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
node_readiness_label:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
oauth_token_secret_name:
|
||||||
|
type: string
|
||||||
|
pdb_name_format:
|
||||||
|
type: string
|
||||||
|
pod_antiaffinity_topology_key:
|
||||||
|
type: string
|
||||||
|
pod_environment_configmap:
|
||||||
|
type: string
|
||||||
|
pod_management_policy:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "ordered_ready"
|
||||||
|
- "parallel"
|
||||||
|
pod_role_label:
|
||||||
|
type: string
|
||||||
|
pod_service_account_name:
|
||||||
|
type: string
|
||||||
|
pod_terminate_grace_period:
|
||||||
|
type: string
|
||||||
|
secret_name_template:
|
||||||
|
type: string
|
||||||
|
spilo_fsgroup:
|
||||||
|
type: integer
|
||||||
|
spilo_privileged:
|
||||||
|
type: boolean
|
||||||
|
toleration:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
watched_namespace:
|
||||||
|
type: string
|
||||||
|
postgres_pod_resources:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
default_cpu_limit:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+m|\d+(\.\d{1,3})?)$'
|
||||||
|
default_cpu_request:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+m|\d+(\.\d{1,3})?)$'
|
||||||
|
default_memory_limit:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
default_memory_request:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
timeouts:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
pod_label_wait_timeout:
|
||||||
|
type: string
|
||||||
|
pod_deletion_wait_timeout:
|
||||||
|
type: string
|
||||||
|
ready_wait_interval:
|
||||||
|
type: string
|
||||||
|
ready_wait_timeout:
|
||||||
|
type: string
|
||||||
|
resource_check_interval:
|
||||||
|
type: string
|
||||||
|
resource_check_timeout:
|
||||||
|
type: string
|
||||||
|
load_balancer:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
db_hosted_zone:
|
||||||
|
type: string
|
||||||
|
enable_master_load_balancer:
|
||||||
|
type: boolean
|
||||||
|
enable_replica_load_balancer:
|
||||||
|
type: boolean
|
||||||
|
custom_service_annotations:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
master_dns_name_format:
|
||||||
|
type: string
|
||||||
|
replica_dns_name_format:
|
||||||
|
type: string
|
||||||
|
aws_or_gcp:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
additional_secret_mount:
|
||||||
|
type: string
|
||||||
|
additional_secret_mount_path:
|
||||||
|
type: string
|
||||||
|
aws_region:
|
||||||
|
type: string
|
||||||
|
kube_iam_role:
|
||||||
|
type: string
|
||||||
|
log_s3_bucket:
|
||||||
|
type: string
|
||||||
|
wal_s3_bucket:
|
||||||
|
type: string
|
||||||
|
logical_backup:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
logical_backup_schedule:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
|
||||||
|
logical_backup_docker_image:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_bucket:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_endpoint:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_sse:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_access_key_id:
|
||||||
|
type: string
|
||||||
|
logical_backup_s3_secret_access_key:
|
||||||
|
type: string
|
||||||
|
debug:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
debug_logging:
|
||||||
|
type: boolean
|
||||||
|
enable_database_access:
|
||||||
|
type: boolean
|
||||||
|
teams_api:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
enable_admin_role_for_users:
|
||||||
|
type: boolean
|
||||||
|
enable_team_superuser:
|
||||||
|
type: boolean
|
||||||
|
enable_teams_api:
|
||||||
|
type: boolean
|
||||||
|
pam_configuration:
|
||||||
|
type: string
|
||||||
|
pam_role_name:
|
||||||
|
type: string
|
||||||
|
postgres_superuser_teams:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
protected_role_names:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
team_admin_role:
|
||||||
|
type: string
|
||||||
|
team_api_role_configuration:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
teams_api_url:
|
||||||
|
type: string
|
||||||
|
logging_rest_api:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
api_port:
|
||||||
|
type: integer
|
||||||
|
cluster_history_entries:
|
||||||
|
type: integer
|
||||||
|
ring_log_lines:
|
||||||
|
type: integer
|
||||||
|
scalyr:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
scalyr_api_key:
|
||||||
|
type: string
|
||||||
|
scalyr_cpu_limit:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+m|\d+(\.\d{1,3})?)$'
|
||||||
|
scalyr_cpu_request:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+m|\d+(\.\d{1,3})?)$'
|
||||||
|
scalyr_image:
|
||||||
|
type: string
|
||||||
|
scalyr_memory_limit:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
scalyr_memory_request:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
scalyr_server_url:
|
||||||
|
type: string
|
||||||
|
|
@ -3,6 +3,7 @@ kind: OperatorConfiguration
|
||||||
metadata:
|
metadata:
|
||||||
name: postgresql-operator-default-configuration
|
name: postgresql-operator-default-configuration
|
||||||
configuration:
|
configuration:
|
||||||
|
# enable_crd_validation: true
|
||||||
etcd_host: ""
|
etcd_host: ""
|
||||||
docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
|
docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
|
||||||
# enable_shm_volume: true
|
# enable_shm_volume: true
|
||||||
|
|
@ -27,18 +28,19 @@ configuration:
|
||||||
# keyb: valueb
|
# keyb: valueb
|
||||||
enable_pod_antiaffinity: false
|
enable_pod_antiaffinity: false
|
||||||
enable_pod_disruption_budget: true
|
enable_pod_disruption_budget: true
|
||||||
# infrastructure_roles_secret_name: ""
|
# infrastructure_roles_secret_name: postgresql-infrastructure-roles
|
||||||
# inherited_labels:
|
# inherited_labels:
|
||||||
# - application
|
# - application
|
||||||
# - environment
|
# - environment
|
||||||
# node_readiness_label: ""
|
# node_readiness_label:
|
||||||
|
# status: ready
|
||||||
oauth_token_secret_name: postgresql-operator
|
oauth_token_secret_name: postgresql-operator
|
||||||
pdb_name_format: "postgres-{cluster}-pdb"
|
pdb_name_format: "postgres-{cluster}-pdb"
|
||||||
pod_antiaffinity_topology_key: "kubernetes.io/hostname"
|
pod_antiaffinity_topology_key: "kubernetes.io/hostname"
|
||||||
# pod_environment_configmap: ""
|
# pod_environment_configmap: ""
|
||||||
pod_management_policy: "ordered_ready"
|
pod_management_policy: "ordered_ready"
|
||||||
pod_role_label: spilo-role
|
pod_role_label: spilo-role
|
||||||
pod_service_account_name: operator
|
pod_service_account_name: zalando-postgres-operator
|
||||||
pod_terminate_grace_period: 5m
|
pod_terminate_grace_period: 5m
|
||||||
secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}"
|
secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}"
|
||||||
# spilo_fsgroup: 103
|
# spilo_fsgroup: 103
|
||||||
|
|
@ -74,9 +76,13 @@ configuration:
|
||||||
# log_s3_bucket: ""
|
# log_s3_bucket: ""
|
||||||
# wal_s3_bucket: ""
|
# wal_s3_bucket: ""
|
||||||
logical_backup:
|
logical_backup:
|
||||||
logical_backup_schedule: "30 00 * * *"
|
|
||||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
|
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
|
||||||
|
logical_backup_s3_access_key_id: ""
|
||||||
logical_backup_s3_bucket: "my-bucket-url"
|
logical_backup_s3_bucket: "my-bucket-url"
|
||||||
|
logical_backup_s3_endpoint: ""
|
||||||
|
logical_backup_s3_secret_access_key: ""
|
||||||
|
logical_backup_s3_sse: "AES256"
|
||||||
|
logical_backup_schedule: "30 00 * * *"
|
||||||
debug:
|
debug:
|
||||||
debug_logging: true
|
debug_logging: true
|
||||||
enable_database_access: true
|
enable_database_access: true
|
||||||
|
|
@ -86,7 +92,8 @@ configuration:
|
||||||
enable_teams_api: false
|
enable_teams_api: false
|
||||||
# pam_configuration: ""
|
# pam_configuration: ""
|
||||||
pam_role_name: zalandos
|
pam_role_name: zalandos
|
||||||
# postgres_superuser_teams: "postgres_superusers"
|
# postgres_superuser_teams:
|
||||||
|
# - postgres_superusers
|
||||||
protected_role_names:
|
protected_role_names:
|
||||||
- admin
|
- admin
|
||||||
team_admin_role: admin
|
team_admin_role: admin
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,327 @@
|
||||||
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: postgresqls.acid.zalan.do
|
||||||
|
spec:
|
||||||
|
group: acid.zalan.do
|
||||||
|
names:
|
||||||
|
kind: postgresql
|
||||||
|
listKind: postgresqlList
|
||||||
|
plural: postgresqls
|
||||||
|
singular: postgresql
|
||||||
|
shortNames:
|
||||||
|
- pg
|
||||||
|
scope: Namespaced
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
version: v1
|
||||||
|
validation:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- kind
|
||||||
|
- apiVersion
|
||||||
|
- spec
|
||||||
|
properties:
|
||||||
|
kind:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- postgresql
|
||||||
|
apiVersion:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- acid.zalan.do/v1
|
||||||
|
spec:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- numberOfInstances
|
||||||
|
- teamId
|
||||||
|
- postgresql
|
||||||
|
properties:
|
||||||
|
allowedSourceRanges:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\/(\d|[1-2]\d|3[0-2])$'
|
||||||
|
clone:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- cluster
|
||||||
|
properties:
|
||||||
|
cluster:
|
||||||
|
type: string
|
||||||
|
s3_endpoint:
|
||||||
|
type: string
|
||||||
|
s3_access_key_id:
|
||||||
|
type: string
|
||||||
|
s3_secret_access_key:
|
||||||
|
type: string
|
||||||
|
s3_force_path_style:
|
||||||
|
type: string
|
||||||
|
s3_wal_path:
|
||||||
|
type: string
|
||||||
|
timestamp:
|
||||||
|
type: string
|
||||||
|
pattern: '^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([+-]([01][0-9]|2[0-3]):[0-5][0-9]))$'
|
||||||
|
# The regexp matches the date-time format (RFC 3339 Section 5.6) that specifies a timezone as an offset relative to UTC
|
||||||
|
# Example: 1996-12-19T16:39:57-08:00
|
||||||
|
# Note: this field requires a timezone
|
||||||
|
uid:
|
||||||
|
format: uuid
|
||||||
|
type: string
|
||||||
|
databases:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
# Note: usernames specified here as database owners must be declared in the users key of the spec key.
|
||||||
|
dockerImage:
|
||||||
|
type: string
|
||||||
|
enableLogicalBackup:
|
||||||
|
type: boolean
|
||||||
|
enableMasterLoadBalancer:
|
||||||
|
type: boolean
|
||||||
|
enableReplicaLoadBalancer:
|
||||||
|
type: boolean
|
||||||
|
enableShmVolume:
|
||||||
|
type: boolean
|
||||||
|
init_containers: # deprecated
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
initContainers:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
logicalBackupSchedule:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$'
|
||||||
|
maintenanceWindows:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
pattern: '^\ *((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))-((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))\ *$'
|
||||||
|
numberOfInstances:
|
||||||
|
type: integer
|
||||||
|
minimum: 0
|
||||||
|
patroni:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
initdb:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
pg_hba:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
slots:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
ttl:
|
||||||
|
type: integer
|
||||||
|
loop_wait:
|
||||||
|
type: integer
|
||||||
|
retry_timeout:
|
||||||
|
type: integer
|
||||||
|
maximum_lag_on_failover:
|
||||||
|
type: integer
|
||||||
|
podAnnotations:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
pod_priority_class_name: # deprecated
|
||||||
|
type: string
|
||||||
|
podPriorityClassName:
|
||||||
|
type: string
|
||||||
|
postgresql:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- version
|
||||||
|
properties:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- "9.3"
|
||||||
|
- "9.4"
|
||||||
|
- "9.5"
|
||||||
|
- "9.6"
|
||||||
|
- "10"
|
||||||
|
- "11"
|
||||||
|
- "12"
|
||||||
|
parameters:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
replicaLoadBalancer: # deprecated
|
||||||
|
type: boolean
|
||||||
|
resources:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- requests
|
||||||
|
- limits
|
||||||
|
properties:
|
||||||
|
limits:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- cpu
|
||||||
|
- memory
|
||||||
|
properties:
|
||||||
|
cpu:
|
||||||
|
type: string
|
||||||
|
# Decimal natural followed by m, or decimal natural followed by
|
||||||
|
# dot followed by up to three decimal digits.
|
||||||
|
#
|
||||||
|
# This is because the Kubernetes CPU resource has millis as the
|
||||||
|
# maximum precision. The actual values are checked in code
|
||||||
|
# because the regular expression would be huge and horrible and
|
||||||
|
# not very helpful in validation error messages; this one checks
|
||||||
|
# only the format of the given number.
|
||||||
|
#
|
||||||
|
# https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu
|
||||||
|
pattern: '^(\d+m|\d+\.\d{1,3})$'
|
||||||
|
# Note: the value specified here must not be zero or be lower
|
||||||
|
# than the corresponding request.
|
||||||
|
memory:
|
||||||
|
type: string
|
||||||
|
# You can express memory as a plain integer or as a fixed-point
|
||||||
|
# integer using one of these suffixes: E, P, T, G, M, k. You can
|
||||||
|
# also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki
|
||||||
|
#
|
||||||
|
# https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
# Note: the value specified here must not be zero or be lower
|
||||||
|
# than the corresponding request.
|
||||||
|
requests:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- cpu
|
||||||
|
- memory
|
||||||
|
properties:
|
||||||
|
cpu:
|
||||||
|
type: string
|
||||||
|
# Decimal natural followed by m, or decimal natural followed by
|
||||||
|
# dot followed by up to three decimal digits.
|
||||||
|
#
|
||||||
|
# This is because the Kubernetes CPU resource has millis as the
|
||||||
|
# maximum precision. The actual values are checked in code
|
||||||
|
# because the regular expression would be huge and horrible and
|
||||||
|
# not very helpful in validation error messages; this one checks
|
||||||
|
# only the format of the given number.
|
||||||
|
#
|
||||||
|
# https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu
|
||||||
|
pattern: '^(\d+m|\d+\.\d{1,3})$'
|
||||||
|
# Note: the value specified here must not be zero or be higher
|
||||||
|
# than the corresponding limit.
|
||||||
|
memory:
|
||||||
|
type: string
|
||||||
|
# You can express memory as a plain integer or as a fixed-point
|
||||||
|
# integer using one of these suffixes: E, P, T, G, M, k. You can
|
||||||
|
# also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki
|
||||||
|
#
|
||||||
|
# https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
# Note: the value specified here must not be zero or be higher
|
||||||
|
# than the corresponding limit.
|
||||||
|
sidecars:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
spiloFSGroup:
|
||||||
|
type: integer
|
||||||
|
standby:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- s3_wal_path
|
||||||
|
properties:
|
||||||
|
s3_wal_path:
|
||||||
|
type: string
|
||||||
|
teamId:
|
||||||
|
type: string
|
||||||
|
tolerations:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
- operator
|
||||||
|
- effect
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
type: string
|
||||||
|
operator:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- Equal
|
||||||
|
- Exists
|
||||||
|
value:
|
||||||
|
type: string
|
||||||
|
effect:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- NoExecute
|
||||||
|
- NoSchedule
|
||||||
|
- PreferNoSchedule
|
||||||
|
tolerationSeconds:
|
||||||
|
type: integer
|
||||||
|
useLoadBalancer: # deprecated
|
||||||
|
type: boolean
|
||||||
|
users:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
description: "Role flags specified here must not contradict each other"
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- bypassrls
|
||||||
|
- BYPASSRLS
|
||||||
|
- nobypassrls
|
||||||
|
- NOBYPASSRLS
|
||||||
|
- createdb
|
||||||
|
- CREATEDB
|
||||||
|
- nocreatedb
|
||||||
|
- NOCREATEDB
|
||||||
|
- createrole
|
||||||
|
- CREATEROLE
|
||||||
|
- nocreaterole
|
||||||
|
- NOCREATEROLE
|
||||||
|
- inherit
|
||||||
|
- INHERIT
|
||||||
|
- noinherit
|
||||||
|
- NOINHERIT
|
||||||
|
- login
|
||||||
|
- LOGIN
|
||||||
|
- nologin
|
||||||
|
- NOLOGIN
|
||||||
|
- replication
|
||||||
|
- REPLICATION
|
||||||
|
- noreplication
|
||||||
|
- NOREPLICATION
|
||||||
|
- superuser
|
||||||
|
- SUPERUSER
|
||||||
|
- nosuperuser
|
||||||
|
- NOSUPERUSER
|
||||||
|
volume:
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- size
|
||||||
|
properties:
|
||||||
|
size:
|
||||||
|
type: string
|
||||||
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
|
# Note: the value specified here must not be zero.
|
||||||
|
storageClass:
|
||||||
|
type: string
|
||||||
|
subPath:
|
||||||
|
type: string
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do"
|
acidzalando "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do"
|
||||||
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
@ -103,7 +103,902 @@ var OperatorConfigCRDResourceColumns = []apiextv1beta1.CustomResourceColumnDefin
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomResourceColumnDefinition) *apiextv1beta1.CustomResourceDefinition {
|
var min0 = 0.0
|
||||||
|
var min1 = 1.0
|
||||||
|
var minDisable = -1.0
|
||||||
|
|
||||||
|
// PostgresCRDResourceValidation to check applied manifest parameters
|
||||||
|
var PostgresCRDResourceValidation = apiextv1beta1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"kind", "apiVersion", "spec"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"kind": {
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"postgresql"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"apiVersion": {
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"acid.zalan.do/v1"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"numberOfInstances", "teamId", "postgresql"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"allowedSourceRanges": {
|
||||||
|
Type: "array",
|
||||||
|
Nullable: true,
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\/(\\d|[1-2]\\d|3[0-2])$",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"clone": {
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"cluster"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"cluster": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"s3_endpoint": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"s3_access_key_id": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"s3_secret_access_key": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"s3_force_path_style": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"s3_wal_path": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"timestamp": {
|
||||||
|
Type: "string",
|
||||||
|
Description: "Date-time format that specifies a timezone as an offset relative to UTC e.g. 1996-12-19T16:39:57-08:00",
|
||||||
|
Pattern: "^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(([Zz])|([+-]([01][0-9]|2[0-3]):[0-5][0-9]))$",
|
||||||
|
},
|
||||||
|
"uid": {
|
||||||
|
Type: "string",
|
||||||
|
Format: "uuid",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"databases": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
Description: "User names specified here as database owners must be declared in the users key of the spec key",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"dockerImage": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"enableLogicalBackup": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enableMasterLoadBalancer": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enableReplicaLoadBalancer": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enableShmVolume": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"init_containers": {
|
||||||
|
Type: "array",
|
||||||
|
Description: "Deprecated",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Allows: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"initContainers": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Allows: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"logicalBackupSchedule": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+|\\*)(/\\d+)?(\\s+(\\d+|\\*)(/\\d+)?){4}$",
|
||||||
|
},
|
||||||
|
"maintenanceWindows": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^\\ *((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\\d):([0-5]?\\d)|(2[0-3]|[01]?\\d):([0-5]?\\d))-((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\\d):([0-5]?\\d)|(2[0-3]|[01]?\\d):([0-5]?\\d))\\ *$",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"numberOfInstances": {
|
||||||
|
Type: "integer",
|
||||||
|
Minimum: &min0,
|
||||||
|
},
|
||||||
|
"patroni": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"initdb": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"pg_hba": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"slots": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"ttl": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
"loop_wait": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
"retry_timeout": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
"maximum_lag_on_failover": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"podAnnotations": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"pod_priority_class_name": {
|
||||||
|
Type: "string",
|
||||||
|
Description: "Deprecated",
|
||||||
|
},
|
||||||
|
"podPriorityClassName": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"postgresql": {
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"version"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"version": {
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"9.3"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"9.4"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"9.5"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"9.6"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"10"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"11"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"12"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"replicaLoadBalancer": {
|
||||||
|
Type: "boolean",
|
||||||
|
Description: "Deprecated",
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"requests", "limits"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"limits": {
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"cpu", "memory"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"cpu": {
|
||||||
|
Type: "string",
|
||||||
|
Description: "Decimal natural followed by m, or decimal natural followed by dot followed by up to three decimal digits (precision used by Kubernetes). Must be greater than 0",
|
||||||
|
Pattern: "^(\\d+m|\\d+\\.\\d{1,3})$",
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
Type: "string",
|
||||||
|
Description: "Plain integer or fixed-point integer using one of these suffixes: E, P, T, G, M, k (with or without a tailing i). Must be greater than 0",
|
||||||
|
Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"requests": {
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"cpu", "memory"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"cpu": {
|
||||||
|
Type: "string",
|
||||||
|
Description: "Decimal natural followed by m, or decimal natural followed by dot followed by up to three decimal digits (precision used by Kubernetes). Must be greater than 0",
|
||||||
|
Pattern: "^(\\d+m|\\d+\\.\\d{1,3})$",
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
Type: "string",
|
||||||
|
Description: "Plain integer or fixed-point integer using one of these suffixes: E, P, T, G, M, k (with or without a tailing i). Must be greater than 0",
|
||||||
|
Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"sidecars": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Allows: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spiloFSGroup": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
"standby": {
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"s3_wal_path"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"s3_wal_path": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"teamId": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"tolerations": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"key", "operator", "effect"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"key": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"operator": {
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"Equal"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"Exists"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"effect": {
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NoExecute"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NoSchedule"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"PreferNoSchedule"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"tolerationSeconds": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"useLoadBalancer": {
|
||||||
|
Type: "boolean",
|
||||||
|
Description: "Deprecated",
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "array",
|
||||||
|
Description: "Role flags specified here must not contradict each other",
|
||||||
|
Nullable: true,
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"bypassrls"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"BYPASSRLS"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"nobypassrls"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NOBYPASSRLS"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"createdb"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"CREATEDB"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"nocreatedb"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NOCREATEDB"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"createrole"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"CREATEROLE"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"nocreaterole"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NOCREATEROLE"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"inherit"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"INHERIT"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"noinherit"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NOINHERIT"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"login"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"LOGIN"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"nologin"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NOLOGIN"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"replication"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"REPLICATION"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"noreplication"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NOREPLICATION"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"superuser"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"SUPERUSER"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"nosuperuser"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"NOSUPERUSER"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"size"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"size": {
|
||||||
|
Type: "string",
|
||||||
|
Description: "Value must not be zero",
|
||||||
|
Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$",
|
||||||
|
},
|
||||||
|
"storageClass": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"subPath": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// OperatorConfigCRDResourceValidation to check applied manifest parameters
|
||||||
|
var OperatorConfigCRDResourceValidation = apiextv1beta1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
Required: []string{"kind", "apiVersion", "configuration"},
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"kind": {
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"OperatorConfiguration"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"apiVersion": {
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"acid.zalan.do/v1"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"configuration": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"docker_image": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"enable_crd_validation": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enable_shm_volume": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"etcd_host": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"max_instances": {
|
||||||
|
Type: "integer",
|
||||||
|
Description: "-1 = disabled",
|
||||||
|
Minimum: &minDisable,
|
||||||
|
},
|
||||||
|
"min_instances": {
|
||||||
|
Type: "integer",
|
||||||
|
Description: "-1 = disabled",
|
||||||
|
Minimum: &minDisable,
|
||||||
|
},
|
||||||
|
"resync_period": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"repair_period": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"set_memory_request_to_limit": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"sidecar_docker_images": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"workers": {
|
||||||
|
Type: "integer",
|
||||||
|
Minimum: &min1,
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"replication_username": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"super_username": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"kubernetes": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"cluster_domain": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"cluster_labels": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"cluster_name_label": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"custom_pod_annotations": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"enable_pod_antiaffinity": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enable_pod_disruption_budget": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"infrastructure_roles_secret_name": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"inherited_labels": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"node_readiness_label": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"oauth_token_secret_name": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"pdb_name_format": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"pod_antiaffinity_topology_key": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"pod_environment_configmap": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"pod_management_policy": {
|
||||||
|
Type: "string",
|
||||||
|
Enum: []apiextv1beta1.JSON{
|
||||||
|
{
|
||||||
|
Raw: []byte(`"ordered_ready"`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Raw: []byte(`"parallel"`),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"pod_role_label": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"pod_service_account_name": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"pod_terminate_grace_period": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"secret_name_template": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"spilo_fsgroup": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
"spilo_privileged": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"toleration": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"watched_namespace": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"postgres_pod_resources": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"default_cpu_limit": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$",
|
||||||
|
},
|
||||||
|
"default_cpu_request": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$",
|
||||||
|
},
|
||||||
|
"default_memory_limit": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$",
|
||||||
|
},
|
||||||
|
"default_memory_request": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"timeouts": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"pod_label_wait_timeout": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"pod_deletion_wait_timeout": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"ready_wait_interval": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"ready_wait_timeout": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"resource_check_interval": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"resource_check_timeout": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"load_balancer": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"db_hosted_zone": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"enable_master_load_balancer": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enable_replica_load_balancer": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"custom_service_annotations": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"master_dns_name_format": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"replica_dns_name_format": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"aws_or_gcp": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"additional_secret_mount": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"additional_secret_mount_path": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"aws_region": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"kube_iam_role": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"log_s3_bucket": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"wal_s3_bucket": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"logical_backup": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"logical_backup_schedule": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+|\\*)(/\\d+)?(\\s+(\\d+|\\*)(/\\d+)?){4}$",
|
||||||
|
},
|
||||||
|
"logical_backup_docker_image": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"logical_backup_s3_bucket": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"logical_backup_s3_endpoint": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"logical_backup_s3_sse": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"logical_backup_s3_access_key_id": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"logical_backup_s3_secret_access_key": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"debug_logging": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enable_database_access": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"teams_api": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"enable_admin_role_for_users": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enable_team_superuser": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"enable_teams_api": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"pam_configuration": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"pam_role_name": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"postgres_superuser_teams": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"protected_role_names": {
|
||||||
|
Type: "array",
|
||||||
|
Items: &apiextv1beta1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"team_admin_role": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"team_api_role_configuration": {
|
||||||
|
Type: "object",
|
||||||
|
AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{
|
||||||
|
Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"teams_api_url": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"logging_rest_api": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"api_port": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
"cluster_history_entries": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
"ring_log_lines": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"scalyr": {
|
||||||
|
Type: "object",
|
||||||
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
"scalyr_api_key": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"scalyr_cpu_limit": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$",
|
||||||
|
},
|
||||||
|
"scalyr_cpu_request": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$",
|
||||||
|
},
|
||||||
|
"scalyr_image": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
"scalyr_memory_limit": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$",
|
||||||
|
},
|
||||||
|
"scalyr_memory_request": {
|
||||||
|
Type: "string",
|
||||||
|
Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$",
|
||||||
|
},
|
||||||
|
"scalyr_server_url": {
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomResourceColumnDefinition, validation apiextv1beta1.CustomResourceValidation) *apiextv1beta1.CustomResourceDefinition {
|
||||||
return &apiextv1beta1.CustomResourceDefinition{
|
return &apiextv1beta1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
|
@ -121,24 +1016,39 @@ func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomRe
|
||||||
Status: &apiextv1beta1.CustomResourceSubresourceStatus{},
|
Status: &apiextv1beta1.CustomResourceSubresourceStatus{},
|
||||||
},
|
},
|
||||||
AdditionalPrinterColumns: columns,
|
AdditionalPrinterColumns: columns,
|
||||||
|
Validation: &validation,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostgresCRD returns CustomResourceDefinition built from PostgresCRDResource
|
// PostgresCRD returns CustomResourceDefinition built from PostgresCRDResource
|
||||||
func PostgresCRD() *apiextv1beta1.CustomResourceDefinition {
|
func PostgresCRD(enableValidation *bool) *apiextv1beta1.CustomResourceDefinition {
|
||||||
|
postgresCRDvalidation := apiextv1beta1.CustomResourceValidation{}
|
||||||
|
|
||||||
|
if enableValidation != nil && *enableValidation {
|
||||||
|
postgresCRDvalidation = PostgresCRDResourceValidation
|
||||||
|
}
|
||||||
|
|
||||||
return buildCRD(PostgresCRDResouceName,
|
return buildCRD(PostgresCRDResouceName,
|
||||||
PostgresCRDResourceKind,
|
PostgresCRDResourceKind,
|
||||||
PostgresCRDResourcePlural,
|
PostgresCRDResourcePlural,
|
||||||
PostgresCRDResourceShort,
|
PostgresCRDResourceShort,
|
||||||
PostgresCRDResourceColumns)
|
PostgresCRDResourceColumns,
|
||||||
|
postgresCRDvalidation)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigurationCRD returns CustomResourceDefinition built from OperatorConfigCRDResource
|
// ConfigurationCRD returns CustomResourceDefinition built from OperatorConfigCRDResource
|
||||||
func ConfigurationCRD() *apiextv1beta1.CustomResourceDefinition {
|
func ConfigurationCRD(enableValidation *bool) *apiextv1beta1.CustomResourceDefinition {
|
||||||
|
opconfigCRDvalidation := apiextv1beta1.CustomResourceValidation{}
|
||||||
|
|
||||||
|
if enableValidation != nil && *enableValidation {
|
||||||
|
opconfigCRDvalidation = OperatorConfigCRDResourceValidation
|
||||||
|
}
|
||||||
|
|
||||||
return buildCRD(OperatorConfigCRDResourceName,
|
return buildCRD(OperatorConfigCRDResourceName,
|
||||||
OperatorConfigCRDResouceKind,
|
OperatorConfigCRDResouceKind,
|
||||||
OperatorConfigCRDResourcePlural,
|
OperatorConfigCRDResourcePlural,
|
||||||
OperatorConfigCRDResourceShort,
|
OperatorConfigCRDResourceShort,
|
||||||
OperatorConfigCRDResourceColumns)
|
OperatorConfigCRDResourceColumns,
|
||||||
|
opconfigCRDvalidation)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ type ScalyrConfiguration struct {
|
||||||
|
|
||||||
// OperatorConfigurationData defines the operation config
|
// OperatorConfigurationData defines the operation config
|
||||||
type OperatorConfigurationData struct {
|
type OperatorConfigurationData struct {
|
||||||
|
EnableCRDValidation *bool `json:"enable_crd_validation,omitempty"`
|
||||||
EtcdHost string `json:"etcd_host,omitempty"`
|
EtcdHost string `json:"etcd_host,omitempty"`
|
||||||
DockerImage string `json:"docker_image,omitempty"`
|
DockerImage string `json:"docker_image,omitempty"`
|
||||||
Workers uint32 `json:"workers,omitempty"`
|
Workers uint32 `json:"workers,omitempty"`
|
||||||
|
|
@ -184,8 +185,13 @@ type OperatorConfigurationUsers struct {
|
||||||
//Duration shortens this frequently used name
|
//Duration shortens this frequently used name
|
||||||
type Duration time.Duration
|
type Duration time.Duration
|
||||||
|
|
||||||
|
// OperatorLogicalBackupConfiguration defines configration for logical backup
|
||||||
type OperatorLogicalBackupConfiguration struct {
|
type OperatorLogicalBackupConfiguration struct {
|
||||||
Schedule string `json:"logical_backup_schedule,omitempty"`
|
Schedule string `json:"logical_backup_schedule,omitempty"`
|
||||||
DockerImage string `json:"logical_backup_docker_image,omitempty"`
|
DockerImage string `json:"logical_backup_docker_image,omitempty"`
|
||||||
S3Bucket string `json:"logical_backup_s3_bucket,omitempty"`
|
S3Bucket string `json:"logical_backup_s3_bucket,omitempty"`
|
||||||
|
S3Endpoint string `json:"logical_backup_s3_endpoint,omitempty"`
|
||||||
|
S3AccessKeyID string `json:"logical_backup_s3_access_key_id,omitempty"`
|
||||||
|
S3SecretAccessKey string `json:"logical_backup_s3_secret_access_key,omitempty"`
|
||||||
|
S3SSE string `json:"logical_backup_s3_sse,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,11 @@ func (in *OperatorConfiguration) DeepCopyObject() runtime.Object {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *OperatorConfigurationData) DeepCopyInto(out *OperatorConfigurationData) {
|
func (in *OperatorConfigurationData) DeepCopyInto(out *OperatorConfigurationData) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.EnableCRDValidation != nil {
|
||||||
|
in, out := &in.EnableCRDValidation, &out.EnableCRDValidation
|
||||||
|
*out = new(bool)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
if in.ShmVolume != nil {
|
if in.ShmVolume != nil {
|
||||||
in, out := &in.ShmVolume, &out.ShmVolume
|
in, out := &in.ShmVolume, &out.ShmVolume
|
||||||
*out = new(bool)
|
*out = new(bool)
|
||||||
|
|
|
||||||
|
|
@ -1575,6 +1575,14 @@ func (c *Cluster) generateLogicalBackupPodEnvVars() []v1.EnvVar {
|
||||||
Name: "LOGICAL_BACKUP_S3_BUCKET",
|
Name: "LOGICAL_BACKUP_S3_BUCKET",
|
||||||
Value: c.OpConfig.LogicalBackup.LogicalBackupS3Bucket,
|
Value: c.OpConfig.LogicalBackup.LogicalBackupS3Bucket,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "LOGICAL_BACKUP_S3_ENDPOINT",
|
||||||
|
Value: c.OpConfig.LogicalBackup.LogicalBackupS3Endpoint,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "LOGICAL_BACKUP_S3_SSE",
|
||||||
|
Value: c.OpConfig.LogicalBackup.LogicalBackupS3SSE,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX",
|
Name: "LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX",
|
||||||
Value: getBucketScopeSuffix(string(c.Postgresql.GetUID())),
|
Value: getBucketScopeSuffix(string(c.Postgresql.GetUID())),
|
||||||
|
|
@ -1613,8 +1621,15 @@ func (c *Cluster) generateLogicalBackupPodEnvVars() []v1.EnvVar {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
c.logger.Debugf("Generated logical backup env vars %v", envVars)
|
if c.OpConfig.LogicalBackup.LogicalBackupS3AccessKeyID != "" {
|
||||||
|
envVars = append(envVars, v1.EnvVar{Name: "AWS_ACCESS_KEY_ID", Value: c.OpConfig.LogicalBackup.LogicalBackupS3AccessKeyID})
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.OpConfig.LogicalBackup.LogicalBackupS3SecretAccessKey != "" {
|
||||||
|
envVars = append(envVars, v1.EnvVar{Name: "AWS_SECRET_ACCESS_KEY", Value: c.OpConfig.LogicalBackup.LogicalBackupS3SecretAccessKey})
|
||||||
|
}
|
||||||
|
|
||||||
|
c.logger.Debugf("Generated logical backup env vars %v", envVars)
|
||||||
return envVars
|
return envVars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
||||||
"github.com/zalando/postgres-operator/pkg/util"
|
"github.com/zalando/postgres-operator/pkg/util"
|
||||||
"github.com/zalando/postgres-operator/pkg/util/constants"
|
|
||||||
"github.com/zalando/postgres-operator/pkg/util/k8sutil"
|
"github.com/zalando/postgres-operator/pkg/util/k8sutil"
|
||||||
"github.com/zalando/postgres-operator/pkg/util/retryutil"
|
"github.com/zalando/postgres-operator/pkg/util/retryutil"
|
||||||
)
|
)
|
||||||
|
|
@ -278,7 +277,8 @@ func (c *Cluster) replaceStatefulSet(newStatefulSet *appsv1.StatefulSet) error {
|
||||||
oldStatefulset := c.Statefulset
|
oldStatefulset := c.Statefulset
|
||||||
|
|
||||||
options := metav1.DeleteOptions{PropagationPolicy: &deletePropagationPolicy}
|
options := metav1.DeleteOptions{PropagationPolicy: &deletePropagationPolicy}
|
||||||
if err := c.KubeClient.StatefulSets(oldStatefulset.Namespace).Delete(oldStatefulset.Name, &options); err != nil {
|
err := c.KubeClient.StatefulSets(oldStatefulset.Namespace).Delete(oldStatefulset.Name, &options)
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("could not delete statefulset %q: %v", statefulSetName, err)
|
return fmt.Errorf("could not delete statefulset %q: %v", statefulSetName, err)
|
||||||
}
|
}
|
||||||
// make sure we clear the stored statefulset status if the subsequent create fails.
|
// make sure we clear the stored statefulset status if the subsequent create fails.
|
||||||
|
|
@ -286,11 +286,16 @@ func (c *Cluster) replaceStatefulSet(newStatefulSet *appsv1.StatefulSet) error {
|
||||||
// wait until the statefulset is truly deleted
|
// wait until the statefulset is truly deleted
|
||||||
c.logger.Debugf("waiting for the statefulset to be deleted")
|
c.logger.Debugf("waiting for the statefulset to be deleted")
|
||||||
|
|
||||||
err := retryutil.Retry(constants.StatefulsetDeletionInterval, constants.StatefulsetDeletionTimeout,
|
err = retryutil.Retry(c.OpConfig.ResourceCheckInterval, c.OpConfig.ResourceCheckTimeout,
|
||||||
func() (bool, error) {
|
func() (bool, error) {
|
||||||
_, err := c.KubeClient.StatefulSets(oldStatefulset.Namespace).Get(oldStatefulset.Name, metav1.GetOptions{})
|
_, err2 := c.KubeClient.StatefulSets(oldStatefulset.Namespace).Get(oldStatefulset.Name, metav1.GetOptions{})
|
||||||
|
if err2 == nil {
|
||||||
return err != nil, nil
|
return false, nil
|
||||||
|
}
|
||||||
|
if k8sutil.ResourceNotFound(err2) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, err2
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not delete statefulset: %v", err)
|
return fmt.Errorf("could not delete statefulset: %v", err)
|
||||||
|
|
@ -380,13 +385,27 @@ func (c *Cluster) updateService(role PostgresRole, newService *v1.Service) error
|
||||||
return fmt.Errorf("could not delete service %q: %v", serviceName, err)
|
return fmt.Errorf("could not delete service %q: %v", serviceName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Endpoints[role] = nil
|
// wait until the service is truly deleted
|
||||||
svc, err := c.KubeClient.Services(serviceName.Namespace).Create(newService)
|
c.logger.Debugf("waiting for service to be deleted")
|
||||||
|
|
||||||
|
err = retryutil.Retry(c.OpConfig.ResourceCheckInterval, c.OpConfig.ResourceCheckTimeout,
|
||||||
|
func() (bool, error) {
|
||||||
|
_, err2 := c.KubeClient.Services(serviceName.Namespace).Get(serviceName.Name, metav1.GetOptions{})
|
||||||
|
if err2 == nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if k8sutil.ResourceNotFound(err2) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, err2
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not create service %q: %v", serviceName, err)
|
return fmt.Errorf("could not delete service %q: %v", serviceName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Services[role] = svc
|
// make sure we clear the stored service and endpoint status if the subsequent create fails.
|
||||||
|
c.Services[role] = nil
|
||||||
|
c.Endpoints[role] = nil
|
||||||
if role == Master {
|
if role == Master {
|
||||||
// create the new endpoint using the addresses obtained from the previous one
|
// create the new endpoint using the addresses obtained from the previous one
|
||||||
endpointSpec := c.generateEndpoint(role, currentEndpoint.Subsets)
|
endpointSpec := c.generateEndpoint(role, currentEndpoint.Subsets)
|
||||||
|
|
@ -398,6 +417,13 @@ func (c *Cluster) updateService(role PostgresRole, newService *v1.Service) error
|
||||||
c.Endpoints[role] = ep
|
c.Endpoints[role] = ep
|
||||||
}
|
}
|
||||||
|
|
||||||
|
svc, err := c.KubeClient.Services(serviceName.Namespace).Create(newService)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not create service %q: %v", serviceName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Services[role] = svc
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ func (c *Controller) initController() {
|
||||||
c.initClients()
|
c.initClients()
|
||||||
|
|
||||||
if configObjectName := os.Getenv("POSTGRES_OPERATOR_CONFIGURATION_OBJECT"); configObjectName != "" {
|
if configObjectName := os.Getenv("POSTGRES_OPERATOR_CONFIGURATION_OBJECT"); configObjectName != "" {
|
||||||
if err := c.createConfigurationCRD(); err != nil {
|
if err := c.createConfigurationCRD(c.opConfig.EnableCRDValidation); err != nil {
|
||||||
c.logger.Fatalf("could not register Operator Configuration CustomResourceDefinition: %v", err)
|
c.logger.Fatalf("could not register Operator Configuration CustomResourceDefinition: %v", err)
|
||||||
}
|
}
|
||||||
if cfg, err := c.readOperatorConfigurationFromCRD(spec.GetOperatorNamespace(), configObjectName); err != nil {
|
if cfg, err := c.readOperatorConfigurationFromCRD(spec.GetOperatorNamespace(), configObjectName); err != nil {
|
||||||
|
|
@ -256,7 +256,7 @@ func (c *Controller) initController() {
|
||||||
|
|
||||||
c.modifyConfigFromEnvironment()
|
c.modifyConfigFromEnvironment()
|
||||||
|
|
||||||
if err := c.createPostgresCRD(); err != nil {
|
if err := c.createPostgresCRD(c.opConfig.EnableCRDValidation); err != nil {
|
||||||
c.logger.Fatalf("could not register Postgres CustomResourceDefinition: %v", err)
|
c.logger.Fatalf("could not register Postgres CustomResourceDefinition: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
||||||
result := &config.Config{}
|
result := &config.Config{}
|
||||||
|
|
||||||
// general config
|
// general config
|
||||||
|
result.EnableCRDValidation = fromCRD.EnableCRDValidation
|
||||||
result.EtcdHost = fromCRD.EtcdHost
|
result.EtcdHost = fromCRD.EtcdHost
|
||||||
result.DockerImage = fromCRD.DockerImage
|
result.DockerImage = fromCRD.DockerImage
|
||||||
result.Workers = fromCRD.Workers
|
result.Workers = fromCRD.Workers
|
||||||
|
|
@ -101,6 +102,10 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
||||||
result.LogicalBackupSchedule = fromCRD.LogicalBackup.Schedule
|
result.LogicalBackupSchedule = fromCRD.LogicalBackup.Schedule
|
||||||
result.LogicalBackupDockerImage = fromCRD.LogicalBackup.DockerImage
|
result.LogicalBackupDockerImage = fromCRD.LogicalBackup.DockerImage
|
||||||
result.LogicalBackupS3Bucket = fromCRD.LogicalBackup.S3Bucket
|
result.LogicalBackupS3Bucket = fromCRD.LogicalBackup.S3Bucket
|
||||||
|
result.LogicalBackupS3Endpoint = fromCRD.LogicalBackup.S3Endpoint
|
||||||
|
result.LogicalBackupS3AccessKeyID = fromCRD.LogicalBackup.S3AccessKeyID
|
||||||
|
result.LogicalBackupS3SecretAccessKey = fromCRD.LogicalBackup.S3SecretAccessKey
|
||||||
|
result.LogicalBackupS3SSE = fromCRD.LogicalBackup.S3SSE
|
||||||
|
|
||||||
// debug config
|
// debug config
|
||||||
result.DebugLogging = fromCRD.OperatorDebug.DebugLogging
|
result.DebugLogging = fromCRD.OperatorDebug.DebugLogging
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
@ -91,12 +91,12 @@ func (c *Controller) createOperatorCRD(crd *apiextv1beta1.CustomResourceDefiniti
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) createPostgresCRD() error {
|
func (c *Controller) createPostgresCRD(enableValidation *bool) error {
|
||||||
return c.createOperatorCRD(acidv1.PostgresCRD())
|
return c.createOperatorCRD(acidv1.PostgresCRD(enableValidation))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) createConfigurationCRD() error {
|
func (c *Controller) createConfigurationCRD(enableValidation *bool) error {
|
||||||
return c.createOperatorCRD(acidv1.ConfigurationCRD())
|
return c.createOperatorCRD(acidv1.ConfigurationCRD(enableValidation))
|
||||||
}
|
}
|
||||||
|
|
||||||
func readDecodedRole(s string) (*spec.PgUser, error) {
|
func readDecodedRole(s string) (*spec.PgUser, error) {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ type CRD struct {
|
||||||
ReadyWaitTimeout time.Duration `name:"ready_wait_timeout" default:"30s"`
|
ReadyWaitTimeout time.Duration `name:"ready_wait_timeout" default:"30s"`
|
||||||
ResyncPeriod time.Duration `name:"resync_period" default:"30m"`
|
ResyncPeriod time.Duration `name:"resync_period" default:"30m"`
|
||||||
RepairPeriod time.Duration `name:"repair_period" default:"5m"`
|
RepairPeriod time.Duration `name:"repair_period" default:"5m"`
|
||||||
|
EnableCRDValidation *bool `name:"enable_crd_validation" default:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resources describes kubernetes resource specific configuration parameters
|
// Resources describes kubernetes resource specific configuration parameters
|
||||||
|
|
@ -68,11 +69,15 @@ type Scalyr struct {
|
||||||
ScalyrMemoryLimit string `name:"scalyr_memory_limit" default:"1Gi"`
|
ScalyrMemoryLimit string `name:"scalyr_memory_limit" default:"1Gi"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogicalBackup
|
// LogicalBackup defines configration for logical backup
|
||||||
type LogicalBackup struct {
|
type LogicalBackup struct {
|
||||||
LogicalBackupSchedule string `name:"logical_backup_schedule" default:"30 00 * * *"`
|
LogicalBackupSchedule string `name:"logical_backup_schedule" default:"30 00 * * *"`
|
||||||
LogicalBackupDockerImage string `name:"logical_backup_docker_image" default:"registry.opensource.zalan.do/acid/logical-backup"`
|
LogicalBackupDockerImage string `name:"logical_backup_docker_image" default:"registry.opensource.zalan.do/acid/logical-backup"`
|
||||||
LogicalBackupS3Bucket string `name:"logical_backup_s3_bucket" default:""`
|
LogicalBackupS3Bucket string `name:"logical_backup_s3_bucket" default:""`
|
||||||
|
LogicalBackupS3Endpoint string `name:"logical_backup_s3_endpoint" default:""`
|
||||||
|
LogicalBackupS3AccessKeyID string `name:"logical_backup_s3_access_key_id" default:""`
|
||||||
|
LogicalBackupS3SecretAccessKey string `name:"logical_backup_s3_secret_access_key" default:""`
|
||||||
|
LogicalBackupS3SSE string `name:"logical_backup_s3_sse" default:"AES256"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config describes operator config
|
// Config describes operator config
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ const (
|
||||||
PostgresContainerName = "postgres"
|
PostgresContainerName = "postgres"
|
||||||
PostgresContainerIdx = 0
|
PostgresContainerIdx = 0
|
||||||
K8sAPIPath = "/apis"
|
K8sAPIPath = "/apis"
|
||||||
StatefulsetDeletionInterval = 1 * time.Second
|
|
||||||
StatefulsetDeletionTimeout = 30 * time.Second
|
|
||||||
|
|
||||||
QueueResyncPeriodPod = 5 * time.Minute
|
QueueResyncPeriodPod = 5 * time.Minute
|
||||||
QueueResyncPeriodTPR = 5 * time.Minute
|
QueueResyncPeriodTPR = 5 * time.Minute
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ function build_operator_binary(){
|
||||||
|
|
||||||
# redirecting stderr greatly reduces non-informative output during normal builds
|
# redirecting stderr greatly reduces non-informative output during normal builds
|
||||||
echo "Build operator binary (stderr redirected to /dev/null)..."
|
echo "Build operator binary (stderr redirected to /dev/null)..."
|
||||||
make clean tools deps local test > /dev/null 2>&1
|
make clean deps local test > /dev/null 2>&1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue