diff --git a/manifests/apply.sh b/manifests/apply.sh index 6200485..fd3990c 100755 --- a/manifests/apply.sh +++ b/manifests/apply.sh @@ -18,5 +18,4 @@ helm upgrade --install cnpg \ sleep 5 kubectl apply -k . -./immich/apply.sh ./tailscale/apply.sh diff --git a/manifests/cnpg-system/barman-cloud.yaml b/manifests/cnpg-system/barman-cloud.yaml new file mode 100644 index 0000000..fd19fbc --- /dev/null +++ b/manifests/cnpg-system/barman-cloud.yaml @@ -0,0 +1,1085 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.18.0 + name: objectstores.barmancloud.cnpg.io +spec: + group: barmancloud.cnpg.io + names: + kind: ObjectStore + listKind: ObjectStoreList + plural: objectstores + singular: objectstore + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ObjectStore is the Schema for the objectstores 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: |- + Specification of the desired behavior of the ObjectStore. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + properties: + configuration: + description: The configuration for the barman-cloud tool suite + properties: + azureCredentials: + description: The credentials to use to upload data to Azure Blob + Storage + properties: + connectionString: + description: The connection string to be used + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + inheritFromAzureAD: + description: Use the Azure AD based authentication without + providing explicitly the keys. + type: boolean + storageAccount: + description: The storage account where to upload data + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + storageKey: + description: |- + The storage account key to be used in conjunction + with the storage account name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + storageSasToken: + description: |- + A shared-access-signature to be used in conjunction with + the storage account name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: object + data: + description: |- + The configuration to be used to backup the data files + When not defined, base backups files will be stored uncompressed and may + be unencrypted in the object store, according to the bucket default + policy. + properties: + additionalCommandArgs: + description: |- + AdditionalCommandArgs represents additional arguments that can be appended + to the 'barman-cloud-backup' command-line invocation. These arguments + provide flexibility to customize the backup process further according to + specific requirements or configurations. + + Example: + In a scenario where specialized backup options are required, such as setting + a specific timeout or defining custom behavior, users can use this field + to specify additional command arguments. + + Note: + It's essential to ensure that the provided arguments are valid and supported + by the 'barman-cloud-backup' command, to avoid potential errors or unintended + behavior during execution. + items: + type: string + type: array + compression: + description: |- + Compress a backup file (a tar file per tablespace) while streaming it + to the object store. Available options are empty string (no + compression, default), `gzip`, `bzip2`, and `snappy`. + enum: + - bzip2 + - gzip + - snappy + type: string + encryption: + description: |- + Whenever to force the encryption of files (if the bucket is + not already configured for that). + Allowed options are empty string (use the bucket policy, default), + `AES256` and `aws:kms` + enum: + - AES256 + - aws:kms + type: string + immediateCheckpoint: + description: |- + Control whether the I/O workload for the backup initial checkpoint will + be limited, according to the `checkpoint_completion_target` setting on + the PostgreSQL server. If set to true, an immediate checkpoint will be + used, meaning PostgreSQL will complete the checkpoint as soon as + possible. `false` by default. + type: boolean + jobs: + description: |- + The number of parallel jobs to be used to upload the backup, defaults + to 2 + format: int32 + minimum: 1 + type: integer + type: object + destinationPath: + description: |- + The path where to store the backup (i.e. s3://bucket/path/to/folder) + this path, with different destination folders, will be used for WALs + and for data + minLength: 1 + type: string + endpointCA: + description: |- + EndpointCA store the CA bundle of the barman endpoint. + Useful when using self-signed certificates to avoid + errors with certificate issuer and barman-cloud-wal-archive + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + endpointURL: + description: |- + Endpoint to be used to upload data to the cloud, + overriding the automatic endpoint discovery + type: string + googleCredentials: + description: The credentials to use to upload data to Google Cloud + Storage + properties: + applicationCredentials: + description: The secret containing the Google Cloud Storage + JSON file with the credentials + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + gkeEnvironment: + description: |- + If set to true, will presume that it's running inside a GKE environment, + default to false. + type: boolean + type: object + historyTags: + additionalProperties: + type: string + description: |- + HistoryTags is a list of key value pairs that will be passed to the + Barman --history-tags option. + type: object + s3Credentials: + description: The credentials to use to upload data to S3 + properties: + accessKeyId: + description: The reference to the access key id + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + inheritFromIAMRole: + description: Use the role based authentication without providing + explicitly the keys. + type: boolean + region: + description: The reference to the secret containing the region + name + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + secretAccessKey: + description: The reference to the secret access key + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + sessionToken: + description: The references to the session key + properties: + key: + description: The key to select + type: string + name: + description: Name of the referent. + type: string + required: + - key + - name + type: object + type: object + serverName: + description: |- + The server name on S3, the cluster name is used if this + parameter is omitted + type: string + tags: + additionalProperties: + type: string + description: |- + Tags is a list of key value pairs that will be passed to the + Barman --tags option. + type: object + wal: + description: |- + The configuration for the backup of the WAL stream. + When not defined, WAL files will be stored uncompressed and may be + unencrypted in the object store, according to the bucket default policy. + properties: + archiveAdditionalCommandArgs: + description: |- + Additional arguments that can be appended to the 'barman-cloud-wal-archive' + command-line invocation. These arguments provide flexibility to customize + the WAL archive process further, according to specific requirements or configurations. + + Example: + In a scenario where specialized backup options are required, such as setting + a specific timeout or defining custom behavior, users can use this field + to specify additional command arguments. + + Note: + It's essential to ensure that the provided arguments are valid and supported + by the 'barman-cloud-wal-archive' command, to avoid potential errors or unintended + behavior during execution. + items: + type: string + type: array + compression: + description: |- + Compress a WAL file before sending it to the object store. Available + options are empty string (no compression, default), `gzip`, `bzip2`, + `lz4`, `snappy`, `xz`, and `zstd`. + enum: + - bzip2 + - gzip + - lz4 + - snappy + - xz + - zstd + type: string + encryption: + description: |- + Whenever to force the encryption of files (if the bucket is + not already configured for that). + Allowed options are empty string (use the bucket policy, default), + `AES256` and `aws:kms` + enum: + - AES256 + - aws:kms + type: string + maxParallel: + description: |- + Number of WAL files to be either archived in parallel (when the + PostgreSQL instance is archiving to a backup object store) or + restored in parallel (when a PostgreSQL standby is fetching WAL + files from a recovery object store). If not specified, WAL files + will be processed one at a time. It accepts a positive integer as a + value - with 1 being the minimum accepted value. + minimum: 1 + type: integer + restoreAdditionalCommandArgs: + description: |- + Additional arguments that can be appended to the 'barman-cloud-wal-restore' + command-line invocation. These arguments provide flexibility to customize + the WAL restore process further, according to specific requirements or configurations. + + Example: + In a scenario where specialized backup options are required, such as setting + a specific timeout or defining custom behavior, users can use this field + to specify additional command arguments. + + Note: + It's essential to ensure that the provided arguments are valid and supported + by the 'barman-cloud-wal-restore' command, to avoid potential errors or unintended + behavior during execution. + items: + type: string + type: array + type: object + required: + - destinationPath + type: object + x-kubernetes-validations: + - fieldPath: .serverName + message: use the 'serverName' plugin parameter in the Cluster resource + reason: FieldValueForbidden + rule: '!has(self.serverName)' + instanceSidecarConfiguration: + description: The configuration for the sidecar that runs in the instance + pods + properties: + additionalContainerArgs: + description: |- + AdditionalContainerArgs is an optional list of command-line arguments + to be passed to the sidecar container when it starts. + The provided arguments are appended to the container’s default arguments. + items: + type: string + type: array + x-kubernetes-validations: + - message: do not set --log-level in additionalContainerArgs; + use spec.instanceSidecarConfiguration.logLevel + reason: FieldValueForbidden + rule: '!self.exists(a, a.startsWith(''--log-level''))' + env: + description: The environment to be explicitly passed to the sidecar + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + 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 + x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) 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 + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + logLevel: + default: info + description: 'The log level for PostgreSQL instances. Valid values + are: `error`, `warning`, `info` (default), `debug`, `trace`' + enum: + - error + - warning + - info + - debug + - trace + type: string + resources: + description: Resources define cpu/memory requests and limits for + the sidecar that runs in the instance pods. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + 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-resources-containers/ + 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. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + retentionPolicyIntervalSeconds: + default: 1800 + description: |- + The retentionCheckInterval defines the frequency at which the + system checks and enforces retention policies. + type: integer + type: object + retentionPolicy: + description: |- + RetentionPolicy is the retention policy to be used for backups + and WALs (i.e. '60d'). The retention policy is expressed in the form + of `XXu` where `XX` is a positive integer and `u` is in `[dwm]` - + days, weeks, months. + pattern: ^[1-9][0-9]*[dwm]$ + type: string + required: + - configuration + type: object + status: + description: |- + Most recently observed status of the ObjectStore. This data may not be up to + date. Populated by the system. Read-only. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + properties: + serverRecoveryWindow: + additionalProperties: + description: |- + RecoveryWindow represents the time span between the first + recoverability point and the last successful backup of a PostgreSQL + server, defining the period during which data can be restored. + properties: + firstRecoverabilityPoint: + description: |- + The first recoverability point in a PostgreSQL server refers to + the earliest point in time to which the database can be + restored. + format: date-time + type: string + lastFailedBackupTime: + description: The last failed backup time + format: date-time + type: string + lastSuccessfulBackupTime: + description: The last successful backup time + format: date-time + type: string + type: object + description: ServerRecoveryWindow maps each server to its recovery + window + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: plugin-barman-cloud + name: plugin-barman-cloud + namespace: cnpg-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: plugin-barman-cloud + name: leader-election-role + namespace: cnpg-system +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: metrics-auth-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: metrics-reader +rules: +- nonResourceURLs: + - /metrics + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: plugin-barman-cloud + name: objectstore-editor-role +rules: +- apiGroups: + - barmancloud.cnpg.io + resources: + - objectstores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - barmancloud.cnpg.io + resources: + - objectstores/status + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: plugin-barman-cloud + name: objectstore-viewer-role +rules: +- apiGroups: + - barmancloud.cnpg.io + resources: + - objectstores + verbs: + - get + - list + - watch +- apiGroups: + - barmancloud.cnpg.io + resources: + - objectstores/status + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: plugin-barman-cloud +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - get + - list + - watch +- apiGroups: + - barmancloud.cnpg.io + resources: + - objectstores + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - barmancloud.cnpg.io + resources: + - objectstores/finalizers + verbs: + - update +- apiGroups: + - barmancloud.cnpg.io + resources: + - objectstores/status + verbs: + - get + - patch + - update +- apiGroups: + - postgresql.cnpg.io + resources: + - backups + verbs: + - get + - list + - watch +- apiGroups: + - postgresql.cnpg.io + resources: + - clusters/finalizers + verbs: + - update +- apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + - roles + verbs: + - create + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: plugin-barman-cloud + name: leader-election-rolebinding + namespace: cnpg-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: plugin-barman-cloud + namespace: cnpg-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: metrics-auth-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: metrics-auth-role +subjects: +- kind: ServiceAccount + name: plugin-barman-cloud + namespace: cnpg-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: plugin-barman-cloud + name: plugin-barman-cloud-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: plugin-barman-cloud +subjects: +- kind: ServiceAccount + name: plugin-barman-cloud + namespace: cnpg-system +--- +apiVersion: v1 +data: + SIDECAR_IMAGE: | + Z2hjci5pby9jbG91ZG5hdGl2ZS1wZy9wbHVnaW4tYmFybWFuLWNsb3VkLXNpZGVjYXI6dj + AuNy4w +kind: Secret +metadata: + name: plugin-barman-cloud-7g4226tm68 + namespace: cnpg-system +type: Opaque +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + cnpg.io/pluginClientSecret: barman-cloud-client-tls + cnpg.io/pluginPort: "9090" + cnpg.io/pluginServerSecret: barman-cloud-server-tls + labels: + app: barman-cloud + cnpg.io/pluginName: barman-cloud.cloudnative-pg.io + name: barman-cloud + namespace: cnpg-system +spec: + ports: + - port: 9090 + protocol: TCP + targetPort: 9090 + selector: + app: barman-cloud +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: barman-cloud + name: barman-cloud + namespace: cnpg-system +spec: + replicas: 1 + selector: + matchLabels: + app: barman-cloud + strategy: + type: Recreate + template: + metadata: + labels: + app: barman-cloud + spec: + containers: + - args: + - operator + - --server-cert=/server/tls.crt + - --server-key=/server/tls.key + - --client-cert=/client/tls.crt + - --server-address=:9090 + - --leader-elect + - --log-level=debug + env: + - name: SIDECAR_IMAGE + valueFrom: + secretKeyRef: + key: SIDECAR_IMAGE + name: plugin-barman-cloud-7g4226tm68 + image: ghcr.io/cloudnative-pg/plugin-barman-cloud:v0.7.0 + name: barman-cloud + ports: + - containerPort: 9090 + protocol: TCP + readinessProbe: + initialDelaySeconds: 10 + periodSeconds: 10 + tcpSocket: + port: 9090 + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsGroup: 10001 + runAsUser: 10001 + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /server + name: server + - mountPath: /client + name: client + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + serviceAccountName: plugin-barman-cloud + volumes: + - name: server + secret: + secretName: barman-cloud-server-tls + - name: client + secret: + secretName: barman-cloud-client-tls +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: barman-cloud-client + namespace: cnpg-system +spec: + commonName: barman-cloud-client + duration: 2160h + isCA: false + issuerRef: + group: cert-manager.io + kind: Issuer + name: selfsigned-issuer + renewBefore: 360h + secretName: barman-cloud-client-tls + usages: + - client auth +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: barman-cloud-server + namespace: cnpg-system +spec: + commonName: barman-cloud + dnsNames: + - barman-cloud + duration: 2160h + isCA: false + issuerRef: + group: cert-manager.io + kind: Issuer + name: selfsigned-issuer + renewBefore: 360h + secretName: barman-cloud-server-tls + usages: + - server auth +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer + namespace: cnpg-system +spec: + selfSigned: {} diff --git a/manifests/cnpg-system/kustomization.yaml b/manifests/cnpg-system/kustomization.yaml new file mode 100644 index 0000000..4515dd7 --- /dev/null +++ b/manifests/cnpg-system/kustomization.yaml @@ -0,0 +1,5 @@ +namespace: cnpg-system + +resources: + # https://github.com/cloudnative-pg/plugin-barman-cloud/releases/download/v0.7.0/manifest.yaml + - barman-cloud.yaml diff --git a/manifests/databases/immich.yaml b/manifests/databases/immich.yaml new file mode 100644 index 0000000..274f236 --- /dev/null +++ b/manifests/databases/immich.yaml @@ -0,0 +1,89 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: immich +spec: + imageName: "ghcr.io/corentingiraud/cnpg-pgvector-vectorchord:16-migration" + #imageName: "ghcr.io/tensorchord/cloudnative-pgvecto.rs:16-v0.3.0" + #postgresUID: 1 + instances: 1 + storage: + size: 60Gi + primaryUpdateStrategy: unsupervised + postgresql: + shared_preload_libraries: + - vectors.so + - vchord.so + + bootstrap: + recovery: + source: origin + # initdb: + # database: immich + # owner: immich + # secret: + # name: postgres-user-immich + # dataChecksums: true + # postInitApplicationSQL: + # - ALTER SYSTEM SET search_path TO "$user", public, vectors; + # - SET search_path TO "$user", public, vectors; + # - CREATE EXTENSION IF NOT EXISTS "cube"; + # - CREATE EXTENSION IF NOT EXISTS "earthdistance"; + # - GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "immich"; + + externalClusters: + - name: origin + plugin: + name: barman-cloud.cloudnative-pg.io + parameters: + barmanObjectName: k3sbackup-objectstore + serverName: pgvector + + managed: + roles: + - name: immich + ensure: present + comment: Immich DB user + login: true + superuser: true + passwordSecret: + name: postgres-user-immich + + # plugins: + # - name: barman-cloud.cloudnative-pg.io + # isWALArchiver: true + # parameters: + # barmanObjectName: k3sbackup-objectstore +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: database-immich +spec: + name: immich + owner: immich + cluster: + name: immich + extensions: + - name: vectors + ensure: present + - name: vectorchord + ensure: present + - name: cube + ensure: present + - name: earthdistance + ensure: present +--- +apiVersion: postgresql.cnpg.io/v1 +kind: ScheduledBackup +metadata: + name: immich-backup +spec: + immediate: true # Create one when this is added to the cluster + schedule: "0 2 0 * * *" # 1AM, nightly + backupOwnerReference: self + cluster: + name: immich + method: plugin + pluginConfiguration: + name: barman-cloud.cloudnative-pg.io diff --git a/manifests/databases/kustomization.yaml b/manifests/databases/kustomization.yaml index 3d46a2d..4a5c0e7 100644 --- a/manifests/databases/kustomization.yaml +++ b/manifests/databases/kustomization.yaml @@ -7,4 +7,5 @@ resources: - postgres-gitlab.yaml - postgres-pgadmin.yaml - postgres-matrix.yaml + - immich.yaml - ingress.yaml diff --git a/manifests/databases/postgres-cluster.yaml b/manifests/databases/postgres-cluster.yaml index 554959d..45716f1 100644 --- a/manifests/databases/postgres-cluster.yaml +++ b/manifests/databases/postgres-cluster.yaml @@ -35,7 +35,7 @@ spec: plugins: - name: barman-cloud.cloudnative-pg.io - isWALArchiver: false + isWALArchiver: true parameters: barmanObjectName: k3sbackup-objectstore @@ -85,3 +85,6 @@ spec: backupOwnerReference: self cluster: name: postgres + method: plugin + pluginConfiguration: + name: barman-cloud.cloudnative-pg.io diff --git a/manifests/databases/secrets.yaml b/manifests/databases/secrets.yaml index 946b660..b7533a1 100644 --- a/manifests/databases/secrets.yaml +++ b/manifests/databases/secrets.yaml @@ -133,3 +133,37 @@ spec: remoteRef: key: 685b29c6-9264-4e60-ba4a-b2ea005a5d7b property: password +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: postgres-user-immich + namespace: db +spec: + target: + name: postgres-user-immich + deletionPolicy: Delete + template: + type: Opaque + data: + username: |- + {{ .username }} + password: |- + {{ .password }} + data: + - secretKey: username + sourceRef: + storeRef: + name: bitwarden-login + kind: ClusterSecretStore + remoteRef: + key: 5ce63e26-dd7f-46d4-b7ed-b310002ef93f + property: username + - secretKey: password + sourceRef: + storeRef: + name: bitwarden-login + kind: ClusterSecretStore + remoteRef: + key: 5ce63e26-dd7f-46d4-b7ed-b310002ef93f + property: password diff --git a/manifests/immich/apply.sh b/manifests/immich/apply.sh deleted file mode 100755 index 03213a4..0000000 --- a/manifests/immich/apply.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - - -# Get the directory where the script is located -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" - -# Change to the script directory -cd "$SCRIPT_DIR" - -kubectl apply -k "$SCRIPT_DIR" - -# https://www.dragonflydb.io/guides/redis-kubernetes -# Deploys into immich namespace, directly, in order to allow the password to be -# accessed by the immich installer -helm upgrade --install --create-namespace --namespace immich redis \ - oci://registry-1.docker.io/bitnamicharts/redis \ - -f "${SCRIPT_DIR}/values-redis.yaml" \ - --wait -# https://github.com/immich-app/immich-charts/tree/main -helm upgrade --install --create-namespace --namespace immich immich \ - oci://ghcr.io/immich-app/immich-charts/immich \ - -f "${SCRIPT_DIR}/values.yaml" \ - --wait diff --git a/manifests/immich/chart.yaml b/manifests/immich/chart.yaml new file mode 100644 index 0000000..7cc1bb8 --- /dev/null +++ b/manifests/immich/chart.yaml @@ -0,0 +1,77 @@ +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: immich +spec: + interval: "24h" + url: oci://ghcr.io/immich-app/immich-charts/immich + ref: + # Version 0.10.0 + # For some reason, I can't get it to pull by tag or by auto-discovery + digest: "sha256:bcffd3d504664710baa7c0bcd66dc246437c51a9a76f9b8ed1a10c7aecd80766" +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: immich +spec: + interval: "1h" + chartRef: + kind: OCIRepository + name: immich + namespace: immich + dependsOn: + - name: longhorn + namespace: longhorn-system + values: + controllers: + main: + containers: + main: + image: + tag: v2.1.0 + env: + DB_HOSTNAME: immich-rw.db.svc.cluster.local + DB_DATABASE_NAME: immich + DB_USERNAME: + valueFrom: + secretKeyRef: + name: postgres-user-immich + key: username + DB_PASSWORD: + valueFrom: + secretKeyRef: + name: postgres-user-immich + key: password + immich: + persistence: + library: + existingClaim: immich-storage + server: + ingress: + main: + enabled: true + annogations: + ingressClassName: traefik + # Set body size to 10G to allow uploading large things + traefik.ingress.kubernetes.io/buffering: | + maxrequestbodybytes: 10000000000 + memrequestbodybytes: 20000000000 + hosts: + - host: immich.cluster + paths: + - path: "/" + machine-learning: + persistence: + cache: + type: persistentVolumeClaim + storageClass: longhorn-default + size: 25Gi + valkey: + enabled: true + persistence: + data: + enabled: true + size: 2Gi + type: persistentVolumeClaim + storageClass: longhorn-default diff --git a/manifests/immich/database.yaml b/manifests/immich/database.yaml deleted file mode 100644 index 5981cf4..0000000 --- a/manifests/immich/database.yaml +++ /dev/null @@ -1,74 +0,0 @@ -apiVersion: postgresql.cnpg.io/v1 -kind: Cluster -metadata: - namespace: db - name: pgvector -spec: - imageName: "ghcr.io/tensorchord/cloudnative-pgvecto.rs:16-v0.3.0" - instances: 1 - storage: - size: 40Gi - primaryUpdateStrategy: unsupervised - postgresql: - shared_preload_libraries: - - "vectors.so" - - bootstrap: - initdb: - database: immich - owner: immich - secret: - name: postgres-user-immich - dataChecksums: true - postInitApplicationSQL: - - ALTER SYSTEM SET search_path TO "$user", public, vectors; - - SET search_path TO "$user", public, vectors; - - CREATE EXTENSION IF NOT EXISTS "vectors"; - - CREATE EXTENSION IF NOT EXISTS "cube"; - - CREATE EXTENSION IF NOT EXISTS "earthdistance"; - - ALTER SCHEMA vectors OWNER TO "immich"; - - GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA vectors TO "immich"; - - GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO "immich"; - managed: - roles: - - name: immich - ensure: present - comment: Immich DB user - login: true - superuser: false - passwordSecret: - name: postgres-user-immich - backup: - retentionPolicy: "30d" - barmanObjectStore: - destinationPath: "s3://k3sbackup/pgvector" - endpointURL: "http://s3.thehellings.lan:9000/" - s3Credentials: - accessKeyId: - name: k3sbackup - key: username - secretAccessKey: - name: k3sbackup - key: password - wal: - compression: gzip ---- -apiVersion: postgresql.cnpg.io/v1 -kind: Database -metadata: - namespace: db - name: database-immich -spec: - name: immich - owner: immich - cluster: - name: pgvector - extensions: - - name: vectors - ensure: present - - name: vectorchord - ensure: present - - name: cube - ensure: present - - name: earthdistance - ensure: present diff --git a/manifests/immich/db-restore.yaml b/manifests/immich/db-restore.yaml new file mode 100644 index 0000000..d20a09a --- /dev/null +++ b/manifests/immich/db-restore.yaml @@ -0,0 +1,89 @@ +# This one needs to have a different name than the cluster it is being +# restored from, so we create a restore cluster here and do not configure +# it with any backup settings +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + namespace: db + name: pgvector-restore +spec: + imageName: "ghcr.io/tensorchord/cloudnative-pgvecto.rs:16-v0.3.0" + instances: 1 + storage: + size: 60Gi + primaryUpdateStrategy: unsupervised + postgresql: + shared_preload_libraries: + - "vectors.so" + + bootstrap: + recovery: + source: origin + externalClusters: + - name: origin + plugin: + name: barman-cloud.cloudnative-pg.io + parameters: + barmanObjectName: k3sbackup-objectstore + serverName: pgvector + managed: + roles: + - name: immich + ensure: present + comment: Immich DB user + login: true + superuser: true + passwordSecret: + name: postgres-user-immich +--- +# This cluster will stream from the above one, since we cannot rename +# objects in Kubernetes +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + namespace: db + name: pgvector +spec: + imageName: "ghcr.io/immich-app/postgres:16-vectorchord0.5.3" + #imageName: "ghcr.io/tensorchord/cloudnative-pgvecto.rs:16-v0.3.0" + instances: 1 + storage: + size: 60Gi + primaryUpdateStrategy: unsupervised + postgresUID: 26 + postgresql: + shared_preload_libraries: + - "vectors.so" + + bootstrap: + pg_basebackup: + source: pgvector-restore + externalClusters: + - name: pgvector-restore + connectionParameters: + host: pgvector-restore-rw + user: streaming_replica + sslmode: verify-full + sslKey: + name: pgvector-restore-replication + key: tls.key + sslCert: + name: pgvector-restore-replication + key: tls.crt + sslRootCert: + name: pgvector-restore-ca + key: ca.crt + managed: + roles: + - name: immich + ensure: present + comment: Immich DB user + login: true + superuser: true + passwordSecret: + name: postgres-user-immich + plugins: + - name: barman-cloud.cloudnative-pg.io + isWALArchiver: true + parameters: + barmanObjectName: k3sbackup-objectstore diff --git a/manifests/immich/kustomization.yaml b/manifests/immich/kustomization.yaml index db99467..03bc10d 100644 --- a/manifests/immich/kustomization.yaml +++ b/manifests/immich/kustomization.yaml @@ -1,6 +1,8 @@ +namespace: immich + resources: - namespace.yaml + - chart.yaml - postgres-user-secret.yaml - - database.yaml - pvc.yaml - ingress.yaml diff --git a/manifests/immich/postgres-user-secret.yaml b/manifests/immich/postgres-user-secret.yaml index 1e100bf..7875a37 100644 --- a/manifests/immich/postgres-user-secret.yaml +++ b/manifests/immich/postgres-user-secret.yaml @@ -2,41 +2,6 @@ apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: postgres-user-immich - namespace: db -spec: - target: - name: postgres-user-immich - deletionPolicy: Delete - template: - type: Opaque - data: - username: |- - {{ .username }} - password: |- - {{ .password }} - data: - - secretKey: username - sourceRef: - storeRef: - name: bitwarden-login - kind: ClusterSecretStore - remoteRef: - key: 5ce63e26-dd7f-46d4-b7ed-b310002ef93f - property: username - - secretKey: password - sourceRef: - storeRef: - name: bitwarden-login - kind: ClusterSecretStore - remoteRef: - key: 5ce63e26-dd7f-46d4-b7ed-b310002ef93f - property: password ---- -apiVersion: external-secrets.io/v1 -kind: ExternalSecret -metadata: - name: postgres-user-immich - namespace: immich spec: target: name: postgres-user-immich diff --git a/manifests/immich/values-redis.yaml b/manifests/immich/values-redis.yaml deleted file mode 100644 index 4991c5d..0000000 --- a/manifests/immich/values-redis.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# https://github.com/bitnami/charts/blob/main/bitnami/redis/values.yaml -# https://github.com/bitnami/charts/tree/main/bitnami/redis -architecture: standalone -global: - defaultStorageClass: longhorn-default -master: - persistence: - storageClass: longhorn-default diff --git a/manifests/immich/values.yaml b/manifests/immich/values.yaml deleted file mode 100644 index 64142bb..0000000 --- a/manifests/immich/values.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# https://github.com/immich-app/immich-charts/blob/main/charts/immich/values.yaml -env: - DB_HOSTNAME: pgvector-rw.db.svc.cluster.local - DB_DATABASE_NAME: immich - DB_USERNAME: - valueFrom: - secretKeyRef: - name: postgres-user-immich - key: username - DB_PASSWORD: - valueFrom: - secretKeyRef: - name: postgres-user-immich - key: password - REDIS_HOSTNAME: redis-master - REDIS_PASSWORD: - valueFrom: - secretKeyRef: - name: redis - key: redis-password -image: - tag: "v1.135.3" -immich: - persistence: - library: - existingClaim: immich-storage -server: - ingress: - main: - enabled: true - annogations: - ingressClassName: traefik - # Set body size to 10G to allow uploading large things - traefik.ingress.kubernetes.io/buffering: | - maxrequestbodybytes: 10000000000 - memrequestbodybytes: 20000000000 - hosts: - - host: immich.cluster - paths: - - path: "/" -machine-learning: - persistence: - cache: - type: pvc - storageClass: longhorn-default - size: 25Gi diff --git a/manifests/kustomization.yaml b/manifests/kustomization.yaml index 292400e..0a2dd2b 100644 --- a/manifests/kustomization.yaml +++ b/manifests/kustomization.yaml @@ -2,6 +2,7 @@ resources: - helm - bitwarden - secrets + - cnpg-system - databases - matrix - gitlab-runner