diff --git a/kubernetes/apps/database/crunchy-postgres-operator/README.md b/kubernetes/apps/database/crunchy-postgres-operator/README.md new file mode 100644 index 00000000..0b71c3a8 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/README.md @@ -0,0 +1,28 @@ +# Helpful PGO Commands + +Grab the cli from Github: +[GitHub](https://github.com/CrunchyData/postgres-operator-client) [Docs](https://access.crunchydata.com/documentation/postgres-operator-client/latest/) + +## Point In Time Restore + +`pgo show postgres -n database` for backup information + +### Whole cluster +```sh +pgo restore postgres -n database \ + --options "--type=time --target='2024-04-09 11:00:03+00'" \ + --repoName repo1 +``` + +### Individual databases +```sh +pgo restore postgres -n database \ + --options "--type=time --target='2024-04-09 11:00:03+00' --db-include=postgres" \ + --repoName repo1 +``` + +## Manual full backup + +```sh +pgo backup postgres -n database --repoName repo1 +``` diff --git a/kubernetes/apps/database/crunchy-postgres-operator/cluster/externalsecret.yaml b/kubernetes/apps/database/crunchy-postgres-operator/cluster/externalsecret.yaml new file mode 100644 index 00000000..e822613a --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/cluster/externalsecret.yaml @@ -0,0 +1,38 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/externalsecret_v1beta1.json +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: &name crunchy-postgres +spec: + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-connect + target: + name: crunchy-postgres-secret + template: + engineVersion: v2 + data: + s3.conf: | + [global] + repo1-s3-key={{ .minio_crunchy_postgres_access_key }} + repo1-s3-key-secret={{ .minio_crunchy_postgres_secret_key }} + encryption.conf: | + [global] + repo1-cipher-pass={{ .crunchy_postgres_backup_encryption_cipher }} + dataFrom: + - extract: + key: crunchy-postgres + rewrite: + - regexp: + source: "(.*)" + target: "crunchy_postgres_$1" + - extract: + key: minio + rewrite: + - regexp: + source: "[-]" + target: "_" + - regexp: + source: "(.*)" + target: "minio_$1" diff --git a/kubernetes/apps/database/crunchy-postgres-operator/cluster/gatus.yaml b/kubernetes/apps/database/crunchy-postgres-operator/cluster/gatus.yaml new file mode 100644 index 00000000..d111914f --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/cluster/gatus.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-gatus-ep + labels: + gatus.io/enabled: "true" +data: + config.yaml: | + endpoints: + - name: postgres + group: infrastructure + url: tcp://postgres-primary.database.svc.cluster.local:5432 + interval: 1m + ui: + hide-url: true + hide-hostname: true + conditions: + - "[CONNECTED] == true" + alerts: + - type: pushover diff --git a/kubernetes/apps/database/crunchy-postgres-operator/cluster/kustomization.yaml b/kubernetes/apps/database/crunchy-postgres-operator/cluster/kustomization.yaml new file mode 100644 index 00000000..ef1ce0d0 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/cluster/kustomization.yaml @@ -0,0 +1,10 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./externalsecret.yaml + - ./gatus.yaml + - ./postgrescluster.yaml + - ./pushsecret.yaml + - ./service.yaml diff --git a/kubernetes/apps/database/crunchy-postgres-operator/cluster/postgrescluster.yaml b/kubernetes/apps/database/crunchy-postgres-operator/cluster/postgrescluster.yaml new file mode 100644 index 00000000..28e2c4fd --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/cluster/postgrescluster.yaml @@ -0,0 +1,179 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/postgres-operator.crunchydata.com/postgrescluster_v1beta1.json +apiVersion: postgres-operator.crunchydata.com/v1beta1 +kind: PostgresCluster +metadata: + name: &name postgres +spec: + postgresVersion: 16 + + metadata: + labels: + crunchy-userinit.ramblurr.github.com/enabled: "true" + crunchy-userinit.ramblurr.github.com/superuser: "postgres" + + service: + type: LoadBalancer + metadata: + annotations: + external-dns.alpha.kubernetes.io/hostname: postgres.jahanson.tech + io.cilium/lb-ipam-ips: 10.1.1.35 + + monitoring: + pgmonitor: + exporter: + # https://github.com/CrunchyData/postgres-operator-examples/blob/main/helm/install/values.yaml + image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres-exporter:ubi8-0.15.0-3 + + patroni: # turn on sync writes to at least 1 other replica + dynamicConfiguration: + synchronous_mode: true + postgresql: + synchronous_commit: "on" + pg_hba: + - hostnossl all all 10.244.0.0/16 md5 # Needed because dbman does not support SSL yet + - hostssl all all all md5 + + instances: + - name: postgres + metadata: + labels: + app.kubernetes.io/name: crunchy-postgres + replicas: &replica 1 + dataVolumeClaimSpec: + storageClassName: openebs-hostpath + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: "kubernetes.io/hostname" + whenUnsatisfiable: "DoNotSchedule" + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: *name + postgres-operator.crunchydata.com/data: postgres + + users: + # Superuser + - name: postgres + databases: + - postgres + options: "SUPERUSER" + password: + type: AlphaNumeric + # Applications + - name: atuin + databases: + - atuin + password: + type: AlphaNumeric + - name: autobrr + databases: + - autobrr + password: + type: AlphaNumeric + - name: gatus + databases: + - gatus + password: + type: AlphaNumeric + - name: grafana + databases: + - grafana + password: + type: AlphaNumeric + - name: kasm + databases: + - kasm + password: + type: AlphaNumeric + - name: prowlarr + databases: + - prowlarr_logs + - prowlarr_main + password: + type: AlphaNumeric + - name: radarr + databases: + - radarr_logs + - radarr_main + password: + type: AlphaNumeric + - name: sonarr + databases: + - sonarr_logs + - sonarr_main + password: + type: AlphaNumeric + - name: jellyseerr + databases: + - jellyseerr + password: + type: AlphaNumeric + + + backups: + pgbackrest: + configuration: &backupConfig + - secret: + name: crunchy-postgres-secret + global: &backupFlag + archive-timeout: "60" + compress-type: "bz2" + compress-level: "9" + delta: "y" + repo1-retention-full-type: "time" + repo1-retention-full: "14" + repo1-retention-diff: "30" + repo1-path: "/crunchy-pgo" + repo1-s3-uri-style: path + archive-push-queue-max: 4GiB + manual: + repoName: repo1 + options: + - --type=full + metadata: + labels: + app.kubernetes.io/name: crunchy-postgres-backup + repos: + - name: repo1 # Minio + s3: &minio + bucket: "crunchy-main" + endpoint: "s3.hsn.dev" + region: "us-east-1" + schedules: + full: "0 1 * * 0" # Sunday at 01:00 + differential: "0 1 * * 1-6" # Mon-Sat at 01:00 + incremental: "0 2-23 * * *" # Every hour except 01:00 + + dataSource: + pgbackrest: + stanza: "db" + configuration: *backupConfig + global: *backupFlag + repo: + name: "repo1" + s3: *minio + + proxy: + pgBouncer: + port: 5432 + replicas: *replica + metadata: + labels: + app.kubernetes.io/name: crunchy-postgres-pgbouncer + config: + global: + pool_mode: "transaction" # pgBouncer is set to transaction for Authentik. Grafana requires session https://github.com/grafana/grafana/issues/74260#issuecomment-1702795311. Everything else is happy with transaction + client_tls_sslmode: prefer + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: "kubernetes.io/hostname" + whenUnsatisfiable: "DoNotSchedule" + labelSelector: + matchLabels: + postgres-operator.crunchydata.com/cluster: *name + postgres-operator.crunchydata.com/role: "pgbouncer" diff --git a/kubernetes/apps/database/crunchy-postgres-operator/cluster/pushsecret.yaml b/kubernetes/apps/database/crunchy-postgres-operator/cluster/pushsecret.yaml new file mode 100644 index 00000000..63a69a50 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/cluster/pushsecret.yaml @@ -0,0 +1,280 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: grafana +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-grafana + data: + - match: + secretKey: dbname + remoteRef: + remoteKey: grafana + property: GF_DATABASE_NAME + - match: + secretKey: host + remoteRef: + remoteKey: grafana + property: GF_DATABASE_HOST + - match: + secretKey: user + remoteRef: + remoteKey: grafana + property: GF_DATABASE_USER + - match: + secretKey: password + remoteRef: + remoteKey: grafana + property: GF_DATABASE_PASSWORD +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: gatus +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-gatus + data: + - match: + secretKey: dbname + remoteRef: + remoteKey: gatus + property: pg_database + - match: + secretKey: port + remoteRef: + remoteKey: gatus + property: pg_port + - match: + secretKey: user + remoteRef: + remoteKey: gatus + property: pg_username + - match: + secretKey: password + remoteRef: + remoteKey: gatus + property: pg_password +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: prowlarr +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-prowlarr + data: + - match: + secretKey: host + remoteRef: + remoteKey: prowlarr + property: PROWLARR_POSTGRES_HOST + - match: + secretKey: user + remoteRef: + remoteKey: prowlarr + property: PROWLARR_POSTGRES_USER + - match: + secretKey: password + remoteRef: + remoteKey: prowlarr + property: PROWLARR_POSTGRES_PASSWORD +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: sonarr +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-sonarr + data: + - match: + secretKey: host + remoteRef: + remoteKey: sonarr + property: SONARR_POSTGRES_HOST + - match: + secretKey: user + remoteRef: + remoteKey: sonarr + property: SONARR_POSTGRES_USER + - match: + secretKey: password + remoteRef: + remoteKey: sonarr + property: SONARR_POSTGRES_PASSWORD +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: radarr +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-radarr + data: + - match: + secretKey: host + remoteRef: + remoteKey: radarr + property: RADARR_POSTGRES_HOST + - match: + secretKey: user + remoteRef: + remoteKey: radarr + property: RADARR_POSTGRES_USER + - match: + secretKey: password + remoteRef: + remoteKey: radarr + property: RADARR_POSTGRES_PASSWORD +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: atuin +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-atuin + data: + - match: + secretKey: host + remoteRef: + remoteKey: atuin + property: ATUIN_POSTGRES_HOST + - match: + secretKey: user + remoteRef: + remoteKey: atuin + property: ATUIN_POSTGRES_USER + - match: + secretKey: password + remoteRef: + remoteKey: atuin + property: ATUIN_POSTGRES_PASSWORD +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: jellyseerr +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-jellyseerr + data: + - match: + secretKey: host + remoteRef: + remoteKey: jellyseerr + property: JELLYSEERR_POSTGRES_HOST + - match: + secretKey: user + remoteRef: + remoteKey: jellyseerr + property: JELLYSEERR_POSTGRES_USER + - match: + secretKey: password + remoteRef: + remoteKey: jellyseerr + property: JELLYSEERR_POSTGRES_PASSWORD +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: autobrr +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-autobrr + data: + - match: + secretKey: host + remoteRef: + remoteKey: autobrr + property: AUTOBRR_POSTGRES_HOST + - match: + secretKey: user + remoteRef: + remoteKey: autobrr + property: AUTOBRR_POSTGRES_USER + - match: + secretKey: password + remoteRef: + remoteKey: autobrr + property: AUTOBRR_POSTGRES_PASSWORD +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/pushsecret_v1alpha1.json +apiVersion: external-secrets.io/v1alpha1 +kind: PushSecret +metadata: + name: kasm +spec: + refreshInterval: 1h + secretStoreRefs: + - name: onepassword-connect + kind: ClusterSecretStore + selector: + secret: + name: postgres-pguser-kasm + data: + - match: + secretKey: host + remoteRef: + remoteKey: kasm + property: KASM_POSTGRES_HOST + - match: + secretKey: user + remoteRef: + remoteKey: kasm + property: KASM_POSTGRES_USER + - match: + secretKey: password + remoteRef: + remoteKey: kasm + property: KASM_POSTGRES_PASSWORD diff --git a/kubernetes/apps/database/crunchy-postgres-operator/cluster/service.yaml b/kubernetes/apps/database/crunchy-postgres-operator/cluster/service.yaml new file mode 100644 index 00000000..730576ae --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/cluster/service.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: v1 +kind: Service +metadata: + labels: + postgres-operator.crunchydata.com/cluster: postgres + postgres-operator.crunchydata.com/role: primary + name: postgres-primary-real + namespace: media +spec: + internalTrafficPolicy: Cluster + ports: + - name: postgres + port: 5432 + protocol: TCP + targetPort: postgres + selector: + postgres-operator.crunchydata.com/cluster: postgres + postgres-operator.crunchydata.com/role: master + type: ClusterIP diff --git a/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/clustersecretstore.yaml b/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/clustersecretstore.yaml new file mode 100644 index 00000000..0eabb154 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/clustersecretstore.yaml @@ -0,0 +1,20 @@ +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/clustersecretstore_v1beta1.json +--- +apiVersion: external-secrets.io/v1beta1 +kind: ClusterSecretStore +metadata: + name: crunchy-pgo-secrets +spec: + provider: + kubernetes: + remoteNamespace: database + server: + caProvider: + type: "ConfigMap" + name: "kube-root-ca.crt" + namespace: database + key: "ca.crt" + auth: + serviceAccount: + name: external-secrets-pg + namespace: database diff --git a/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/kustomization.yaml b/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/kustomization.yaml new file mode 100644 index 00000000..dbaceab8 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/kustomization.yaml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./rbac.yaml + - ./clustersecretstore.yaml diff --git a/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/rbac.yaml b/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/rbac.yaml new file mode 100644 index 00000000..ab172165 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore/rbac.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: external-secrets-pg +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["authorization.k8s.io"] + resources: ["selfsubjectrulesreviews"] + verbs: ["create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: &name external-secrets-pg +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: *name +subjects: + - kind: ServiceAccount + name: *name + namespace: database +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: external-secrets-pg + namespace: database diff --git a/kubernetes/apps/database/crunchy-postgres-operator/ks.yaml b/kubernetes/apps/database/crunchy-postgres-operator/ks.yaml new file mode 100644 index 00000000..c02ced4e --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/ks.yaml @@ -0,0 +1,83 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &appname crunchy-postgres-operator + namespace: flux-system +spec: + targetNamespace: database + commonMetadata: + labels: + app.kubernetes.io/name: *appname + interval: 10m + path: "./kubernetes/apps/database/crunchy-postgres-operator/operator" + prune: true + sourceRef: + kind: GitRepository + name: theshire + wait: true +--- +# yaml-language-server: $schema=https://ks.hsn.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &appname crunchy-postgres-operator-cluster + namespace: flux-system +spec: + targetNamespace: database + commonMetadata: + labels: + app.kubernetes.io/name: *appname + interval: 10m + path: ./kubernetes/apps/database/crunchy-postgres-operator/cluster + prune: true + sourceRef: + kind: GitRepository + name: theshire + wait: true + dependsOn: + - name: crunchy-postgres-operator +--- +# yaml-language-server: $schema=https://ks.hsn.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &appname crunchy-postgres-operator-secretstore + namespace: flux-system +spec: + targetNamespace: database + commonMetadata: + labels: + app.kubernetes.io/name: *appname + interval: 10m + path: ./kubernetes/apps/database/crunchy-postgres-operator/clustersecretstore + prune: true + sourceRef: + kind: GitRepository + name: theshire + wait: true + dependsOn: + - name: crunchy-postgres-operator-cluster + - name: external-secrets +--- +# yaml-language-server: $schema=https://ks.hsn.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &appname crunchy-postgres-userinit-controller + namespace: flux-system +spec: + targetNamespace: database + commonMetadata: + labels: + app.kubernetes.io/name: *appname + interval: 10m + path: ./kubernetes/apps/database/crunchy-postgres-operator/userinit-controller + prune: true + sourceRef: + kind: GitRepository + name: theshire + wait: true + dependsOn: + - name: crunchy-postgres-operator-cluster diff --git a/kubernetes/apps/database/crunchy-postgres-operator/operator/helmrelease.yaml b/kubernetes/apps/database/crunchy-postgres-operator/operator/helmrelease.yaml new file mode 100644 index 00000000..3b1a4443 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/operator/helmrelease.yaml @@ -0,0 +1,25 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/helm.toolkit.fluxcd.io/helmrelease_v2beta2.json +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: crunchy-postgres-operator +spec: + interval: 30m + chart: + spec: + chart: pgo + version: 5.6.1 + sourceRef: + kind: HelmRepository + name: crunchydata + namespace: flux-system + interval: 5m + install: + crds: CreateReplace + upgrade: + crds: CreateReplace + values: + install: + clusterLabels: + app.kubernetes.io/name: pgo diff --git a/kubernetes/apps/database/crunchy-postgres-operator/operator/kustomization.yaml b/kubernetes/apps/database/crunchy-postgres-operator/operator/kustomization.yaml new file mode 100644 index 00000000..17cbc72b --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/operator/kustomization.yaml @@ -0,0 +1,6 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml diff --git a/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/helmrelease.yaml b/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/helmrelease.yaml new file mode 100644 index 00000000..768f0047 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/helmrelease.yaml @@ -0,0 +1,17 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/helmrelease-helm-v2beta2.json +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: userinit-controller +spec: + interval: 30m + chart: + spec: + chart: crunchy-userinit-controller + version: 0.0.4 + sourceRef: + kind: HelmRepository + name: crunchy-userinit + values: + fullnameOverride: crunchy-userinit-controller diff --git a/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/helmrepository.yaml b/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/helmrepository.yaml new file mode 100644 index 00000000..f3e2c1a6 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/helmrepository.yaml @@ -0,0 +1,10 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/helmrepository-source-v1beta2.json +apiVersion: source.toolkit.fluxcd.io/v1 +kind: HelmRepository +metadata: + name: crunchy-userinit +spec: + interval: 30m + url: https://ramblurr.github.io/crunchy-userinit-controller + timeout: 3m diff --git a/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/kustomization.yaml b/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/kustomization.yaml new file mode 100644 index 00000000..4ceb6e75 --- /dev/null +++ b/kubernetes/apps/database/crunchy-postgres-operator/userinit-controller/kustomization.yaml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrepository.yaml + - ./helmrelease.yaml diff --git a/kubernetes/apps/database/dragonfly/app/dragonfly.yaml b/kubernetes/apps/database/dragonfly/app/dragonfly.yaml new file mode 100644 index 00000000..216d7099 --- /dev/null +++ b/kubernetes/apps/database/dragonfly/app/dragonfly.yaml @@ -0,0 +1,30 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/dragonflydb.io/dragonfly_v1alpha1.json +apiVersion: dragonflydb.io/v1alpha1 +kind: Dragonfly +metadata: + labels: + app.kubernetes.io/name: dragonfly + name: dragonfly +spec: + replicas: 1 + resources: + requests: + cpu: 500m + memory: 500Mi + limits: + memory: 3Gi + args: + - "--proactor_threads=4" + - "--default_lua_flags=allow-undeclared-keys" + + # Need retention policy before this is enabled + # Or add S3 details and enable retention policy on the bucket. + # snapshot: + # cron: "*/5 * * * *" + # persistentVolumeClaimSpec: + # accessModes: + # - ReadWriteOnce + # resources: + # requests: + # storage: 2Gi diff --git a/kubernetes/apps/database/dragonfly/app/kustomization.yaml b/kubernetes/apps/database/dragonfly/app/kustomization.yaml new file mode 100644 index 00000000..f7d16c4c --- /dev/null +++ b/kubernetes/apps/database/dragonfly/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./dragonfly.yaml diff --git a/kubernetes/apps/database/dragonfly/ks.yaml b/kubernetes/apps/database/dragonfly/ks.yaml new file mode 100644 index 00000000..e9999fd6 --- /dev/null +++ b/kubernetes/apps/database/dragonfly/ks.yaml @@ -0,0 +1,21 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &app dragonfly + namespace: flux-system +spec: + targetNamespace: database + commonMetadata: + labels: + app.kubernetes.io/name: *app + path: ./kubernetes/apps/database/dragonfly/app + prune: true + sourceRef: + kind: GitRepository + name: homelab + wait: false + interval: 30m + retryInterval: 1m + timeout: 15m diff --git a/kubernetes/apps/database/emqx/app/externalsecret.yaml b/kubernetes/apps/database/emqx/app/externalsecret.yaml new file mode 100644 index 00000000..d39645ac --- /dev/null +++ b/kubernetes/apps/database/emqx/app/externalsecret.yaml @@ -0,0 +1,41 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/externalsecret_v1beta1.json +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: emqx +spec: + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-connect + target: + name: emqx-secret + template: + engineVersion: v2 + data: + EMQX_DASHBOARD__DEFAULT_USERNAME: "{{ .EMQX_DASHBOARD__DEFAULT_USERNAME }}" + EMQX_DASHBOARD__DEFAULT_PASSWORD: "{{ .EMQX_DASHBOARD__DEFAULT_PASSWORD }}" + dataFrom: + - extract: + key: emqx +--- +# yaml-language-server: $schema=https://ks.hsn.dev/external-secrets.io/externalsecret_v1beta1.json +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: emqx-init-user +spec: + refreshInterval: 5m + secretStoreRef: + kind: ClusterSecretStore + name: onepassword-connect + target: + name: emqx-init-user-secret + template: + engineVersion: v2 + data: + init-user.json: | + [{"user_id": "{{ .X_EMQX_MQTT_USERNAME }}", "password": "{{ .X_EMQX_MQTT_PASSWORD }}", "is_superuser": true}] + dataFrom: + - extract: + key: emqx diff --git a/kubernetes/apps/database/emqx/app/helmrelease.yaml b/kubernetes/apps/database/emqx/app/helmrelease.yaml new file mode 100644 index 00000000..41fc3e1f --- /dev/null +++ b/kubernetes/apps/database/emqx/app/helmrelease.yaml @@ -0,0 +1,31 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: emqx +spec: + interval: 30m + chart: + spec: + chart: emqx-operator + version: 2.2.23 + sourceRef: + kind: HelmRepository + name: emqx + namespace: flux-system + install: + remediation: + retries: 3 + upgrade: + cleanupOnFail: true + remediation: + strategy: rollback + retries: 3 + dependsOn: + - name: cert-manager + namespace: cert-manager + values: + fullnameOverride: emqx-operator + image: + repository: ghcr.io/emqx/emqx-operator diff --git a/kubernetes/apps/database/emqx/app/kustomization.yaml b/kubernetes/apps/database/emqx/app/kustomization.yaml new file mode 100644 index 00000000..4eed917b --- /dev/null +++ b/kubernetes/apps/database/emqx/app/kustomization.yaml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./externalsecret.yaml + - ./helmrelease.yaml diff --git a/kubernetes/apps/database/emqx/cluster/cluster.yaml b/kubernetes/apps/database/emqx/cluster/cluster.yaml new file mode 100644 index 00000000..cbc48169 --- /dev/null +++ b/kubernetes/apps/database/emqx/cluster/cluster.yaml @@ -0,0 +1,53 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/apps.emqx.io/emqx_v2beta1.json +apiVersion: apps.emqx.io/v2beta1 +kind: EMQX +metadata: + name: emqx +spec: + image: public.ecr.aws/emqx/emqx:5.8.0 + config: + data: | + authentication { + backend = "built_in_database" + mechanism = "password_based" + password_hash_algorithm { + name = "bcrypt", + } + user_id_type = "username" + bootstrap_file = "/opt/init-user.json" + bootstrap_type = "plain" + } + authorization { + sources = [ + { + type = built_in_database + enable = true + } + ] + no_match: "deny" + } + coreTemplate: + metadata: + annotations: + reloader.stakater.com/auto: "true" + spec: + replicas: 1 + envFrom: + - secretRef: + name: emqx-secret + extraVolumeMounts: + - name: init-user + mountPath: /opt/init-user.json + subPath: init-user.json + readOnly: true + extraVolumes: + - name: init-user + secret: + secretName: emqx-init-user-secret + listenersServiceTemplate: + metadata: + annotations: + io.cilium/lb-ipam-ips: 10.1.1.38 + spec: + type: LoadBalancer diff --git a/kubernetes/apps/database/emqx/cluster/ingress.yaml b/kubernetes/apps/database/emqx/cluster/ingress.yaml new file mode 100644 index 00000000..b334613f --- /dev/null +++ b/kubernetes/apps/database/emqx/cluster/ingress.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: emqx-dashboard +spec: + ingressClassName: internal-nginx + rules: + - host: &host emqx.jahanson.tech + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: emqx-dashboard + port: + number: 18083 + tls: + - hosts: + - *host diff --git a/kubernetes/apps/database/emqx/cluster/kustomization.yaml b/kubernetes/apps/database/emqx/cluster/kustomization.yaml new file mode 100644 index 00000000..83d325dd --- /dev/null +++ b/kubernetes/apps/database/emqx/cluster/kustomization.yaml @@ -0,0 +1,8 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./cluster.yaml + - ./ingress.yaml + - ./podmonitor.yaml diff --git a/kubernetes/apps/database/emqx/cluster/podmonitor.yaml b/kubernetes/apps/database/emqx/cluster/podmonitor.yaml new file mode 100644 index 00000000..a62f5766 --- /dev/null +++ b/kubernetes/apps/database/emqx/cluster/podmonitor.yaml @@ -0,0 +1,27 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/monitoring.coreos.com/podmonitor_v1.json +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: emqx +spec: + selector: + matchLabels: + apps.emqx.io/instance: emqx + apps.emqx.io/managed-by: emqx-operator + podMetricsEndpoints: + - port: dashboard + path: /api/v5/prometheus/stats + relabelings: + - action: replace + # user-defined cluster name, requires unique + replacement: emqx5 + targetLabel: cluster + - action: replace + # fix value, don't modify + replacement: emqx + targetLabel: from + - action: replace + # fix value, don't modify + sourceLabels: ['pod'] + targetLabel: "instance" diff --git a/kubernetes/apps/database/emqx/ks.yaml b/kubernetes/apps/database/emqx/ks.yaml new file mode 100644 index 00000000..0c3ffb8e --- /dev/null +++ b/kubernetes/apps/database/emqx/ks.yaml @@ -0,0 +1,46 @@ +--- +# yaml-language-server: $schema=https://ks.hsn.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &app emqx + namespace: flux-system +spec: + targetNamespace: database + commonMetadata: + labels: + app.kubernetes.io/name: *app + dependsOn: + - name: external-secrets-stores + path: ./kubernetes/apps/database/emqx/app + prune: true + sourceRef: + kind: GitRepository + name: homelab + wait: true + interval: 30m + retryInterval: 1m + timeout: 5m +--- +# yaml-language-server: $schema=https://ks.hsn.dev/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: &app emqx-cluster + namespace: flux-system +spec: + targetNamespace: database + commonMetadata: + labels: + app.kubernetes.io/name: *app + dependsOn: + - name: emqx + path: ./kubernetes/apps/database/emqx/cluster + prune: true + sourceRef: + kind: GitRepository + name: homelab + wait: true + interval: 30m + retryInterval: 1m + timeout: 5m diff --git a/kubernetes/apps/database/kustomization.yaml b/kubernetes/apps/database/kustomization.yaml new file mode 100644 index 00000000..9e308de6 --- /dev/null +++ b/kubernetes/apps/database/kustomization.yaml @@ -0,0 +1,11 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + # Pre Flux-Kustomizations + - ./namespace.yaml + # Flux-Kustomizations + - ./crunchy-postgres-operator/ks.yaml + - ./dragonfly/ks.yaml + - ./emqx/ks.yaml diff --git a/kubernetes/apps/database/namespace.yaml b/kubernetes/apps/database/namespace.yaml new file mode 100644 index 00000000..93da4e01 --- /dev/null +++ b/kubernetes/apps/database/namespace.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: database + labels: + kustomize.toolkit.fluxcd.io/prune: disabled + volsync.backube/privileged-movers: "true"