From cade7d339ef2e962a019d1dd721f6cbffc05b2a2 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 20 Nov 2023 17:03:38 +0000 Subject: [PATCH 01/19] First pass at updating Helm chart. --- charts/budibase/Chart.yaml | 6 +--- charts/budibase/templates/alb-ingress.yaml | 16 ++++----- .../templates/app-service-deployment.yaml | 8 +---- .../templates/app-service-service.yaml | 10 ++---- charts/budibase/templates/couchdb-backup.yaml | 8 ----- .../minio-data-persistentvolumeclaim.yaml | 1 - .../templates/minio-service-deployment.yaml | 8 ----- .../templates/minio-service-service.yaml | 4 --- .../templates/proxy-service-deployment.yaml | 5 --- .../templates/proxy-service-service.yaml | 12 +++---- .../redis-data-persistentvolumeclaim.yaml | 1 - .../templates/redis-service-deployment.yaml | 8 ----- .../templates/redis-service-service.yaml | 4 --- .../templates/worker-service-deployment.yaml | 6 ---- .../templates/worker-service-service.yaml | 10 ++---- charts/budibase/values.yaml | 33 +++++-------------- 16 files changed, 29 insertions(+), 111 deletions(-) diff --git a/charts/budibase/Chart.yaml b/charts/budibase/Chart.yaml index 05b3f24dbd..b62c1ca248 100644 --- a/charts/budibase/Chart.yaml +++ b/charts/budibase/Chart.yaml @@ -17,10 +17,6 @@ version: 0.0.0 appVersion: 0.0.0 dependencies: - name: couchdb - version: 3.3.4 + version: 4.4.5 repository: https://apache.github.io/couchdb-helm condition: services.couchdb.enabled - - name: ingress-nginx - version: 4.0.13 - repository: https://kubernetes.github.io/ingress-nginx - condition: ingress.nginx diff --git a/charts/budibase/templates/alb-ingress.yaml b/charts/budibase/templates/alb-ingress.yaml index 6cd1cf2cba..01d7fe0bf0 100644 --- a/charts/budibase/templates/alb-ingress.yaml +++ b/charts/budibase/templates/alb-ingress.yaml @@ -1,4 +1,4 @@ -{{- if .Values.ingress.aws }} +{{- if .Values.awsAlbIngress.enabled }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -9,22 +9,22 @@ metadata: alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/success-codes: 200,301 alb.ingress.kubernetes.io/healthcheck-path: / - {{- if .Values.ingress.certificateArn }} + {{- if .Values.awsAlbIngress.certificateArn }} alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' - alb.ingress.kubernetes.io/certificate-arn: {{ .Values.ingress.certificateArn }} + alb.ingress.kubernetes.io/certificate-arn: {{ .Values.awsAlbIngress.certificateArn }} {{- end }} - {{- if .Values.ingress.sslPolicy }} - alb.ingress.kubernetes.io/actions.ssl-policy: {{ .Values.ingress.sslPolicy }} + {{- if .Values.awsAlbIngress.sslPolicy }} + alb.ingress.kubernetes.io/actions.ssl-policy: {{ .Values.awsAlbIngress.sslPolicy }} {{- end }} - {{- if .Values.ingress.securityGroups }} - alb.ingress.kubernetes.io/security-groups: {{ .Values.ingress.securityGroups }} + {{- if .Values.awsAlbIngress.securityGroups }} + alb.ingress.kubernetes.io/security-groups: {{ .Values.awsAlbIngress.securityGroups }} {{- end }} spec: rules: - http: paths: - {{- if .Values.ingress.certificateArn }} + {{- if .Values.awsAlbIngress.certificateArn }} - path: / pathType: Prefix backend: diff --git a/charts/budibase/templates/app-service-deployment.yaml b/charts/budibase/templates/app-service-deployment.yaml index 73c6d990d2..fbe9c1d363 100644 --- a/charts/budibase/templates/app-service-deployment.yaml +++ b/charts/budibase/templates/app-service-deployment.yaml @@ -2,12 +2,9 @@ apiVersion: apps/v1 kind: Deployment metadata: annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) {{ if .Values.services.apps.deploymentAnnotations }} {{- toYaml .Values.services.apps.deploymentAnnotations | indent 4 -}} {{ end }} - creationTimestamp: null labels: io.kompose.service: app-service {{ if .Values.services.apps.deploymentLabels }} @@ -24,12 +21,9 @@ spec: template: metadata: annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) {{ if .Values.services.apps.templateAnnotations }} {{- toYaml .Values.services.apps.templateAnnotations | indent 8 -}} {{ end }} - creationTimestamp: null labels: io.kompose.service: app-service {{ if .Values.services.apps.templateLabels }} @@ -200,7 +194,7 @@ spec: {{ end }} image: budibase/apps:{{ .Values.globals.appVersion | default .Chart.AppVersion }} - imagePullPolicy: Always + imagePullPolicy: IfNotPresent {{- if .Values.services.apps.startupProbe }} {{- with .Values.services.apps.startupProbe }} startupProbe: diff --git a/charts/budibase/templates/app-service-service.yaml b/charts/budibase/templates/app-service-service.yaml index 5247b4de09..390fbfe782 100644 --- a/charts/budibase/templates/app-service-service.yaml +++ b/charts/budibase/templates/app-service-service.yaml @@ -1,18 +1,14 @@ apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: io.kompose.service: app-service name: app-service spec: ports: - - name: {{ .Values.services.apps.port | quote }} - port: {{ .Values.services.apps.port }} - targetPort: {{ .Values.services.apps.port }} + - name: {{ .Values.services.apps.port | quote }} + port: {{ .Values.services.apps.port }} + targetPort: {{ .Values.services.apps.port }} selector: io.kompose.service: app-service status: diff --git a/charts/budibase/templates/couchdb-backup.yaml b/charts/budibase/templates/couchdb-backup.yaml index 7396f97476..6f842537a7 100644 --- a/charts/budibase/templates/couchdb-backup.yaml +++ b/charts/budibase/templates/couchdb-backup.yaml @@ -2,10 +2,6 @@ apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: app.kubernetes.io/name: couchdb-backup name: couchdb-backup @@ -18,10 +14,6 @@ spec: type: Recreate template: metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: app.kubernetes.io/name: couchdb-backup spec: diff --git a/charts/budibase/templates/minio-data-persistentvolumeclaim.yaml b/charts/budibase/templates/minio-data-persistentvolumeclaim.yaml index abcf341bc5..c17001a436 100644 --- a/charts/budibase/templates/minio-data-persistentvolumeclaim.yaml +++ b/charts/budibase/templates/minio-data-persistentvolumeclaim.yaml @@ -2,7 +2,6 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - creationTimestamp: null labels: io.kompose.service: minio-data name: minio-data diff --git a/charts/budibase/templates/minio-service-deployment.yaml b/charts/budibase/templates/minio-service-deployment.yaml index f98ecc139d..28e8eb9991 100644 --- a/charts/budibase/templates/minio-service-deployment.yaml +++ b/charts/budibase/templates/minio-service-deployment.yaml @@ -2,10 +2,6 @@ apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: io.kompose.service: minio-service name: minio-service @@ -18,10 +14,6 @@ spec: type: Recreate template: metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: io.kompose.service: minio-service spec: diff --git a/charts/budibase/templates/minio-service-service.yaml b/charts/budibase/templates/minio-service-service.yaml index cfdb22002b..ce89f1347c 100644 --- a/charts/budibase/templates/minio-service-service.yaml +++ b/charts/budibase/templates/minio-service-service.yaml @@ -2,10 +2,6 @@ apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: io.kompose.service: minio-service name: minio-service diff --git a/charts/budibase/templates/proxy-service-deployment.yaml b/charts/budibase/templates/proxy-service-deployment.yaml index 53bba6232d..26f4265e4c 100644 --- a/charts/budibase/templates/proxy-service-deployment.yaml +++ b/charts/budibase/templates/proxy-service-deployment.yaml @@ -2,12 +2,9 @@ apiVersion: apps/v1 kind: Deployment metadata: annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) {{ if .Values.services.proxy.deploymentAnnotations }} {{- toYaml .Values.services.proxy.deploymentAnnotations | indent 4 -}} {{ end }} - creationTimestamp: null labels: app.kubernetes.io/name: budibase-proxy {{ if .Values.services.proxy.deploymentLabels }} @@ -24,8 +21,6 @@ spec: template: metadata: annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) {{ if .Values.services.proxy.templateAnnotations }} {{- toYaml .Values.services.proxy.templateAnnotations | indent 8 -}} {{ end }} diff --git a/charts/budibase/templates/proxy-service-service.yaml b/charts/budibase/templates/proxy-service-service.yaml index bf2b199ee5..e5dde301fa 100644 --- a/charts/budibase/templates/proxy-service-service.yaml +++ b/charts/budibase/templates/proxy-service-service.yaml @@ -1,19 +1,15 @@ apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: app.kubernetes.io/name: budibase-proxy name: proxy-service spec: ports: - - name: {{ .Values.services.proxy.port | quote }} - port: {{ .Values.services.proxy.port }} - targetPort: {{ .Values.services.proxy.port }} + - name: { { .Values.services.proxy.port | quote } } + port: { { .Values.services.proxy.port } } + targetPort: { { .Values.services.proxy.port } } selector: app.kubernetes.io/name: budibase-proxy status: - loadBalancer: {} \ No newline at end of file + loadBalancer: {} diff --git a/charts/budibase/templates/redis-data-persistentvolumeclaim.yaml b/charts/budibase/templates/redis-data-persistentvolumeclaim.yaml index 6f11492b58..e605a98376 100644 --- a/charts/budibase/templates/redis-data-persistentvolumeclaim.yaml +++ b/charts/budibase/templates/redis-data-persistentvolumeclaim.yaml @@ -2,7 +2,6 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - creationTimestamp: null labels: io.kompose.service: redis-data name: redis-data diff --git a/charts/budibase/templates/redis-service-deployment.yaml b/charts/budibase/templates/redis-service-deployment.yaml index 9b39d14291..bca40d2237 100644 --- a/charts/budibase/templates/redis-service-deployment.yaml +++ b/charts/budibase/templates/redis-service-deployment.yaml @@ -2,10 +2,6 @@ apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: io.kompose.service: redis-service name: redis-service @@ -18,10 +14,6 @@ spec: type: Recreate template: metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: io.kompose.service: redis-service spec: diff --git a/charts/budibase/templates/redis-service-service.yaml b/charts/budibase/templates/redis-service-service.yaml index 55ca40ed88..b8f998925a 100644 --- a/charts/budibase/templates/redis-service-service.yaml +++ b/charts/budibase/templates/redis-service-service.yaml @@ -2,10 +2,6 @@ apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: io.kompose.service: redis-service name: redis-service diff --git a/charts/budibase/templates/worker-service-deployment.yaml b/charts/budibase/templates/worker-service-deployment.yaml index 5e0addb9dd..6427aa70e8 100644 --- a/charts/budibase/templates/worker-service-deployment.yaml +++ b/charts/budibase/templates/worker-service-deployment.yaml @@ -2,12 +2,9 @@ apiVersion: apps/v1 kind: Deployment metadata: annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) {{ if .Values.services.worker.deploymentAnnotations }} {{- toYaml .Values.services.worker.deploymentAnnotations | indent 4 -}} {{ end }} - creationTimestamp: null labels: io.kompose.service: worker-service {{ if .Values.services.worker.deploymentLabels }} @@ -24,12 +21,9 @@ spec: template: metadata: annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) {{ if .Values.services.worker.templateAnnotations }} {{- toYaml .Values.services.worker.templateAnnotations | indent 8 -}} {{ end }} - creationTimestamp: null labels: io.kompose.service: worker-service {{ if .Values.services.worker.templateLabels }} diff --git a/charts/budibase/templates/worker-service-service.yaml b/charts/budibase/templates/worker-service-service.yaml index a79ba1e04b..214ee7191e 100644 --- a/charts/budibase/templates/worker-service-service.yaml +++ b/charts/budibase/templates/worker-service-service.yaml @@ -1,18 +1,14 @@ apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.21.0 (992df58d8) - creationTimestamp: null labels: io.kompose.service: worker-service name: worker-service spec: ports: - - name: {{ .Values.services.worker.port | quote }} - port: {{ .Values.services.worker.port }} - targetPort: {{ .Values.services.worker.port }} + - name: { { .Values.services.worker.port | quote } } + port: { { .Values.services.worker.port } } + targetPort: { { .Values.services.worker.port } } selector: io.kompose.service: worker-service status: diff --git a/charts/budibase/values.yaml b/charts/budibase/values.yaml index 857067d0f1..5c750ce2ca 100644 --- a/charts/budibase/values.yaml +++ b/charts/budibase/values.yaml @@ -2,11 +2,6 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -image: - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "" - imagePullSecrets: [] nameOverride: "" # fullnameOverride: "" @@ -41,14 +36,10 @@ service: ingress: enabled: true - aws: false - nginx: true - certificateArn: "" className: "" annotations: - kubernetes.io/ingress.class: nginx - nginx.ingress.kubernetes.io/client-max-body-size: 150M - nginx.ingress.kubernetes.io/proxy-body-size: 50m + # nginx.ingress.kubernetes.io/client-max-body-size: 150M + # nginx.ingress.kubernetes.io/proxy-body-size: 50m hosts: - host: # change if using custom domain paths: @@ -60,6 +51,10 @@ ingress: port: number: 10000 +awsAlbIngress: + enabled: false + certificateArn: "" + autoscaling: enabled: false minReplicas: 1 @@ -111,7 +106,6 @@ globals: # globalAgentNoProxy: services: - budibaseVersion: latest dns: cluster.local # tlsRejectUnauthorized: 0 @@ -145,10 +139,6 @@ services: scheme: HTTP failureThreshold: 3 periodSeconds: 5 - # annotations: - # co.elastic.logs/module: nginx - # co.elastic.logs/fileset.stdout: access - # co.elastic.logs/fileset.stderr: error apps: port: 4002 @@ -280,7 +270,6 @@ couchdb: # adminUsername: budibase # adminPassword: budibase - # adminHash: -pbkdf2-this_is_not_necessarily_secure_either # cookieAuthSecret: admin ## When enabled, will deploy a networkpolicy that allows CouchDB pods to @@ -310,16 +299,12 @@ couchdb: ## The CouchDB image image: - repository: couchdb - tag: 3.1.1 + repository: budibase/couchdb + tag: 3.2.1 pullPolicy: IfNotPresent ## Experimental integration with Lucene-powered fulltext search - enableSearch: true - searchImage: - repository: kocolosk/couchdb-search - tag: 0.2.0 - pullPolicy: IfNotPresent + enableSearch: false initImage: repository: busybox From 08d45820a2d752de1e26e420a607aca649800ed4 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 21 Nov 2023 10:29:27 +0000 Subject: [PATCH 02/19] Update chart dependencies, fix some syntactic errors. --- charts/budibase/Chart.lock | 9 +- charts/budibase/Chart.yaml | 2 +- charts/budibase/charts/couchdb-3.3.4.tgz | Bin 9668 -> 0 bytes charts/budibase/charts/couchdb-4.3.0.tgz | Bin 0 -> 14629 bytes .../budibase/charts/ingress-nginx-4.0.13.tgz | Bin 27766 -> 0 bytes .../templates/app-service-service.yaml | 6 +- .../templates/proxy-service-service.yaml | 6 +- .../templates/worker-service-service.yaml | 6 +- charts/budibase/values.yaml | 175 +++++++++++++++--- 9 files changed, 159 insertions(+), 45 deletions(-) delete mode 100644 charts/budibase/charts/couchdb-3.3.4.tgz create mode 100644 charts/budibase/charts/couchdb-4.3.0.tgz delete mode 100644 charts/budibase/charts/ingress-nginx-4.0.13.tgz diff --git a/charts/budibase/Chart.lock b/charts/budibase/Chart.lock index 75b9de07b5..3ee752a362 100644 --- a/charts/budibase/Chart.lock +++ b/charts/budibase/Chart.lock @@ -1,9 +1,6 @@ dependencies: - name: couchdb repository: https://apache.github.io/couchdb-helm - version: 3.3.4 -- name: ingress-nginx - repository: https://kubernetes.github.io/ingress-nginx - version: 4.0.13 -digest: sha256:20892705c2d8e64c98257d181063a514ac55013e2b43399a6e54868a97f97845 -generated: "2021-12-30T18:55:30.878411Z" + version: 4.3.0 +digest: sha256:94449a7f195b186f5af33ec5aa66d58b36bede240fae710f021ca87837b30606 +generated: "2023-11-20T17:43:02.777596Z" diff --git a/charts/budibase/Chart.yaml b/charts/budibase/Chart.yaml index b62c1ca248..e2c9378f2c 100644 --- a/charts/budibase/Chart.yaml +++ b/charts/budibase/Chart.yaml @@ -17,6 +17,6 @@ version: 0.0.0 appVersion: 0.0.0 dependencies: - name: couchdb - version: 4.4.5 + version: 4.3.0 repository: https://apache.github.io/couchdb-helm condition: services.couchdb.enabled diff --git a/charts/budibase/charts/couchdb-3.3.4.tgz b/charts/budibase/charts/couchdb-3.3.4.tgz deleted file mode 100644 index f7ebfd3e9653ef2e0fba07de4e498b46311de606..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9668 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 GzyJWm|L4yD diff --git a/charts/budibase/charts/couchdb-4.3.0.tgz b/charts/budibase/charts/couchdb-4.3.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..d3cce28ee630a20d8bdc0051746b6e2dac95f7fd GIT binary patch literal 14629 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 K0YMK1@&5p2<=4Le diff --git a/charts/budibase/templates/app-service-service.yaml b/charts/budibase/templates/app-service-service.yaml index 390fbfe782..6d19590d45 100644 --- a/charts/budibase/templates/app-service-service.yaml +++ b/charts/budibase/templates/app-service-service.yaml @@ -6,9 +6,9 @@ metadata: name: app-service spec: ports: - - name: {{ .Values.services.apps.port | quote }} - port: {{ .Values.services.apps.port }} - targetPort: {{ .Values.services.apps.port }} + - name: {{ .Values.services.apps.port | quote }} + port: {{ .Values.services.apps.port }} + targetPort: {{ .Values.services.apps.port }} selector: io.kompose.service: app-service status: diff --git a/charts/budibase/templates/proxy-service-service.yaml b/charts/budibase/templates/proxy-service-service.yaml index e5dde301fa..988c540599 100644 --- a/charts/budibase/templates/proxy-service-service.yaml +++ b/charts/budibase/templates/proxy-service-service.yaml @@ -6,9 +6,9 @@ metadata: name: proxy-service spec: ports: - - name: { { .Values.services.proxy.port | quote } } - port: { { .Values.services.proxy.port } } - targetPort: { { .Values.services.proxy.port } } + - name: {{ .Values.services.proxy.port | quote }} + port: {{ .Values.services.proxy.port }} + targetPort: {{ .Values.services.proxy.port }} selector: app.kubernetes.io/name: budibase-proxy status: diff --git a/charts/budibase/templates/worker-service-service.yaml b/charts/budibase/templates/worker-service-service.yaml index 214ee7191e..c5f56ba205 100644 --- a/charts/budibase/templates/worker-service-service.yaml +++ b/charts/budibase/templates/worker-service-service.yaml @@ -6,9 +6,9 @@ metadata: name: worker-service spec: ports: - - name: { { .Values.services.worker.port | quote } } - port: { { .Values.services.worker.port } } - targetPort: { { .Values.services.worker.port } } + - name: {{ .Values.services.worker.port | quote }} + port: {{ .Values.services.worker.port }} + targetPort: {{ .Values.services.worker.port }} selector: io.kompose.service: worker-service status: diff --git a/charts/budibase/values.yaml b/charts/budibase/values.yaml index 5c750ce2ca..9409363bbb 100644 --- a/charts/budibase/values.yaml +++ b/charts/budibase/values.yaml @@ -261,22 +261,45 @@ services: # Override values in couchDB subchart couchdb: - ## clusterSize is the initial size of the CouchDB cluster. - clusterSize: 1 + # -- the initial number of nodes in the CouchDB cluster. + clusterSize: 3 + + # -- If allowAdminParty is enabled the cluster will start up without any database + # administrator account; i.e., all users will be granted administrative + # access. Otherwise, the system will look for a Secret called + # -couchdb containing `adminUsername`, `adminPassword` and + # `cookieAuthSecret` keys. See the `createAdminSecret` flag. + # ref: https://kubernetes.io/docs/concepts/configuration/secret/ allowAdminParty: false - # Secret Management + # -- If createAdminSecret is enabled a Secret called -couchdb will + # be created containing auto-generated credentials. Users who prefer to set + # these values themselves have a couple of options: + # + # 1) The `adminUsername`, `adminPassword`, `adminHash`, and `cookieAuthSecret` + # can be defined directly in the chart's values. Note that all of a chart's + # values are currently stored in plaintext in a ConfigMap in the tiller + # namespace. + # + # 2) This flag can be disabled and a Secret with the required keys can be + # created ahead of time. createAdminSecret: true - # adminUsername: budibase - # adminPassword: budibase - # cookieAuthSecret: admin + adminUsername: admin + # adminPassword: this_is_not_secure + # adminHash: -pbkdf2-this_is_not_necessarily_secure_either + # cookieAuthSecret: neither_is_this ## When enabled, will deploy a networkpolicy that allows CouchDB pods to ## communicate with each other for clustering and ingress on port 5984 networkPolicy: enabled: true + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: + # Use a service account serviceAccount: enabled: true @@ -285,25 +308,28 @@ couchdb: # imagePullSecrets: # - name: myimagepullsecret - ## The storage volume used by each Pod in the StatefulSet. If a - ## persistentVolume is not enabled, the Pods will use `emptyDir` ephemeral - ## local storage. Setting the storageClass attribute to "-" disables dynamic - ## provisioning of Persistent Volumes; leaving it unset will invoke the default - ## provisioner. + # -- The storage volume used by each Pod in the StatefulSet. If a + # persistentVolume is not enabled, the Pods will use `emptyDir` ephemeral + # local storage. Setting the storageClass attribute to "-" disables dynamic + # provisioning of Persistent Volumes; leaving it unset will invoke the default + # provisioner. persistentVolume: enabled: false + # NOTE: the number of existing claims must match the cluster size + existingClaims: [] + annotations: {} accessModes: - ReadWriteOnce size: 10Gi - storageClass: "" + # storageClass: "-" ## The CouchDB image image: repository: budibase/couchdb - tag: 3.2.1 + tag: v3.2.1 pullPolicy: IfNotPresent - ## Experimental integration with Lucene-powered fulltext search + # -- Flip this to flag to include the Search container in each Pod enableSearch: false initImage: @@ -316,19 +342,52 @@ couchdb: ## `OrderedReady` podManagementPolicy: Parallel + ## To better tolerate Node failures, we can prevent Kubernetes scheduler from + ## assigning more than one Pod of CouchDB StatefulSet per Node using podAntiAffinity. + affinity: + {} + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: "app" + # operator: In + # values: + # - couchdb + # topologyKey: "kubernetes.io/hostname" + + ## To control how Pods are spread across your cluster among failure-domains such as regions, + ## zones, nodes, and other user-defined topology domains use topologySpreadConstraints. + topologySpreadConstraints: + {} + # topologySpreadConstraints: + # - maxSkew: 1 + # topologyKey: "topology.kubernetes.io/zone" + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app: couchdb + + ## Optional pod labels + labels: {} + ## Optional pod annotations annotations: {} ## Optional tolerations tolerations: [] - affinity: {} - + ## A StatefulSet requires a headless Service to establish the stable network + ## identities of the Pods, and that Service is created automatically by this + ## chart without any additional configuration. The Service block below refers + ## to a second Service that governs how clients connect to the CouchDB cluster. service: - # annotations: + annotations: {} enabled: true type: ClusterIP externalPort: 5984 + targetPort: 5984 + labels: {} ## An Ingress resource can provide name-based virtual hosting and TLS ## termination among other things for CouchDB deployments which are accessed @@ -336,11 +395,12 @@ couchdb: ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/ ingress: enabled: false + # className: nginx hosts: - chart-example.local path: / annotations: - [] + {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" tls: @@ -360,21 +420,35 @@ couchdb: # cpu: 56 # memory: 256Gi - ## erlangFlags is a map that is passed to the Erlang VM as flags using the - ## ERL_FLAGS env. `name` and `setcookie` flags are minimally required to - ## establish connectivity between cluster nodes. - ## ref: http://erlang.org/doc/man/erl.html#init_flags + ## Optional resource requests and limits for the CouchDB init container + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + initResources: + {} + # requests: + # cpu: 100m + # memory: 128Mi + # limits: + # cpu: 500m + # memory: 128Mi + + # -- erlangFlags is a map that is passed to the Erlang VM as flags using the + # ERL_FLAGS env. The `name` flag is required to establish connectivity + # between cluster nodes. + # ref: http://erlang.org/doc/man/erl.html#init_flags erlangFlags: name: couchdb - setcookie: monster + # Older versions of the official CouchDB image (anything prior to 3.2.1) + # do not act on the COUCHDB_ERLANG_COOKIE environment variable, so if you + # want to cluster these deployments it's necessary to pass in a cookie here + # setcookie: make-something-up - ## couchdbConfig will override default CouchDB configuration settings. - ## The contents of this map are reformatted into a .ini file laid down - ## by a ConfigMap object. - ## ref: http://docs.couchdb.org/en/latest/config/index.html + # -- couchdbConfig will override default CouchDB configuration settings. + # The contents of this map are reformatted into a .ini file laid down + # by a ConfigMap object. + # ref: http://docs.couchdb.org/en/latest/config/index.html couchdbConfig: couchdb: - uuid: budibase-couchdb # REQUIRED: Unique identifier for this CouchDB server instance + uuid: decafbaddecafbaddecafbaddecafbad # Unique identifier for this CouchDB server instance # cluster: # q: 8 # Create 8 shards for each database chttpd: @@ -382,6 +456,9 @@ couchdb: # chttpd.require_valid_user disables all the anonymous requests to the port # 5984 when is set to true. require_valid_user: false + # required to use Fauxton if chttpd.require_valid_user is set to true + # httpd: + # WWW-Authenticate: "Basic realm=\"administrator\"" # Kubernetes local cluster domain. # This is used to generate FQDNs for peers when joining the CouchDB cluster. @@ -390,16 +467,56 @@ couchdb: ## Configure liveness and readiness probe values ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes - # FOR COUCHDB livenessProbe: + enabled: true failureThreshold: 3 initialDelaySeconds: 0 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 readinessProbe: + enabled: true failureThreshold: 3 initialDelaySeconds: 0 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 + + # Control an optional pod disruption budget + podDisruptionBudget: + # toggle creation of pod disruption budget, disabled by default + enabled: false + # minAvailable: 1 + maxUnavailable: 1 + + # CouchDB 3.2.0 adds in a metrics endpoint on the path `/_node/_local/_prometheus`. + # Optionally, a standalone, unauthenticated port can be exposed for these metrics. + prometheusPort: + enabled: false + bind_address: "0.0.0.0" + port: 17986 + + # Configure arbitrary sidecar containers for CouchDB pods created by the + # StatefulSet + sidecars: + {} + # - name: foo + # image: "busybox" + # imagePullPolicy: IfNotPresent + # resources: + # requests: + # cpu: "0.1" + # memory: 10Mi + # command: ['echo "foo";'] + # volumeMounts: + # - name: database-storage + # mountPath: /opt/couchdb/data/ + + # Placement manager to annotate each document in the nodes DB with "zone" attribute + # recording the zone where node has been scheduled + # Ref: https://docs.couchdb.org/en/stable/cluster/sharding.html#specifying-database-placement + placementConfig: + enabled: false + image: + repository: caligrafix/couchdb-autoscaler-placement-manager + tag: 0.1.0 From b7a704d06e1a6dc57d9967aa63468e2fb2998bbb Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 21 Nov 2023 17:32:58 +0000 Subject: [PATCH 03/19] Remove -name param from CouchDB image. Clouseau works without it and it fixes the image in Kubernetes. --- hosting/couchdb/clouseau/clouseau.ini | 3 --- hosting/couchdb/couch/vm.args | 1 - 2 files changed, 4 deletions(-) diff --git a/hosting/couchdb/clouseau/clouseau.ini b/hosting/couchdb/clouseau/clouseau.ini index 578a5acafa..9e03f8bc6e 100644 --- a/hosting/couchdb/clouseau/clouseau.ini +++ b/hosting/couchdb/clouseau/clouseau.ini @@ -1,8 +1,5 @@ [clouseau] -; the name of the Erlang node created by the service, leave this unchanged -name=clouseau@127.0.0.1 - ; set this to the same distributed Erlang cookie used by the CouchDB nodes cookie=monster diff --git a/hosting/couchdb/couch/vm.args b/hosting/couchdb/couch/vm.args index e9e4416863..33873b91a7 100644 --- a/hosting/couchdb/couch/vm.args +++ b/hosting/couchdb/couch/vm.args @@ -11,7 +11,6 @@ # the License. # erlang cookie for clouseau security --name couchdb@127.0.0.1 -setcookie monster # Ensure that the Erlang VM listens on a known port From 4af7bf459a64e6c041c1ac710e58c38cc1f7f386 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 21 Nov 2023 17:35:23 +0000 Subject: [PATCH 04/19] Remove extraneous creation timestamp. --- charts/budibase/templates/proxy-service-deployment.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/charts/budibase/templates/proxy-service-deployment.yaml b/charts/budibase/templates/proxy-service-deployment.yaml index 26f4265e4c..2e23f12793 100644 --- a/charts/budibase/templates/proxy-service-deployment.yaml +++ b/charts/budibase/templates/proxy-service-deployment.yaml @@ -24,7 +24,6 @@ spec: {{ if .Values.services.proxy.templateAnnotations }} {{- toYaml .Values.services.proxy.templateAnnotations | indent 8 -}} {{ end }} - creationTimestamp: null labels: app.kubernetes.io/name: budibase-proxy {{ if .Values.services.proxy.templateLabels }} From 423fa68f34007d36c83a51b3732d6fd1be8c7fb1 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 22 Nov 2023 10:35:53 +0000 Subject: [PATCH 05/19] Make the CouchDB image use the right directory on Kubernetes. --- hosting/couchdb/build-target-paths.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hosting/couchdb/build-target-paths.sh b/hosting/couchdb/build-target-paths.sh index 34227011f4..8bad974a1f 100644 --- a/hosting/couchdb/build-target-paths.sh +++ b/hosting/couchdb/build-target-paths.sh @@ -18,6 +18,11 @@ if [[ "${TARGETBUILD}" = "aas" ]]; then /etc/init.d/ssh restart sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini +elif [[ -n $KUBERNETES_SERVICE_HOST ]]; then + # In Kubernetes the directory /opt/couchdb/data has a persistent volume + # mount for storing database data. + sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/couchdb/etc/local.ini else sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini From 08ae4ef1328e87f8f420f0e6a494e2e4870be37f Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 22 Nov 2023 16:20:47 +0000 Subject: [PATCH 06/19] Fix the single image build working on Kubernetes. --- hosting/couchdb/build-target-paths.sh | 5 ++++- hosting/couchdb/runner.sh | 1 + hosting/single/Dockerfile.v2 | 1 - hosting/single/runner.sh | 4 ++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/hosting/couchdb/build-target-paths.sh b/hosting/couchdb/build-target-paths.sh index 8bad974a1f..90d9130cd4 100644 --- a/hosting/couchdb/build-target-paths.sh +++ b/hosting/couchdb/build-target-paths.sh @@ -18,7 +18,10 @@ if [[ "${TARGETBUILD}" = "aas" ]]; then /etc/init.d/ssh restart sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini -elif [[ -n $KUBERNETES_SERVICE_HOST ]]; then +elif [[ "${TARGETBUILD}" = "single" ]]; then + sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini +elif [[ -n $KUBERNETES_SERVICE_HOST ]]; then # In Kubernetes the directory /opt/couchdb/data has a persistent volume # mount for storing database data. sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/clouseau/clouseau.ini diff --git a/hosting/couchdb/runner.sh b/hosting/couchdb/runner.sh index 4102d2a751..32951cb539 100644 --- a/hosting/couchdb/runner.sh +++ b/hosting/couchdb/runner.sh @@ -1,6 +1,7 @@ #!/bin/bash DATA_DIR=${DATA_DIR:-/data} + mkdir -p ${DATA_DIR} mkdir -p ${DATA_DIR}/couch/{dbs,views} mkdir -p ${DATA_DIR}/search diff --git a/hosting/single/Dockerfile.v2 b/hosting/single/Dockerfile.v2 index ec03a1b5a2..dd61c779b5 100644 --- a/hosting/single/Dockerfile.v2 +++ b/hosting/single/Dockerfile.v2 @@ -94,7 +94,6 @@ RUN chmod +x ./healthcheck.sh # For Azure App Service install SSH & point data locations to /home COPY hosting/single/ssh/sshd_config /etc/ COPY hosting/single/ssh/ssh_setup.sh /tmp -RUN /build-target-paths.sh # setup letsencrypt certificate diff --git a/hosting/single/runner.sh b/hosting/single/runner.sh index 87201c95c0..f4b2b5b127 100644 --- a/hosting/single/runner.sh +++ b/hosting/single/runner.sh @@ -22,11 +22,11 @@ declare -a DOCKER_VARS=("APP_PORT" "APPS_URL" "ARCHITECTURE" "BUDIBASE_ENVIRONME # Azure App Service customisations if [[ "${TARGETBUILD}" = "aas" ]]; then - DATA_DIR="${DATA_DIR:-/home}" + export DATA_DIR="${DATA_DIR:-/home}" WEBSITES_ENABLE_APP_SERVICE_STORAGE=true /etc/init.d/ssh start else - DATA_DIR=${DATA_DIR:-/data} + export DATA_DIR=${DATA_DIR:-/data} fi mkdir -p ${DATA_DIR} # Mount NFS or GCP Filestore if env vars exist for it From 40fd056237099f53d627d955e2d0090ed3f4885b Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 23 Nov 2023 11:40:21 +0000 Subject: [PATCH 07/19] Make Clouseau work in both single image and Helm deployments. --- hosting/couchdb/Dockerfile | 3 +- hosting/couchdb/build-target-paths.sh | 32 --------------------- hosting/couchdb/clouseau/clouseau.ini | 3 ++ hosting/couchdb/couch/vm.args | 5 ++-- hosting/couchdb/runner.sh | 41 +++++++++++++++++++++++++-- hosting/single/Dockerfile | 1 - hosting/single/Dockerfile.v2 | 2 +- 7 files changed, 47 insertions(+), 40 deletions(-) delete mode 100644 hosting/couchdb/build-target-paths.sh diff --git a/hosting/couchdb/Dockerfile b/hosting/couchdb/Dockerfile index 792856cac7..f83df7038b 100644 --- a/hosting/couchdb/Dockerfile +++ b/hosting/couchdb/Dockerfile @@ -29,7 +29,6 @@ WORKDIR /opt/couchdb ADD couch/vm.args couch/local.ini ./etc/ WORKDIR / -ADD build-target-paths.sh . ADD runner.sh ./bbcouch-runner.sh -RUN chmod +x ./bbcouch-runner.sh /opt/clouseau/bin/clouseau ./build-target-paths.sh +RUN chmod +x ./bbcouch-runner.sh /opt/clouseau/bin/clouseau CMD ["./bbcouch-runner.sh"] diff --git a/hosting/couchdb/build-target-paths.sh b/hosting/couchdb/build-target-paths.sh deleted file mode 100644 index 90d9130cd4..0000000000 --- a/hosting/couchdb/build-target-paths.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -echo ${TARGETBUILD} > /buildtarget.txt -if [[ "${TARGETBUILD}" = "aas" ]]; then - # Azure AppService uses /home for persistent data & SSH on port 2222 - DATA_DIR="${DATA_DIR:-/home}" - WEBSITES_ENABLE_APP_SERVICE_STORAGE=true - mkdir -p $DATA_DIR/{search,minio,couch} - mkdir -p $DATA_DIR/couch/{dbs,views} - chown -R couchdb:couchdb $DATA_DIR/couch/ - apt update - apt-get install -y openssh-server - echo "root:Docker!" | chpasswd - mkdir -p /tmp - chmod +x /tmp/ssh_setup.sh \ - && (sleep 1;/tmp/ssh_setup.sh 2>&1 > /dev/null) - cp /etc/sshd_config /etc/ssh/sshd_config - /etc/init.d/ssh restart - sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini - sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini -elif [[ "${TARGETBUILD}" = "single" ]]; then - sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini - sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini -elif [[ -n $KUBERNETES_SERVICE_HOST ]]; then - # In Kubernetes the directory /opt/couchdb/data has a persistent volume - # mount for storing database data. - sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/clouseau/clouseau.ini - sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/couchdb/etc/local.ini -else - sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini - sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini -fi \ No newline at end of file diff --git a/hosting/couchdb/clouseau/clouseau.ini b/hosting/couchdb/clouseau/clouseau.ini index 9e03f8bc6e..578a5acafa 100644 --- a/hosting/couchdb/clouseau/clouseau.ini +++ b/hosting/couchdb/clouseau/clouseau.ini @@ -1,5 +1,8 @@ [clouseau] +; the name of the Erlang node created by the service, leave this unchanged +name=clouseau@127.0.0.1 + ; set this to the same distributed Erlang cookie used by the CouchDB nodes cookie=monster diff --git a/hosting/couchdb/couch/vm.args b/hosting/couchdb/couch/vm.args index 33873b91a7..ea2b4d26ae 100644 --- a/hosting/couchdb/couch/vm.args +++ b/hosting/couchdb/couch/vm.args @@ -11,6 +11,7 @@ # the License. # erlang cookie for clouseau security +-name couchdb@127.0.0.1 -setcookie monster # Ensure that the Erlang VM listens on a known port @@ -18,8 +19,8 @@ -kernel inet_dist_listen_max 9100 # Tell kernel and SASL not to log anything --kernel error_logger silent --sasl sasl_error_logger false +# -kernel error_logger silent +# -sasl sasl_error_logger false # Use kernel poll functionality if supported by emulator +K true diff --git a/hosting/couchdb/runner.sh b/hosting/couchdb/runner.sh index 32951cb539..2e4d26122f 100644 --- a/hosting/couchdb/runner.sh +++ b/hosting/couchdb/runner.sh @@ -6,10 +6,47 @@ mkdir -p ${DATA_DIR} mkdir -p ${DATA_DIR}/couch/{dbs,views} mkdir -p ${DATA_DIR}/search chown -R couchdb:couchdb ${DATA_DIR}/couch -/build-target-paths.sh + +echo ${TARGETBUILD} > /buildtarget.txt +if [[ "${TARGETBUILD}" = "aas" ]]; then + # Azure AppService uses /home for persistent data & SSH on port 2222 + DATA_DIR="${DATA_DIR:-/home}" + WEBSITES_ENABLE_APP_SERVICE_STORAGE=true + mkdir -p $DATA_DIR/{search,minio,couch} + mkdir -p $DATA_DIR/couch/{dbs,views} + chown -R couchdb:couchdb $DATA_DIR/couch/ + apt update + apt-get install -y openssh-server + echo "root:Docker!" | chpasswd + mkdir -p /tmp + chmod +x /tmp/ssh_setup.sh \ + && (sleep 1;/tmp/ssh_setup.sh 2>&1 > /dev/null) + cp /etc/sshd_config /etc/ssh/sshd_config + /etc/init.d/ssh restart + sed -i "s#DATA_DIR#/home#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/home#g" /opt/couchdb/etc/local.ini +elif [[ "${TARGETBUILD}" = "single" ]]; then + sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini +elif [[ -n $KUBERNETES_SERVICE_HOST ]]; then + # In Kubernetes the directory /opt/couchdb/data has a persistent volume + # mount for storing database data. + sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/opt/couchdb/data#g" /opt/couchdb/etc/local.ini + sed -i "s/^-name .*$//g" /opt/couchdb/etc/vm.args +else + sed -i "s#DATA_DIR#/data#g" /opt/clouseau/clouseau.ini + sed -i "s#DATA_DIR#/data#g" /opt/couchdb/etc/local.ini +fi + /opt/clouseau/bin/clouseau > /dev/stdout 2>&1 & /docker-entrypoint.sh /opt/couchdb/bin/couchdb & -sleep 10 + +while [[ $(curl -s -w "%{http_code}\n" http://localhost:5984/_up -o /dev/null) -ne 200 ]]; do + echo 'Waiting for CouchDB to start...'; + sleep 5; +done + curl -X PUT http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@localhost:5984/_users curl -X PUT http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@localhost:5984/_replicator sleep infinity \ No newline at end of file diff --git a/hosting/single/Dockerfile b/hosting/single/Dockerfile index c7b90dbdc4..84c3b824fb 100644 --- a/hosting/single/Dockerfile +++ b/hosting/single/Dockerfile @@ -81,7 +81,6 @@ RUN chmod +x ./healthcheck.sh # For Azure App Service install SSH & point data locations to /home ADD hosting/single/ssh/sshd_config /etc/ ADD hosting/single/ssh/ssh_setup.sh /tmp -RUN /build-target-paths.sh # cleanup cache RUN yarn cache clean -f diff --git a/hosting/single/Dockerfile.v2 b/hosting/single/Dockerfile.v2 index dd61c779b5..afbb377a4b 100644 --- a/hosting/single/Dockerfile.v2 +++ b/hosting/single/Dockerfile.v2 @@ -39,7 +39,7 @@ COPY packages/worker/pm2.config.js packages/worker/pm2.config.js COPY packages/string-templates packages/string-templates -FROM budibase/couchdb as runner +FROM samwho/test as runner ARG TARGETARCH ENV TARGETARCH $TARGETARCH ENV NODE_MAJOR 18 From c50770da0a31e1104844cb2d7bf0b9e6a80656bf Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 23 Nov 2023 17:06:52 +0000 Subject: [PATCH 08/19] Tidy up the chart. --- charts/budibase/values.yaml | 8 +++++--- hosting/couchdb/couch/vm.args | 4 ++-- hosting/single/Dockerfile.v2 | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/charts/budibase/values.yaml b/charts/budibase/values.yaml index 9409363bbb..5df6e980f0 100644 --- a/charts/budibase/values.yaml +++ b/charts/budibase/values.yaml @@ -262,7 +262,7 @@ services: # Override values in couchDB subchart couchdb: # -- the initial number of nodes in the CouchDB cluster. - clusterSize: 3 + clusterSize: 1 # -- If allowAdminParty is enabled the cluster will start up without any database # administrator account; i.e., all users will be granted administrative @@ -329,7 +329,9 @@ couchdb: tag: v3.2.1 pullPolicy: IfNotPresent - # -- Flip this to flag to include the Search container in each Pod + # This should remain false. We ship Clouseau ourselves as part of the + # budibase/couchdb image, and it's not possible to disable it because it's a + # core part of the Budibase experience. enableSearch: false initImage: @@ -448,7 +450,7 @@ couchdb: # ref: http://docs.couchdb.org/en/latest/config/index.html couchdbConfig: couchdb: - uuid: decafbaddecafbaddecafbaddecafbad # Unique identifier for this CouchDB server instance + uuid: budibase-couchdb # Unique identifier for this CouchDB server instance # cluster: # q: 8 # Create 8 shards for each database chttpd: diff --git a/hosting/couchdb/couch/vm.args b/hosting/couchdb/couch/vm.args index ea2b4d26ae..e9e4416863 100644 --- a/hosting/couchdb/couch/vm.args +++ b/hosting/couchdb/couch/vm.args @@ -19,8 +19,8 @@ -kernel inet_dist_listen_max 9100 # Tell kernel and SASL not to log anything -# -kernel error_logger silent -# -sasl sasl_error_logger false +-kernel error_logger silent +-sasl sasl_error_logger false # Use kernel poll functionality if supported by emulator +K true diff --git a/hosting/single/Dockerfile.v2 b/hosting/single/Dockerfile.v2 index afbb377a4b..dd61c779b5 100644 --- a/hosting/single/Dockerfile.v2 +++ b/hosting/single/Dockerfile.v2 @@ -39,7 +39,7 @@ COPY packages/worker/pm2.config.js packages/worker/pm2.config.js COPY packages/string-templates packages/string-templates -FROM samwho/test as runner +FROM budibase/couchdb as runner ARG TARGETARCH ENV TARGETARCH $TARGETARCH ENV NODE_MAJOR 18 From 6674bf139b08375d00f75c2380bf64afaaa8bf79 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 27 Nov 2023 17:12:13 +0000 Subject: [PATCH 09/19] Expand chart documentation, fix HPA definition. --- charts/budibase/README.md | 194 +++++- charts/budibase/README.md.gotmpl | 92 +++ .../budibase/templates/app-service-hpa.yaml | 32 + charts/budibase/templates/hpa.yaml | 28 - .../budibase/templates/proxy-service-hpa.yaml | 32 + .../templates/worker-service-hpa.yaml | 32 + charts/budibase/values.yaml | 598 ++++++++---------- 7 files changed, 630 insertions(+), 378 deletions(-) create mode 100644 charts/budibase/README.md.gotmpl create mode 100644 charts/budibase/templates/app-service-hpa.yaml delete mode 100644 charts/budibase/templates/hpa.yaml create mode 100644 charts/budibase/templates/proxy-service-hpa.yaml create mode 100644 charts/budibase/templates/worker-service-hpa.yaml diff --git a/charts/budibase/README.md b/charts/budibase/README.md index efa78ba75c..961776b977 100644 --- a/charts/budibase/README.md +++ b/charts/budibase/README.md @@ -1,39 +1,193 @@ -# Budibase +# budibase -[Budibase](https://budibase.com/) Budibase is an open source low-code platform, helping thousands of teams build apps for their workplace in minutes. - -## TL;DR; -```console -$ cd chart -$ helm install budibase . -``` - -## Introduction - -This chart bootstraps a [Budibase](https://budibase.com/) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. +Budibase is an open source low-code platform, helping thousands of teams build apps for their workplace in minutes. ## Prerequisites -- helm v3 or above +- `helm` v3 or above - Kubernetes 1.4+ -- PV provisioner support in the underlying infrastructure (with persistence storage enabled) +- A storage controller (for `PersistentVolume` creation, if you want to ensure your data does not get lost when pods restart) ## Installing the Chart -To install the chart with the release name `budi-release`: +To install the chart from our repository: ```console -$ helm install budi-release . +$ helm repo add budibase https://budibase.github.io/budibase/ +$ helm repo update +$ helm install --create-namespace --namespace budibase budibase budibase/budibase ``` -The command deploys Budibase on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. +To install the chart from this repo: -> **Tip**: List all releases using `helm list` +```console +$ git clone git@github.com:budibase/budibase.git +$ cd budibase/charts/budibase +$ helm install --create-namespace --namespace budibase budibase . +``` + +## Example minimal configuration + +Here's an example `values.yaml` that would get a Budibase instance running in a home +cluster using an nginx ingress controller and NFS as cluster storage (basically one of our +staff's homelabs). + +
+ +```yaml +ingress: + enabled: true + annotations: + nginx.ingress.kubernetes.io/client-max-body-size: 150M + nginx.ingress.kubernetes.io/proxy-body-size: 50m + className: "nginx" + hosts: + - host: budibase.local # set this to whatever DNS name you'd use + paths: + - backend: + service: + name: proxy-service + port: + number: 10000 + path: / + pathType: Prefix + +couchdb: + persistentVolume: + enabled: true + storageClass: "nfs-client" + adminPassword: admin + + image: + repository: samwho/test + tag: latest + pullPolicy: Always + + objectStore: + storageClass: "nfs-client" + redis: + storageClass: "nfs-client" +``` + +If you wanted to use this when bringing up Budibase in your own cluster, you could save it +to your hard disk and run the following: + +```console +$ helm install --create-namespace --namespace budibase budibase . -f values.yaml +``` + +
+ +## Configuration reference + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | Sets the affinity for all pods created by this chart. Should not ordinarily need to be changed. See for more information on affinity. | +| awsAlbIngress.certificateArn | string | `""` | If you're wanting to use HTTPS, you'll need to create an ACM certificate and specify the ARN here. | +| awsAlbIngress.enabled | bool | `false` | Whether to create an ALB Ingress resource pointing to the Budibase proxy. Requires the AWS ALB Ingress Controller. | +| couchdb.clusterSize | int | `1` | The number of replicas to run in the CouchDB cluster. We set this to 1 by default to make things simpler, but you can set it to 3 if you need a high-availability CouchDB cluster. | +| couchdb.couchdbConfig.couchdb.uuid | string | `"budibase-couchdb"` | Unique identifier for this CouchDB server instance. You shouldn't need to change this. | +| couchdb.image | object | `{}` | We use a custom CouchDB image for running Budibase and we don't support using any other CouchDB image. You shouldn't change this, and if you do we can't guarantee that Budibase will work. | +| globals.apiEncryptionKey | string | `""` | Used for encrypting API keys and environment variables when stored in the database. You don't need to set this if `createSecrets` is true. | +| globals.appVersion | string | `""` | The version of Budibase to deploy. Defaults to what's specified by {{ .Chart.AppVersion }}. Ends up being used as the image version tag for the apps, proxy, and worker images. | +| globals.automationMaxIterations | string | `"200"` | The maximum number of iterations allows for an automation loop step. You can read more about looping here: . | +| globals.budibaseEnv | string | `"PRODUCTION"` | Sets the environment variable BUDIBASE_ENVIRONMENT for the apps and worker pods. Should not ordinarily need to be changed. | +| globals.cookieDomain | string | `""` | Sets the domain attribute of the cookie that Budibase uses to store session information. See for details on why you might want to set this. | +| globals.createSecrets | bool | `true` | Create an internal API key, JWT secret, object store access key and secret, and store them in a Kubernetes `Secret`. | +| globals.enableAnalytics | string | `"1"` | Whether to enable analytics or not. You can read more about our analytics here: . | +| globals.google | object | `{"clientId":"","secret":""}` | Google OAuth settings. These can also be set in the Budibase UI, see for details. | +| globals.google.clientId | string | `""` | Client ID of your Google OAuth app. | +| globals.google.secret | string | `""` | Client secret of your Google OAuth app. | +| globals.httpMigrations | string | `"0"` | Whether or not to enable doing data migrations over the HTTP API. If this is set to "0", migrations are run on startup. You shouldn't ordinarily need to change this. | +| globals.internalApiKey | string | `""` | API key used for internal Budibase API calls. You don't need to set this if `createSecrets` is true. | +| globals.internalApiKeyFallback | string | `""` | A fallback value for `internalApiKey`. If you're rotating your encryption key, you can set this to the old value for the duration of the rotation. | +| globals.jwtSecret | string | `""` | Secret used for signing JWTs. You don't need to set this if `createSecrets` is true. | +| globals.jwtSecretFallback | string | `""` | A fallback value for `jwtSecret`. If you're rotating your JWT secret, you can set this to the old value for the duration of the rotation. | +| globals.multiTenancy | string | `"0"` | Whether to enable the multi-tenancy feature or not. "0" means an installation can only have one tenant. "1" allows multiple tenants. | +| globals.platformUrl | string | `""` | Set the `platformUrl` binding. You can also do this in Settings > Organisation if you are self-hosting. | +| globals.smtp.enabled | bool | `false` | Whether to enable SMTP or not. | +| globals.smtp.from | string | `""` | The email address to use in the "From:" field of emails sent by Budibase. | +| globals.smtp.host | string | `""` | The hostname of your SMTP server. | +| globals.smtp.password | string | `""` | The password to use when authenticating with your SMTP server. | +| globals.smtp.port | string | `"587"` | The port of your SMTP server. | +| globals.smtp.user | string | `""` | The username to use when authenticating with your SMTP server. | +| globals.tenantFeatureFlags | string | `"*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR"` | Sets what feature flags are enabled and for which tenants. Should not ordinarily need to be changed. | +| imagePullSecrets | list | `[]` | Passed to all pods created by this chart. Should not ordinarily need to be changed. | +| ingress.className | string | `""` | What ingress class to use. | +| ingress.enabled | bool | `true` | Whether to create an Ingress resource pointing to the Budibase proxy. | +| ingress.hosts | list | `[]` | Standard hosts block for the Ingress resource. Defaults to pointing to the Budibase proxy. | +| nameOverride | string | `""` | Override the name of the deploymen. Defaults to {{ .Chart.Name }}. | +| service.port | int | `10000` | Port to expose on the service. | +| service.type | string | `"ClusterIP"` | Service type for the service that points to the main Budibase proxy pod. | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | +| services.apps.autoscaling.enabled | bool | `false` | Whether to enable horizontal pod autoscaling for the apps service. | +| services.apps.autoscaling.maxReplicas | int | `10` | | +| services.apps.autoscaling.minReplicas | int | `1` | | +| services.apps.autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage for the apps service. Note that for autoscaling to work, you will need to have metrics-server configured, and resources set for the apps pods. | +| services.apps.httpLogging | int | `1` | Whether or not to log HTTP requests to the apps service. | +| services.apps.livenessProbe | object | HTTP health checks. | Liveness probe configuration for apps pods. You shouldn't need to change this, but if you want to you can find more information here: | +| services.apps.logLevel | string | `"info"` | The log level for the apps service. | +| services.apps.readinessProbe | object | HTTP health checks. | Readiness probe configuration for apps pods. You shouldn't need to change this, but if you want to you can find more information here: | +| services.apps.replicaCount | int | `1` | The number of apps replicas to run. | +| services.apps.resources | object | `{}` | The resources to use for apps pods. See for more information on how to set these. | +| services.apps.startupProbe | object | HTTP health checks. | Startup probe configuration for apps pods. You shouldn't need to change this, but if you want to you can find more information here: | +| services.couchdb.backup.enabled | bool | `false` | Whether or not to enable periodic CouchDB backups. This works by replicating to another CouchDB instance. | +| services.couchdb.backup.interval | string | `""` | Backup interval in seconds | +| services.couchdb.backup.resources | object | `{}` | The resources to use for CouchDB backup pods. See for more information on how to set these. | +| services.couchdb.backup.target | string | `""` | Target couchDB instance to back up to, either a hostname or an IP address. | +| services.couchdb.enabled | bool | `true` | Whether or not to spin up a CouchDB instance in your cluster. True by default, and the configuration for the CouchDB instance is under the `couchdb` key at the root of this file. You can see what options are available to you by looking at the official CouchDB Helm chart: . | +| services.couchdb.port | int | `5984` | | +| services.dns | string | `"cluster.local"` | The DNS suffix to use for service discovery. You only need to change this if you've configured your cluster to use a different DNS suffix. | +| services.objectStore.accessKey | string | `""` | AWS_ACCESS_KEY if using S3 | +| services.objectStore.browser | bool | `true` | Whether to enable the Minio web console or not. If you're exposing Minio to the Internet (via a custom Ingress record, for example), you should set this to false. If you're only exposing Minio to your cluster, you can leave this as true. | +| services.objectStore.cloudfront.cdn | string | `""` | Set the url of a distribution to enable cloudfront. | +| services.objectStore.cloudfront.privateKey64 | string | `""` | Base64 encoded private key for the above public key. | +| services.objectStore.cloudfront.publicKeyId | string | `""` | ID of public key stored in cloudfront. | +| services.objectStore.minio | bool | `true` | Set to false if using another object store, such as S3. You will need to set `services.objectStore.url` to point to your bucket if you do this. | +| services.objectStore.region | string | `""` | AWS_REGION if using S3 | +| services.objectStore.resources | object | `{}` | The resources to use for Minio pods. See for more information on how to set these. | +| services.objectStore.secretKey | string | `""` | AWS_SECRET_ACCESS_KEY if using S3 | +| services.objectStore.storage | string | `"100Mi"` | How much storage to give Minio in its PersistentVolumeClaim. | +| services.objectStore.storageClass | string | `""` | If defined, storageClassName: If set to "-", storageClassName: "", which disables dynamic provisioning If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. | +| services.objectStore.url | string | `"http://minio-service:9000"` | URL to use for object storage. Only change this if you're using an external object store, such as S3. Remember to set `minio: false` if you do this. | +| services.proxy.autoscaling.enabled | bool | `false` | Whether to enable horizontal pod autoscaling for the proxy service. | +| services.proxy.autoscaling.maxReplicas | int | `10` | | +| services.proxy.autoscaling.minReplicas | int | `1` | | +| services.proxy.autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage for the proxy service. Note that for autoscaling to work, you will need to have metrics-server configured, and resources set for the proxy pods. | +| services.proxy.livenessProbe | object | HTTP health checks. | Liveness probe configuration for proxy pods. You shouldn't need to change this, but if you want to you can find more information here: | +| services.proxy.readinessProbe | object | HTTP health checks. | Readiness probe configuration for proxy pods. You shouldn't need to change this, but if you want to you can find more information here: | +| services.proxy.replicaCount | int | `1` | The number of proxy replicas to run. | +| services.proxy.resources | object | `{}` | The resources to use for proxy pods. See for more information on how to set these. | +| services.proxy.startupProbe | object | HTTP health checks. | Startup probe configuration for proxy pods. You shouldn't need to change this, but if you want to you can find more information here: | +| services.redis.enabled | bool | `true` | Whether or not to deploy a Redis pod into your cluster. | +| services.redis.password | string | `"budibase"` | The password to use when connecting to Redis. It's recommended that you change this from the default if you're running Redis in-cluster. | +| services.redis.port | int | `6379` | Port to expose Redis on. | +| services.redis.resources | object | `{}` | The resources to use for Redis pods. See for more information on how to set these. | +| services.redis.storage | string | `"100Mi"` | How much persistent storage to allocate to Redis. | +| services.redis.storageClass | string | `""` | If defined, storageClassName: If set to "-", storageClassName: "", which disables dynamic provisioning If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. | +| services.redis.url | string | `""` | If you choose to run Redis externally to this chart, you can specify the connection details here. | +| services.worker.autoscaling.enabled | bool | `false` | Whether to enable horizontal pod autoscaling for the worker service. | +| services.worker.autoscaling.maxReplicas | int | `10` | | +| services.worker.autoscaling.minReplicas | int | `1` | | +| services.worker.autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage for the worker service. Note that for autoscaling to work, you will need to have metrics-server configured, and resources set for the worker pods. | +| services.worker.httpLogging | int | `1` | Whether or not to log HTTP requests to the worker service. | +| services.worker.livenessProbe | object | HTTP health checks. | Liveness probe configuration for worker pods. You shouldn't need to change this, but if you want to you can find more information here: | +| services.worker.logLevel | string | `"info"` | The log level for the worker service. | +| services.worker.readinessProbe | object | HTTP health checks. | Readiness probe configuration for worker pods. You shouldn't need to change this, but if you want to you can find more information here: | +| services.worker.replicaCount | int | `1` | The number of worker replicas to run. | +| services.worker.resources | object | `{}` | The resources to use for worker pods. See for more information on how to set these. | +| services.worker.startupProbe | object | HTTP health checks. | Startup probe configuration for worker pods. You shouldn't need to change this, but if you want to you can find more information here: | +| tolerations | list | `[]` | Sets the tolerations for all pods created by this chart. Should not ordinarily need to be changed. See for more information on tolerations. | ## Uninstalling the Chart -To uninstall/delete the `my-release` deployment: +To uninstall the chart, assuming you named the release `budibase` (both commands in the installation section do so): ```console -$ helm delete my-release +$ helm uninstall --namespace budibase budibase ``` + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.3](https://github.com/norwoodj/helm-docs/releases/v1.11.3) diff --git a/charts/budibase/README.md.gotmpl b/charts/budibase/README.md.gotmpl new file mode 100644 index 0000000000..eacd832e74 --- /dev/null +++ b/charts/budibase/README.md.gotmpl @@ -0,0 +1,92 @@ +{{ template "chart.header" . }} +{{ template "chart.description" . }} + +## Prerequisites + +- `helm` v3 or above +- Kubernetes 1.4+ +- A storage controller (for `PersistentVolume` creation, if you want to ensure your data does not get lost when pods restart) + +## Installing the Chart + +To install the chart from our repository: + +```console +$ helm repo add budibase https://budibase.github.io/budibase/ +$ helm repo update +$ helm install --create-namespace --namespace budibase budibase budibase/budibase +``` + +To install the chart from this repo: + +```console +$ git clone git@github.com:budibase/budibase.git +$ cd budibase/charts/budibase +$ helm install --create-namespace --namespace budibase budibase . +``` + +## Example minimal configuration + +Here's an example `values.yaml` that would get a Budibase instance running in a home +cluster using an nginx ingress controller and NFS as cluster storage (basically one of our +staff's homelabs). + +
+ +```yaml +ingress: + enabled: true + annotations: + nginx.ingress.kubernetes.io/client-max-body-size: 150M + nginx.ingress.kubernetes.io/proxy-body-size: 50m + className: "nginx" + hosts: + - host: budibase.local # set this to whatever DNS name you'd use + paths: + - backend: + service: + name: proxy-service + port: + number: 10000 + path: / + pathType: Prefix + +couchdb: + persistentVolume: + enabled: true + storageClass: "nfs-client" + adminPassword: admin + + image: + repository: samwho/test + tag: latest + pullPolicy: Always + + objectStore: + storageClass: "nfs-client" + redis: + storageClass: "nfs-client" +``` + +If you wanted to use this when bringing up Budibase in your own cluster, you could save it +to your hard disk and run the following: + +```console +$ helm install --create-namespace --namespace budibase budibase . -f values.yaml +``` + +
+ +## Configuration reference + +{{ template "chart.valuesTable" . }} + +## Uninstalling the Chart + +To uninstall the chart, assuming you named the release `budibase` (both commands in the installation section do so): + +```console +$ helm uninstall --namespace budibase budibase +``` + +{{ template "helm-docs.versionFooter" . }} diff --git a/charts/budibase/templates/app-service-hpa.yaml b/charts/budibase/templates/app-service-hpa.yaml new file mode 100644 index 0000000000..e819ecb9e3 --- /dev/null +++ b/charts/budibase/templates/app-service-hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.services.apps.autoscaling.enabled }} +apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "budibase.fullname" . }}-apps + labels: + {{- include "budibase.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: app-service + minReplicas: {{ .Values.services.apps.autoscaling.minReplicas }} + maxReplicas: {{ .Values.services.apps.autoscaling.maxReplicas }} + metrics: + {{- if .Values.services.apps.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.services.apps.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.services.apps.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.services.apps.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/charts/budibase/templates/hpa.yaml b/charts/budibase/templates/hpa.yaml deleted file mode 100644 index 2f901b4664..0000000000 --- a/charts/budibase/templates/hpa.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "budibase.fullname" . }} - labels: - {{- include "budibase.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "budibase.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/charts/budibase/templates/proxy-service-hpa.yaml b/charts/budibase/templates/proxy-service-hpa.yaml new file mode 100644 index 0000000000..b6c6022008 --- /dev/null +++ b/charts/budibase/templates/proxy-service-hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.services.proxy.autoscaling.enabled }} +apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "budibase.fullname" . }}-proxy + labels: + {{- include "budibase.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: proxy-service + minReplicas: {{ .Values.services.proxy.autoscaling.minReplicas }} + maxReplicas: {{ .Values.services.proxy.autoscaling.maxReplicas }} + metrics: + {{- if .Values.services.proxy.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.services.proxy.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.services.proxy.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.services.proxy.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/charts/budibase/templates/worker-service-hpa.yaml b/charts/budibase/templates/worker-service-hpa.yaml new file mode 100644 index 0000000000..a04cc259a0 --- /dev/null +++ b/charts/budibase/templates/worker-service-hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.services.worker.autoscaling.enabled }} +apiVersion: {{ ternary "autoscaling/v2" "autoscaling/v2beta2" (.Capabilities.APIVersions.Has "autoscaling/v2") }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "budibase.fullname" . }}-worker + labels: + {{- include "budibase.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: worker-service + minReplicas: {{ .Values.services.worker.autoscaling.minReplicas }} + maxReplicas: {{ .Values.services.worker.autoscaling.maxReplicas }} + metrics: + {{- if .Values.services.worker.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.services.worker.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.services.worker.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.services.worker.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/charts/budibase/values.yaml b/charts/budibase/values.yaml index 5df6e980f0..0b693a4df3 100644 --- a/charts/budibase/values.yaml +++ b/charts/budibase/values.yaml @@ -1,47 +1,32 @@ -# Default values for budibase. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - +# -- Passed to all pods created by this chart. Should not ordinarily need to be changed. imagePullSecrets: [] +# -- Override the name of the deploymen. Defaults to {{ .Chart.Name }}. nameOverride: "" -# fullnameOverride: "" serviceAccount: - # Specifies whether a service account should be created + # -- Specifies whether a service account should be created create: true - # Annotations to add to the service account + # -- Annotations to add to the service account annotations: {} - # The name of the service account to use. + # -- The name of the service account to use. # If not set and create is true, a name is generated using the fullname template name: "" -podAnnotations: {} - -podSecurityContext: - {} - # fsGroup: 2000 - -securityContext: - {} - # capabilities: - # drop: - # - ALL - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - service: + # -- Service type for the service that points to the main Budibase proxy pod. type: ClusterIP + # -- Port to expose on the service. port: 10000 ingress: + # -- Whether to create an Ingress resource pointing to the Budibase proxy. enabled: true + # -- What ingress class to use. className: "" - annotations: - # nginx.ingress.kubernetes.io/client-max-body-size: 150M - # nginx.ingress.kubernetes.io/proxy-body-size: 50m + # -- Standard hosts block for the Ingress resource. Defaults to pointing to the Budibase proxy. hosts: - - host: # change if using custom domain + # @ignore + - host: paths: - path: / pathType: Prefix @@ -52,473 +37,426 @@ ingress: number: 10000 awsAlbIngress: + # -- Whether to create an ALB Ingress resource pointing to the Budibase proxy. Requires the AWS ALB Ingress Controller. enabled: false + # -- If you're wanting to use HTTPS, you'll need to create an ACM certificate and specify the ARN here. certificateArn: "" -autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - -nodeSelector: {} - +# -- Sets the tolerations for all pods created by this chart. Should not ordinarily need to be changed. +# See for more information +# on tolerations. tolerations: [] +# -- Sets the affinity for all pods created by this chart. Should not ordinarily +# need to be changed. See +# +# for more information on affinity. affinity: {} globals: - appVersion: "" # Use as an override to .Chart.AppVersion + # -- The version of Budibase to deploy. Defaults to what's specified by {{ .Chart.AppVersion }}. + # Ends up being used as the image version tag for the apps, proxy, and worker images. + appVersion: "" + # -- Sets the environment variable BUDIBASE_ENVIRONMENT for the apps and worker pods. Should not + # ordinarily need to be changed. budibaseEnv: PRODUCTION + # -- Sets what feature flags are enabled and for which tenants. Should not ordinarily need to be + # changed. tenantFeatureFlags: "*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR" + # -- Whether to enable analytics or not. You can read more about our analytics here: + # . enableAnalytics: "1" + # @ignore (only used if enableAnalytics is set to 1) posthogToken: "phc_bIjZL7oh2GEUd2vqvTBH8WvrX0fWTFQMs6H5KQxiUxU" - selfHosted: "1" # set to 0 for budibase cloud environment, set to 1 for self-hosted setup - multiTenancy: "0" # set to 0 to disable multiple orgs, set to 1 to enable multiple orgs - offlineMode: "0" # set to 1 to enable offline mode + # @ignore (should not normally need to be changed, we only set this to "0" + # when deploying to our Cloud environment) + selfHosted: "1" + # -- Whether to enable the multi-tenancy feature or not. "0" means an installation can only + # have one tenant. "1" allows multiple tenants. + multiTenancy: "0" + # @ignore (only currently used to determine whether to fetch licenses offline or not, should + # not normally need to be changed) + offlineMode: "0" + # @ignore (only needs to be set in our cloud environment) accountPortalUrl: "" + # @ignore (only needs to be set in our cloud environment) accountPortalApiKey: "" + # -- Sets the domain attribute of the cookie that Budibase uses to store session information. + # See + # for details on why you might want to set this. cookieDomain: "" + # -- Set the `platformUrl` binding. You can also do this in Settings > Organisation if you are + # self-hosting. platformUrl: "" + # -- Whether or not to enable doing data migrations over the HTTP API. If this is set to "0", + # migrations are run on startup. You shouldn't ordinarily need to change this. httpMigrations: "0" + # -- Google OAuth settings. These can also be set in the Budibase UI, see + # for details. google: + # -- Client ID of your Google OAuth app. clientId: "" + # -- Client secret of your Google OAuth app. secret: "" + # -- The maximum number of iterations allows for an automation loop step. You can read more about + # looping here: . automationMaxIterations: "200" - createSecrets: true # creates an internal API key, JWT secrets and redis password for you + # -- Create an internal API key, JWT secret, object store access key and + # secret, and store them in a Kubernetes `Secret`. + createSecrets: true - # if createSecrets is set to false, you can hard-code your secrets here + # -- Used for encrypting API keys and environment variables when stored in the database. + # You don't need to set this if `createSecrets` is true. apiEncryptionKey: "" + # -- API key used for internal Budibase API calls. You don't need to set this + # if `createSecrets` is true. internalApiKey: "" + # -- Secret used for signing JWTs. You don't need to set this if `createSecrets` is true. jwtSecret: "" - cdnUrl: "" - # fallback values used during live rotation + + # -- A fallback value for `internalApiKey`. If you're rotating your encryption key, you can + # set this to the old value for the duration of the rotation. internalApiKeyFallback: "" + # -- A fallback value for `jwtSecret`. If you're rotating your JWT secret, you can set this + # to the old value for the duration of the rotation. jwtSecretFallback: "" smtp: + # -- Whether to enable SMTP or not. enabled: false - -# globalAgentHttpProxy: -# globalAgentHttpsProxy: -# globalAgentNoProxy: + # -- The hostname of your SMTP server. + host: "" + # -- The port of your SMTP server. + port: "587" + # -- The email address to use in the "From:" field of emails sent by Budibase. + from: "" + # -- The username to use when authenticating with your SMTP server. + user: "" + # -- The password to use when authenticating with your SMTP server. + password: "" services: + # -- The DNS suffix to use for service discovery. You only need to change this + # if you've configured your cluster to use a different DNS suffix. dns: cluster.local - # tlsRejectUnauthorized: 0 proxy: + # @ignore (you shouldn't need to change this) port: 10000 + # -- The number of proxy replicas to run. replicaCount: 1 + # @ignore (you should never need to change this) upstreams: apps: "http://app-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.apps.port }}" worker: "http://worker-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.worker.port }}" minio: "http://minio-service.{{ .Release.Namespace }}.svc.{{ .Values.services.dns }}:{{ .Values.services.objectStore.port }}" couchdb: "http://{{ .Release.Name }}-svc-couchdb:{{ .Values.services.couchdb.port }}" + # -- The resources to use for proxy pods. See + # + # for more information on how to set these. resources: {} + # -- Startup probe configuration for proxy pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. startupProbe: + # @ignore httpGet: path: /health port: 10000 scheme: HTTP + # @ignore failureThreshold: 30 + # @ignore periodSeconds: 3 + # -- Readiness probe configuration for proxy pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. readinessProbe: + # @ignore httpGet: path: /health port: 10000 scheme: HTTP + # @ignore periodSeconds: 3 + # @ignore failureThreshold: 1 + # -- Liveness probe configuration for proxy pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. livenessProbe: + # @ignore httpGet: path: /health port: 10000 scheme: HTTP + # @ignore failureThreshold: 3 + # @ignore periodSeconds: 5 + autoscaling: + # -- Whether to enable horizontal pod autoscaling for the proxy service. + enabled: false + minReplicas: 1 + maxReplicas: 10 + # -- Target CPU utilization percentage for the proxy service. Note that + # for autoscaling to work, you will need to have metrics-server + # configured, and resources set for the proxy pods. + targetCPUUtilizationPercentage: 80 apps: + # @ignore (you shouldn't need to change this) port: 4002 + # -- The number of apps replicas to run. replicaCount: 1 + # -- The log level for the apps service. logLevel: info + # -- Whether or not to log HTTP requests to the apps service. httpLogging: 1 + # -- The resources to use for apps pods. See + # + # for more information on how to set these. resources: {} + # -- Startup probe configuration for apps pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. startupProbe: + # @ignore httpGet: path: /health port: 4002 scheme: HTTP + # @ignore failureThreshold: 30 + # @ignore periodSeconds: 3 + # -- Readiness probe configuration for apps pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. readinessProbe: + # @ignore httpGet: path: /health port: 4002 scheme: HTTP + # @ignore periodSeconds: 3 + # @ignore failureThreshold: 1 + # -- Liveness probe configuration for apps pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. livenessProbe: + # @ignore httpGet: path: /health port: 4002 scheme: HTTP + # @ignore failureThreshold: 3 + # @ignore periodSeconds: 5 - # nodeDebug: "" # set the value of NODE_DEBUG - # annotations: - # co.elastic.logs/multiline.type: pattern - # co.elastic.logs/multiline.pattern: '^[[:space:]]' - # co.elastic.logs/multiline.negate: false - # co.elastic.logs/multiline.match: after + autoscaling: + # -- Whether to enable horizontal pod autoscaling for the apps service. + enabled: false + minReplicas: 1 + maxReplicas: 10 + # -- Target CPU utilization percentage for the apps service. Note that for + # autoscaling to work, you will need to have metrics-server configured, + # and resources set for the apps pods. + targetCPUUtilizationPercentage: 80 + worker: + # @ignore (you shouldn't need to change this) port: 4003 + # -- The number of worker replicas to run. replicaCount: 1 + # -- The log level for the worker service. logLevel: info + # -- Whether or not to log HTTP requests to the worker service. httpLogging: 1 + # -- The resources to use for worker pods. See + # + # for more information on how to set these. resources: {} + # -- Startup probe configuration for worker pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. startupProbe: + # @ignore httpGet: path: /health port: 4003 scheme: HTTP + # @ignore failureThreshold: 30 + # @ignore periodSeconds: 3 + # -- Readiness probe configuration for worker pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. readinessProbe: + # @ignore httpGet: path: /health port: 4003 scheme: HTTP + # @ignore periodSeconds: 3 + # @ignore failureThreshold: 1 + # -- Liveness probe configuration for worker pods. You shouldn't need to + # change this, but if you want to you can find more information here: + # + # @default -- HTTP health checks. livenessProbe: + # @ignore httpGet: path: /health port: 4003 scheme: HTTP + # @ignore failureThreshold: 3 + # @ignore periodSeconds: 5 - # annotations: - # co.elastic.logs/multiline.type: pattern - # co.elastic.logs/multiline.pattern: '^[[:space:]]' - # co.elastic.logs/multiline.negate: false - # co.elastic.logs/multiline.match: after + autoscaling: + # -- Whether to enable horizontal pod autoscaling for the worker service. + enabled: false + minReplicas: 1 + maxReplicas: 10 + # -- Target CPU utilization percentage for the worker service. Note that + # for autoscaling to work, you will need to have metrics-server + # configured, and resources set for the worker pods. + targetCPUUtilizationPercentage: 80 couchdb: + # -- Whether or not to spin up a CouchDB instance in your cluster. True by + # default, and the configuration for the CouchDB instance is under the + # `couchdb` key at the root of this file. You can see what options are + # available to you by looking at the official CouchDB Helm chart: + # . enabled: true # url: "" # only change if pointing to existing couch server # user: "" # only change if pointing to existing couch server # password: "" # only change if pointing to existing couch server port: 5984 backup: + # -- Whether or not to enable periodic CouchDB backups. This works by replicating + # to another CouchDB instance. enabled: false - # target couchDB instance to back up to + # -- Target couchDB instance to back up to, either a hostname or an IP address. target: "" - # backup interval in seconds + # -- Backup interval in seconds interval: "" + # -- The resources to use for CouchDB backup pods. See + # + # for more information on how to set these. resources: {} redis: - enabled: true # disable if using external redis + # -- Whether or not to deploy a Redis pod into your cluster. + enabled: true + # -- Port to expose Redis on. port: 6379 + # @ignore (you should leave this as 1, we don't support clustering Redis) replicaCount: 1 - url: "" # only change if pointing to existing redis cluster and enabled: false - password: "budibase" # recommended to override if using built-in redis + # -- If you choose to run Redis externally to this chart, you can specify the + # connection details here. + url: "" + # -- The password to use when connecting to Redis. It's recommended that you change + # this from the default if you're running Redis in-cluster. + password: "budibase" + # -- How much persistent storage to allocate to Redis. storage: 100Mi - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. + # -- If defined, storageClassName: If set to "-", + # storageClassName: "", which disables dynamic provisioning If undefined + # (the default) or set to null, no storageClassName spec is set, choosing + # the default provisioner. storageClass: "" + # -- The resources to use for Redis pods. See + # + # for more information on how to set these. resources: {} objectStore: - # Set to false if using another object store such as S3 + # -- Set to false if using another object store, such as S3. You will need + # to set `services.objectStore.url` to point to your bucket if you do this. minio: true + # -- Whether to enable the Minio web console or not. If you're exposing + # Minio to the Internet (via a custom Ingress record, for example), you + # should set this to false. If you're only exposing Minio to your cluster, + # you can leave this as true. browser: true + # @ignore port: 9000 + # @ignore (you should leave this as 1, we don't support clustering Minio) replicaCount: 1 - accessKey: "" # AWS_ACCESS_KEY if using S3 or existing minio access key - secretKey: "" # AWS_SECRET_ACCESS_KEY if using S3 or existing minio secret - region: "" # AWS_REGION if using S3 or existing minio secret - url: "http://minio-service:9000" # only change if pointing to existing minio cluster or S3 and minio: false + # -- AWS_ACCESS_KEY if using S3 + accessKey: "" + # -- AWS_SECRET_ACCESS_KEY if using S3 + secretKey: "" + # -- AWS_REGION if using S3 + region: "" + # -- URL to use for object storage. Only change this if you're using an + # external object store, such as S3. Remember to set `minio: false` if you + # do this. + url: "http://minio-service:9000" + # -- How much storage to give Minio in its PersistentVolumeClaim. storage: 100Mi - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. + # -- If defined, storageClassName: If set to "-", + # storageClassName: "", which disables dynamic provisioning If undefined + # (the default) or set to null, no storageClassName spec is set, choosing + # the default provisioner. storageClass: "" + # -- The resources to use for Minio pods. See + # + # for more information on how to set these. resources: {} cloudfront: - # Set the url of a distribution to enable cloudfront + # -- Set the url of a distribution to enable cloudfront. cdn: "" - # ID of public key stored in cloudfront + # -- ID of public key stored in cloudfront. publicKeyId: "" - # Base64 encoded private key for the above public key + # -- Base64 encoded private key for the above public key. privateKey64: "" -# Override values in couchDB subchart +# Override values in couchDB subchart. We're only specifying the values we're changing. +# If you want to see all of the available values, see: +# https://github.com/apache/couchdb-helm/tree/couchdb-4.3.0/couchdb couchdb: - # -- the initial number of nodes in the CouchDB cluster. + # -- The number of replicas to run in the CouchDB cluster. We set this to + # 1 by default to make things simpler, but you can set it to 3 if you need + # a high-availability CouchDB cluster. clusterSize: 1 - # -- If allowAdminParty is enabled the cluster will start up without any database - # administrator account; i.e., all users will be granted administrative - # access. Otherwise, the system will look for a Secret called - # -couchdb containing `adminUsername`, `adminPassword` and - # `cookieAuthSecret` keys. See the `createAdminSecret` flag. - # ref: https://kubernetes.io/docs/concepts/configuration/secret/ - allowAdminParty: false - - # -- If createAdminSecret is enabled a Secret called -couchdb will - # be created containing auto-generated credentials. Users who prefer to set - # these values themselves have a couple of options: - # - # 1) The `adminUsername`, `adminPassword`, `adminHash`, and `cookieAuthSecret` - # can be defined directly in the chart's values. Note that all of a chart's - # values are currently stored in plaintext in a ConfigMap in the tiller - # namespace. - # - # 2) This flag can be disabled and a Secret with the required keys can be - # created ahead of time. - createAdminSecret: true - - adminUsername: admin - # adminPassword: this_is_not_secure - # adminHash: -pbkdf2-this_is_not_necessarily_secure_either - # cookieAuthSecret: neither_is_this - - ## When enabled, will deploy a networkpolicy that allows CouchDB pods to - ## communicate with each other for clustering and ingress on port 5984 - networkPolicy: - enabled: true - - ## Use an alternate scheduler, e.g. "stork". - ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ - ## - # schedulerName: - - # Use a service account - serviceAccount: - enabled: true - create: true - # name: - # imagePullSecrets: - # - name: myimagepullsecret - - # -- The storage volume used by each Pod in the StatefulSet. If a - # persistentVolume is not enabled, the Pods will use `emptyDir` ephemeral - # local storage. Setting the storageClass attribute to "-" disables dynamic - # provisioning of Persistent Volumes; leaving it unset will invoke the default - # provisioner. - persistentVolume: - enabled: false - # NOTE: the number of existing claims must match the cluster size - existingClaims: [] - annotations: {} - accessModes: - - ReadWriteOnce - size: 10Gi - # storageClass: "-" - - ## The CouchDB image + # -- We use a custom CouchDB image for running Budibase and we don't support + # using any other CouchDB image. You shouldn't change this, and if you do we + # can't guarantee that Budibase will work. image: + # @ignore repository: budibase/couchdb + # @ignore tag: v3.2.1 - pullPolicy: IfNotPresent + # @ignore + pullPolicy: Always + # @ignore # This should remain false. We ship Clouseau ourselves as part of the # budibase/couchdb image, and it's not possible to disable it because it's a # core part of the Budibase experience. enableSearch: false - initImage: - repository: busybox - tag: latest - pullPolicy: Always - - ## CouchDB is happy to spin up cluster nodes in parallel, but if you encounter - ## problems you can try setting podManagementPolicy to the StatefulSet default - ## `OrderedReady` - podManagementPolicy: Parallel - - ## To better tolerate Node failures, we can prevent Kubernetes scheduler from - ## assigning more than one Pod of CouchDB StatefulSet per Node using podAntiAffinity. - affinity: - {} - # podAntiAffinity: - # requiredDuringSchedulingIgnoredDuringExecution: - # - labelSelector: - # matchExpressions: - # - key: "app" - # operator: In - # values: - # - couchdb - # topologyKey: "kubernetes.io/hostname" - - ## To control how Pods are spread across your cluster among failure-domains such as regions, - ## zones, nodes, and other user-defined topology domains use topologySpreadConstraints. - topologySpreadConstraints: - {} - # topologySpreadConstraints: - # - maxSkew: 1 - # topologyKey: "topology.kubernetes.io/zone" - # whenUnsatisfiable: ScheduleAnyway - # labelSelector: - # matchLabels: - # app: couchdb - - ## Optional pod labels - labels: {} - - ## Optional pod annotations - annotations: {} - - ## Optional tolerations - tolerations: [] - - ## A StatefulSet requires a headless Service to establish the stable network - ## identities of the Pods, and that Service is created automatically by this - ## chart without any additional configuration. The Service block below refers - ## to a second Service that governs how clients connect to the CouchDB cluster. - service: - annotations: {} - enabled: true - type: ClusterIP - externalPort: 5984 - targetPort: 5984 - labels: {} - - ## An Ingress resource can provide name-based virtual hosting and TLS - ## termination among other things for CouchDB deployments which are accessed - ## from outside the Kubernetes cluster. - ## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/ - ingress: - enabled: false - # className: nginx - hosts: - - chart-example.local - path: / - annotations: - {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - tls: - # Secrets must be manually created in the namespace. - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - - ## Optional resource requests and limits for the CouchDB container - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - resources: - {} - # requests: - # cpu: 100m - # memory: 128Mi - # limits: - # cpu: 56 - # memory: 256Gi - - ## Optional resource requests and limits for the CouchDB init container - ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ - initResources: - {} - # requests: - # cpu: 100m - # memory: 128Mi - # limits: - # cpu: 500m - # memory: 128Mi - - # -- erlangFlags is a map that is passed to the Erlang VM as flags using the - # ERL_FLAGS env. The `name` flag is required to establish connectivity - # between cluster nodes. - # ref: http://erlang.org/doc/man/erl.html#init_flags - erlangFlags: - name: couchdb - # Older versions of the official CouchDB image (anything prior to 3.2.1) - # do not act on the COUCHDB_ERLANG_COOKIE environment variable, so if you - # want to cluster these deployments it's necessary to pass in a cookie here - # setcookie: make-something-up - - # -- couchdbConfig will override default CouchDB configuration settings. - # The contents of this map are reformatted into a .ini file laid down - # by a ConfigMap object. - # ref: http://docs.couchdb.org/en/latest/config/index.html couchdbConfig: couchdb: - uuid: budibase-couchdb # Unique identifier for this CouchDB server instance - # cluster: - # q: 8 # Create 8 shards for each database - chttpd: - bind_address: any - # chttpd.require_valid_user disables all the anonymous requests to the port - # 5984 when is set to true. - require_valid_user: false - # required to use Fauxton if chttpd.require_valid_user is set to true - # httpd: - # WWW-Authenticate: "Basic realm=\"administrator\"" - - # Kubernetes local cluster domain. - # This is used to generate FQDNs for peers when joining the CouchDB cluster. - dns: - clusterDomainSuffix: cluster.local - - ## Configure liveness and readiness probe values - ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes - livenessProbe: - enabled: true - failureThreshold: 3 - initialDelaySeconds: 0 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - readinessProbe: - enabled: true - failureThreshold: 3 - initialDelaySeconds: 0 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - - # Control an optional pod disruption budget - podDisruptionBudget: - # toggle creation of pod disruption budget, disabled by default - enabled: false - # minAvailable: 1 - maxUnavailable: 1 - - # CouchDB 3.2.0 adds in a metrics endpoint on the path `/_node/_local/_prometheus`. - # Optionally, a standalone, unauthenticated port can be exposed for these metrics. - prometheusPort: - enabled: false - bind_address: "0.0.0.0" - port: 17986 - - # Configure arbitrary sidecar containers for CouchDB pods created by the - # StatefulSet - sidecars: - {} - # - name: foo - # image: "busybox" - # imagePullPolicy: IfNotPresent - # resources: - # requests: - # cpu: "0.1" - # memory: 10Mi - # command: ['echo "foo";'] - # volumeMounts: - # - name: database-storage - # mountPath: /opt/couchdb/data/ - - # Placement manager to annotate each document in the nodes DB with "zone" attribute - # recording the zone where node has been scheduled - # Ref: https://docs.couchdb.org/en/stable/cluster/sharding.html#specifying-database-placement - placementConfig: - enabled: false - image: - repository: caligrafix/couchdb-autoscaler-placement-manager - tag: 0.1.0 + # -- Unique identifier for this CouchDB server instance. You shouldn't need + # to change this. + uuid: budibase-couchdb From 7e1036251519bc97f8fdd8e8330598650af450b6 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 27 Nov 2023 17:14:52 +0000 Subject: [PATCH 10/19] More README tweaks. --- charts/budibase/README.md | 9 ++++++++- charts/budibase/README.md.gotmpl | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/charts/budibase/README.md b/charts/budibase/README.md index 961776b977..9164ace2ce 100644 --- a/charts/budibase/README.md +++ b/charts/budibase/README.md @@ -6,7 +6,14 @@ Budibase is an open source low-code platform, helping thousands of teams build a - `helm` v3 or above - Kubernetes 1.4+ -- A storage controller (for `PersistentVolume` creation, if you want to ensure your data does not get lost when pods restart) +- A storage controller (if you want to use persistent storage) +- An ingress controller (if you want to define an `Ingress` resource) + +## Chart dependencies + +This chart depends on the official Apache CouchDB chart. You can see its +documentation here: +. ## Installing the Chart diff --git a/charts/budibase/README.md.gotmpl b/charts/budibase/README.md.gotmpl index eacd832e74..23c2399a15 100644 --- a/charts/budibase/README.md.gotmpl +++ b/charts/budibase/README.md.gotmpl @@ -5,7 +5,14 @@ - `helm` v3 or above - Kubernetes 1.4+ -- A storage controller (for `PersistentVolume` creation, if you want to ensure your data does not get lost when pods restart) +- A storage controller (if you want to use persistent storage) +- An ingress controller (if you want to define an `Ingress` resource) + +## Chart dependencies + +This chart depends on the official Apache CouchDB chart. You can see its +documentation here: +. ## Installing the Chart From f917e5624560fa0b370a2a7ab12a086e820d9708 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 27 Nov 2023 17:16:06 +0000 Subject: [PATCH 11/19] Note metrics-server dependency. --- charts/budibase/README.md | 1 + charts/budibase/README.md.gotmpl | 1 + 2 files changed, 2 insertions(+) diff --git a/charts/budibase/README.md b/charts/budibase/README.md index 9164ace2ce..ac25ccf7c9 100644 --- a/charts/budibase/README.md +++ b/charts/budibase/README.md @@ -8,6 +8,7 @@ Budibase is an open source low-code platform, helping thousands of teams build a - Kubernetes 1.4+ - A storage controller (if you want to use persistent storage) - An ingress controller (if you want to define an `Ingress` resource) +- `metrics-server` (if you want to make use of horizontal pod autoscaling) ## Chart dependencies diff --git a/charts/budibase/README.md.gotmpl b/charts/budibase/README.md.gotmpl index 23c2399a15..91f9822cb3 100644 --- a/charts/budibase/README.md.gotmpl +++ b/charts/budibase/README.md.gotmpl @@ -7,6 +7,7 @@ - Kubernetes 1.4+ - A storage controller (if you want to use persistent storage) - An ingress controller (if you want to define an `Ingress` resource) +- `metrics-server` (if you want to make use of horizontal pod autoscaling) ## Chart dependencies From adeb29a6a7109cdc9e201f0aa5f50f14d1b1323a Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Tue, 28 Nov 2023 14:21:27 +0000 Subject: [PATCH 12/19] Update pro to same as master. --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index 5e3d59fc40..1037b032d4 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 5e3d59fc4060fd44b14b2599269c207753d4e5be +Subproject commit 1037b032d49244678204704d1bca779a29e395eb From 7ba412d5c85a5cc8e816eb9868604301dd7f2fa9 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 29 Nov 2023 16:53:17 +0000 Subject: [PATCH 13/19] List breaking changes between 2.x and 3.0.0 in chart readme. --- charts/budibase/README.md | 29 ++++++++++++++++++++++++++--- charts/budibase/README.md.gotmpl | 29 ++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/charts/budibase/README.md b/charts/budibase/README.md index ac25ccf7c9..808943186e 100644 --- a/charts/budibase/README.md +++ b/charts/budibase/README.md @@ -16,7 +16,30 @@ This chart depends on the official Apache CouchDB chart. You can see its documentation here: . -## Installing the Chart +## Upgrading + +### `2.x` to `3.0.0` + +We made a number of breaking changes in this release to make the chart more +idiomatic and easier to use. + +1. We no longer bundle `ingress-nginx`. If you were relying on this to supply + an ingress controller to your cluster, you will now need to deploy that + separately. You'll find guidance for that here: + . +2. We've upgraded the version of the [CouchDB chart](https://github.com/apache/couchdb-helm) + we use from `3.3.4` to `4.3.0`. The primary motivation for this was to align + the CouchDB chart used with the CouchDB version used, which has also updated + from 3.1.1 to 3.2.1. +3. We've separated out the supplied AWS ALB ingress resource for those deploying + into EKS. Where previously you enabled this by setting `ingress.enabled: false` + and `ingress.aws: true`, you now set `awsAlbIngress.enabled: true` and all + configuration for it is under `awsAlbIngress`. +4. The `HorizontalPodAutoscaler` that was configured at `hpa.enabled: true` has + been split into 3 separate HPAs, one for each of `apps`, `worker`, and `proxy`. + They are configured at `services.{apps,worker,proxy}.autoscaling`. + +## Installing To install the chart from our repository: @@ -86,7 +109,7 @@ $ helm install --create-namespace --namespace budibase budibase . -f values.yaml -## Configuration reference +## Configuring | Key | Type | Default | Description | |-----|------|---------|-------------| @@ -189,7 +212,7 @@ $ helm install --create-namespace --namespace budibase budibase . -f values.yaml | services.worker.startupProbe | object | HTTP health checks. | Startup probe configuration for worker pods. You shouldn't need to change this, but if you want to you can find more information here: | | tolerations | list | `[]` | Sets the tolerations for all pods created by this chart. Should not ordinarily need to be changed. See for more information on tolerations. | -## Uninstalling the Chart +## Uninstalling To uninstall the chart, assuming you named the release `budibase` (both commands in the installation section do so): diff --git a/charts/budibase/README.md.gotmpl b/charts/budibase/README.md.gotmpl index 91f9822cb3..66c8370ab8 100644 --- a/charts/budibase/README.md.gotmpl +++ b/charts/budibase/README.md.gotmpl @@ -15,7 +15,30 @@ This chart depends on the official Apache CouchDB chart. You can see its documentation here: . -## Installing the Chart +## Upgrading + +### `2.x` to `3.0.0` + +We made a number of breaking changes in this release to make the chart more +idiomatic and easier to use. + +1. We no longer bundle `ingress-nginx`. If you were relying on this to supply + an ingress controller to your cluster, you will now need to deploy that + separately. You'll find guidance for that here: + . +2. We've upgraded the version of the [CouchDB chart](https://github.com/apache/couchdb-helm) + we use from `3.3.4` to `4.3.0`. The primary motivation for this was to align + the CouchDB chart used with the CouchDB version used, which has also updated + from 3.1.1 to 3.2.1. +3. We've separated out the supplied AWS ALB ingress resource for those deploying + into EKS. Where previously you enabled this by setting `ingress.enabled: false` + and `ingress.aws: true`, you now set `awsAlbIngress.enabled: true` and all + configuration for it is under `awsAlbIngress`. +4. The `HorizontalPodAutoscaler` that was configured at `hpa.enabled: true` has + been split into 3 separate HPAs, one for each of `apps`, `worker`, and `proxy`. + They are configured at `services.{apps,worker,proxy}.autoscaling`. + +## Installing To install the chart from our repository: @@ -85,11 +108,11 @@ $ helm install --create-namespace --namespace budibase budibase . -f values.yaml -## Configuration reference +## Configuring {{ template "chart.valuesTable" . }} -## Uninstalling the Chart +## Uninstalling To uninstall the chart, assuming you named the release `budibase` (both commands in the installation section do so): From e4b1cf77053556d7674a3a8b54f86e26f58abf58 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 29 Nov 2023 16:57:11 +0000 Subject: [PATCH 14/19] Note that we're moving to our own CouchDB image in the helm chart readme. --- charts/budibase/README.md.gotmpl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/charts/budibase/README.md.gotmpl b/charts/budibase/README.md.gotmpl index 66c8370ab8..ac3bfef77d 100644 --- a/charts/budibase/README.md.gotmpl +++ b/charts/budibase/README.md.gotmpl @@ -29,7 +29,8 @@ idiomatic and easier to use. 2. We've upgraded the version of the [CouchDB chart](https://github.com/apache/couchdb-helm) we use from `3.3.4` to `4.3.0`. The primary motivation for this was to align the CouchDB chart used with the CouchDB version used, which has also updated - from 3.1.1 to 3.2.1. + from 3.1.1 to 3.2.1. Additionally, we're moving away from the official CouchDB + to one we're building ourselves. 3. We've separated out the supplied AWS ALB ingress resource for those deploying into EKS. Where previously you enabled this by setting `ingress.enabled: false` and `ingress.aws: true`, you now set `awsAlbIngress.enabled: true` and all From 1642d18d7dcdfad9a858f3049a1fa5d69aed859a Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 29 Nov 2023 17:01:08 +0000 Subject: [PATCH 15/19] Remove incorrect image from values.yaml example. --- charts/budibase/README.md | 8 ++------ charts/budibase/README.md.gotmpl | 5 ----- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/charts/budibase/README.md b/charts/budibase/README.md index 808943186e..5d74e05e0b 100644 --- a/charts/budibase/README.md +++ b/charts/budibase/README.md @@ -30,7 +30,8 @@ idiomatic and easier to use. 2. We've upgraded the version of the [CouchDB chart](https://github.com/apache/couchdb-helm) we use from `3.3.4` to `4.3.0`. The primary motivation for this was to align the CouchDB chart used with the CouchDB version used, which has also updated - from 3.1.1 to 3.2.1. + from 3.1.1 to 3.2.1. Additionally, we're moving away from the official CouchDB + to one we're building ourselves. 3. We've separated out the supplied AWS ALB ingress resource for those deploying into EKS. Where previously you enabled this by setting `ingress.enabled: false` and `ingress.aws: true`, you now set `awsAlbIngress.enabled: true` and all @@ -89,11 +90,6 @@ couchdb: storageClass: "nfs-client" adminPassword: admin - image: - repository: samwho/test - tag: latest - pullPolicy: Always - objectStore: storageClass: "nfs-client" redis: diff --git a/charts/budibase/README.md.gotmpl b/charts/budibase/README.md.gotmpl index ac3bfef77d..d7bc25c789 100644 --- a/charts/budibase/README.md.gotmpl +++ b/charts/budibase/README.md.gotmpl @@ -89,11 +89,6 @@ couchdb: storageClass: "nfs-client" adminPassword: admin - image: - repository: samwho/test - tag: latest - pullPolicy: Always - objectStore: storageClass: "nfs-client" redis: From e1b16c06ea941ed8e07fceb5419365347d447044 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 29 Nov 2023 17:01:52 +0000 Subject: [PATCH 16/19] Remove unnecessary annotations from example values.yaml. --- charts/budibase/README.md.gotmpl | 3 --- 1 file changed, 3 deletions(-) diff --git a/charts/budibase/README.md.gotmpl b/charts/budibase/README.md.gotmpl index d7bc25c789..92e91f8e09 100644 --- a/charts/budibase/README.md.gotmpl +++ b/charts/budibase/README.md.gotmpl @@ -68,9 +68,6 @@ staff's homelabs). ```yaml ingress: enabled: true - annotations: - nginx.ingress.kubernetes.io/client-max-body-size: 150M - nginx.ingress.kubernetes.io/proxy-body-size: 50m className: "nginx" hosts: - host: budibase.local # set this to whatever DNS name you'd use From 98ae0014a86fc735e87e0af789117bd666ea4fa1 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 4 Dec 2023 11:47:11 +0000 Subject: [PATCH 17/19] Respond to PR comments. --- charts/budibase/README.md | 4 ---- charts/budibase/values.yaml | 5 ++--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/charts/budibase/README.md b/charts/budibase/README.md index 5d74e05e0b..164388b730 100644 --- a/charts/budibase/README.md +++ b/charts/budibase/README.md @@ -69,9 +69,6 @@ staff's homelabs). ```yaml ingress: enabled: true - annotations: - nginx.ingress.kubernetes.io/client-max-body-size: 150M - nginx.ingress.kubernetes.io/proxy-body-size: 50m className: "nginx" hosts: - host: budibase.local # set this to whatever DNS name you'd use @@ -130,7 +127,6 @@ $ helm install --create-namespace --namespace budibase budibase . -f values.yaml | globals.internalApiKeyFallback | string | `""` | A fallback value for `internalApiKey`. If you're rotating your encryption key, you can set this to the old value for the duration of the rotation. | | globals.jwtSecret | string | `""` | Secret used for signing JWTs. You don't need to set this if `createSecrets` is true. | | globals.jwtSecretFallback | string | `""` | A fallback value for `jwtSecret`. If you're rotating your JWT secret, you can set this to the old value for the duration of the rotation. | -| globals.multiTenancy | string | `"0"` | Whether to enable the multi-tenancy feature or not. "0" means an installation can only have one tenant. "1" allows multiple tenants. | | globals.platformUrl | string | `""` | Set the `platformUrl` binding. You can also do this in Settings > Organisation if you are self-hosting. | | globals.smtp.enabled | bool | `false` | Whether to enable SMTP or not. | | globals.smtp.from | string | `""` | The email address to use in the "From:" field of emails sent by Budibase. | diff --git a/charts/budibase/values.yaml b/charts/budibase/values.yaml index 0b693a4df3..13054e75fc 100644 --- a/charts/budibase/values.yaml +++ b/charts/budibase/values.yaml @@ -71,11 +71,10 @@ globals: # @ignore (should not normally need to be changed, we only set this to "0" # when deploying to our Cloud environment) selfHosted: "1" - # -- Whether to enable the multi-tenancy feature or not. "0" means an installation can only - # have one tenant. "1" allows multiple tenants. + # @ignore (doesn't work out of the box for self-hosted users, only meant for Budicloud) multiTenancy: "0" # @ignore (only currently used to determine whether to fetch licenses offline or not, should - # not normally need to be changed) + # not normally need to be changed, and only applies to Enterprise customers) offlineMode: "0" # @ignore (only needs to be set in our cloud environment) accountPortalUrl: "" From 1c0976b97a075710df385c7c1b4c2124658a808b Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Mon, 4 Dec 2023 12:31:05 +0000 Subject: [PATCH 18/19] Bump version to 2.13.31 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index e6231eb660..ccbd2d9d60 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.13.30", + "version": "2.13.31", "npmClient": "yarn", "packages": [ "packages/*" From e4237c0620704bab8c3ca116d44c3f554d856c28 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 4 Dec 2023 15:15:40 +0100 Subject: [PATCH 19/19] Remove conflicting typing --- packages/backend-core/src/redis/redlockImpl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-core/src/redis/redlockImpl.ts b/packages/backend-core/src/redis/redlockImpl.ts index a7b2e2b4c6..4de2516ab2 100644 --- a/packages/backend-core/src/redis/redlockImpl.ts +++ b/packages/backend-core/src/redis/redlockImpl.ts @@ -109,7 +109,7 @@ export async function doWithLock( ): Promise> { const redlock = await getClient(opts.type, opts.customOptions) let lock: Redlock.Lock | undefined - let timeout: NodeJS.Timeout | undefined + let timeout try { const name = getLockName(opts)