diff --git a/README.md b/README.md new file mode 100644 index 00000000..8fd315ae --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# [PGO](https://github.com/CrunchyData/postgres-operator), Crunchy [Postgres Operator](https://github.com/CrunchyData/postgres-operator) Examples + +This repository contains examples for deploying PGO, the Postgres Operator from Crunchy Data, using a variety of examples. + +The examples are grouped by various tools that can be used to deploy them. + +The best way to get started is to fork this repository and experiment with the examples. + +Each of the examples has its own README that guides you through the process of deploying it. + +You can find out more information about [PGO](https://github.com/CrunchyData/postgres-operator), the [Postgres Operator](https://github.com/CrunchyData/postgres-operator) from [Crunchy Data](https://www.crunchydata.com) at the project page: + +[https://github.com/CrunchyData/postgres-operator](https://github.com/CrunchyData/postgres-operator) diff --git a/helm/install/Chart.yaml b/helm/install/Chart.yaml new file mode 100644 index 00000000..62b0a1b2 --- /dev/null +++ b/helm/install/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v3 +name: postgres-operator +description: A Helm chart for Kubernetes +type: application +version: 0.1.0 +appVersion: 5.0.0 diff --git a/helm/install/crds/postgres-operator.crunchydata.com_postgresclusters.yaml b/helm/install/crds/postgres-operator.crunchydata.com_postgresclusters.yaml new file mode 100644 index 00000000..45c29825 --- /dev/null +++ b/helm/install/crds/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -0,0 +1,4583 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: postgresclusters.postgres-operator.crunchydata.com +spec: + group: postgres-operator.crunchydata.com + names: + kind: PostgresCluster + listKind: PostgresClusterList + plural: postgresclusters + singular: postgrescluster + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: PostgresCluster is the Schema for the postgresclusters API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: PostgresClusterSpec defines the desired state of PostgresCluster + properties: + backups: + description: PostgreSQL backup configuration + properties: + pgbackrest: + description: pgBackRest archive configuration + properties: + configuration: + description: 'Projected volumes containing custom pgBackRest + configuration. These files are mounted under "/etc/pgbackrest/conf.d" + alongside any pgBackRest configuration generated by the + PostgreSQL Operator: https://pgbackrest.org/configuration.html' + items: + description: Projection that may be projected along with + other supported volume types + properties: + configMap: + description: information about the configMap data to + project + properties: + items: + description: If unspecified, each key-value pair + in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to + set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file + to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + downwardAPI: + description: information about the downwardAPI data + to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: information about the secret data to project + properties: + items: + description: If unspecified, each key-value pair + in the Data field of the referenced Secret will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to + set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file + to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + type: object + serviceAccountToken: + description: information about the serviceAccountToken + data to project + properties: + audience: + description: Audience is the intended audience of + the token. A recipient of a token must identify + itself with an identifier specified in the audience + of the token, and otherwise should reject the + token. The audience defaults to the identifier + of the apiserver. + type: string + expirationSeconds: + description: ExpirationSeconds is the requested + duration of validity of the service account token. + As the token approaches expiration, the kubelet + volume plugin will proactively rotate the service + account token. The kubelet will start trying to + rotate the token if the token is older than 80 + percent of its time to live or if the token is + older than 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: Path is the path relative to the mount + point of the file to project the token into. + type: string + required: + - path + type: object + type: object + type: array + global: + additionalProperties: + type: string + description: 'Global pgBackRest configuration settings. These + settings are included in the "global" section of the pgBackRest + configuration generated by the PostgreSQL Operator, and + then mounted under "/etc/pgbackrest/conf.d": https://pgbackrest.org/configuration.html' + type: object + image: + description: The image name to use for pgBackRest containers. Utilized + to run pgBackRest repository hosts and backups. + type: string + manual: + description: Defines details for manual pgBackRest backup + Jobs + properties: + options: + description: Command line options to include when running + the pgBackRest backup command. https://pgbackrest.org/command.html#command-backup + items: + type: string + type: array + repoName: + description: The name of the pgBackRest repo to run the + backup command against. + pattern: ^repo[1-4] + type: string + required: + - repoName + type: object + metadata: + description: Metadata contains metadata for PostgresCluster + resources + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + repoHost: + description: Defines a pgBackRest repository host + properties: + dedicated: + description: Defines a dedicated repository host configuration + properties: + affinity: + description: 'Scheduling constraints of the Dedicated + repo host pod. Changing this value causes repo host + to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the + most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null preferred + scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest + sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + which namespaces the labelSelector + applies to (matches against); + null or empty list means "this + pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to a pod + label update), the system may or may not + try to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies + to (matches against); null or empty + list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + anti-affinity expressions specified by this + field, but it may choose a node that violates + one or more of the expressions. The node + that is most preferred is the one with the + greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute + a sum by iterating through the elements + of this field and adding "weight" to the + sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + which namespaces the labelSelector + applies to (matches against); + null or empty list means "this + pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the anti-affinity requirements + specified by this field cease to be met + at some point during pod execution (e.g. + due to a pod label update), the system may + or may not try to eventually evict the pod + from its node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies + to (matches against); null or empty + list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + resources: + description: Resource requirements for the dedicated + repository host + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is + omitted for a container, it defaults to Limits + if that is explicitly specified, otherwise to + an implementation-defined value. More info: + https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + tolerations: + description: 'Tolerations of a PgBackRest repo host + pod. Changing this value causes a restart. More + info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint effect + to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; + this combination means to match all values + and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and + Equal. Defaults to Equal. Exists is equivalent + to wildcard for value, so that a pod can tolerate + all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the + period of time the toleration (which must + be of effect NoExecute, otherwise this field + is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint + forever (do not evict). Zero and negative + values will be treated as 0 (evict immediately) + by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the + value should be empty, otherwise just a regular + string. + type: string + type: object + type: array + type: object + resources: + description: Resource requirements for a pgBackRest repository + host + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + sshConfigMap: + description: ConfigMap containing custom SSH configuration + properties: + items: + description: If unspecified, each key-value pair in + the Data field of the referenced ConfigMap will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If + a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked + optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set + permissions on this file. Must be an octal + value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal + values for mode bits. If not specified, the + volume defaultMode will be used. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to + map the key to. May not be an absolute path. + May not contain the path element '..'. May + not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + sshSecret: + description: Secret containing custom SSH keys + properties: + items: + description: If unspecified, each key-value pair in + the Data field of the referenced Secret will be + projected into the volume as a file whose name is + the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If + a key is specified which is not present in the Secret, + the volume setup will error unless it is marked + optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set + permissions on this file. Must be an octal + value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal + values for mode bits. If not specified, the + volume defaultMode will be used. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to + map the key to. May not be an absolute path. + May not contain the path element '..'. May + not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + type: object + type: object + repos: + description: Defines a pgBackRest repository + items: + description: PGBackRestRepo represents a pgBackRest repository. Only + one of its members may be specified. + properties: + azure: + description: Represents a pgBackRest repository that + is created using Azure storage + properties: + container: + description: The Azure container utilized for the + repository + type: string + required: + - container + type: object + gcs: + description: Represents a pgBackRest repository that + is created using Google Cloud Storage + properties: + bucket: + description: The GCS bucket utilized for the repository + type: string + required: + - bucket + type: object + name: + description: The name of the the repository + pattern: ^repo[1-4] + type: string + s3: + description: RepoS3 represents a pgBackRest repository + that is created using AWS S3 (or S3-compatible) storage + properties: + bucket: + description: The S3 bucket utilized for the repository + type: string + endpoint: + description: A valid endpoint corresponding to the + specified region + type: string + region: + description: The region corresponding to the S3 + bucket + type: string + required: + - bucket + - endpoint + - region + type: object + schedules: + description: 'Defines the schedules for the pgBackRest + backups Full, Differential and Incremental backup + types are supported: https://pgbackrest.org/user-guide.html#concept/backup' + properties: + differential: + description: 'Defines the Cron schedule for a differential + pgBackRest backup. Follows the standard Cron schedule + syntax: https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax' + minLength: 6 + type: string + full: + description: 'Defines the Cron schedule for a full + pgBackRest backup. Follows the standard Cron schedule + syntax: https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax' + minLength: 6 + type: string + incremental: + description: 'Defines the Cron schedule for an incremental + pgBackRest backup. Follows the standard Cron schedule + syntax: https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax' + minLength: 6 + type: string + type: object + volume: + description: Represents a pgBackRest repository that + is created using a PersistentVolumeClaim + properties: + volumeClaimSpec: + description: Defines a PersistentVolumeClaim spec + used to create and/or bind a volume + properties: + accessModes: + description: 'AccessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'This field can be used to specify + either: * An existing VolumeSnapshot object + (snapshot.storage.k8s.io/VolumeSnapshot) * + An existing PVC (PersistentVolumeClaim) * + An existing custom resource that implements + data population (Alpha) In order to use custom + resource types that implement data population, + the AnyVolumeDataSource feature gate must + be enabled. If the provisioner or an external + controller can support the specified data + source, it will create a new volume based + on the contents of the specified data source.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'Resources represents the minimum + resources the volume should have. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + selector: + description: A label query over volumes to consider + for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'Name of the StorageClass required + by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of + volume is required by the claim. Value of + Filesystem is implied when not included in + claim spec. + type: string + volumeName: + description: VolumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - volumeClaimSpec + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Defines details for performing an in-place restore + using pgBackRest + properties: + clusterName: + description: The name of an existing PostgresCluster to + use as the data source for the new PostgresCluster. + Defaults to the name of the PostgresCluster being created + if not provided. + type: string + clusterNamespace: + description: The namespace of the cluster specified as + the data source using the clusterName field. Defaults + to the namespace of the PostgresCluster being created + if not provided. + type: string + enabled: + default: false + description: Whether or not in-place pgBackRest restores + are enabled for this PostgresCluster. + type: boolean + options: + description: Command line options to include when running + the pgBackRest restore command. https://pgbackrest.org/command.html#command-restore + items: + type: string + type: array + repoName: + description: The name of the pgBackRest repo within the + source PostgresCluster that contains the backups that + should be utilized to perform a pgBackRest restore when + initializing the data source for the new PostgresCluster. + pattern: ^repo[1-4] + type: string + resources: + description: Resource requirements for the pgBackRest + restore Job. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + required: + - enabled + - repoName + type: object + required: + - image + type: object + required: + - pgbackrest + type: object + customReplicationTLSSecret: + description: 'The secret containing the replication client certificates + and keys for secure connections to the PostgreSQL server. It will + need to contain the client TLS certificate, TLS key and the Certificate + Authority certificate with the data keys set to tls.crt, tls.key + and ca.crt, respectively. NOTE: If CustomReplicationClientTLSSecret + is provided, CustomTLSSecret MUST be provided and the ca.crt provided + must be the same.' + properties: + items: + description: If unspecified, each key-value pair in the Data field + of the referenced Secret will be projected into the volume as + a file whose name is the key and content is the value. If specified, + the listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is specified + which is not present in the Secret, the volume setup will error + unless it is marked optional. Paths must be relative and may + not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set permissions + on this file. Must be an octal value between 0000 and + 0777 or a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume defaultMode + will be used. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to map the key + to. May not be an absolute path. May not contain the path + element '..'. May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + type: object + customTLSSecret: + description: 'The secret containing the Certificates and Keys to encrypt + PostgreSQL traffic will need to contain the server TLS certificate, + TLS key and the Certificate Authority certificate with the data + keys set to tls.crt, tls.key and ca.crt, respectively. It will then + be mounted as a volume projection to the ''/pgconf/tls'' directory. + For more information on Kubernetes secret projections, please see + https://k8s.io/docs/concepts/configuration/secret/#projection-of-secret-keys-to-specific-paths + NOTE: If CustomTLSSecret is provided, CustomReplicationClientTLSSecret + MUST be provided and the ca.crt provided must be the same.' + properties: + items: + description: If unspecified, each key-value pair in the Data field + of the referenced Secret will be projected into the volume as + a file whose name is the key and content is the value. If specified, + the listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is specified + which is not present in the Secret, the volume setup will error + unless it is marked optional. Paths must be relative and may + not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set permissions + on this file. Must be an octal value between 0000 and + 0777 or a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume defaultMode + will be used. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to map the key + to. May not be an absolute path. May not contain the path + element '..'. May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + type: object + dataSource: + description: Specifies a data source for bootstrapping the PostgreSQL + cluster. + properties: + postgresCluster: + description: Defines a pgBackRest data source that can be used + to pre-populate the PostgreSQL data directory for a new PostgreSQL + cluster using a pgBackRest restore. + properties: + clusterName: + description: The name of an existing PostgresCluster to use + as the data source for the new PostgresCluster. Defaults + to the name of the PostgresCluster being created if not + provided. + type: string + clusterNamespace: + description: The namespace of the cluster specified as the + data source using the clusterName field. Defaults to the + namespace of the PostgresCluster being created if not provided. + type: string + options: + description: Command line options to include when running + the pgBackRest restore command. https://pgbackrest.org/command.html#command-restore + items: + type: string + type: array + repoName: + description: The name of the pgBackRest repo within the source + PostgresCluster that contains the backups that should be + utilized to perform a pgBackRest restore when initializing + the data source for the new PostgresCluster. + pattern: ^repo[1-4] + type: string + resources: + description: Resource requirements for the pgBackRest restore + Job. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of + compute resources required. If Requests is omitted for + a container, it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + required: + - repoName + type: object + type: object + image: + description: The image name to use for PostgreSQL containers + type: string + imagePullSecrets: + description: The image pull secrets used to pull from a private registry + Changing this value causes all running pods to restart. https://k8s.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + instances: + items: + properties: + affinity: + description: 'Scheduling constraints of a PostgreSQL pod. Changing + this value causes PostgreSQL to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node' + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a + no-op). A null preferred scheduling term matches + no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range + 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an + update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) with the + highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range + 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a + pod label update), the system may or may not try to + eventually evict the pod from its node. When there + are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or + not co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any + node on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified + namespaces, where co-located is defined as running + on a node whose value of the label with key + topologyKey matches that of any node on which + any of the selected pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all + of the scheduling requirements (resource request, + requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the + node has pods which matches the corresponding podAffinityTerm; + the node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range + 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a + pod label update), the system may or may not try to + eventually evict the pod from its node. When there + are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or + not co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any + node on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified + namespaces, where co-located is defined as running + on a node whose value of the label with key + topologyKey matches that of any node on which + any of the selected pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + dataVolumeClaimSpec: + description: 'Defines a PersistentVolumeClaim for PostgreSQL + data. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes' + properties: + accessModes: + description: 'AccessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'This field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) * An existing + custom resource that implements data population (Alpha) + In order to use custom resource types that implement data + population, the AnyVolumeDataSource feature gate must + be enabled. If the provisioner or an external controller + can support the specified data source, it will create + a new volume based on the contents of the specified data + source.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'Resources represents the minimum resources + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of + compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + selector: + description: A label query over volumes to consider for + binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'Name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not + included in claim spec. + type: string + volumeName: + description: VolumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + metadata: + description: Metadata contains metadata for PostgresCluster + resources + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + name: + default: "" + type: string + replicas: + default: 1 + format: int32 + minimum: 0 + type: integer + resources: + description: Compute resources of a PostgreSQL container. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. More info: + https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + tolerations: + description: 'Tolerations of a PostgreSQL pod. Changing this + value causes PostgreSQL to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + walVolumeClaimSpec: + description: 'Defines a separate PersistentVolumeClaim for PostgreSQL''s + write-ahead log. More info: https://www.postgresql.org/docs/current/wal.html' + properties: + accessModes: + description: 'AccessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'This field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) * An existing + custom resource that implements data population (Alpha) + In order to use custom resource types that implement data + population, the AnyVolumeDataSource feature gate must + be enabled. If the provisioner or an external controller + can support the specified data source, it will create + a new volume based on the contents of the specified data + source.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'Resources represents the minimum resources + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of + compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + selector: + description: A label query over volumes to consider for + binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'Name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not + included in claim spec. + type: string + volumeName: + description: VolumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + required: + - dataVolumeClaimSpec + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + metadata: + description: Metadata contains metadata for PostgresCluster resources + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + monitoring: + description: The specification of monitoring tools that connect to + PostgreSQL + properties: + pgmonitor: + description: PGMonitorSpec defines the desired state of the pgMonitor + tool suite + properties: + exporter: + properties: + configuration: + description: 'Projected volumes containing custom PostgreSQL + Exporter configuration. Currently supports the customization + of PostgreSQL Exporter queries. If a "queries.yaml" + file is detected in any volume projected using this + field, it will be loaded using the "extend.query-path" + flag: https://github.com/prometheus-community/postgres_exporter#flags + Changing the values of field causes PostgreSQL and the + exporter to restart.' + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: information about the configMap data + to project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the ConfigMap, the + volume setup will error unless it is marked + optional. Paths must be relative and may not + contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used + to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the + string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its keys must be defined + type: boolean + type: object + downwardAPI: + description: information about the downwardAPI data + to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. + Must not be absolute or contain the + ''..'' path. Must be utf-8 encoded. + The first item of the relative path + must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and + requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) are + currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: information about the secret data to + project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the Secret, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used + to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the + string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + type: object + serviceAccountToken: + description: information about the serviceAccountToken + data to project + properties: + audience: + description: Audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: ExpirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if the + token is older than 80 percent of its time + to live or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: Path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + image: + description: The image name to use for crunchy-postgres-exporter + containers + type: string + resources: + description: 'Changing this value causes PostgreSQL and + the exporter to restart. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + required: + - image + type: object + type: object + type: object + openshift: + description: Whether or not the PostgreSQL cluster is being deployed + to an OpenShift envioronment + type: boolean + patroni: + properties: + dynamicConfiguration: + type: object + x-kubernetes-preserve-unknown-fields: true + leaderLeaseDurationSeconds: + default: 30 + description: TTL of the cluster leader lock. "Think of it as the + length of time before initiation of the automatic failover process." + format: int32 + minimum: 3 + type: integer + port: + default: 8008 + description: The port on which Patroni should listen. + format: int32 + minimum: 1024 + type: integer + syncPeriodSeconds: + default: 10 + description: The interval for refreshing the leader lock and applying + dynamicConfiguration. Must be less than leaderLeaseDurationSeconds. + format: int32 + minimum: 1 + type: integer + type: object + port: + default: 5432 + description: The port on which PostgreSQL should listen. + format: int32 + minimum: 1024 + type: integer + postgresVersion: + description: The major version of PostgreSQL installed in the PostgreSQL + container + maximum: 13 + minimum: 10 + type: integer + proxy: + description: The specification of a proxy that connects to PostgreSQL. + properties: + pgBouncer: + description: Defines a PgBouncer proxy and connection pooler. + properties: + affinity: + description: 'Scheduling constraints of a PgBouncer pod. Changing + this value causes PgBouncer to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node' + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies to + (matches against); null or empty list + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies to + (matches against); null or empty list + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + config: + description: 'Configuration settings for the PgBouncer process. + Changes to any of these values will be automatically reloaded + without validation. Be careful, as you may put PgBouncer + into an unusable state. More info: https://www.pgbouncer.org/usage.html#reload' + properties: + databases: + additionalProperties: + type: string + description: 'PgBouncer database definitions. The key + is the database requested by a client while the value + is a libpq-styled connection string. The special key + "*" acts as a fallback. When this field is empty, PgBouncer + is configured with a single "*" entry that connects + to the primary PostgreSQL instance. More info: https://www.pgbouncer.org/config.html#section-databases' + type: object + files: + description: 'Files to mount under "/etc/pgbouncer". When + specified, settings in the "pgbouncer.ini" file are + loaded before all others. From there, other files may + be included by absolute path. Changing these references + causes PgBouncer to restart, but changes to the file + contents are automatically reloaded. More info: https://www.pgbouncer.org/config.html#include-directive' + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: information about the configMap data + to project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the ConfigMap, the + volume setup will error unless it is marked + optional. Paths must be relative and may not + contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used + to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the + string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its keys must be defined + type: boolean + type: object + downwardAPI: + description: information about the downwardAPI data + to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. + Must not be absolute or contain the + ''..'' path. Must be utf-8 encoded. + The first item of the relative path + must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and + requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) are + currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: information about the secret data to + project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the Secret, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used + to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the + string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + type: object + serviceAccountToken: + description: information about the serviceAccountToken + data to project + properties: + audience: + description: Audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: ExpirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if the + token is older than 80 percent of its time + to live or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: Path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + global: + additionalProperties: + type: string + description: 'Settings that apply to the entire PgBouncer + process. More info: https://www.pgbouncer.org/config.html' + type: object + users: + additionalProperties: + type: string + description: 'Connection settings specific to particular + users. More info: https://www.pgbouncer.org/config.html#section-users' + type: object + type: object + customTLSSecret: + description: 'A secret projection containing a certificate + and key with which to encrypt connections to PgBouncer. + The "tls.crt", "tls.key", and "ca.crt" paths must be PEM-encoded + certificates and keys. Changing this value causes PgBouncer + to restart. More info: https://kubernetes.io/docs/concepts/configuration/secret/#projection-of-secret-keys-to-specific-paths' + properties: + items: + description: If unspecified, each key-value pair in the + Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and + content is the value. If specified, the listed keys + will be projected into the specified paths, and unlisted + keys will not be present. If a key is specified which + is not present in the Secret, the volume setup will + error unless it is marked optional. Paths must be relative + and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set permissions + on this file. Must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to map + the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + type: object + image: + description: 'Name of a container image that can run PgBouncer + 1.15 or newer. Changing this value causes PgBouncer to restart. + More info: https://kubernetes.io/docs/concepts/containers/images' + type: string + metadata: + description: Metadata contains metadata for PostgresCluster + resources + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + port: + default: 5432 + description: Port on which PgBouncer should listen for client + connections. Changing this value causes PgBouncer to restart. + format: int32 + minimum: 1024 + type: integer + replicas: + default: 1 + description: Number of desired PgBouncer pods. + format: int32 + minimum: 0 + type: integer + resources: + description: 'Compute resources of a PgBouncer container. + Changing this value causes PgBouncer to restart. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of + compute resources required. If Requests is omitted for + a container, it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + tolerations: + description: 'Tolerations of a PgBouncer pod. Changing this + value causes PgBouncer to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value should + be empty, otherwise just a regular string. + type: string + type: object + type: array + required: + - image + type: object + required: + - pgBouncer + type: object + shutdown: + description: Whether or not the PostgreSQL cluster should be stopped. + When this is true, workloads are scaled to zero and CronJobs are + suspended. Other resources, such as Services and Volumes, remain + in place. + type: boolean + standby: + description: Run this cluster as a read-only copy of an existing cluster + or archive. + properties: + enabled: + default: true + description: Whether or not the PostgreSQL cluster should be read-only. + When this is true, WAL files are applied from the pgBackRest + repository. + type: boolean + repoName: + description: The name of the pgBackRest repository to follow for + WAL files. + pattern: ^repo[1-4] + type: string + required: + - repoName + type: object + required: + - backups + - image + - instances + - postgresVersion + type: object + status: + description: PostgresClusterStatus defines the observed state of PostgresCluster + properties: + conditions: + description: 'conditions represent the observations of postgrescluster''s + current state. Known .status.conditions.type are: "PersistentVolumeResizing", + "ProxyAvailable"' + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + instances: + description: Current state of PostgreSQL instances. + items: + properties: + name: + type: string + readyReplicas: + description: Total number of ready pods. + format: int32 + type: integer + replicas: + description: Total number of non-terminated pods. + format: int32 + type: integer + updatedReplicas: + description: Total number of non-terminated pods that have the + desired specification. + format: int32 + type: integer + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + monitoring: + description: Current state of PostgreSQL cluster monitoring tool configuration + properties: + exporterConfiguration: + type: string + type: object + observedGeneration: + description: observedGeneration represents the .metadata.generation + on which the status was based. + format: int64 + minimum: 0 + type: integer + patroni: + properties: + systemIdentifier: + description: The PostgreSQL system identifier reported by Patroni. + type: string + type: object + pgbackrest: + description: Status information for pgBackRest + properties: + manualBackup: + description: Status information for manual backups + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: Represents the time the manual backup Job was + determined by the Job controller to be completed. This + field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in + UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: Specifies whether or not the Job is finished + executing (does not indicate success or failure). + type: boolean + id: + description: A unique identifier for the manual backup as + provided using the "pgbackrest-backup" annotation when initiating + a backup. + type: string + startTime: + description: Represents the time the manual backup Job was + acknowledged by the Job controller. It is represented in + RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + repoHost: + description: Status information for the pgBackRest dedicated repository + host + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + ready: + description: Whether or not the pgBackRest repository host + is ready for use + type: boolean + type: object + repos: + description: Status information for pgBackRest repositories + items: + description: RepoVolumeStatus the status of a pgBackRest repository + properties: + bound: + description: Whether or not the pgBackRest repository PersistentVolumeClaim + is bound to a volume + type: boolean + name: + description: The name of the pgBackRest repository + type: string + replicaCreateBackupComplete: + description: ReplicaCreateBackupReady indicates whether + a backup exists in the repository as needed to bootstrap + replicas. + type: boolean + repoOptionsHash: + description: A hash of the required fields in the spec for + defining an Azure, GCS or S3 repository, Utilizd to detect + changes to these fields and then execute pgBackRest stanza-create + commands accordingly. + type: string + stanzaCreated: + description: Specifies whether or not a stanza has been + successfully created for the repository + type: boolean + volume: + description: The name of the volume the containing the pgBackRest + repository + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Status information for in-place restores + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: Represents the time the manual backup Job was + determined by the Job controller to be completed. This + field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in + UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: Specifies whether or not the Job is finished + executing (does not indicate success or failure). + type: boolean + id: + description: A unique identifier for the manual backup as + provided using the "pgbackrest-backup" annotation when initiating + a backup. + type: string + startTime: + description: Represents the time the manual backup Job was + acknowledged by the Job controller. It is represented in + RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + scheduledBackups: + description: Status information for scheduled backups + items: + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: Represents the time the manual backup Job was + determined by the Job controller to be completed. This + field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is + in UTC. + format: date-time + type: string + cronJobName: + description: The name of the associated pgBackRest scheduled + backup CronJob + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + repo: + description: The name of the associated pgBackRest repository + type: string + startTime: + description: Represents the time the manual backup Job was + acknowledged by the Job controller. It is represented + in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + type: + description: The pgBackRest backup type for this Job + type: string + type: object + type: array + type: object + proxy: + description: Current state of the PostgreSQL proxy. + properties: + pgBouncer: + properties: + postgresRevision: + description: Identifies the revision of PgBouncer assets that + have been installed into PostgreSQL. + type: string + readyReplicas: + description: Total number of ready pods. + format: int32 + type: integer + replicas: + description: Total number of non-terminated pods. + format: int32 + type: integer + type: object + type: object + startupInstance: + description: The instance that should be started first when bootstrapping + and/or starting a PostgresCluster. + type: string + startupInstanceSet: + description: The instance set associated with the startupInstance + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/helm/install/templates/NOTES.txt b/helm/install/templates/NOTES.txt new file mode 100644 index 00000000..61223133 --- /dev/null +++ b/helm/install/templates/NOTES.txt @@ -0,0 +1,31 @@ +Thank you for deploying PGO v{{ .Chart.AppVersion }}! + + (((((((((((((((((((((( + (((((((((((((%%%%%%%((((((((((((((( + (((((((((((%%% %%%%(((((((((((( + (((((((((((%%( (((( ( %%%((((((((((( + (((((((((((((%% (( ,(( %%%((((((((((( + (((((((((((((((%% *%%/ %%%%%%%(((((((((( + (((((((((((((((((((%%(( %%%%%%%%%%#(((((%%%%%%%%%%#(((((((((((( + ((((((((((((((((((%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%(((((((((((((( + *((((((((((((((((((((%%%%%% /%%%%%%%%%%%%%%%%%%%(((((((((((((((( + (((((((((((((((((((((((%%%/ .%, %%%((((((((((((((((((, + ((((((((((((((((((((((% %#((((((((((((((((( +(((((((((((((((%%%%%% #%((((((((((((((((( +((((((((((((((%% %%(((((((((((((((, +((((((((((((%%%#% % %%((((((((((((((( +((((((((((((%. % % #(((((((((((((( +(((((((((((%% % %%* %((((((((((((( +#(###(###(#%% %%% %% %%% #%%#(###(###(# +###########%%%%% /%%%%%%%%%%%%% %% %%%%% ,%%####### +###############%% %%%%%% %%% %%%%%%%% %%##### + ################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %%## + ################%% %%%%%%%%%%%%%%%%% %%%% % + ##############%# %% (%%%%%%% %%%%%% + #############% %%%%% %%%%%%%%%%% + ###########% %%%%%%%%%%% %%%%%%%%% + #########%% %% %%%%%%%%%%%%%%%# + ########%% %% %%%%%%%%% + ######%% %% %%%%%% + ####%%% %%%%% % + %% %%%% diff --git a/helm/install/templates/_helpers.tpl b/helm/install/templates/_helpers.tpl new file mode 100644 index 00000000..7a75c9c1 --- /dev/null +++ b/helm/install/templates/_helpers.tpl @@ -0,0 +1,80 @@ +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "install.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Crunchy labels +*/}} +{{- define "install.crunchyLabels" -}} +postgres-operator.crunchydata.com/control-plane: {{ .Chart.Name }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "install.labels" -}} +helm.sh/chart: {{ include "install.chart" . }} +{{ include "install.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{ include "install.crunchyLabels" .}} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "install.selectorLabels" -}} +app.kubernetes.io/name: {{ .Chart.Name }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{ include "install.crunchyLabels" .}} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "install.serviceAccountName" -}} +{{ .Chart.Name }} +{{- end }} + +{{/* +Create the name of the Role/ClusterRole to use +*/}} +{{- define "install.roleName" -}} +{{ .Chart.Name }} +{{- end }} + +{{/* +Create the name of the RoleBinding/ClusterRoleBinding to use +*/}} +{{- define "install.roleBindingName" -}} +{{ .Chart.Name }} +{{- end }} + +{{/* +Create the kind for rolebindings. Will be RoleBinding in single +namespace mode or ClusterRoleBinding by default. +*/}} +{{- define "install.roleBindingKind" -}} +{{- if .Values.singleNamespace -}} +RoleBinding +{{- else -}} +ClusterRoleBinding +{{- end }} +{{- end }} + +{{/* +Create the kind for role. Will be Role in single +namespace mode or ClusterRole by default. +*/}} +{{- define "install.roleKind" -}} +{{- if .Values.singleNamespace -}} +Role +{{- else -}} +ClusterRole +{{- end }} +{{- end }} diff --git a/helm/install/templates/manager.yaml b/helm/install/templates/manager.yaml new file mode 100644 index 00000000..204b712d --- /dev/null +++ b/helm/install/templates/manager.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Chart.Name }} + labels: + {{- include "install.labels" . | nindent 4 }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "install.crunchyLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "install.crunchyLabels" . | nindent 8 }} + spec: + containers: + - name: operator + image: "{{ .Values.image.repository }}/postgres-operator:{{ .Values.image.tag }}" + env: + - name: CRUNCHY_DEBUG + value: "true" + {{- if .Values.singleNamespace }} + - name: PGO_TARGET_NAMESPACE + valueFrom: { fieldRef: { apiVersion: v1, fieldPath: metadata.namespace } } + {{- end }} + serviceAccount: {{ include "install.serviceAccountName" . }} diff --git a/helm/install/templates/role.yaml b/helm/install/templates/role.yaml new file mode 100644 index 00000000..ef05d4b7 --- /dev/null +++ b/helm/install/templates/role.yaml @@ -0,0 +1,123 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ include "install.roleKind" . }} +metadata: + name: {{ include "install.roleName" . }} + labels: + {{- include "install.labels" . | nindent 4 }} +rules: +- apiGroups: + - '' + resources: + - configmaps + - persistentvolumeclaims + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - endpoints + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - endpoints/restricted + - pods/exec + verbs: + - create +- apiGroups: + - '' + resources: + - events + verbs: + - create + - patch +- apiGroups: + - '' + resources: + - pods + verbs: + - delete + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - serviceaccounts + verbs: + - create + - get + - list + - patch + - watch +- apiGroups: + - apps + resources: + - deployments + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - batch + resources: + - cronjobs + - jobs + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters + verbs: + - get + - list + - patch + - watch +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters/finalizers + verbs: + - update +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters/status + verbs: + - patch +- apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + - roles + verbs: + - create + - get + - list + - patch + - watch diff --git a/helm/install/templates/role_binding.yaml b/helm/install/templates/role_binding.yaml new file mode 100644 index 00000000..d7d9e13c --- /dev/null +++ b/helm/install/templates/role_binding.yaml @@ -0,0 +1,14 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: {{ include "install.roleBindingKind" . }} +metadata: + name: {{ include "install.roleBindingName" . }} + labels: + {{- include "install.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: {{ include "install.roleKind" . }} + name: {{ include "install.roleName" . }} +subjects: +- kind: ServiceAccount + name: {{ include "install.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} diff --git a/helm/install/templates/service_account.yaml b/helm/install/templates/service_account.yaml new file mode 100644 index 00000000..9a4438cb --- /dev/null +++ b/helm/install/templates/service_account.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "install.serviceAccountName" . }} + labels: + {{- include "install.labels" . | nindent 4 }} diff --git a/helm/install/values.yaml b/helm/install/values.yaml new file mode 100644 index 00000000..e0dc04b1 --- /dev/null +++ b/helm/install/values.yaml @@ -0,0 +1,8 @@ +--- +## Provide image repository and tag +image: + repository: registry.developers.crunchydata.com/crunchydata + tag: ubi8-5.0.0-0 + +## Install in default or single namespace mode +singleNamespace: false diff --git a/helm/postgres/Chart.yaml b/helm/postgres/Chart.yaml new file mode 100644 index 00000000..182e9a3f --- /dev/null +++ b/helm/postgres/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v3 +name: postgrescluster +description: A Helm chart for Kubernetes +type: application +version: 0.1.0 +appVersion: 5.0.0 diff --git a/helm/postgres/templates/NOTES.txt b/helm/postgres/templates/NOTES.txt new file mode 100644 index 00000000..13d13742 --- /dev/null +++ b/helm/postgres/templates/NOTES.txt @@ -0,0 +1,31 @@ +Thank you for deploying a Crunchy PostgreSQL cluster! + + (((((((((((((((((((((( + (((((((((((((%%%%%%%((((((((((((((( + (((((((((((%%% %%%%(((((((((((( + (((((((((((%%( (((( ( %%%((((((((((( + (((((((((((((%% (( ,(( %%%((((((((((( + (((((((((((((((%% *%%/ %%%%%%%(((((((((( + (((((((((((((((((((%%(( %%%%%%%%%%#(((((%%%%%%%%%%#(((((((((((( + ((((((((((((((((((%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%(((((((((((((( + *((((((((((((((((((((%%%%%% /%%%%%%%%%%%%%%%%%%%(((((((((((((((( + (((((((((((((((((((((((%%%/ .%, %%%((((((((((((((((((, + ((((((((((((((((((((((% %#((((((((((((((((( +(((((((((((((((%%%%%% #%((((((((((((((((( +((((((((((((((%% %%(((((((((((((((, +((((((((((((%%%#% % %%((((((((((((((( +((((((((((((%. % % #(((((((((((((( +(((((((((((%% % %%* %((((((((((((( +#(###(###(#%% %%% %% %%% #%%#(###(###(# +###########%%%%% /%%%%%%%%%%%%% %% %%%%% ,%%####### +###############%% %%%%%% %%% %%%%%%%% %%##### + ################%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %%## + ################%% %%%%%%%%%%%%%%%%% %%%% % + ##############%# %% (%%%%%%% %%%%%% + #############% %%%%% %%%%%%%%%%% + ###########% %%%%%%%%%%% %%%%%%%%% + #########%% %% %%%%%%%%%%%%%%%# + ########%% %% %%%%%%%%% + ######%% %% %%%%%% + ####%%% %%%%% % + %% %%%% diff --git a/helm/postgres/templates/postgres.yaml b/helm/postgres/templates/postgres.yaml new file mode 100644 index 00000000..92258aec --- /dev/null +++ b/helm/postgres/templates/postgres.yaml @@ -0,0 +1,40 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: {{ .Values.name }} +spec: + image: {{ .Values.postgres }} + postgresVersion: {{ .Values.postgresVersion }} + instances: + - name: instance1 + dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + image: {{ .Values.pgBackRest}} + repoHost: + dedicated: {} + repos: + - name: repo1 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + - name: repo2 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + proxy: + pgBouncer: + image: {{ .Values.pgBouncer}} diff --git a/helm/postgres/values.yaml b/helm/postgres/values.yaml new file mode 100644 index 00000000..bfd8c1b2 --- /dev/null +++ b/helm/postgres/values.yaml @@ -0,0 +1,12 @@ +--- +# Cluster name +name: hippo + +# PostgreSQL Version +# Version should match version defined in PostgreSQL images +postgresVersion: 13 + +# Images +postgres: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 +pgBackRest: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 +pgBouncer: registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:centos8-1.15-0 diff --git a/kustomize/azure/.gitignore b/kustomize/azure/.gitignore new file mode 100644 index 00000000..26509155 --- /dev/null +++ b/kustomize/azure/.gitignore @@ -0,0 +1 @@ +azure.conf diff --git a/kustomize/azure/azure.conf.example b/kustomize/azure/azure.conf.example new file mode 100644 index 00000000..deaa04cd --- /dev/null +++ b/kustomize/azure/azure.conf.example @@ -0,0 +1,3 @@ +[global] +repo1-azure-account= +repo1-azure-key= diff --git a/kustomize/azure/kustomization.yaml b/kustomize/azure/kustomization.yaml new file mode 100644 index 00000000..5e802ec5 --- /dev/null +++ b/kustomize/azure/kustomization.yaml @@ -0,0 +1,12 @@ +namespace: postgres-operator + +secretGenerator: +- name: pgo-azure-creds + files: + - azure.conf + +generatorOptions: + disableNameSuffixHash: true + +resources: +- postgres.yaml diff --git a/kustomize/azure/postgres.yaml b/kustomize/azure/postgres.yaml new file mode 100644 index 00000000..b44ba481 --- /dev/null +++ b/kustomize/azure/postgres.yaml @@ -0,0 +1,28 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: hippo-azure +spec: + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 + postgresVersion: 13 + instances: + - dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 + repoHost: + dedicated: {} + configuration: + - secret: + name: pgo-azure-creds + global: + repo1-path: /pgbackrest/postgres-operator/hippo-azure/repo1 + repos: + - name: repo1 + azure: + container: "" diff --git a/kustomize/gcs/.gitignore b/kustomize/gcs/.gitignore new file mode 100644 index 00000000..5470592b --- /dev/null +++ b/kustomize/gcs/.gitignore @@ -0,0 +1 @@ +gcs-key.json diff --git a/kustomize/gcs/gcs.conf b/kustomize/gcs/gcs.conf new file mode 100644 index 00000000..c70d4a37 --- /dev/null +++ b/kustomize/gcs/gcs.conf @@ -0,0 +1,2 @@ +[global] +repo1-gcs-key=/etc/pgbackrest/conf.d/gcs-key.json diff --git a/kustomize/gcs/kustomization.yaml b/kustomize/gcs/kustomization.yaml new file mode 100644 index 00000000..891b11bf --- /dev/null +++ b/kustomize/gcs/kustomization.yaml @@ -0,0 +1,13 @@ +namespace: postgres-operator + +secretGenerator: +- name: pgo-gcs-creds + files: + - gcs.conf + - gcs-key.json + +generatorOptions: + disableNameSuffixHash: true + +resources: +- postgres.yaml diff --git a/kustomize/gcs/postgres.yaml b/kustomize/gcs/postgres.yaml new file mode 100644 index 00000000..655a67d6 --- /dev/null +++ b/kustomize/gcs/postgres.yaml @@ -0,0 +1,28 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: hippo-gcs +spec: + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 + postgresVersion: 13 + instances: + - dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 + repoHost: + dedicated: {} + configuration: + - secret: + name: pgo-gcs-creds + global: + repo1-path: /pgbackrest/postgres-operator/hippo-gcs/repo1 + repos: + - name: repo1 + gcs: + bucket: "" diff --git a/kustomize/high-availability/ha-postgres.yaml b/kustomize/high-availability/ha-postgres.yaml new file mode 100644 index 00000000..e7c789ee --- /dev/null +++ b/kustomize/high-availability/ha-postgres.yaml @@ -0,0 +1,54 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: hippo-ha +spec: + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 + postgresVersion: 13 + instances: + - name: pgha1 + replicas: 2 + dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: hippo-ha + postgres-operator.crunchydata.com/instance-set: pgha1 + backups: + pgbackrest: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 + repoHost: + dedicated: {} + repos: + - name: repo1 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + proxy: + pgBouncer: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbouncer:centos8-1.15-0 + replicas: 2 + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: hippo-ha + postgres-operator.crunchydata.com/role: pgbouncer diff --git a/kustomize/high-availability/kustomization.yaml b/kustomize/high-availability/kustomization.yaml new file mode 100644 index 00000000..ae3abd7a --- /dev/null +++ b/kustomize/high-availability/kustomization.yaml @@ -0,0 +1,4 @@ +namespace: postgres-operator + +resources: +- ha-postgres.yaml diff --git a/kustomize/install/bases/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/kustomize/install/bases/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml new file mode 100644 index 00000000..45c29825 --- /dev/null +++ b/kustomize/install/bases/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -0,0 +1,4583 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: postgresclusters.postgres-operator.crunchydata.com +spec: + group: postgres-operator.crunchydata.com + names: + kind: PostgresCluster + listKind: PostgresClusterList + plural: postgresclusters + singular: postgrescluster + scope: Namespaced + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: PostgresCluster is the Schema for the postgresclusters API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: PostgresClusterSpec defines the desired state of PostgresCluster + properties: + backups: + description: PostgreSQL backup configuration + properties: + pgbackrest: + description: pgBackRest archive configuration + properties: + configuration: + description: 'Projected volumes containing custom pgBackRest + configuration. These files are mounted under "/etc/pgbackrest/conf.d" + alongside any pgBackRest configuration generated by the + PostgreSQL Operator: https://pgbackrest.org/configuration.html' + items: + description: Projection that may be projected along with + other supported volume types + properties: + configMap: + description: information about the configMap data to + project + properties: + items: + description: If unspecified, each key-value pair + in the Data field of the referenced ConfigMap + will be projected into the volume as a file whose + name is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the ConfigMap, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to + set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file + to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + downwardAPI: + description: information about the downwardAPI data + to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing the + pod field + properties: + fieldRef: + description: 'Required: Selects a field of + the pod: only annotations, labels, name + and namespace are supported.' + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, defaults + to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used to + set permissions on this file, must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must + not be absolute or contain the ''..'' path. + Must be utf-8 encoded. The first item of + the relative path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: information about the secret data to project + properties: + items: + description: If unspecified, each key-value pair + in the Data field of the referenced Secret will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. + If a key is specified which is not present in + the Secret, the volume setup will error unless + it is marked optional. Paths must be relative + and may not contain the '..' path or start with + '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to + set permissions on this file. Must be an + octal value between 0000 and 0777 or a decimal + value between 0 and 511. YAML accepts both + octal and decimal values, JSON requires + decimal values for mode bits. If not specified, + the volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file + to map the key to. May not be an absolute + path. May not contain the path element '..'. + May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + type: object + serviceAccountToken: + description: information about the serviceAccountToken + data to project + properties: + audience: + description: Audience is the intended audience of + the token. A recipient of a token must identify + itself with an identifier specified in the audience + of the token, and otherwise should reject the + token. The audience defaults to the identifier + of the apiserver. + type: string + expirationSeconds: + description: ExpirationSeconds is the requested + duration of validity of the service account token. + As the token approaches expiration, the kubelet + volume plugin will proactively rotate the service + account token. The kubelet will start trying to + rotate the token if the token is older than 80 + percent of its time to live or if the token is + older than 24 hours.Defaults to 1 hour and must + be at least 10 minutes. + format: int64 + type: integer + path: + description: Path is the path relative to the mount + point of the file to project the token into. + type: string + required: + - path + type: object + type: object + type: array + global: + additionalProperties: + type: string + description: 'Global pgBackRest configuration settings. These + settings are included in the "global" section of the pgBackRest + configuration generated by the PostgreSQL Operator, and + then mounted under "/etc/pgbackrest/conf.d": https://pgbackrest.org/configuration.html' + type: object + image: + description: The image name to use for pgBackRest containers. Utilized + to run pgBackRest repository hosts and backups. + type: string + manual: + description: Defines details for manual pgBackRest backup + Jobs + properties: + options: + description: Command line options to include when running + the pgBackRest backup command. https://pgbackrest.org/command.html#command-backup + items: + type: string + type: array + repoName: + description: The name of the pgBackRest repo to run the + backup command against. + pattern: ^repo[1-4] + type: string + required: + - repoName + type: object + metadata: + description: Metadata contains metadata for PostgresCluster + resources + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + repoHost: + description: Defines a pgBackRest repository host + properties: + dedicated: + description: Defines a dedicated repository host configuration + properties: + affinity: + description: 'Scheduling constraints of the Dedicated + repo host pod. Changing this value causes repo host + to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the + most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null preferred + scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest + sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + which namespaces the labelSelector + applies to (matches against); + null or empty list means "this + pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to a pod + label update), the system may or may not + try to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies + to (matches against); null or empty + list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + anti-affinity expressions specified by this + field, but it may choose a node that violates + one or more of the expressions. The node + that is most preferred is the one with the + greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute + a sum by iterating through the elements + of this field and adding "weight" to the + sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + which namespaces the labelSelector + applies to (matches against); + null or empty list means "this + pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the anti-affinity requirements + specified by this field cease to be met + at some point during pod execution (e.g. + due to a pod label update), the system may + or may not try to eventually evict the pod + from its node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies + to (matches against); null or empty + list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + resources: + description: Resource requirements for the dedicated + repository host + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is + omitted for a container, it defaults to Limits + if that is explicitly specified, otherwise to + an implementation-defined value. More info: + https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + tolerations: + description: 'Tolerations of a PgBackRest repo host + pod. Changing this value causes a restart. More + info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint effect + to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; + this combination means to match all values + and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and + Equal. Defaults to Equal. Exists is equivalent + to wildcard for value, so that a pod can tolerate + all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the + period of time the toleration (which must + be of effect NoExecute, otherwise this field + is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint + forever (do not evict). Zero and negative + values will be treated as 0 (evict immediately) + by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the + value should be empty, otherwise just a regular + string. + type: string + type: object + type: array + type: object + resources: + description: Resource requirements for a pgBackRest repository + host + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + sshConfigMap: + description: ConfigMap containing custom SSH configuration + properties: + items: + description: If unspecified, each key-value pair in + the Data field of the referenced ConfigMap will + be projected into the volume as a file whose name + is the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If + a key is specified which is not present in the ConfigMap, + the volume setup will error unless it is marked + optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set + permissions on this file. Must be an octal + value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal + values for mode bits. If not specified, the + volume defaultMode will be used. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to + map the key to. May not be an absolute path. + May not contain the path element '..'. May + not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap or its + keys must be defined + type: boolean + type: object + sshSecret: + description: Secret containing custom SSH keys + properties: + items: + description: If unspecified, each key-value pair in + the Data field of the referenced Secret will be + projected into the volume as a file whose name is + the key and content is the value. If specified, + the listed keys will be projected into the specified + paths, and unlisted keys will not be present. If + a key is specified which is not present in the Secret, + the volume setup will error unless it is marked + optional. Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set + permissions on this file. Must be an octal + value between 0000 and 0777 or a decimal value + between 0 and 511. YAML accepts both octal + and decimal values, JSON requires decimal + values for mode bits. If not specified, the + volume defaultMode will be used. This might + be in conflict with other options that affect + the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to + map the key to. May not be an absolute path. + May not contain the path element '..'. May + not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + type: object + type: object + repos: + description: Defines a pgBackRest repository + items: + description: PGBackRestRepo represents a pgBackRest repository. Only + one of its members may be specified. + properties: + azure: + description: Represents a pgBackRest repository that + is created using Azure storage + properties: + container: + description: The Azure container utilized for the + repository + type: string + required: + - container + type: object + gcs: + description: Represents a pgBackRest repository that + is created using Google Cloud Storage + properties: + bucket: + description: The GCS bucket utilized for the repository + type: string + required: + - bucket + type: object + name: + description: The name of the the repository + pattern: ^repo[1-4] + type: string + s3: + description: RepoS3 represents a pgBackRest repository + that is created using AWS S3 (or S3-compatible) storage + properties: + bucket: + description: The S3 bucket utilized for the repository + type: string + endpoint: + description: A valid endpoint corresponding to the + specified region + type: string + region: + description: The region corresponding to the S3 + bucket + type: string + required: + - bucket + - endpoint + - region + type: object + schedules: + description: 'Defines the schedules for the pgBackRest + backups Full, Differential and Incremental backup + types are supported: https://pgbackrest.org/user-guide.html#concept/backup' + properties: + differential: + description: 'Defines the Cron schedule for a differential + pgBackRest backup. Follows the standard Cron schedule + syntax: https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax' + minLength: 6 + type: string + full: + description: 'Defines the Cron schedule for a full + pgBackRest backup. Follows the standard Cron schedule + syntax: https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax' + minLength: 6 + type: string + incremental: + description: 'Defines the Cron schedule for an incremental + pgBackRest backup. Follows the standard Cron schedule + syntax: https://k8s.io/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax' + minLength: 6 + type: string + type: object + volume: + description: Represents a pgBackRest repository that + is created using a PersistentVolumeClaim + properties: + volumeClaimSpec: + description: Defines a PersistentVolumeClaim spec + used to create and/or bind a volume + properties: + accessModes: + description: 'AccessModes contains the desired + access modes the volume should have. More + info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'This field can be used to specify + either: * An existing VolumeSnapshot object + (snapshot.storage.k8s.io/VolumeSnapshot) * + An existing PVC (PersistentVolumeClaim) * + An existing custom resource that implements + data population (Alpha) In order to use custom + resource types that implement data population, + the AnyVolumeDataSource feature gate must + be enabled. If the provisioner or an external + controller can support the specified data + source, it will create a new volume based + on the contents of the specified data source.' + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup + is not specified, the specified Kind must + be in the core API group. For any other + third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'Resources represents the minimum + resources the volume should have. More info: + https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + selector: + description: A label query over volumes to consider + for binding. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'Name of the StorageClass required + by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of + volume is required by the claim. Value of + Filesystem is implied when not included in + claim spec. + type: string + volumeName: + description: VolumeName is the binding reference + to the PersistentVolume backing this claim. + type: string + type: object + required: + - volumeClaimSpec + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Defines details for performing an in-place restore + using pgBackRest + properties: + clusterName: + description: The name of an existing PostgresCluster to + use as the data source for the new PostgresCluster. + Defaults to the name of the PostgresCluster being created + if not provided. + type: string + clusterNamespace: + description: The namespace of the cluster specified as + the data source using the clusterName field. Defaults + to the namespace of the PostgresCluster being created + if not provided. + type: string + enabled: + default: false + description: Whether or not in-place pgBackRest restores + are enabled for this PostgresCluster. + type: boolean + options: + description: Command line options to include when running + the pgBackRest restore command. https://pgbackrest.org/command.html#command-restore + items: + type: string + type: array + repoName: + description: The name of the pgBackRest repo within the + source PostgresCluster that contains the backups that + should be utilized to perform a pgBackRest restore when + initializing the data source for the new PostgresCluster. + pattern: ^repo[1-4] + type: string + resources: + description: Resource requirements for the pgBackRest + restore Job. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + required: + - enabled + - repoName + type: object + required: + - image + type: object + required: + - pgbackrest + type: object + customReplicationTLSSecret: + description: 'The secret containing the replication client certificates + and keys for secure connections to the PostgreSQL server. It will + need to contain the client TLS certificate, TLS key and the Certificate + Authority certificate with the data keys set to tls.crt, tls.key + and ca.crt, respectively. NOTE: If CustomReplicationClientTLSSecret + is provided, CustomTLSSecret MUST be provided and the ca.crt provided + must be the same.' + properties: + items: + description: If unspecified, each key-value pair in the Data field + of the referenced Secret will be projected into the volume as + a file whose name is the key and content is the value. If specified, + the listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is specified + which is not present in the Secret, the volume setup will error + unless it is marked optional. Paths must be relative and may + not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set permissions + on this file. Must be an octal value between 0000 and + 0777 or a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume defaultMode + will be used. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to map the key + to. May not be an absolute path. May not contain the path + element '..'. May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + type: object + customTLSSecret: + description: 'The secret containing the Certificates and Keys to encrypt + PostgreSQL traffic will need to contain the server TLS certificate, + TLS key and the Certificate Authority certificate with the data + keys set to tls.crt, tls.key and ca.crt, respectively. It will then + be mounted as a volume projection to the ''/pgconf/tls'' directory. + For more information on Kubernetes secret projections, please see + https://k8s.io/docs/concepts/configuration/secret/#projection-of-secret-keys-to-specific-paths + NOTE: If CustomTLSSecret is provided, CustomReplicationClientTLSSecret + MUST be provided and the ca.crt provided must be the same.' + properties: + items: + description: If unspecified, each key-value pair in the Data field + of the referenced Secret will be projected into the volume as + a file whose name is the key and content is the value. If specified, + the listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is specified + which is not present in the Secret, the volume setup will error + unless it is marked optional. Paths must be relative and may + not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set permissions + on this file. Must be an octal value between 0000 and + 0777 or a decimal value between 0 and 511. YAML accepts + both octal and decimal values, JSON requires decimal values + for mode bits. If not specified, the volume defaultMode + will be used. This might be in conflict with other options + that affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to map the key + to. May not be an absolute path. May not contain the path + element '..'. May not start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be defined + type: boolean + type: object + dataSource: + description: Specifies a data source for bootstrapping the PostgreSQL + cluster. + properties: + postgresCluster: + description: Defines a pgBackRest data source that can be used + to pre-populate the PostgreSQL data directory for a new PostgreSQL + cluster using a pgBackRest restore. + properties: + clusterName: + description: The name of an existing PostgresCluster to use + as the data source for the new PostgresCluster. Defaults + to the name of the PostgresCluster being created if not + provided. + type: string + clusterNamespace: + description: The namespace of the cluster specified as the + data source using the clusterName field. Defaults to the + namespace of the PostgresCluster being created if not provided. + type: string + options: + description: Command line options to include when running + the pgBackRest restore command. https://pgbackrest.org/command.html#command-restore + items: + type: string + type: array + repoName: + description: The name of the pgBackRest repo within the source + PostgresCluster that contains the backups that should be + utilized to perform a pgBackRest restore when initializing + the data source for the new PostgresCluster. + pattern: ^repo[1-4] + type: string + resources: + description: Resource requirements for the pgBackRest restore + Job. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of + compute resources required. If Requests is omitted for + a container, it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + required: + - repoName + type: object + type: object + image: + description: The image name to use for PostgreSQL containers + type: string + imagePullSecrets: + description: The image pull secrets used to pull from a private registry + Changing this value causes all running pods to restart. https://k8s.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + instances: + items: + properties: + affinity: + description: 'Scheduling constraints of a PostgreSQL pod. Changing + this value causes PostgreSQL to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node' + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a + no-op). A null preferred scheduling term matches + no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range + 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an + update), the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If + the operator is Exists or DoesNotExist, + the values array must be empty. If + the operator is Gt or Lt, the values + array must have a single element, + which will be interpreted as an integer. + This array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) with the + highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range + 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a + pod label update), the system may or may not try to + eventually evict the pod from its node. When there + are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or + not co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any + node on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified + namespaces, where co-located is defined as running + on a node whose value of the label with key + topologyKey matches that of any node on which + any of the selected pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the greatest + sum of weights, i.e. for each node that meets all + of the scheduling requirements (resource request, + requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if the + node has pods which matches the corresponding podAffinityTerm; + the node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose value + of the label with key topologyKey matches + that of any node on which any of the selected + pods is running. Empty topologyKey is not + allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range + 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a + pod label update), the system may or may not try to + eventually evict the pod from its node. When there + are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or + not co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any + node on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of + label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, a + key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified + namespaces, where co-located is defined as running + on a node whose value of the label with key + topologyKey matches that of any node on which + any of the selected pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + dataVolumeClaimSpec: + description: 'Defines a PersistentVolumeClaim for PostgreSQL + data. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes' + properties: + accessModes: + description: 'AccessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'This field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) * An existing + custom resource that implements data population (Alpha) + In order to use custom resource types that implement data + population, the AnyVolumeDataSource feature gate must + be enabled. If the provisioner or an external controller + can support the specified data source, it will create + a new volume based on the contents of the specified data + source.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'Resources represents the minimum resources + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of + compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + selector: + description: A label query over volumes to consider for + binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'Name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not + included in claim spec. + type: string + volumeName: + description: VolumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + metadata: + description: Metadata contains metadata for PostgresCluster + resources + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + name: + default: "" + type: string + replicas: + default: 1 + format: int32 + minimum: 0 + type: integer + resources: + description: Compute resources of a PostgreSQL container. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. More info: + https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + tolerations: + description: 'Tolerations of a PostgreSQL pod. Changing this + value causes PostgreSQL to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + walVolumeClaimSpec: + description: 'Defines a separate PersistentVolumeClaim for PostgreSQL''s + write-ahead log. More info: https://www.postgresql.org/docs/current/wal.html' + properties: + accessModes: + description: 'AccessModes contains the desired access modes + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'This field can be used to specify either: + * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) * An existing + custom resource that implements data population (Alpha) + In order to use custom resource types that implement data + population, the AnyVolumeDataSource feature gate must + be enabled. If the provisioner or an external controller + can support the specified data source, it will create + a new volume based on the contents of the specified data + source.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, the + specified Kind must be in the core API group. For + any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + resources: + description: 'Resources represents the minimum resources + the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of + compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + selector: + description: A label query over volumes to consider for + binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + storageClassName: + description: 'Name of the StorageClass required by the claim. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is required + by the claim. Value of Filesystem is implied when not + included in claim spec. + type: string + volumeName: + description: VolumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + required: + - dataVolumeClaimSpec + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + metadata: + description: Metadata contains metadata for PostgresCluster resources + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + monitoring: + description: The specification of monitoring tools that connect to + PostgreSQL + properties: + pgmonitor: + description: PGMonitorSpec defines the desired state of the pgMonitor + tool suite + properties: + exporter: + properties: + configuration: + description: 'Projected volumes containing custom PostgreSQL + Exporter configuration. Currently supports the customization + of PostgreSQL Exporter queries. If a "queries.yaml" + file is detected in any volume projected using this + field, it will be loaded using the "extend.query-path" + flag: https://github.com/prometheus-community/postgres_exporter#flags + Changing the values of field causes PostgreSQL and the + exporter to restart.' + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: information about the configMap data + to project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the ConfigMap, the + volume setup will error unless it is marked + optional. Paths must be relative and may not + contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used + to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the + string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its keys must be defined + type: boolean + type: object + downwardAPI: + description: information about the downwardAPI data + to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. + Must not be absolute or contain the + ''..'' path. Must be utf-8 encoded. + The first item of the relative path + must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and + requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) are + currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: information about the secret data to + project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the Secret, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used + to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the + string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + type: object + serviceAccountToken: + description: information about the serviceAccountToken + data to project + properties: + audience: + description: Audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: ExpirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if the + token is older than 80 percent of its time + to live or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: Path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + image: + description: The image name to use for crunchy-postgres-exporter + containers + type: string + resources: + description: 'Changing this value causes PostgreSQL and + the exporter to restart. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + required: + - image + type: object + type: object + type: object + openshift: + description: Whether or not the PostgreSQL cluster is being deployed + to an OpenShift envioronment + type: boolean + patroni: + properties: + dynamicConfiguration: + type: object + x-kubernetes-preserve-unknown-fields: true + leaderLeaseDurationSeconds: + default: 30 + description: TTL of the cluster leader lock. "Think of it as the + length of time before initiation of the automatic failover process." + format: int32 + minimum: 3 + type: integer + port: + default: 8008 + description: The port on which Patroni should listen. + format: int32 + minimum: 1024 + type: integer + syncPeriodSeconds: + default: 10 + description: The interval for refreshing the leader lock and applying + dynamicConfiguration. Must be less than leaderLeaseDurationSeconds. + format: int32 + minimum: 1 + type: integer + type: object + port: + default: 5432 + description: The port on which PostgreSQL should listen. + format: int32 + minimum: 1024 + type: integer + postgresVersion: + description: The major version of PostgreSQL installed in the PostgreSQL + container + maximum: 13 + minimum: 10 + type: integer + proxy: + description: The specification of a proxy that connects to PostgreSQL. + properties: + pgBouncer: + description: Defines a PgBouncer proxy and connection pooler. + properties: + affinity: + description: 'Scheduling constraints of a PgBouncer pod. Changing + this value causes PgBouncer to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node' + properties: + nodeAffinity: + description: Describes node affinity scheduling rules + for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies to + (matches against); null or empty list + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, + etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which + namespaces the labelSelector applies to + (matches against); null or empty list + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + config: + description: 'Configuration settings for the PgBouncer process. + Changes to any of these values will be automatically reloaded + without validation. Be careful, as you may put PgBouncer + into an unusable state. More info: https://www.pgbouncer.org/usage.html#reload' + properties: + databases: + additionalProperties: + type: string + description: 'PgBouncer database definitions. The key + is the database requested by a client while the value + is a libpq-styled connection string. The special key + "*" acts as a fallback. When this field is empty, PgBouncer + is configured with a single "*" entry that connects + to the primary PostgreSQL instance. More info: https://www.pgbouncer.org/config.html#section-databases' + type: object + files: + description: 'Files to mount under "/etc/pgbouncer". When + specified, settings in the "pgbouncer.ini" file are + loaded before all others. From there, other files may + be included by absolute path. Changing these references + causes PgBouncer to restart, but changes to the file + contents are automatically reloaded. More info: https://www.pgbouncer.org/config.html#include-directive' + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: information about the configMap data + to project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced ConfigMap + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the ConfigMap, the + volume setup will error unless it is marked + optional. Paths must be relative and may not + contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used + to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the + string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or + its keys must be defined + type: boolean + type: object + downwardAPI: + description: information about the downwardAPI data + to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits used + to set permissions on this file, must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. + Must not be absolute or contain the + ''..'' path. Must be utf-8 encoded. + The first item of the relative path + must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the + container: only resources limits and + requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) are + currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: information about the secret data to + project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced Secret + will be projected into the volume as a file + whose name is the key and content is the value. + If specified, the listed keys will be projected + into the specified paths, and unlisted keys + will not be present. If a key is specified + which is not present in the Secret, the volume + setup will error unless it is marked optional. + Paths must be relative and may not contain + the '..' path or start with '..'. + items: + description: Maps a string key to a path within + a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used + to set permissions on this file. Must + be an octal value between 0000 and 0777 + or a decimal value between 0 and 511. + YAML accepts both octal and decimal + values, JSON requires decimal values + for mode bits. If not specified, the + volume defaultMode will be used. This + might be in conflict with other options + that affect the file mode, like fsGroup, + and the result can be other mode bits + set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be an + absolute path. May not contain the path + element '..'. May not start with the + string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + type: object + serviceAccountToken: + description: information about the serviceAccountToken + data to project + properties: + audience: + description: Audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: ExpirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if the + token is older than 80 percent of its time + to live or if the token is older than 24 hours.Defaults + to 1 hour and must be at least 10 minutes. + format: int64 + type: integer + path: + description: Path is the path relative to the + mount point of the file to project the token + into. + type: string + required: + - path + type: object + type: object + type: array + global: + additionalProperties: + type: string + description: 'Settings that apply to the entire PgBouncer + process. More info: https://www.pgbouncer.org/config.html' + type: object + users: + additionalProperties: + type: string + description: 'Connection settings specific to particular + users. More info: https://www.pgbouncer.org/config.html#section-users' + type: object + type: object + customTLSSecret: + description: 'A secret projection containing a certificate + and key with which to encrypt connections to PgBouncer. + The "tls.crt", "tls.key", and "ca.crt" paths must be PEM-encoded + certificates and keys. Changing this value causes PgBouncer + to restart. More info: https://kubernetes.io/docs/concepts/configuration/secret/#projection-of-secret-keys-to-specific-paths' + properties: + items: + description: If unspecified, each key-value pair in the + Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and + content is the value. If specified, the listed keys + will be projected into the specified paths, and unlisted + keys will not be present. If a key is specified which + is not present in the Secret, the volume setup will + error unless it is marked optional. Paths must be relative + and may not contain the '..' path or start with '..'. + items: + description: Maps a string key to a path within a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits used to set permissions + on this file. Must be an octal value between 0000 + and 0777 or a decimal value between 0 and 511. + YAML accepts both octal and decimal values, JSON + requires decimal values for mode bits. If not + specified, the volume defaultMode will be used. + This might be in conflict with other options that + affect the file mode, like fsGroup, and the result + can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to map + the key to. May not be an absolute path. May not + contain the path element '..'. May not start with + the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + type: object + image: + description: 'Name of a container image that can run PgBouncer + 1.15 or newer. Changing this value causes PgBouncer to restart. + More info: https://kubernetes.io/docs/concepts/containers/images' + type: string + metadata: + description: Metadata contains metadata for PostgresCluster + resources + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + port: + default: 5432 + description: Port on which PgBouncer should listen for client + connections. Changing this value causes PgBouncer to restart. + format: int32 + minimum: 1024 + type: integer + replicas: + default: 1 + description: Number of desired PgBouncer pods. + format: int32 + minimum: 0 + type: integer + resources: + description: 'Compute resources of a PgBouncer container. + Changing this value causes PgBouncer to restart. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of + compute resources required. If Requests is omitted for + a container, it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + tolerations: + description: 'Tolerations of a PgBouncer pod. Changing this + value causes PgBouncer to restart. More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value should + be empty, otherwise just a regular string. + type: string + type: object + type: array + required: + - image + type: object + required: + - pgBouncer + type: object + shutdown: + description: Whether or not the PostgreSQL cluster should be stopped. + When this is true, workloads are scaled to zero and CronJobs are + suspended. Other resources, such as Services and Volumes, remain + in place. + type: boolean + standby: + description: Run this cluster as a read-only copy of an existing cluster + or archive. + properties: + enabled: + default: true + description: Whether or not the PostgreSQL cluster should be read-only. + When this is true, WAL files are applied from the pgBackRest + repository. + type: boolean + repoName: + description: The name of the pgBackRest repository to follow for + WAL files. + pattern: ^repo[1-4] + type: string + required: + - repoName + type: object + required: + - backups + - image + - instances + - postgresVersion + type: object + status: + description: PostgresClusterStatus defines the observed state of PostgresCluster + properties: + conditions: + description: 'conditions represent the observations of postgrescluster''s + current state. Known .status.conditions.type are: "PersistentVolumeResizing", + "ProxyAvailable"' + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + instances: + description: Current state of PostgreSQL instances. + items: + properties: + name: + type: string + readyReplicas: + description: Total number of ready pods. + format: int32 + type: integer + replicas: + description: Total number of non-terminated pods. + format: int32 + type: integer + updatedReplicas: + description: Total number of non-terminated pods that have the + desired specification. + format: int32 + type: integer + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + monitoring: + description: Current state of PostgreSQL cluster monitoring tool configuration + properties: + exporterConfiguration: + type: string + type: object + observedGeneration: + description: observedGeneration represents the .metadata.generation + on which the status was based. + format: int64 + minimum: 0 + type: integer + patroni: + properties: + systemIdentifier: + description: The PostgreSQL system identifier reported by Patroni. + type: string + type: object + pgbackrest: + description: Status information for pgBackRest + properties: + manualBackup: + description: Status information for manual backups + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: Represents the time the manual backup Job was + determined by the Job controller to be completed. This + field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in + UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: Specifies whether or not the Job is finished + executing (does not indicate success or failure). + type: boolean + id: + description: A unique identifier for the manual backup as + provided using the "pgbackrest-backup" annotation when initiating + a backup. + type: string + startTime: + description: Represents the time the manual backup Job was + acknowledged by the Job controller. It is represented in + RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + repoHost: + description: Status information for the pgBackRest dedicated repository + host + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this + representation of an object. Servers should convert recognized + schemas to the latest internal value, and may reject unrecognized + values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST + resource this object represents. Servers may infer this + from the endpoint the client submits requests to. Cannot + be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + ready: + description: Whether or not the pgBackRest repository host + is ready for use + type: boolean + type: object + repos: + description: Status information for pgBackRest repositories + items: + description: RepoVolumeStatus the status of a pgBackRest repository + properties: + bound: + description: Whether or not the pgBackRest repository PersistentVolumeClaim + is bound to a volume + type: boolean + name: + description: The name of the pgBackRest repository + type: string + replicaCreateBackupComplete: + description: ReplicaCreateBackupReady indicates whether + a backup exists in the repository as needed to bootstrap + replicas. + type: boolean + repoOptionsHash: + description: A hash of the required fields in the spec for + defining an Azure, GCS or S3 repository, Utilizd to detect + changes to these fields and then execute pgBackRest stanza-create + commands accordingly. + type: string + stanzaCreated: + description: Specifies whether or not a stanza has been + successfully created for the repository + type: boolean + volume: + description: The name of the volume the containing the pgBackRest + repository + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + restore: + description: Status information for in-place restores + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: Represents the time the manual backup Job was + determined by the Job controller to be completed. This + field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is in + UTC. + format: date-time + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + finished: + description: Specifies whether or not the Job is finished + executing (does not indicate success or failure). + type: boolean + id: + description: A unique identifier for the manual backup as + provided using the "pgbackrest-backup" annotation when initiating + a backup. + type: string + startTime: + description: Represents the time the manual backup Job was + acknowledged by the Job controller. It is represented in + RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + required: + - finished + - id + type: object + scheduledBackups: + description: Status information for scheduled backups + items: + properties: + active: + description: The number of actively running manual backup + Pods. + format: int32 + type: integer + completionTime: + description: Represents the time the manual backup Job was + determined by the Job controller to be completed. This + field is only set if the backup completed successfully. + Additionally, it is represented in RFC3339 form and is + in UTC. + format: date-time + type: string + cronJobName: + description: The name of the associated pgBackRest scheduled + backup CronJob + type: string + failed: + description: The number of Pods for the manual backup Job + that reached the "Failed" phase. + format: int32 + type: integer + repo: + description: The name of the associated pgBackRest repository + type: string + startTime: + description: Represents the time the manual backup Job was + acknowledged by the Job controller. It is represented + in RFC3339 form and is in UTC. + format: date-time + type: string + succeeded: + description: The number of Pods for the manual backup Job + that reached the "Succeeded" phase. + format: int32 + type: integer + type: + description: The pgBackRest backup type for this Job + type: string + type: object + type: array + type: object + proxy: + description: Current state of the PostgreSQL proxy. + properties: + pgBouncer: + properties: + postgresRevision: + description: Identifies the revision of PgBouncer assets that + have been installed into PostgreSQL. + type: string + readyReplicas: + description: Total number of ready pods. + format: int32 + type: integer + replicas: + description: Total number of non-terminated pods. + format: int32 + type: integer + type: object + type: object + startupInstance: + description: The instance that should be started first when bootstrapping + and/or starting a PostgresCluster. + type: string + startupInstanceSet: + description: The instance set associated with the startupInstance + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/kustomize/install/bases/crd/kustomization.yaml b/kustomize/install/bases/crd/kustomization.yaml new file mode 100644 index 00000000..fde899fa --- /dev/null +++ b/kustomize/install/bases/crd/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- bases/postgres-operator.crunchydata.com_postgresclusters.yaml diff --git a/kustomize/install/bases/kustomization.yaml b/kustomize/install/bases/kustomization.yaml new file mode 100644 index 00000000..570718d5 --- /dev/null +++ b/kustomize/install/bases/kustomization.yaml @@ -0,0 +1,14 @@ +namespace: postgres-operator + +commonLabels: + postgres-operator.crunchydata.com/control-plane: postgres-operator + +bases: +- crd +- rbac/cluster +- manager + +images: +- name: postgres-operator + newName: registry.developers.crunchydata.com/crunchydata + newTag: ubi8-5.0.0-0 diff --git a/kustomize/install/bases/manager/kustomization.yaml b/kustomize/install/bases/manager/kustomization.yaml new file mode 100644 index 00000000..5c5f0b84 --- /dev/null +++ b/kustomize/install/bases/manager/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- manager.yaml diff --git a/kustomize/install/bases/manager/manager.yaml b/kustomize/install/bases/manager/manager.yaml new file mode 100644 index 00000000..3f702bc7 --- /dev/null +++ b/kustomize/install/bases/manager/manager.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres-operator +spec: + replicas: 1 + template: + spec: + containers: + - name: operator + image: postgres-operator + env: + - name: CRUNCHY_DEBUG + value: "true" + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + serviceAccountName: postgres-operator diff --git a/kustomize/install/bases/rbac/cluster/kustomization.yaml b/kustomize/install/bases/rbac/cluster/kustomization.yaml new file mode 100644 index 00000000..664fcac0 --- /dev/null +++ b/kustomize/install/bases/rbac/cluster/kustomization.yaml @@ -0,0 +1,4 @@ +resources: +- service_account.yaml +- role.yaml +- role_binding.yaml diff --git a/kustomize/install/bases/rbac/cluster/role.yaml b/kustomize/install/bases/rbac/cluster/role.yaml new file mode 100644 index 00000000..9eafa0c5 --- /dev/null +++ b/kustomize/install/bases/rbac/cluster/role.yaml @@ -0,0 +1,122 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: postgres-operator +rules: +- apiGroups: + - '' + resources: + - configmaps + - persistentvolumeclaims + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - endpoints + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - endpoints/restricted + - pods/exec + verbs: + - create +- apiGroups: + - '' + resources: + - events + verbs: + - create + - patch +- apiGroups: + - '' + resources: + - pods + verbs: + - delete + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - serviceaccounts + verbs: + - create + - get + - list + - patch + - watch +- apiGroups: + - apps + resources: + - deployments + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - batch + resources: + - cronjobs + - jobs + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters + verbs: + - get + - list + - patch + - watch +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters/finalizers + verbs: + - update +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters/status + verbs: + - patch +- apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + - roles + verbs: + - create + - get + - list + - patch + - watch diff --git a/kustomize/install/bases/rbac/cluster/role_binding.yaml b/kustomize/install/bases/rbac/cluster/role_binding.yaml new file mode 100644 index 00000000..56f5c0f9 --- /dev/null +++ b/kustomize/install/bases/rbac/cluster/role_binding.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: postgres-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: postgres-operator +subjects: +- kind: ServiceAccount + name: postgres-operator diff --git a/kustomize/install/bases/rbac/cluster/service_account.yaml b/kustomize/install/bases/rbac/cluster/service_account.yaml new file mode 100644 index 00000000..a795566b --- /dev/null +++ b/kustomize/install/bases/rbac/cluster/service_account.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: postgres-operator diff --git a/kustomize/install/bases/rbac/namespace/kustomization.yaml b/kustomize/install/bases/rbac/namespace/kustomization.yaml new file mode 100644 index 00000000..664fcac0 --- /dev/null +++ b/kustomize/install/bases/rbac/namespace/kustomization.yaml @@ -0,0 +1,4 @@ +resources: +- service_account.yaml +- role.yaml +- role_binding.yaml diff --git a/kustomize/install/bases/rbac/namespace/role.yaml b/kustomize/install/bases/rbac/namespace/role.yaml new file mode 100644 index 00000000..1f512076 --- /dev/null +++ b/kustomize/install/bases/rbac/namespace/role.yaml @@ -0,0 +1,122 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: postgres-operator +rules: +- apiGroups: + - '' + resources: + - configmaps + - persistentvolumeclaims + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - endpoints + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - endpoints/restricted + - pods/exec + verbs: + - create +- apiGroups: + - '' + resources: + - events + verbs: + - create + - patch +- apiGroups: + - '' + resources: + - pods + verbs: + - delete + - get + - list + - patch + - watch +- apiGroups: + - '' + resources: + - serviceaccounts + verbs: + - create + - get + - list + - patch + - watch +- apiGroups: + - apps + resources: + - deployments + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - batch + resources: + - cronjobs + - jobs + verbs: + - create + - delete + - get + - list + - patch + - watch +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters + verbs: + - get + - list + - patch + - watch +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters/finalizers + verbs: + - update +- apiGroups: + - postgres-operator.crunchydata.com + resources: + - postgresclusters/status + verbs: + - patch +- apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + - roles + verbs: + - create + - get + - list + - patch + - watch diff --git a/kustomize/install/bases/rbac/namespace/role_binding.yaml b/kustomize/install/bases/rbac/namespace/role_binding.yaml new file mode 100644 index 00000000..1698e107 --- /dev/null +++ b/kustomize/install/bases/rbac/namespace/role_binding.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: postgres-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: postgres-operator +subjects: +- kind: ServiceAccount + name: postgres-operator diff --git a/kustomize/install/bases/rbac/namespace/service_account.yaml b/kustomize/install/bases/rbac/namespace/service_account.yaml new file mode 100644 index 00000000..a795566b --- /dev/null +++ b/kustomize/install/bases/rbac/namespace/service_account.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: postgres-operator diff --git a/kustomize/install/kustomization.yaml b/kustomize/install/kustomization.yaml new file mode 100644 index 00000000..b781aa31 --- /dev/null +++ b/kustomize/install/kustomization.yaml @@ -0,0 +1,5 @@ +resources: +- namespace.yaml + +bases: +- bases diff --git a/kustomize/install/namespace.yaml b/kustomize/install/namespace.yaml new file mode 100644 index 00000000..bfebd8ac --- /dev/null +++ b/kustomize/install/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: postgres-operator diff --git a/kustomize/keycloak/keycloak.yaml b/kustomize/keycloak/keycloak.yaml new file mode 100644 index 00000000..ed33f985 --- /dev/null +++ b/kustomize/keycloak/keycloak.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: keycloak + namespace: postgres-operator + labels: + app.kubernetes.io/name: keycloak +spec: + selector: + matchLabels: + app.kubernetes.io/name: keycloak + template: + metadata: + labels: + app.kubernetes.io/name: keycloak + spec: + containers: + - image: quay.io/keycloak/keycloak:latest + name: keycloak + env: + - name: DB_VENDOR + value: "postgres" + - name: DB_ADDR + valueFrom: { secretKeyRef: { name: keycloakdb-pguser, key: host } } + - name: DB_PORT + valueFrom: { secretKeyRef: { name: keycloakdb-pguser, key: port } } + - name: DB_DATABASE + valueFrom: { secretKeyRef: { name: keycloakdb-pguser, key: dbname } } + - name: DB_USER + valueFrom: { secretKeyRef: { name: keycloakdb-pguser, key: user } } + - name: DB_PASSWORD + valueFrom: { secretKeyRef: { name: keycloakdb-pguser, key: password } } + - name: KEYCLOAK_USER + value: "admin" + - name: KEYCLOAK_PASSWORD + value: "admin" + - name: PROXY_ADDRESS_FORWARDING + value: "true" + ports: + - name: http + containerPort: 8080 + - name: https + containerPort: 8443 + readinessProbe: + httpGet: + path: /auth/realms/master + port: 8080 + restartPolicy: Always diff --git a/kustomize/keycloak/kustomization.yaml b/kustomize/keycloak/kustomization.yaml new file mode 100644 index 00000000..6e0df20e --- /dev/null +++ b/kustomize/keycloak/kustomization.yaml @@ -0,0 +1,5 @@ +namespace: postgres-operator + +resources: +- postgres.yaml +- keycloak.yaml diff --git a/kustomize/keycloak/postgres.yaml b/kustomize/keycloak/postgres.yaml new file mode 100644 index 00000000..f4553e5b --- /dev/null +++ b/kustomize/keycloak/postgres.yaml @@ -0,0 +1,40 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: keycloakdb +spec: + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 + postgresVersion: 13 + openshift: false + instances: + - replicas: 2 + dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: keycloakdb + postgres-operator.crunchydata.com/instance-set: "00" + backups: + pgbackrest: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 + repoHost: + dedicated: {} + repos: + - name: repo1 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi diff --git a/kustomize/monitoring/README.md b/kustomize/monitoring/README.md new file mode 100644 index 00000000..cd9d45a7 --- /dev/null +++ b/kustomize/monitoring/README.md @@ -0,0 +1,5 @@ +To deploy monitoring, + +1. verify the namespace is correct in kustomization.yaml +2. If you are deploying in openshift, edit deploy*.yaml and comment out fsGroup line under securityContext +3. kubectl apply -k . diff --git a/kustomize/monitoring/alertmanager-config.yaml b/kustomize/monitoring/alertmanager-config.yaml new file mode 100644 index 00000000..9618e2a9 --- /dev/null +++ b/kustomize/monitoring/alertmanager-config.yaml @@ -0,0 +1,88 @@ +apiVersion: v1 +data: + alertmanager.yml: | + ### + # + # Copyright 2017-2021 Crunchy Data Solutions, Inc. All Rights Reserved. + # + ### + + # Based on upstream example file found here: https://github.com/prometheus/alertmanager/blob/master/doc/examples/simple.yml + global: + smtp_smarthost: 'localhost: 25' + smtp_require_tls: false + smtp_from: 'Alertmanager ' + # smtp_smarthost: 'smtp.example.com:587' + # smtp_from: 'Alertmanager ' + # smtp_auth_username: '' + # smtp_auth_password: '' + + # templates: + # - '/etc/alertmanager/template/*.tmpl' + + inhibit_rules: + # Apply inhibition of warning if the alertname for the same system and service is already critical + - source_match: + severity: 'critical' + target_match: + severity: 'warning' + equal: ['alertname', 'job', 'service'] + + receivers: + - name: 'default-receiver' + email_configs: + - to: 'example@yourcompany.com' + send_resolved: true + + ## Examples of alternative alert receivers. See documentation for more info on how to configure these fully + #- name: 'pagerduty-dba' + # pagerduty_configs: + # - service_key: + + #- name: 'pagerduty-sre' + # pagerduty_configs: + # - service_key: + + #- name: 'dba-team' + # email_configs: + # - to: 'example-dba-team@crunchydata.com' + # send_resolved: true + + #- name: 'sre-team' + # email_configs: + # - to: 'example-sre-team@crunchydata.com' + # send_resolved: true + + route: + receiver: default-receiver + group_by: [severity, service, job, alertname] + group_wait: 30s + group_interval: 5m + repeat_interval: 24h + + ## Example routes to show how to route outgoing alerts based on the content of that alert + # routes: + # - match_re: + # service: ^(postgresql|mysql|oracle)$ + # receiver: dba-team + # # sub route to send critical dba alerts to pagerduty + # routes: + # - match: + # severity: critical + # receiver: pagerduty-dba + # + # - match: + # service: system + # receiver: sre-team + # # sub route to send critical sre alerts to pagerduty + # routes: + # - match: + # severity: critical + # receiver: pagerduty-sre +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: alertmanager-config + diff --git a/kustomize/monitoring/alertmanager-rules-config.yaml b/kustomize/monitoring/alertmanager-rules-config.yaml new file mode 100644 index 00000000..af201863 --- /dev/null +++ b/kustomize/monitoring/alertmanager-rules-config.yaml @@ -0,0 +1,391 @@ +apiVersion: v1 +data: + crunchy-alert-rules-pg.yml: | + ### + # + # Copyright 2017-2021 Crunchy Data Solutions, Inc. All Rights Reserved. + # + ### + + groups: + - name: alert-rules + rules: + + ########## EXPORTER RULES ########## + - alert: PGExporterScrapeError + expr: pg_exporter_last_scrape_error > 0 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + summary: 'Postgres Exporter running on {{ $labels.job }} (instance: {{ $labels.instance }}) is encountering scrape errors processing queries. Error count: ( {{ $value }} )' + + + ########## POSTGRESQL RULES ########## + - alert: PGIsUp + expr: pg_up < 1 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + summary: 'postgres_exporter running on {{ $labels.job }} is unable to communicate with the configured database' + + + # Example to check for current version of PostgreSQL. Metric returns the version that the exporter is running on, so you can set a rule to check for the minimum version you'd like all systems to be on. Number returned is the 6 digit integer representation contained in the setting "server_version_num". + # + # - alert: PGMinimumVersion + # expr: ccp_postgresql_version_current < 110005 + # for: 60s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # summary: '{{ $labels.job }} is not running at least version 11.5 of PostgreSQL' + + + # Whether a system switches from primary to replica or vice versa must be configured per named job. + # No way to tell what value a system is supposed to be without a rule expression for that specific system + # 2 to 1 means it changed from primary to replica. 1 to 2 means it changed from replica to primary + # Set this alert for each system that you want to monitor a recovery status change + # Below is an example for a target job called "Replica" and watches for the value to change above 1 which means it's no longer a replica + # + # - alert: PGRecoveryStatusSwitch_Replica + # expr: ccp_is_in_recovery_status{job="Replica"} > 1 + # for: 60s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # summary: '{{ $labels.job }} has changed from replica to primary' + + + # Absence alerts must be configured per named job, otherwise there's no way to know which job is down + # Below is an example for a target job called "Prod" + # - alert: PGConnectionAbsent_Prod + # expr: absent(ccp_connection_stats_max_connections{job="Prod"}) + # for: 10s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # description: 'Connection metric is absent from target (Prod). Check that postgres_exporter can connect to PostgreSQL.' + + + # Optional monitor for changes to pg_settings (postgresql.conf) system catalog. + # A similar metric is available for monitoring pg_hba.conf. See ccp_hba_settings_checksum(). + # If metric returns 0, then NO settings have changed for either pg_settings since last known valid state + # If metric returns 1, then pg_settings have changed since last known valid state + # To see what may have changed, check the monitor.pg_settings_checksum table for a history of config state. + # - alert: PGSettingsChecksum + # expr: ccp_pg_settings_checksum > 0 + # for 60s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # description: 'Configuration settings on {{ $labels.job }} have changed from previously known valid state. To reset current config to a valid state after alert fires, run monitor.pg_settings_checksum_set_valid().' + # summary: 'PGSQL Instance settings checksum' + + + # Monitor for data block checksum failures. Only works in PG12+ + # - alert: PGDataChecksum + # expr: ccp_data_checksum_failure > 0 + # for 60s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # description: '{{ $labels.job }} has at least one data checksum failure in database {{ $labels.dbname }}. See pg_stat_database system catalog for more information.' + # summary: 'PGSQL Data Checksum failure' + + - alert: PGIdleTxn + expr: ccp_connection_stats_max_idle_in_txn_time > 300 + for: 60s + labels: + service: postgresql + severity: warning + severity_num: 200 + annotations: + description: '{{ $labels.job }} has at least one session idle in transaction for over 5 minutes.' + summary: 'PGSQL Instance idle transactions' + + - alert: PGIdleTxn + expr: ccp_connection_stats_max_idle_in_txn_time > 900 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: '{{ $labels.job }} has at least one session idle in transaction for over 15 minutes.' + summary: 'PGSQL Instance idle transactions' + + - alert: PGQueryTime + expr: ccp_connection_stats_max_query_time > 43200 + for: 60s + labels: + service: postgresql + severity: warning + severity_num: 200 + annotations: + description: '{{ $labels.job }} has at least one query running for over 12 hours.' + summary: 'PGSQL Max Query Runtime' + + - alert: PGQueryTime + expr: ccp_connection_stats_max_query_time > 86400 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: '{{ $labels.job }} has at least one query running for over 1 day.' + summary: 'PGSQL Max Query Runtime' + + - alert: PGConnPerc + expr: 100 * (ccp_connection_stats_total / ccp_connection_stats_max_connections) > 75 + for: 60s + labels: + service: postgresql + severity: warning + severity_num: 200 + annotations: + description: '{{ $labels.job }} is using 75% or more of available connections ({{ $value }}%)' + summary: 'PGSQL Instance connections' + + - alert: PGConnPerc + expr: 100 * (ccp_connection_stats_total / ccp_connection_stats_max_connections) > 90 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: '{{ $labels.job }} is using 90% or more of available connections ({{ $value }}%)' + summary: 'PGSQL Instance connections' + + - alert: PGDiskSize + expr: 100 * ((ccp_nodemx_data_disk_total_bytes - ccp_nodemx_data_disk_available_bytes) / ccp_nodemx_data_disk_total_bytes) > 75 + for: 60s + labels: + service: postgresql + severity: warning + severity_num: 200 + annotations: + description: 'PGSQL Instance {{ $labels.deployment }} over 75% disk usage at mount point "{{ $labels.mount_point }}": {{ $value }}%' + summary: PGSQL Instance usage warning + + - alert: PGDiskSize + expr: 100 * ((ccp_nodemx_data_disk_total_bytes - ccp_nodemx_data_disk_available_bytes) / ccp_nodemx_data_disk_total_bytes) > 90 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: 'PGSQL Instance {{ $labels.deployment }} over 90% disk usage at mount point "{{ $labels.mount_point }}": {{ $value }}%' + summary: 'PGSQL Instance size critical' + + - alert: PGReplicationByteLag + expr: ccp_replication_status_byte_lag > 5.24288e+07 + for: 60s + labels: + service: postgresql + severity: warning + severity_num: 200 + annotations: + description: 'PGSQL Instance {{ $labels.job }} has at least one replica lagging over 50MB behind.' + summary: 'PGSQL Instance replica lag warning' + + - alert: PGReplicationByteLag + expr: ccp_replication_status_byte_lag > 1.048576e+08 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: 'PGSQL Instance {{ $labels.job }} has at least one replica lagging over 100MB behind.' + summary: 'PGSQL Instance replica lag warning' + + - alert: PGReplicationSlotsInactive + expr: ccp_replication_slots_active == 0 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: 'PGSQL Instance {{ $labels.job }} has one or more inactive replication slots' + summary: 'PGSQL Instance inactive replication slot' + + - alert: PGXIDWraparound + expr: ccp_transaction_wraparound_percent_towards_wraparound > 50 + for: 60s + labels: + service: postgresql + severity: warning + severity_num: 200 + annotations: + description: 'PGSQL Instance {{ $labels.job }} is over 50% towards transaction id wraparound.' + summary: 'PGSQL Instance {{ $labels.job }} transaction id wraparound imminent' + + - alert: PGXIDWraparound + expr: ccp_transaction_wraparound_percent_towards_wraparound > 75 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: 'PGSQL Instance {{ $labels.job }} is over 75% towards transaction id wraparound.' + summary: 'PGSQL Instance transaction id wraparound imminent' + + - alert: PGEmergencyVacuum + expr: ccp_transaction_wraparound_percent_towards_emergency_autovac > 110 + for: 60s + labels: + service: postgresql + severity: warning + severity_num: 200 + annotations: + description: 'PGSQL Instance {{ $labels.job }} is over 110% beyond autovacuum_freeze_max_age value. Autovacuum may need tuning to better keep up.' + summary: 'PGSQL Instance emergency vacuum imminent' + + - alert: PGEmergencyVacuum + expr: ccp_transaction_wraparound_percent_towards_emergency_autovac > 125 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: 'PGSQL Instance {{ $labels.job }} is over 125% beyond autovacuum_freeze_max_age value. Autovacuum needs tuning to better keep up.' + summary: 'PGSQL Instance emergency vacuum imminent' + + - alert: PGArchiveCommandStatus + expr: ccp_archive_command_status_seconds_since_last_fail > 300 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: 'PGSQL Instance {{ $labels.job }} has a recent failing archive command' + summary: 'Seconds since the last recorded failure of the archive_command' + + - alert: PGSequenceExhaustion + expr: ccp_sequence_exhaustion_count > 0 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: 'Count of sequences on instance {{ $labels.job }} at over 75% usage: {{ $value }}. Run following query to see full sequence status: SELECT * FROM monitor.sequence_status() WHERE percent >= 75' + + - alert: PGSettingsPendingRestart + expr: ccp_settings_pending_restart_count > 0 + for: 60s + labels: + service: postgresql + severity: critical + severity_num: 300 + annotations: + description: 'One or more settings in the pg_settings system catalog on system {{ $labels.job }} are in a pending_restart state. Check the system catalog for which settings are pending and review postgresql.conf for changes.' + + ########## PGBACKREST RULES ########## + # + # Uncomment and customize one or more of these rules to monitor your pgbackrest backups. + # Full backups are considered the equivalent of both differentials and incrementals since both are based on the last full + # And differentials are considered incrementals since incrementals will be based off the last diff if one exists + # This avoid false alerts, for example when you don't run diff/incr backups on the days that you run a full + # Stanza should also be set if different intervals are expected for each stanza. + # Otherwise rule will be applied to all stanzas returned on target system if not set. + # + # Relevant metric names are: + # ccp_backrest_last_full_time_since_completion_seconds + # ccp_backrest_last_incr_time_since_completion_seconds + # ccp_backrest_last_diff_time_since_completion_seconds + # + # - alert: PGBackRestLastCompletedFull_main + # expr: ccp_backrest_last_full_backup_time_since_completion_seconds{stanza="main"} > 604800 + # for: 60s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # summary: 'Full backup for stanza [main] on system {{ $labels.job }} has not completed in the last week.' + # + # - alert: PGBackRestLastCompletedIncr_main + # expr: ccp_backrest_last_incr_backup_time_since_completion_seconds{stanza="main"} > 86400 + # for: 60s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # summary: 'Incremental backup for stanza [main] on system {{ $labels.job }} has not completed in the last 24 hours.' + # + # + # Runtime monitoring is handled with a single metric: + # + # ccp_backrest_last_runtime_backup_runtime_seconds + # + # Runtime monitoring should have the "backup_type" label set. + # Otherwise the rule will apply to the last run of all backup types returned (full, diff, incr) + # Stanza should also be set if runtimes per stanza have different expected times + # + # - alert: PGBackRestLastRuntimeFull_main + # expr: ccp_backrest_last_runtime_backup_runtime_seconds{backup_type="full", stanza="main"} > 14400 + # for: 60s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # summary: 'Expected runtime of full backup for stanza [main] has exceeded 4 hours' + # + # - alert: PGBackRestLastRuntimeDiff_main + # expr: ccp_backrest_last_runtime_backup_runtime_seconds{backup_type="diff", stanza="main"} > 3600 + # for: 60s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # summary: 'Expected runtime of diff backup for stanza [main] has exceeded 1 hour' + ## + # + ## If the pgbackrest command fails to run, the metric disappears from the exporter output and the alert never fires. + ## An absence alert must be configured explicitly for each target (job) that backups are being monitored. + ## Checking for absence of just the full backup type should be sufficient (no need for diff/incr). + ## Note that while the backrest check command failing will likely also cause a scrape error alert, the addition of this + ## check gives a clearer answer as to what is causing it and that something is wrong with the backups. + # + # - alert: PGBackrestAbsentFull_Prod + # expr: absent(ccp_backrest_last_full_backup_time_since_completion_seconds{job="Prod"}) + # for: 10s + # labels: + # service: postgresql + # severity: critical + # severity_num: 300 + # annotations: + # description: 'Backup Full status missing for Prod. Check that pgbackrest info command is working on target system.' +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: alertmanager-rules-config + diff --git a/kustomize/monitoring/dashboards/crud_details.json b/kustomize/monitoring/dashboards/crud_details.json new file mode 100644 index 00000000..e5838437 --- /dev/null +++ b/kustomize/monitoring/dashboards/crud_details.json @@ -0,0 +1,331 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "6.7.4" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:111", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": false, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1596817489973, + "links": [ + { + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [], + "type": "dashboards" + } + ], + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 0 + }, + "height": "480", + "hiddenSeries": false, + "id": 1, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "maxPerRow": 2, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ccp_stat_user_tables_n_tup_ins{pg_cluster=\"[[cluster]]\", pod=~\"[[pod]]\", dbname=~\"[[dbname]]\", schemaname=~\"[[schemaname]]\", relname=~\"[[tablename]]\"}[60s]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "inserts - [[dbname]].[[schemaname]].[[tablename]]", + "refId": "A", + "step": 60 + }, + { + "expr": "sum(rate(ccp_stat_user_tables_n_tup_upd{pg_cluster=\"[[cluster]]\", pod=~\"[[pod]]\", dbname=~\"[[dbname]]\", schemaname=~\"[[schemaname]]\", relname=~\"[[tablename]]\"}[60s]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Updates - [[dbname]].[[schemaname]].[[tablename]]", + "refId": "B", + "step": 60 + }, + { + "expr": "sum(rate(ccp_stat_user_tables_n_tup_del{pg_cluster=\"[[cluster]]\", pod=~\"[[pod]]\", dbname=~\"[[dbname]]\", schemaname=~\"[[schemaname]]\", relname=~\"[[tablename]]\"}[60s]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Deletes - [[dbname]].[[schemaname]].[[tablename]]", + "refId": "C", + "step": 60 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CRUD", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "30s", + "schemaVersion": 22, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "", + "hide": 0, + "includeAll": false, + "index": -1, + "label": null, + "multi": false, + "name": "cluster", + "options": [], + "query": "label_values(pg_cluster)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values({pg_cluster=\"[[cluster]]\"},pod)", + "hide": 0, + "includeAll": true, + "index": -1, + "label": "pod", + "multi": true, + "name": "pod", + "options": [], + "query": "label_values({pg_cluster=\"[[cluster]]\"},pod)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(ccp_database_size_bytes{pg_cluster=\"[[cluster]]\"},dbname)", + "hide": 0, + "includeAll": true, + "index": -1, + "label": "dbname", + "multi": true, + "name": "dbname", + "options": [], + "query": "label_values(ccp_database_size_bytes{pg_cluster=\"[[cluster]]\"},dbname)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "PROMETHEUS", + "definition": "", + "hide": 0, + "includeAll": true, + "index": -1, + "label": "schemaname", + "multi": true, + "name": "schemaname", + "options": [], + "query": "label_values(ccp_stat_user_tables_n_tup_ins{pg_cluster=\"[[cluster]]\",dbname=~\"[[dbname]]\"},schemaname)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "PROMETHEUS", + "definition": "", + "hide": 0, + "includeAll": true, + "index": -1, + "label": null, + "multi": true, + "name": "tablename", + "options": [], + "query": "label_values(ccp_stat_user_tables_n_tup_ins{pg_cluster=\"[[cluster]]\",dbname=~\"[[dbname]]\",schemaname=~\"[[schemaname]]\"},relname)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "CRUD_Details", + "uid": "cruddetails", + "variables": { + "list": [] + }, + "version": 2 +} diff --git a/kustomize/monitoring/dashboards/crunchy_grafana_dashboards.yml b/kustomize/monitoring/dashboards/crunchy_grafana_dashboards.yml new file mode 100644 index 00000000..c19b7031 --- /dev/null +++ b/kustomize/monitoring/dashboards/crunchy_grafana_dashboards.yml @@ -0,0 +1,16 @@ +### +# +# Copyright 2017-2021 Crunchy Data Solutions, Inc. All Rights Reserved. +# +### +apiVersion: 1 + +providers: +- name: 'crunchy_dashboards' + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 3 #how often Grafana will scan for changed dashboards + options: + path: $GF_PATHS_PROVISIONING/dashboards diff --git a/kustomize/monitoring/dashboards/pgbackrest.json b/kustomize/monitoring/dashboards/pgbackrest.json new file mode 100644 index 00000000..ec3704e9 --- /dev/null +++ b/kustomize/monitoring/dashboards/pgbackrest.json @@ -0,0 +1,687 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": false, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1624546649377, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "vendor=crunchydata" + ], + "title": "", + "type": "dashboards" + } + ], + "panels": [ + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-blue", + "value": null + } + ] + }, + "unit": "dtdhms" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Value$/", + "values": false + }, + "text": { + "valueSize": 45 + }, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "time()-ccp_backrest_oldest_full_backup_time_seconds{pg_cluster=\"[[cluster]]\", role=\"master\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "Recovery window", + "refId": "A" + } + ], + "title": "Recovery Window", + "type": "stat" + }, + { + "aliasColors": { + "Differential": "dark-blue", + "Differential Backup": "dark-blue", + "Full": "dark-green", + "Full Backup": "dark-green", + "Incremental": "light-blue", + "Incremental Backup": "light-blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 3 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": false + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(ccp_backrest_last_incr_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\", role=\"master\"}) without(deployment,instance,ip,pod)", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Incremental Backup", + "refId": "A" + }, + { + "expr": "min(ccp_backrest_last_diff_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\", role=\"master\"}) without(deployment, instance,ip,pod)", + "hide": false, + "interval": "", + "legendFormat": "Differential Backup", + "refId": "B" + }, + { + "expr": "min(ccp_backrest_last_full_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\", role=\"master\"}) without(deployment, instance,ip,pod)", + "hide": false, + "interval": "", + "legendFormat": "Full Backup", + "refId": "C" + }, + { + "expr": "min(ccp_archive_command_status_seconds_since_last_archive{pg_cluster=\"[[cluster]]\", role=\"master\"}) without(deployment, instance,ip,pod)", + "hide": false, + "interval": "", + "legendFormat": "WAL Archive", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time Since", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Differential": "dark-blue", + "Full": "dark-green", + "Incremental": "light-blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 3 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(ccp_backrest_last_info_backup_runtime_seconds{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"incr\"}) without (deployment,instance,pod,ip)", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Incremental", + "refId": "A" + }, + { + "expr": "min(ccp_backrest_last_info_backup_runtime_seconds{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"diff\"}) without (deployment,instance,pod,ip)", + "hide": false, + "interval": "", + "legendFormat": "Differential", + "refId": "B" + }, + { + "expr": "min(ccp_backrest_last_info_backup_runtime_seconds{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"full\"}) without (deployment,instance,pod,ip)", + "hide": false, + "interval": "", + "legendFormat": "Full", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Backup Runtimes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 2, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Differential": "dark-blue", + "Full": "dark-green", + "Incremental": "light-blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 10 + }, + "hiddenSeries": false, + "id": 5, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "min(ccp_backrest_last_info_repo_backup_size_bytes{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"incr\"}) without (deployment, instance,pod,ip)", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Incremental", + "refId": "A" + }, + { + "expr": "min(ccp_backrest_last_info_repo_backup_size_bytes{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"diff\"}) without (deployment,instance,pod,ip)", + "hide": false, + "interval": "", + "legendFormat": "Differential", + "refId": "B" + }, + { + "expr": "min(ccp_backrest_last_info_repo_backup_size_bytes{pg_cluster=\"[[cluster]]\", role=\"master\", backup_type=\"full\"}) without (deployment,instance,pod,ip)", + "hide": false, + "interval": "", + "legendFormat": "Full", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Backup Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 2, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Archive age": "blue", + "Archive count": "green", + "Differential": "dark-blue", + "Failed count": "red", + "Full": "dark-green", + "Incremental": "light-blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 3, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 10 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(idelta(ccp_archive_command_status_failed_count{pg_cluster=\"[[cluster]]\", role=\"master\"}[1m])) without (instance,ip)", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Failed count", + "refId": "A" + }, + { + "expr": "avg(idelta(ccp_archive_command_status_archived_count{pg_cluster=\"[[cluster]]\", role=\"master\"}[1m])) without (instance,pod, ip)", + "hide": false, + "interval": "", + "legendFormat": "Archive count", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "WAL Stats", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "5m", + "schemaVersion": 27, + "style": "dark", + "tags": [ + "vendor=crunchydata" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(pg_cluster)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(pg_cluster)", + "refId": "PROMETHEUS-cluster-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "pgBackRest", + "uid": "2fcFZ6PGk", + "version": 1 +} diff --git a/kustomize/monitoring/dashboards/pod_details.json b/kustomize/monitoring/dashboards/pod_details.json new file mode 100644 index 00000000..6789e89a --- /dev/null +++ b/kustomize/monitoring/dashboards/pod_details.json @@ -0,0 +1,1178 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1624647381559, + "links": [ + { + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "vendor=crunchydata" + ], + "type": "dashboards" + } + ], + "panels": [ + { + "aliasColors": { + "% Throttled": "yellow", + "% Used": "blue", + "Limit": "red", + "Process count": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": {}, + "custom": {}, + "thresholds": { + "mode": "absolute", + "steps": [] + }, + "unit": "short" + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 11, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Limit", + "dashes": true + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg((idelta(ccp_nodemx_cpuacct_usage{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[30s])/1000000000)/idelta(ccp_nodemx_cpuacct_usage_ts{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[30s])*100) without(instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "% Usage", + "refId": "A" + }, + { + "expr": "avg((ccp_nodemx_cpucfs_quota_us{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}*100/ccp_nodemx_cpucfs_period_us{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"})) without (instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Limit", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "Percent", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "Process count", + "logBase": 1, + "max": null, + "min": "0", + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "% Throttled": "yellow", + "% Used": "blue", + "Limit": "red", + "Process count": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": {}, + "custom": {}, + "thresholds": { + "mode": "absolute", + "steps": [] + }, + "unit": "short" + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 15, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Limit", + "dashes": true + }, + { + "alias": "Process count", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(ccp_nodemx_process_count{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Process count", + "refId": "B" + }, + { + "expr": "avg((idelta(ccp_nodemx_cpustat_throttled_time{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[30s])/1000000000)/idelta(ccp_nodemx_cpustat_snap_ts{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[30s])*100) without (instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "% Throttled", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Throttle", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "Process count", + "logBase": 1, + "max": null, + "min": "0", + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Inactive anon": "super-light-purple", + "Limit": "red", + "Mem free": "green", + "Request": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Limit", + "dashes": true + }, + { + "alias": "Request", + "dashes": true + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(ccp_nodemx_mem_limit{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Limit", + "refId": "A" + }, + { + "expr": "avg(ccp_nodemx_mem_request{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Request", + "refId": "B" + }, + { + "expr": "avg(ccp_nodemx_mem_usage_in_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Usage", + "refId": "J" + }, + { + "expr": "avg(clamp_min((ccp_nodemx_mem_limit{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"} - ccp_nodemx_mem_usage_in_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}),0)) without (instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Free", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/tx bytes/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(ccp_nodemx_network_rx_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\", interface!=\"tunl0\"}[1m])) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{interface}} - rx bytes", + "refId": "A" + }, + { + "expr": "avg(rate(ccp_nodemx_network_tx_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\", interface!=\"tunl0\"}[1m])) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{interface}} - tx bytes", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 6 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg((ccp_nodemx_data_disk_total_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}-ccp_nodemx_data_disk_available_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})*100/ccp_nodemx_data_disk_total_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mount_point}}", + "refId": "A" + }, + { + "expr": "avg((ccp_nodemx_data_disk_total_file_nodes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}-ccp_nodemx_data_disk_free_file_nodes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})*100/ccp_nodemx_data_disk_total_file_nodes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mount_point}} - Inodes", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 6 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Reads/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(ccp_nodemx_disk_activity_sectors_read{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[1m])*512) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mount_point}} - Reads", + "refId": "A" + }, + { + "expr": "avg(rate(ccp_nodemx_disk_activity_sectors_written{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[1m])*512) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mount_point}} - Writes ", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Activity", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Inactive anon": "super-light-purple", + "Limit": "red", + "Request": "green" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 12 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(ccp_nodemx_mem_cache{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Cached", + "refId": "C" + }, + { + "expr": "avg(ccp_nodemx_mem_dirty{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Dirty", + "refId": "D" + }, + { + "expr": "avg(ccp_nodemx_mem_shmem{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "shared mem", + "refId": "E" + }, + { + "expr": "avg(ccp_nodemx_mem_rss{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "F" + }, + { + "expr": "avg(ccp_nodemx_mem_mapped_file{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Mapped file", + "refId": "G" + }, + { + "expr": "avg(ccp_nodemx_mem_kmem_usage_in_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "kmem", + "refId": "H" + }, + { + "expr": "avg(ccp_nodemx_mem_inactive_anon{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Inactive anon", + "refId": "I" + }, + { + "expr": "avg(ccp_nodemx_mem_active_file{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Active file", + "refId": "J" + }, + { + "expr": "avg(ccp_nodemx_mem_inactive_file{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Inactive file", + "refId": "K" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Breakdown", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "CPU limit": "red", + "CPU request": "blue", + "Memory limit": "dark-red", + "Memory request": "dark-green" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 12 + }, + "hiddenSeries": false, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "CPU request", + "yaxis": 2 + }, + { + "alias": "CPU limit", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(ccp_nodemx_cpu_limit{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU limit", + "refId": "A" + }, + { + "expr": "avg(ccp_nodemx_cpu_request{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU request", + "refId": "B" + }, + { + "expr": "avg(ccp_nodemx_mem_limit{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Memory limit", + "refId": "C" + }, + { + "expr": "avg(ccp_nodemx_mem_request{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Memory request", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Container resources", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Memory", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "CPU (millicores)", + "logBase": 1, + "max": null, + "min": "0", + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "5s", + "schemaVersion": 27, + "style": "dark", + "tags": [ + "vendor=crunchydata" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(pg_cluster)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(pg_cluster)", + "refId": "PROMETHEUS-cluster-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values({pg_cluster=\"[[cluster]]\"},pod)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "pod", + "multi": false, + "name": "pod", + "options": [], + "query": { + "query": "label_values({pg_cluster=\"[[cluster]]\"},pod)", + "refId": "PROMETHEUS-pod-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "POD Details", + "uid": "4auP6Mk7k", + "version": 1 +} diff --git a/kustomize/monitoring/dashboards/pod_details2.json b/kustomize/monitoring/dashboards/pod_details2.json new file mode 100644 index 00000000..71026c1e --- /dev/null +++ b/kustomize/monitoring/dashboards/pod_details2.json @@ -0,0 +1,1066 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1624642171995, + "links": [ + { + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "vendor=crunchydata" + ], + "type": "dashboards" + } + ], + "panels": [ + { + "aliasColors": { + "% Throttled": "yellow", + "% Used": "blue", + "Limit": "red", + "Process count": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": {}, + "custom": {}, + "thresholds": { + "mode": "absolute", + "steps": [] + }, + "unit": "short" + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 11, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Process count", + "yaxis": 2 + }, + { + "alias": "Limit", + "dashes": true + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg((idelta(ccp_nodemx_cpuacct_usage{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[30s])/1000000000)/idelta(ccp_nodemx_cpuacct_usage_ts{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[30s])*100) without(instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "% Usage", + "refId": "A" + }, + { + "expr": "avg(ccp_nodemx_process_count{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Process count", + "refId": "B" + }, + { + "expr": "avg((idelta(ccp_nodemx_cpustat_throttled_time{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[30s])/1000000000)/idelta(ccp_nodemx_cpustat_snap_ts{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[30s])*100) without (instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "% Throttled", + "refId": "C" + }, + { + "expr": "avg((ccp_nodemx_cpucfs_quota_us{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}*100/ccp_nodemx_cpucfs_period_us{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"})) without (instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Limit", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "Percent", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "Process count", + "logBase": 1, + "max": null, + "min": "0", + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Inactive anon": "super-light-purple", + "Limit": "red", + "Mem free": "green", + "Request": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 0 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Limit", + "dashes": true + }, + { + "alias": "Request", + "dashes": true + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(ccp_nodemx_mem_limit{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Limit", + "refId": "A" + }, + { + "expr": "avg(ccp_nodemx_mem_request{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Request", + "refId": "B" + }, + { + "expr": "avg(ccp_nodemx_mem_usage_in_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Usage", + "refId": "J" + }, + { + "expr": "avg(clamp_min((ccp_nodemx_mem_limit{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"} - ccp_nodemx_mem_usage_in_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}),0)) without (instance,ip,role)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Free", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 0 + }, + "hiddenSeries": false, + "id": 8, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/tx bytes/", + "transform": "negative-Y" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(ccp_nodemx_network_rx_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\", interface!=\"tunl0\"}[1m])) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{interface}} - rx bytes", + "refId": "A" + }, + { + "expr": "avg(rate(ccp_nodemx_network_tx_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\", interface!=\"tunl0\"}[1m])) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{interface}} - tx bytes", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg((ccp_nodemx_data_disk_total_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}-ccp_nodemx_data_disk_available_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})*100/ccp_nodemx_data_disk_total_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mount_point}}", + "refId": "A" + }, + { + "expr": "avg((ccp_nodemx_data_disk_total_file_nodes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}-ccp_nodemx_data_disk_free_file_nodes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})*100/ccp_nodemx_data_disk_total_file_nodes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mount_point}} - Inodes", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percent", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 6 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(rate(ccp_nodemx_disk_activity_sectors_read{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[1m])*512) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mount_point}} - Reads", + "refId": "A" + }, + { + "expr": "avg(rate(ccp_nodemx_disk_activity_sectors_written{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}[1m])*512) without(instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{mount_point}} - Writes ", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Activity", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Inactive anon": "super-light-purple", + "Limit": "red", + "Request": "green" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 12 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(ccp_nodemx_mem_cache{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Cached", + "refId": "C" + }, + { + "expr": "avg(ccp_nodemx_mem_dirty{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Dirty", + "refId": "D" + }, + { + "expr": "avg(ccp_nodemx_mem_shmem{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "shared mem", + "refId": "E" + }, + { + "expr": "avg(ccp_nodemx_mem_rss{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "RSS", + "refId": "F" + }, + { + "expr": "avg(ccp_nodemx_mem_mapped_file{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Mapped file", + "refId": "G" + }, + { + "expr": "avg(ccp_nodemx_mem_kmem_usage_in_bytes{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "kmem", + "refId": "H" + }, + { + "expr": "avg(ccp_nodemx_mem_inactive_anon{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Inactive anon", + "refId": "I" + }, + { + "expr": "avg(ccp_nodemx_mem_active_file{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Active file", + "refId": "J" + }, + { + "expr": "avg(ccp_nodemx_mem_inactive_file{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Inactive file", + "refId": "K" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Breakdown", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "CPU limit": "red", + "CPU request": "blue", + "Memory limit": "dark-red", + "Memory request": "dark-green" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 12 + }, + "hiddenSeries": false, + "id": 13, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "CPU request", + "yaxis": 2 + }, + { + "alias": "CPU limit", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "avg(ccp_nodemx_cpu_limit{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU limit", + "refId": "A" + }, + { + "expr": "avg(ccp_nodemx_cpu_request{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "CPU request", + "refId": "B" + }, + { + "expr": "avg(ccp_nodemx_mem_limit{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Memory limit", + "refId": "C" + }, + { + "expr": "avg(ccp_nodemx_mem_request{pg_cluster=\"[[cluster]]\",pod=\"[[pod]]\"}) without (instance,ip,role)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Memory request", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Container resources", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "Memory", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": "CPU (millicores)", + "logBase": 1, + "max": null, + "min": "0", + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "5s", + "schemaVersion": 27, + "style": "dark", + "tags": [ + "vendor=crunchydata" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(pg_cluster)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(pg_cluster)", + "refId": "PROMETHEUS-cluster-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values({pg_cluster=\"[[cluster]]\"},pod)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "pod", + "multi": false, + "name": "pod", + "options": [], + "query": { + "query": "label_values({pg_cluster=\"[[cluster]]\"},pod)", + "refId": "PROMETHEUS-pod-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "POD Details", + "uid": "wLzsuGznz", + "version": 1 +} diff --git a/kustomize/monitoring/dashboards/postgres_overview.json b/kustomize/monitoring/dashboards/postgres_overview.json new file mode 100644 index 00000000..145f2d2f --- /dev/null +++ b/kustomize/monitoring/dashboards/postgres_overview.json @@ -0,0 +1,237 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": false, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1624491413218, + "links": [], + "panels": [ + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "links": [ + { + "targetBlank": true, + "title": "Cluster Details", + "url": "dashboard/db/postgresqldetails?$__all_variables" + }, + { + "targetBlank": true, + "title": "Backup Details", + "url": "dashboard/db/pgbackrest?$__all_variables" + }, + { + "targetBlank": true, + "title": "POD Details", + "url": "dashboard/db/pod-details?$__all_variables" + }, + { + "targetBlank": true, + "title": "Query Statistics", + "url": "dashboard/db/query-statistics?$__all_variables" + }, + { + "targetBlank": true, + "title": "Service Health", + "url": "dashboard/db/postgresql-service-health?$__all_variables" + } + ], + "mappings": [ + { + "from": "0", + "id": 0, + "text": "DOWN", + "to": "99", + "type": 2 + }, + { + "from": "100", + "id": 1, + "text": "Standalone Cluster", + "to": "199", + "type": 2 + }, + { + "from": "200", + "id": 2, + "text": "HA CLUSTER", + "to": "1000", + "type": 2 + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#bf1b00", + "value": null + }, + { + "color": "#eab839", + "value": 10 + }, + { + "color": "#56A64B", + "value": 100 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "interval": null, + "links": [], + "maxDataPoints": 100, + "maxPerRow": 2, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "text": { + "valueSize": 30 + }, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "repeat": "cluster", + "repeatDirection": "h", + "targets": [ + { + "$hashKey": "object:243", + "expr": "sum(pg_up{pg_cluster=~\"$cluster\"})*100+sum(ccp_is_in_recovery_status{pg_cluster=~\"$cluster\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{cluster}}", + "metric": "up", + "refId": "A", + "step": 2 + } + ], + "title": "$cluster - Overview", + "type": "stat" + } + ], + "refresh": "5m", + "schemaVersion": 27, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allFormat": "glob", + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(pg_cluster)", + "description": null, + "error": null, + "hide": 1, + "includeAll": true, + "label": "cluster", + "multi": true, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(pg_cluster)", + "refId": "PROMETHEUS-cluster-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "PostgreSQL Overview", + "uid": "D2X39SlGk", + "version": 1 +} diff --git a/kustomize/monitoring/dashboards/postgresql_details.json b/kustomize/monitoring/dashboards/postgresql_details.json new file mode 100644 index 00000000..404b30c9 --- /dev/null +++ b/kustomize/monitoring/dashboards/postgresql_details.json @@ -0,0 +1,2148 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1624495934950, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "vendor=crunchydata" + ], + "title": "", + "type": "dashboards" + } + ], + "panels": [ + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "links": [ + { + "title": "pgBackrest", + "url": "/dashboard/db/pgbackrest?${__all_variables}" + } + ], + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#56A64B", + "value": null + }, + { + "color": "#FF9830", + "value": 86400 + }, + { + "color": "#E02F44", + "value": 172800 + } + ] + }, + "unit": "dtdurations" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 27, + "interval": null, + "links": [ + { + "title": "pgBackRest", + "url": "/dashboard/db/pgbackrest?${__all_variables}" + } + ], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "min" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "min(ccp_backrest_last_incr_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\"} < ccp_backrest_last_diff_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\"} or ccp_backrest_last_incr_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\"} < ccp_backrest_last_full_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\"} or ccp_backrest_last_incr_backup_time_since_completion_seconds{pg_cluster=\"[[cluster]]\"}) ", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "[[cluster]] : Backup Status", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 70 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 0, + "y": 2 + }, + "id": 8, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(pg_stat_activity_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\", state=\"active\"})*100 /sum(pg_settings_max_connections{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "hide": false, + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "metric": "pg_stat_activity_count", + "refId": "A", + "step": 10 + } + ], + "title": "Active Connections", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 10 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 30 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 4, + "y": 2 + }, + "id": 2, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(pg_stat_activity_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",state=\"idle in transaction\"})/sum(pg_settings_max_connections{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + } + ], + "title": "Idle In Transaction", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 1200, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 300 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 900 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 8, + "y": 2 + }, + "id": 34, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "max(abs(ccp_connection_stats_max_idle_in_txn_time{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}))", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "B" + } + ], + "title": "Max Idle In Transaction Time", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 60 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 12, + "y": 2 + }, + "id": 3, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(pg_stat_activity_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",state=\"idle\"})*100/sum(pg_settings_max_connections{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "metric": "pg_stat_activity_count", + "refId": "A", + "step": 10 + } + ], + "title": "Idle", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 60 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 80 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 16, + "y": 2 + }, + "id": 32, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "max(ccp_transaction_wraparound_percent_towards_wraparound{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "metric": "pg_stat_activity_count", + "refId": "A", + "step": 10 + } + ], + "title": "% Toward Wraparound", + "type": "gauge" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#E02F44", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 80 + }, + { + "color": "#56A64B", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 20, + "y": 2 + }, + "id": 33, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "text": {} + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(ccp_stat_database_blks_hit{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})*100/sum(ccp_stat_database_blks_hit{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}+ccp_stat_database_blks_read{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "metric": "pg_stat_activity_count", + "refId": "A", + "step": 10 + } + ], + "title": "Cache Hit Ratio", + "type": "gauge" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(ccp_stat_database_xact_commit{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m])) + sum(irate(ccp_stat_database_xact_rollback{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Transactions", + "metric": "ccp_stat_database_tup_fetched", + "refId": "A", + "step": 2 + }, + { + "expr": "sum(irate(ccp_pg_stat_statements_total_calls_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Queries", + "metric": "ccp_stat_database_tup_fetched", + "refId": "B", + "step": 2 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Activity - [[pod]]-[[datname]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 7 + }, + "hiddenSeries": false, + "id": 26, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (state) (pg_stat_activity_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",state=\"idle\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "idle", + "metric": "ccp_stat_database_tup_fetched", + "refId": "A", + "step": 2 + }, + { + "expr": "sum by (state) (pg_stat_activity_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",state=\"idle in transaction\"})", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Idle in txn", + "refId": "B" + }, + { + "expr": "sum by (state) (pg_stat_activity_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",state=\"active\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "active", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Connections - [[pod]]-[[datname]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 13 + }, + "hiddenSeries": false, + "id": 12, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(ccp_database_size_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})/(1024*1024)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Total : [[cluster]]-[[pod]]", + "refId": "B" + }, + { + "expr": "ccp_database_size_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",dbname=~\"[[datname]]\"}/(1024*1024)", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{dbname}} ({{pod}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "database size - [[pod]]-[[datname]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decmbytes", + "label": null, + "logBase": 2, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Max: ccp_monitoring(postgres)": "red" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 13 + }, + "hiddenSeries": false, + "id": 31, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Max:/", + "color": "#FF9830" + }, + { + "alias": "/Avg:/", + "color": "#5794F2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(ccp_pg_stat_statements_total_mean_exec_time_ms{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\", dbname=~\"[[datname]]\"}) without (instance,ip)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Avg: {{exported_role}}({{dbname}})", + "metric": "ccp_stat_database_tup_fetched", + "refId": "A", + "step": 2 + }, + { + "expr": "max(ccp_pg_stat_statements_top_max_exec_time_ms{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",dbname=~\"[[datname]]\"}) without (instance,ip,query,queryid)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Max: {{exported_role}}({{dbname}})", + "metric": "ccp_stat_database_tup_fetched", + "refId": "B", + "step": 2 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Query Duration - [[pod]]-[[datname]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 19 + }, + "hiddenSeries": false, + "id": 11, + "interval": "", + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(ccp_stat_database_tup_fetched{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Fetched", + "metric": "ccp_stat_database_tup_fetched", + "refId": "A", + "step": 2 + }, + { + "expr": "sum(irate(ccp_stat_database_tup_inserted{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Inserted", + "metric": "ccp_stat_database_tup_inserted", + "refId": "B", + "step": 2 + }, + { + "expr": "sum(irate(ccp_stat_database_tup_updated{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Updated", + "metric": "ccp_stat_database_tup_updated", + "refId": "C", + "step": 2 + }, + { + "expr": "sum(irate(ccp_stat_database_tup_deleted{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Deleted", + "metric": "ccp_stat_database_tup_deleted", + "refId": "D", + "step": 2 + }, + { + "expr": "sum(irate(ccp_stat_database_tup_returned{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "Returned", + "metric": "ccp_stat_database_tup_deleted", + "refId": "E", + "step": 2 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Row activity - [[pod]]-[[datname]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 19 + }, + "hiddenSeries": false, + "id": 30, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "ccp_wal_activity_total_size_bytes{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"}/(1024*1024)", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{pod}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "WAL size MB - [[cluster]]-[[pod]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "decmbytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 25 + }, + "hiddenSeries": false, + "id": 15, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Commits", + "color": "#73BF69" + }, + { + "alias": "DeadLocks", + "color": "#C4162A" + }, + { + "alias": "Conflicts", + "color": "#FF9830" + }, + { + "alias": "Rollbacks", + "color": "#FFCB7D" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(rate(ccp_stat_database_deadlocks{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "Conflicts", + "metric": "ccp_stat_database_conflicts", + "refId": "A", + "step": 2 + }, + { + "expr": "sum(rate(ccp_stat_database_conflicts{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "DeadLocks", + "metric": "ccp_stat_database_deadlocks", + "refId": "B", + "step": 2 + }, + { + "expr": "sum(irate(ccp_stat_database_xact_commit{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Commits", + "metric": "ccp_stat_database_deadlocks", + "refId": "C", + "step": 2 + }, + { + "expr": "sum(irate(ccp_stat_database_xact_rollback{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\"}[5m]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Rollbacks", + "metric": "ccp_stat_database_deadlocks", + "refId": "D", + "step": 2 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Key Counters - [[pod]] - [[datname]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 25 + }, + "hiddenSeries": false, + "id": 29, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Time/", + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": false, + "expr": "ccp_replication_lag_size_bytes{pg_cluster=\"[[cluster]]\", role!=\"replica\"}", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Bytes ({{replica}})", + "refId": "B" + }, + { + "expr": "ccp_replication_lag_replay_time{pg_cluster=\"[[cluster]]\", role=\"replica\"}", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Time ({{ip}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Replication Lag - [[cluster]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Lag bytes", + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "dtdhms", + "label": "Lag time (hh:mm:ss)", + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 31 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(ccp_stat_bgwriter_buffers_alloc{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Allocated", + "metric": "pg_stat_bgwriter_buffers_alloc", + "refId": "A", + "step": 2 + }, + { + "expr": "sum(ccp_stat_bgwriter_buffers_backend{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Backend", + "metric": "pg_stat_bgwriter_buffers_backend", + "refId": "B", + "step": 2 + }, + { + "expr": "sum(ccp_stat_bgwriter_buffers_backend_fsync{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "FSync", + "metric": "pg_stat_bgwriter_buffers_backend_fsync", + "refId": "C", + "step": 2 + }, + { + "expr": "sum(ccp_stat_bgwriter_buffers_checkpoint{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "CheckPoint", + "metric": "pg_stat_bgwriter_buffers_checkpoint", + "refId": "D", + "step": 2 + }, + { + "expr": "sum(ccp_stat_bgwriter_buffers_clean{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "Clean", + "metric": "pg_stat_bgwriter_buffers_clean", + "refId": "E", + "step": 2 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Buffers - [[pod]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 31 + }, + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum by (mode) (ccp_locks_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",mode=\"accessexclusivelock\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{mode}}", + "refId": "A", + "step": 2 + }, + { + "expr": "sum by (mode) (ccp_locks_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",mode=\"exclusivelock\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{mode}}", + "refId": "C", + "step": 2 + }, + { + "expr": "sum by (mode) (ccp_locks_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",mode=\"rowexclusivelock\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{mode}}", + "refId": "D", + "step": 2 + }, + { + "expr": "sum by (mode) (ccp_locks_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",mode=\"sharerowexclusivelock\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{mode}}", + "refId": "G", + "step": 2 + }, + { + "expr": "sum by (mode) (ccp_locks_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",mode=\"shareupdateexclusivelock\"})", + "format": "time_series", + "hide": false, + "intervalFactor": 2, + "legendFormat": "{{mode}}", + "refId": "H", + "step": 2 + }, + { + "expr": "sum by (mode) (ccp_locks_count{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",datname=~\"[[datname]]\",mode=\"accesssharelock\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{mode}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Locks - [[pod]]-[[datname]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 6, + "w": 12, + "x": 12, + "y": 37 + }, + "hiddenSeries": false, + "id": 28, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "ccp_stat_database_blks_hit{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\", dbname!~\"template0\", dbname!~\"template1\"}*100/(ccp_stat_database_blks_hit{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\", dbname!~\"template0\", dbname!~\"template1\"} + ccp_stat_database_blks_read{pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\",dbname!~\"template0\", dbname!~\"template1\"})", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 2, + "legendFormat": "{{dbname}} - ({{pod}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cache Hit Ratio - [[pod]]-[[datname]]", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "percent", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "5s", + "schemaVersion": 27, + "style": "dark", + "tags": [ + "vendor=crunchydata" + ], + "templating": { + "list": [ + { + "allFormat": "glob", + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(pg_cluster)", + "refId": "PROMETHEUS-cluster-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allFormat": "glob", + "allValue": ".*", + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values({pg_cluster=\"[[cluster]]\"},pod)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "pod", + "multi": true, + "name": "pod", + "options": [], + "query": { + "query": "label_values({pg_cluster=\"[[cluster]]\"},pod)", + "refId": "PROMETHEUS-pod-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allFormat": "glob", + "allValue": ".*", + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values({pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"},dbname)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "Database", + "multi": true, + "name": "datname", + "options": [], + "query": { + "query": "label_values({pg_cluster=\"[[cluster]]\",pod=~\"[[pod]]\"},dbname)", + "refId": "PROMETHEUS-datname-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "PostgreSQLDetails", + "uid": "pc4NNgknk", + "version": 1 +} diff --git a/kustomize/monitoring/dashboards/postgresql_service_health.json b/kustomize/monitoring/dashboards/postgresql_service_health.json new file mode 100644 index 00000000..929ea787 --- /dev/null +++ b/kustomize/monitoring/dashboards/postgresql_service_health.json @@ -0,0 +1,649 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1624491530019, + "links": [ + { + "asDropdown": false, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "vendor=crunchydata" + ], + "title": "", + "type": "dashboards" + } + ], + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 5, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 6, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(ccp_connection_stats_total{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip) / sum(ccp_connection_stats_max_connections{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip)", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Connections", + "refId": "C" + }, + { + "expr": "100 - 100 * avg(ccp_nodemx_data_disk_available_bytes{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip) / avg(ccp_nodemx_data_disk_total_bytes{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Mount:{{mount_point}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Saturation (pct used)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "percent", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "cacheTimeout": null, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 5, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 0 + }, + "hiddenSeries": false, + "id": 18, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "exemplar": false, + "expr": " sum(irate(ccp_stat_database_xact_commit{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m])) \n+ sum(irate(ccp_stat_database_xact_rollback{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m]))", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Transactions", + "refId": "A" + }, + { + "expr": "max(ccp_connection_stats_active{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip,dbname)", + "format": "time_series", + "interval": "", + "intervalFactor": 1, + "legendFormat": "Active connections", + "refId": "C" + }, + { + "expr": "sum(irate(ccp_pg_stat_statements_total_calls_count{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m]))", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Queries", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Traffic", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "", + "logBase": 1, + "max": null, + "min": "0.001", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "description": "Errors", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 5, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(ccp_stat_database_xact_rollback{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m]) without(pod,instance,ip))", + "format": "time_series", + "hide": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Rollbacks", + "refId": "A" + }, + { + "expr": "sum(irate(ccp_stat_database_deadlocks{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m])) without(pod,instance,ip,dbname)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Deadlock ", + "refId": "D" + }, + { + "expr": "sum(irate(ccp_stat_database_conflicts{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}[1m])) without(pod,instance,ip,dbname)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Conflicts", + "refId": "B" + }, + { + "expr": "max(pg_exporter_last_scrape_error{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without(pod,instance,ip,dbname)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "scrape error", + "refId": "C" + }, + { + "expr": "max(clamp_max(ccp_archive_command_status_seconds_since_last_fail{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"},1)) without (instance,pod,ip)", + "format": "time_series", + "hide": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "archive error", + "refId": "E" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Errors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "short", + "label": "", + "logBase": 2, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 1, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 7 + }, + "hiddenSeries": false, + "id": 10, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 150, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/Max:/", + "color": "#E02F44", + "nullPointMode": "null as zero" + }, + { + "alias": "/Avg:/", + "color": "#8AB8FF" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(ccp_pg_stat_statements_total_mean_exec_time_ms{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Avg: {{exported_role}}({{dbname}})", + "refId": "A" + }, + { + "expr": "max(ccp_pg_stat_statements_top_max_exec_time_ms{pg_cluster=\"[[cluster]]\",role=\"[[role]]\"}) without (pod,instance,ip,query,queryid)", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Max: {{exported_role}}({{dbname}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Query Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "ms", + "label": null, + "logBase": 2, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "5m", + "schemaVersion": 27, + "style": "dark", + "tags": [ + "vendor=crunchydata" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(pg_cluster)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(pg_cluster)", + "refId": "PROMETHEUS-cluster-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values({pg_cluster=\"[[cluster]]\"},role)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "role", + "options": [], + "query": { + "query": "label_values({pg_cluster=\"[[cluster]]\"},role)", + "refId": "PROMETHEUS-role-Variable-Query" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "PostgreSQL Service Health", + "uid": "dhG1wgsMz", + "version": 1 +} diff --git a/kustomize/monitoring/dashboards/prometheus_alerts.json b/kustomize/monitoring/dashboards/prometheus_alerts.json new file mode 100644 index 00000000..83e6ea06 --- /dev/null +++ b/kustomize/monitoring/dashboards/prometheus_alerts.json @@ -0,0 +1,961 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Show current firing and pending alerts, and severity alert counts.", + "editable": false, + "gnetId": 4181, + "graphTooltip": 0, + "id": null, + "links": [ + { + "icon": "external link", + "tags": [ + "vendor=crunchydata" + ], + "type": "dashboards" + } + ], + "panels": [ + { + "collapsed": false, + "datasource": "PROMETHEUS", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 10, + "panels": [], + "repeat": null, + "title": "Environment Summary", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 6, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "count(count by (kubernetes_namespace) (pg_up))", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "Namespaces", + "refId": "A" + } + ], + "title": "Namespaces", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 13, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "count(count by (pg_cluster) (pg_up))", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "PostgreSQL Clusters", + "refId": "A" + } + ], + "title": "PG Clusters", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 8, + "y": 1 + }, + "id": 14, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "count(pg_up)", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "PostgreSQL Clusters", + "refId": "A" + } + ], + "title": "PG Instances", + "type": "stat" + }, + { + "collapsed": false, + "datasource": "PROMETHEUS", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 11, + "panels": [], + "repeat": null, + "title": "Alert Summary", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-red", + "value": null + }, + { + "color": "#F2495C", + "value": 1 + }, + { + "color": "#F2495C" + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 0, + "y": 4 + }, + "id": 2, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "bucketAggs": [ + { + "id": "2", + "settings": { + "interval": "auto", + "min_doc_count": 0, + "trimEdges": 0 + }, + "type": "date_histogram" + } + ], + "dsType": "elasticsearch", + "expr": "sum(ALERTS{alertstate=\"firing\",severity=\"critical\"} > 0) OR on() vector(0)", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "Critical", + "metrics": [ + { + "field": "select field", + "id": "1", + "type": "count" + } + ], + "refId": "A" + } + ], + "title": "Critical", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-orange", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 4, + "y": 4 + }, + "id": 5, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(ALERTS{alertstate=\"firing\",severity=\"warning\"} > 0) OR on() vector(0)", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Warning", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#299c46", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 4, + "x": 8, + "y": 4 + }, + "id": 9, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(ALERTS{alertstate=\"firing\",severity=\"info\"} > 0) OR on() vector(0)", + "format": "time_series", + "interval": "", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Info", + "type": "stat" + }, + { + "collapsed": false, + "datasource": "PROMETHEUS", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 12, + "panels": [], + "repeat": null, + "title": "Alerts", + "type": "row" + }, + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "displayMode": "auto", + "filterable": true + }, + "decimals": 2, + "displayName": "", + "mappings": [ + { + "from": "", + "id": 1, + "text": "", + "to": "", + "type": 1, + "value": "" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "blue", + "value": 100 + }, + { + "color": "#EAB839", + "value": 200 + }, + { + "color": "red", + "value": 300 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "severity_num" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "custom.width", + "value": 124 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.width", + "value": 170 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "severity" + }, + "properties": [ + { + "id": "custom.width", + "value": 119 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "alertname" + }, + "properties": [ + { + "id": "custom.width", + "value": 206 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "alertstate" + }, + "properties": [ + { + "id": "custom.width", + "value": 128 + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 1, + "links": [], + "options": { + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "ALERTS{alertstate='firing'} > 0", + "format": "table", + "instant": true, + "interval": "2s", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Firing", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Value": true, + "__name__": true, + "alertstate": false, + "deployment": false, + "exp_type": true, + "fs_type": true, + "instance": true, + "job": true, + "kubernetes_namespace": true, + "mount_point": true, + "server": true, + "service": true, + "severity_num": false + }, + "indexByName": { + "Time": 0, + "Value": 16, + "__name__": 3, + "alertname": 4, + "alertstate": 5, + "deployment": 7, + "exp_type": 9, + "instance": 10, + "ip": 11, + "job": 12, + "kubernetes_namespace": 13, + "pg_cluster": 6, + "pod": 8, + "role": 14, + "service": 15, + "severity": 2, + "severity_num": 1 + }, + "renameByName": { + "Time": "", + "__name__": "", + "severity": "", + "severity_num": "" + } + } + } + ], + "type": "table" + }, + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": null, + "filterable": true + }, + "decimals": 2, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/(instance|__name__|Time|alertstate|job|type|Value)/" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.width", + "value": null + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "severity_num" + }, + "properties": [ + { + "id": "custom.width", + "value": 126 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "severity" + }, + "properties": [ + { + "id": "custom.width", + "value": 115 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "alertname" + }, + "properties": [ + { + "id": "custom.width", + "value": 207 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "alertstate" + }, + "properties": [ + { + "id": "custom.width", + "value": 131 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 3, + "links": [], + "options": { + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "ALERTS{alertstate=\"pending\"}", + "format": "table", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Alerts (1 week)", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Value": true, + "__name__": true, + "exp_type": true, + "instance": true, + "job": true, + "kubernetes_namespace": true, + "service": true + }, + "indexByName": { + "Time": 0, + "Value": 16, + "__name__": 3, + "alertname": 4, + "alertstate": 5, + "deployment": 7, + "exp_type": 8, + "instance": 9, + "ip": 11, + "job": 12, + "kubernetes_namespace": 13, + "pg_cluster": 6, + "pod": 10, + "role": 14, + "service": 15, + "severity": 2, + "severity_num": 1 + }, + "renameByName": {} + } + } + ], + "type": "table" + } + ], + "refresh": "15m", + "schemaVersion": 27, + "style": "dark", + "tags": [ + "vendor=crunchydata" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": { + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Prometheus Alerts", + "uid": "lwxXsZsMk", + "version": 1 +} diff --git a/kustomize/monitoring/dashboards/query_statistics.json b/kustomize/monitoring/dashboards/query_statistics.json new file mode 100644 index 00000000..88c64db5 --- /dev/null +++ b/kustomize/monitoring/dashboards/query_statistics.json @@ -0,0 +1,1061 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.5" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "", + "editable": false, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1624501789811, + "links": [ + { + "icon": "external link", + "tags": [ + "vendor=crunchydata" + ], + "type": "dashboards" + } + ], + "panels": [ + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 0, + "y": 0 + }, + "id": 8, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(sum_over_time(ccp_pg_stat_statements_total_calls_count{pg_cluster=\"[[cluster]]\", role=\"[[role]]\",dbname=~\"[[dbname]]\",exported_role=~\"[[dbuser]]\"}[$__range])) without(instance, ip, deployment,pod,dbname,exported_role)", + "instant": false, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Queries Executed", + "type": "stat" + }, + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 5, + "y": 0 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(sum_over_time(ccp_pg_stat_statements_total_exec_time_ms{pg_cluster=\"[[cluster]]\", role=\"[[role]]\",dbname=~\"[[dbname]]\",exported_role=~\"[[dbuser]]\"}[$__range])) without(instance, ip, deployment,pod,dbname,exported_role)", + "format": "time_series", + "instant": false, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Query Runtime ", + "type": "stat" + }, + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 11, + "y": 0 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "avg(sum_over_time(ccp_pg_stat_statements_total_mean_exec_time_ms{pg_cluster=\"[[cluster]]\", role=\"[[role]]\",dbname=~\"[[dbname]]\",exported_role=~\"[[dbuser]]\"}[$__range])) without(instance, ip, deployment,pod,dbname,exported_role)", + "format": "time_series", + "instant": false, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Query Mean Runtime", + "type": "stat" + }, + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 17, + "y": 0 + }, + "id": 11, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "value" + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(sum_over_time(ccp_pg_stat_statements_total_row_count{pg_cluster=\"[[cluster]]\", role=\"[[role]]\",dbname=~\"[[dbname]]\",exported_role=~\"[[dbuser]]\"}[$__range])) without(instance, ip, deployment, pod,dbname,exported_role)", + "format": "time_series", + "instant": false, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Rows Retrieved or Affected", + "type": "stat" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 23, + "x": 0, + "y": 3 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.4.5", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(ccp_pg_stat_statements_total_calls_count{pg_cluster=\"[[cluster]]\", role=\"[[role]]\",dbname=~\"[[dbname]]\",exported_role=~\"[[dbuser]]\"}[$__range])) without(instance, ip, deployment, pod)", + "instant": false, + "interval": "", + "legendFormat": "db: {{dbname}}, user: {{exported_role}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Query Executions", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "displayMode": "auto", + "filterable": false + }, + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Runtime" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "thresholds", + "value": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 90 + } + ] + } + }, + { + "id": "custom.width", + "value": 169 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "queryid" + }, + "properties": [ + { + "id": "custom.width", + "value": 189 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "query" + }, + "properties": [ + { + "id": "custom.width", + "value": 308 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "role" + }, + "properties": [ + { + "id": "custom.width", + "value": 82 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "dbname" + }, + "properties": [ + { + "id": "custom.width", + "value": 184 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 23, + "x": 0, + "y": 10 + }, + "id": 4, + "options": { + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Runtime" + } + ] + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "avg(avg_over_time(ccp_pg_stat_statements_top_mean_exec_time_ms{pg_cluster=\"[[cluster]]\", role=\"[[role]]\",dbname=~\"[[dbname]]\",exported_role=~\"[[dbuser]]\"}[$__range])) without(instance, ip, deployment,pod)", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Query Mean Runtime (Top N)", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "__name__": true, + "exp_type": true, + "job": true, + "kubernetes_namespace": true, + "queryid": false, + "role": false, + "server": true + }, + "indexByName": { + "Time": 6, + "Value": 5, + "__name__": 7, + "dbname": 0, + "exp_type": 8, + "instance": 2, + "job": 9, + "query": 3, + "queryid": 4, + "role": 1 + }, + "renameByName": { + "Value": "Runtime" + } + } + } + ], + "type": "table" + }, + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "displayMode": "auto", + "filterable": false + }, + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Runtime" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "thresholds", + "value": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 90 + } + ] + } + }, + { + "id": "custom.width", + "value": 170 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "dbname" + }, + "properties": [ + { + "id": "custom.width", + "value": 184 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "role" + }, + "properties": [ + { + "id": "custom.width", + "value": 82 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "query" + }, + "properties": [ + { + "id": "custom.width", + "value": 310 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "queryid" + }, + "properties": [ + { + "id": "custom.width", + "value": 186 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 23, + "x": 0, + "y": 18 + }, + "id": 6, + "options": { + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Runtime" + } + ] + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "max(max_over_time(ccp_pg_stat_statements_top_max_exec_time_ms{pg_cluster=\"[[cluster]]\", role=\"[[role]]\",dbname=~\"[[dbname]]\",exported_role=~\"[[dbuser]]\"}[$__range])) without(instance, ip, deployment,pod)", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "B" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Query Max Runtime (Top N)", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "__name__": true, + "exp_type": true, + "job": true, + "kubernetes_namespace": true, + "queryid": false, + "role": false, + "server": true + }, + "indexByName": { + "Time": 6, + "Value": 5, + "__name__": 7, + "dbname": 0, + "exp_type": 8, + "instance": 2, + "job": 9, + "query": 3, + "queryid": 4, + "role": 1 + }, + "renameByName": { + "Value": "Runtime" + } + } + } + ], + "type": "table" + }, + { + "datasource": "PROMETHEUS", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "filterable": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Runtime" + }, + "properties": [ + { + "id": "unit", + "value": "ms" + }, + { + "id": "custom.displayMode", + "value": "color-background" + }, + { + "id": "thresholds", + "value": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 90 + } + ] + } + }, + { + "id": "custom.width", + "value": 172 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "dbname" + }, + "properties": [ + { + "id": "custom.width", + "value": 182 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "role" + }, + "properties": [ + { + "id": "custom.width", + "value": 84 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "query" + }, + "properties": [ + { + "id": "custom.width", + "value": 309 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "queryid" + }, + "properties": [ + { + "id": "custom.width", + "value": 189 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 23, + "x": 0, + "y": 26 + }, + "id": 5, + "options": { + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Runtime" + } + ] + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "expr": "sum(irate(ccp_pg_stat_statements_top_total_exec_time_ms{pg_cluster=\"[[cluster]]\", role=\"[[role]]\",dbname=~\"[[dbname]]\",exported_role=~\"[[dbuser]]\"}[$__range])) without(instance, ip, deployment,pod)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Query Total Runtime (Top N)", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "__name__": true, + "exp_type": true, + "job": true, + "kubernetes_namespace": true, + "queryid": false, + "role": false, + "server": true + }, + "indexByName": { + "Time": 6, + "Value": 5, + "__name__": 7, + "dbname": 0, + "exp_type": 8, + "instance": 2, + "job": 9, + "query": 3, + "queryid": 4, + "role": 1 + }, + "renameByName": { + "Value": "Runtime" + } + } + } + ], + "type": "table" + } + ], + "refresh": "15m", + "schemaVersion": 27, + "style": "dark", + "tags": [ + "vendor=crunchydata" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(pg_cluster)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": { + "query": "label_values(pg_cluster)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values({pg_cluster=\"[[cluster]]\"},role)", + "description": null, + "error": null, + "hide": 0, + "includeAll": false, + "label": "service", + "multi": false, + "name": "role", + "options": [], + "query": { + "query": "label_values({pg_cluster=\"[[cluster]]\"},role)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(ccp_database_size_bytes{pg_cluster=\"[[cluster]]\"},dbname)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "dbname", + "multi": false, + "name": "dbname", + "options": [], + "query": { + "query": "label_values(ccp_database_size_bytes{pg_cluster=\"[[cluster]]\"},dbname)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "PROMETHEUS", + "definition": "label_values(ccp_pg_stat_statements_total_calls_count{pg_cluster=\"[[cluster]]\", dbname=~\"[[dbname]]\"},exported_role)", + "description": null, + "error": null, + "hide": 0, + "includeAll": true, + "label": "dbuser", + "multi": false, + "name": "dbuser", + "options": [], + "query": { + "query": "label_values(ccp_pg_stat_statements_total_calls_count{pg_cluster=\"[[cluster]]\", dbname=~\"[[dbname]]\"},exported_role)", + "refId": "StandardVariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Query Statistics", + "uid": "ZKoTOHDGk", + "version": 1 +} diff --git a/kustomize/monitoring/deploy-alertmanager.yaml b/kustomize/monitoring/deploy-alertmanager.yaml new file mode 100644 index 00000000..b535192d --- /dev/null +++ b/kustomize/monitoring/deploy-alertmanager.yaml @@ -0,0 +1,82 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "1" + labels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-alertmanager +spec: + progressDeadlineSeconds: 600 + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-alertmanager + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-alertmanager + spec: + containers: + - args: + - --config.file=/etc/alertmanager/alertmanager.yml + - --storage.path=/alertmanager + - --log.level=info + - --cluster.advertise-address=0.0.0.0:9093 + image: prom/alertmanager:v0.22.2 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /-/healthy + port: 9093 + scheme: HTTP + initialDelaySeconds: 25 + periodSeconds: 20 + successThreshold: 1 + timeoutSeconds: 1 + name: alertmanager + ports: + - containerPort: 9093 + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /-/ready + port: 9093 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /etc/alertmanager + name: alertmanagerconf + - mountPath: /alertmanager + name: alertmanagerdata + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: + fsGroup: 26 + # supplementalGroups : 65534 + schedulerName: default-scheduler + serviceAccount: alertmanager + serviceAccountName: alertmanager + terminationGracePeriodSeconds: 30 + volumes: + - name: alertmanagerdata + persistentVolumeClaim: + claimName: alertmanagerdata + - configMap: + defaultMode: 420 + name: alertmanager-config + name: alertmanagerconf diff --git a/kustomize/monitoring/deploy-grafana.yaml b/kustomize/monitoring/deploy-grafana.yaml new file mode 100644 index 00000000..28f9d1e1 --- /dev/null +++ b/kustomize/monitoring/deploy-grafana.yaml @@ -0,0 +1,101 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "1" + labels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-grafana +spec: + progressDeadlineSeconds: 600 + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-grafana + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-grafana + spec: + containers: + - env: + - name: GF_PATHS_DATA + value: /data/grafana/data + - name: GF_SECURITY_ADMIN_USER__FILE + value: /conf/admin/username + - name: GF_SECURITY_ADMIN_PASSWORD__FILE + value: /conf/admin/password + - name: PROM_HOST + value: crunchy-prometheus + - name: PROM_PORT + value: "9090" + image: grafana/grafana:7.4.5 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /api/health + port: 3000 + scheme: HTTP + initialDelaySeconds: 25 + periodSeconds: 20 + successThreshold: 1 + timeoutSeconds: 1 + name: grafana + ports: + - containerPort: 3000 + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /api/health + port: 3000 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /data + name: grafanadata + - mountPath: /conf/admin + name: grafana-secret + - mountPath: /etc/grafana/provisioning/datasources + name: grafana-datasources + - mountPath: /etc/grafana/provisioning/dashboards + name: grafana-dashboards + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: + fsGroup: 26 + # supplementalGroups : 65534 + schedulerName: default-scheduler + serviceAccount: grafana + serviceAccountName: grafana + terminationGracePeriodSeconds: 30 + volumes: + - name: grafanadata + persistentVolumeClaim: + claimName: grafanadata + - name: grafana-secret + secret: + defaultMode: 420 + secretName: grafana-secret + - configMap: + defaultMode: 420 + name: grafana-datasources + name: grafana-datasources + - configMap: + defaultMode: 420 + name: grafana-dashboards + name: grafana-dashboards + diff --git a/kustomize/monitoring/deploy-prometheus.yaml b/kustomize/monitoring/deploy-prometheus.yaml new file mode 100644 index 00000000..94af6295 --- /dev/null +++ b/kustomize/monitoring/deploy-prometheus.yaml @@ -0,0 +1,85 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "1" + labels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-prometheus +spec: + progressDeadlineSeconds: 600 + replicas: 1 + revisionHistoryLimit: 10 + selector: + matchLabels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-prometheus + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + creationTimestamp: null + labels: + app.kubernetes.io/name: postgres-operator-monitoring + name: crunchy-prometheus + spec: + containers: + - image: prom/prometheus:v2.27.1 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /-/healthy + port: 9090 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 20 + successThreshold: 1 + timeoutSeconds: 1 + name: prometheus + ports: + - containerPort: 9090 + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /-/ready + port: 9090 + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /etc/prometheus + name: prometheusconf + - mountPath: /prometheus + name: prometheusdata + - mountPath: /etc/prometheus/alert-rules.d + name: alertmanagerrules + dnsPolicy: ClusterFirst + securityContext: + fsGroup: 26 + # supplementalGroups : 65534 + restartPolicy: Always + schedulerName: default-scheduler + serviceAccount: prometheus-sa + serviceAccountName: prometheus-sa + terminationGracePeriodSeconds: 30 + volumes: + - configMap: + defaultMode: 420 + name: crunchy-prometheus + name: prometheusconf + - name: prometheusdata + persistentVolumeClaim: + claimName: prometheusdata + - configMap: + defaultMode: 420 + name: alertmanager-rules-config + name: alertmanagerrules + diff --git a/kustomize/monitoring/grafana-datasources.yaml b/kustomize/monitoring/grafana-datasources.yaml new file mode 100644 index 00000000..fb155488 --- /dev/null +++ b/kustomize/monitoring/grafana-datasources.yaml @@ -0,0 +1,51 @@ +apiVersion: v1 +data: + crunchy_grafana_datasource.yml: | + ### + # + # Copyright 2017-2021 Crunchy Data Solutions, Inc. All Rights Reserved. + # + ### + + # config file version + apiVersion: 1 + + # list of datasources to insert/update depending + # what's available in the database + datasources: + # name of the datasource. Required + - name: PROMETHEUS + # datasource type. Required + type: prometheus + # access mode. proxy or direct (Server or Browser in the UI). Required + access: proxy + # org id. will default to orgId 1 if not specified + orgId: 1 + # url + url: http://$PROM_HOST:$PROM_PORT + # database password, if used + password: + # database user, if used + user: + # database name, if used + database: + # enable/disable basic auth + basicAuth: + # basic auth username + basicAuthUser: + # basic auth password + basicAuthPassword: + # enable/disable with credentials headers + withCredentials: + # mark as default datasource. Max one per org + isDefault: true + version: 1 + # allow users to edit datasources from the UI. + editable: false +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: grafana-datasources + diff --git a/kustomize/monitoring/grafana-secret.yaml b/kustomize/monitoring/grafana-secret.yaml new file mode 100644 index 00000000..5fbb2755 --- /dev/null +++ b/kustomize/monitoring/grafana-secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +data: + password: YWRtaW4= + username: YWRtaW4= +kind: Secret +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: grafana-secret +type: Opaque + diff --git a/kustomize/monitoring/kustomization.yaml b/kustomize/monitoring/kustomization.yaml new file mode 100644 index 00000000..d44439d6 --- /dev/null +++ b/kustomize/monitoring/kustomization.yaml @@ -0,0 +1,35 @@ +kind: Kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +namespace: postgres-operator +resources: + - pvcs.yaml +# configuration files + - prometheus-config.yaml + - alertmanager-config.yaml + - alertmanager-rules-config.yaml + - grafana-datasources.yaml +# secrets + - grafana-secret.yaml +# RBAC + - rbac-sa.yaml + - rbac-cr.yaml + - rbac-crb.yaml +# Deployments + - deploy-alertmanager.yaml + - deploy-grafana.yaml + - deploy-prometheus.yaml +# Services + - service.yaml +configMapGenerator: +- name: grafana-dashboards + files: + - dashboards/pgbackrest.json + - dashboards/pod_details.json + - dashboards/postgres_overview.json + - dashboards/postgresql_details.json + - dashboards/postgresql_service_health.json + - dashboards/prometheus_alerts.json + - dashboards/query_statistics.json + - dashboards/crunchy_grafana_dashboards.yml +generatorOptions: + disableNameSuffixHash: true diff --git a/kustomize/monitoring/prometheus-config.yaml b/kustomize/monitoring/prometheus-config.yaml new file mode 100644 index 00000000..2ac34ff3 --- /dev/null +++ b/kustomize/monitoring/prometheus-config.yaml @@ -0,0 +1,73 @@ +apiVersion: v1 +data: + prometheus.yml: |+ + ### + # + # Copyright 2017-2021 Crunchy Data Solutions, Inc. All Rights Reserved. + # + ### + + --- + global: + scrape_interval: 15s + scrape_timeout: 15s + evaluation_interval: 5s + + scrape_configs: + - job_name: 'crunchy-postgres-exporter' + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_crunchy_postgres_exporter] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_container_port_number] + action: drop + regex: 5432 + - source_labels: [__meta_kubernetes_pod_container_port_number] + action: drop + regex: ^$ + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: kubernetes_namespace + - source_labels: [__meta_kubernetes_pod_name] + target_label: pod + - source_labels: [__meta_kubernetes_namespace,__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_cluster] + target_label: pg_cluster + separator: ':' + replacement: '$1$2' + - source_labels: [__meta_kubernetes_pod_ip] + target_label: ip + replacement: '$1' + - source_labels: [__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_instance] + target_label: deployment + replacement: '$1' + - source_labels: [__meta_kubernetes_pod_label_postgres_operator_crunchydata_com_role] + target_label: role + replacement: '$1' + - source_labels: [dbname] + target_label: dbname + replacement: '$1' + - source_labels: [relname] + target_label: relname + replacement: '$1' + - source_labels: [schemaname] + target_label: schemaname + replacement: '$1' + + rule_files: + - /etc/prometheus/alert-rules.d/*.yml + alerting: + alertmanagers: + - scheme: http + static_configs: + - targets: + - "crunchy-alertmanager:9093" + +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: crunchy-prometheus diff --git a/kustomize/monitoring/pvcs.yaml b/kustomize/monitoring/pvcs.yaml new file mode 100644 index 00000000..97fd796d --- /dev/null +++ b/kustomize/monitoring/pvcs.yaml @@ -0,0 +1,48 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: alertmanagerdata +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: standard + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: grafanadata +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: standard + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: prometheusdata +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: standard diff --git a/kustomize/monitoring/rbac-cr.yaml b/kustomize/monitoring/rbac-cr.yaml new file mode 100644 index 00000000..0627ba22 --- /dev/null +++ b/kustomize/monitoring/rbac-cr.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: prometheus-cr +rules: +- resources: + - pods + apiGroups: + - "" + verbs: + - get + - list + - watch diff --git a/kustomize/monitoring/rbac-crb.yaml b/kustomize/monitoring/rbac-crb.yaml new file mode 100644 index 00000000..493df1cb --- /dev/null +++ b/kustomize/monitoring/rbac-crb.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + vendor: crunchydata + name: prometheus-crb +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: prometheus-cr +subjects: +- kind: ServiceAccount + name: prometheus-sa diff --git a/kustomize/monitoring/rbac-sa.yaml b/kustomize/monitoring/rbac-sa.yaml new file mode 100644 index 00000000..3b747a96 --- /dev/null +++ b/kustomize/monitoring/rbac-sa.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + vendor: crunchydata + name: prometheus-sa + +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + vendor: crunchydata + name: alertmanager + +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + vendor: crunchydata + name: grafana diff --git a/kustomize/monitoring/service.yaml b/kustomize/monitoring/service.yaml new file mode 100644 index 00000000..8349ede9 --- /dev/null +++ b/kustomize/monitoring/service.yaml @@ -0,0 +1,51 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: crunchy-alertmanager + name: crunchy-alertmanager +spec: + type: ClusterIP + ports: + - name: alertmanager + port: 9093 + selector: + name: crunchy-alertmanager + +--- + +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: crunchy-grafana + name: crunchy-grafana +spec: + type: ClusterIP + ports: + - name: grafana + port: 3000 + selector: + name: crunchy-grafana + +--- + +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: postgres-operator-monitoring + vendor: crunchydata + name: crunchy-prometheus + name: crunchy-prometheus +spec: + type: ClusterIP + ports: + - name: prometheus + port: 9090 + selector: + name: crunchy-prometheus diff --git a/kustomize/multi-backup-repo/.gitignore b/kustomize/multi-backup-repo/.gitignore new file mode 100644 index 00000000..554f4a6e --- /dev/null +++ b/kustomize/multi-backup-repo/.gitignore @@ -0,0 +1,3 @@ +azure.conf +gcs-key.json +s3.conf diff --git a/kustomize/multi-backup-repo/azure.conf.example b/kustomize/multi-backup-repo/azure.conf.example new file mode 100644 index 00000000..838a4694 --- /dev/null +++ b/kustomize/multi-backup-repo/azure.conf.example @@ -0,0 +1,3 @@ +[global] +repo4-azure-account= +repo4-azure-key= diff --git a/kustomize/multi-backup-repo/gcs.conf b/kustomize/multi-backup-repo/gcs.conf new file mode 100644 index 00000000..60b925f4 --- /dev/null +++ b/kustomize/multi-backup-repo/gcs.conf @@ -0,0 +1,2 @@ +[global] +repo3-gcs-key=/etc/pgbackrest/conf.d/gcs-key.json diff --git a/kustomize/multi-backup-repo/kustomization.yaml b/kustomize/multi-backup-repo/kustomization.yaml new file mode 100644 index 00000000..5c349207 --- /dev/null +++ b/kustomize/multi-backup-repo/kustomization.yaml @@ -0,0 +1,15 @@ +namespace: postgres-operator + +secretGenerator: +- name: pgo-multi-repo-creds + files: + - azure.conf + - gcs.conf + - gcs-key.json + - s3.conf + +generatorOptions: + disableNameSuffixHash: true + +resources: +- postgres.yaml diff --git a/kustomize/multi-backup-repo/postgres.yaml b/kustomize/multi-backup-repo/postgres.yaml new file mode 100644 index 00000000..746f3112 --- /dev/null +++ b/kustomize/multi-backup-repo/postgres.yaml @@ -0,0 +1,46 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: hippo-multi-repo +spec: + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 + postgresVersion: 13 + instances: + - dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 + repoHost: + dedicated: {} + configuration: + - secret: + name: pgo-multi-repo-creds + global: + repo2-path: /pgbackrest/postgres-operator/hippo-multi-repo/repo2 + repo3-path: /pgbackrest/postgres-operator/hippo-multi-repo/repo3 + repo4-path: /pgbackrest/postgres-operator/hippo-multi-repo/repo4 + repos: + - name: repo1 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + - name: repo2 + s3: + bucket: "" + endpoint: "" + region: "" + - name: repo3 + gcs: + bucket: "" + - name: repo4 + azure: + container: "" diff --git a/kustomize/multi-backup-repo/s3.conf.example b/kustomize/multi-backup-repo/s3.conf.example new file mode 100644 index 00000000..1e1e1a43 --- /dev/null +++ b/kustomize/multi-backup-repo/s3.conf.example @@ -0,0 +1,3 @@ +[global] +repo2-s3-key= +repo2-s3-key-secret= diff --git a/kustomize/openshift/kustomization.yaml b/kustomize/openshift/kustomization.yaml new file mode 100644 index 00000000..249b4106 --- /dev/null +++ b/kustomize/openshift/kustomization.yaml @@ -0,0 +1,4 @@ +namespace: postgres-operator + +resources: +- postgres.yaml diff --git a/kustomize/openshift/postgres.yaml b/kustomize/openshift/postgres.yaml new file mode 100644 index 00000000..47813422 --- /dev/null +++ b/kustomize/openshift/postgres.yaml @@ -0,0 +1,30 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: hippo +spec: + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 + postgresVersion: 13 + openshift: true + instances: + - name: instance1 + dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 + repoHost: + dedicated: {} + repos: + - name: repo1 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi diff --git a/kustomize/postgres/kustomization.yaml b/kustomize/postgres/kustomization.yaml new file mode 100644 index 00000000..249b4106 --- /dev/null +++ b/kustomize/postgres/kustomization.yaml @@ -0,0 +1,4 @@ +namespace: postgres-operator + +resources: +- postgres.yaml diff --git a/kustomize/postgres/postgres.yaml b/kustomize/postgres/postgres.yaml new file mode 100644 index 00000000..1d56d2da --- /dev/null +++ b/kustomize/postgres/postgres.yaml @@ -0,0 +1,29 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: hippo +spec: + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 + postgresVersion: 13 + instances: + - name: instance1 + dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 + repoHost: + dedicated: {} + repos: + - name: repo1 + volume: + volumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi diff --git a/kustomize/s3/.gitignore b/kustomize/s3/.gitignore new file mode 100644 index 00000000..2e734254 --- /dev/null +++ b/kustomize/s3/.gitignore @@ -0,0 +1 @@ +s3.conf diff --git a/kustomize/s3/kustomization.yaml b/kustomize/s3/kustomization.yaml new file mode 100644 index 00000000..80fde462 --- /dev/null +++ b/kustomize/s3/kustomization.yaml @@ -0,0 +1,12 @@ +namespace: postgres-operator + +secretGenerator: +- name: pgo-s3-creds + files: + - s3.conf + +generatorOptions: + disableNameSuffixHash: true + +resources: +- postgres.yaml diff --git a/kustomize/s3/postgres.yaml b/kustomize/s3/postgres.yaml new file mode 100644 index 00000000..38fb8e8b --- /dev/null +++ b/kustomize/s3/postgres.yaml @@ -0,0 +1,30 @@ +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: hippo-s3 +spec: + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-ha:centos8-13.3-0 + postgresVersion: 13 + instances: + - dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: 1Gi + backups: + pgbackrest: + image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.33-0 + repoHost: + dedicated: {} + configuration: + - secret: + name: pgo-s3-creds + global: + repo1-path: /pgbackrest/postgres-operator/hippo-s3/repo1 + repos: + - name: repo1 + s3: + bucket: "" + endpoint: "" + region: "" diff --git a/kustomize/s3/s3.conf.example b/kustomize/s3/s3.conf.example new file mode 100644 index 00000000..31f3224b --- /dev/null +++ b/kustomize/s3/s3.conf.example @@ -0,0 +1,3 @@ +[global] +repo1-s3-key= +repo1-s3-key-secret=