diff --git a/deploy/helm/.helmignore b/deploy/helm/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/deploy/helm/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deploy/helm/Chart.lock b/deploy/helm/Chart.lock new file mode 100644 index 0000000000..5b164bbc3b --- /dev/null +++ b/deploy/helm/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami + version: 0.3.1 +digest: sha256:a6d6b7927942884d4abd2291b1561b6c86db71aedeb08b33ccd5a4228a776257 +generated: "2021-09-09T10:54:25.247689+07:00" diff --git a/deploy/helm/Chart.yaml b/deploy/helm/Chart.yaml new file mode 100644 index 0000000000..7e8078a986 --- /dev/null +++ b/deploy/helm/Chart.yaml @@ -0,0 +1,20 @@ +annotations: + category: Application +apiVersion: v2 +appVersion: "1.16.0" +name: appsmith +type: application +dependencies: + # This dependency is used to render common declaration (tplvalues.render, storage.class, labels.standard) + # in Deployment, PVC, Service, ServiceAccount and TLS-Secret template + - name: common + version: 0.3.1 + repository: https://charts.bitnami.com/bitnami +description: Appsmith is an open source framework to build admin panels, CRUD apps and workflows. Build everything you need, 10x faster. +maintainer: + - email: tech@appsmith.com + name: Appsmith +sources: + - https://github.com/appsmithorg/appsmith + - https://www.appsmith.com/ +version: 1.3.0 diff --git a/deploy/helm/README.md b/deploy/helm/README.md new file mode 100644 index 0000000000..2bc192adca --- /dev/null +++ b/deploy/helm/README.md @@ -0,0 +1,167 @@ + +# Appsmith +Appsmith is a JS-based internal tool development platform. Internal tools take a lot of time to build even though they involve the same UI components, data integrations, and user access management. Developers love Appsmith because it saves them hundreds of hours. + +Build interactive web apps by using UI components like a table, form components, button, charts, rich text editor, map, tabs, modal, and many more. + +API Support: CURL importer for REST APIs Database Support: PostgreSQL, MongoDB, MySQL, Redshift, Elastic Search, DynamoDB, Redis, & MSFT SQL Server. +## TL;DR +--- +``` +helm repo add appsmith https://appsmithorg.github.io/appsmith + +helm repo update + +helm install appsmith/appsmith --generate-name +``` + +## Introduction +--- +This chart bootstrap an [Appsmith](https://github.com/appsmithorg/appsmith) deployment on a [Kubernetes](kubernetes.io) cluster using [Helm](https://helm.sh) package manager. + +## Prerequisites +--- +* Install Helm package manager: [https://helm.sh/docs/intro/install/](https://helm.sh/docs/intro/install/) +* Ensure `kubectl` is installed and configured to connect to your cluster + * Install kubeclt: [kubernetes.io/vi/docs/tasks/tools/install-kubectl/](https://kubernetes.io/vi/docs/tasks/tools/install-kubectl/) + * Minikube: [Setup Kubectl](https://minikube.sigs.k8s.io/docs/handbook/kubectl/) + * Google Cloud Kubernetes: [Configuring cluster access for kubectl](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) + * Aws EKS: [Create a kubeconfig for Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/create-kubeconfig.html) + + * Microk8s: [Working with kubectl](https://microk8s.io/docs/working-with-kubectl) +* Ensure you have a default storage class running on your cluster. Please follow one of below guideline to enable your default storage class in case of no existing one + * Minikube: [Enable addon default-storageclass](https://kubernetes.io/docs/tutorials/hello-minikube/#enable-addons) + * Google Cloud Kubernetes: [Setting up default storage class on GKE](https://cloud.google.com/anthos/clusters/docs/on-prem/1.3/how-to/default-storage-class) + * AWS EKS: [Create default storage class](https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html) + * Microk8s: [Enable storage](https://microk8s.io/docs/command-reference#heading--microk8s-enable) +* Kubernetes NGINX Ingress Controller should be enable on your cluster by default. Please make sure that you install the right version for your cluster + * Minikube: [Set up Ingress on Minikube with the NGINX Ingress Controller](https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/) + * Google Cloud Kubernetes: [Ingress with NGINX controller on Google Kubernetes Engine](https://kubernetes.github.io/ingress-nginx/deploy/) + * AWS EKS: [Install NGINX Controller for AWS EKS](https://kubernetes.github.io/ingress-nginx/deploy/#network-load-balancer-nlb) + * Microk8s: [Add on: Ingress](https://microk8s.io/docs/addon-ingress) +## Installing the Chart +--- +To install the chart with the release `appsmith` +``` +helm install appsmith/appsmith --generate-name +``` +The command deploys Appsmith application on Kubernetes cluster in the default configuration. The [Parameters](https://github.com/appsmithorg/appsmith/tree/release/deploy/helm#paramters) section lists the parameters that can be configured during installation. +## Uninstalling the Chart +--- +To uninstall the `appsmith` release: +``` +helm list +NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION +appsmith-1631069261 default 1 2021-09-09 11:24:40.152766 +0700 +07 deployed appsmith-1.3.0 1.16.0 + +helm uninstall appsmith-1631069261 +``` +The command uninstalls the release and removes all Kubernetes resources associated with the chart +## Parameters + +### Global parameters + +| Name | Description | Value | +| -------------------------- | ---------------------------------------------------------- | ------- | +| `global.namespaceOverride` | Override the namespace for resource deployed by the chart | `""` | +| `global.storageClass` | Global StorageClass for Persistent Volume(s) | `""` | + +### Common parameters +| Name | Description | Value | +| ------------------- | ------------------------------------------------- | ------------- | +| `fullnameOverride` | String to fully override `appsmith.name` template | `""` | +| `containerName` | Specify container's name running in the pods | `"appsmith"` | +| `commonLabels` | Labels to add to all deployed objects | `{}` | +| `commonAnnotations` | Annotations to add to all deployed objects | `{}` | + +### Appsmith Image parameters +| Name | Description | Value | +| ------------------- | --------------------------- | --------------------------- | +| `image.registry` | Appsmith image registry | `index.docker.io` | +| `image.repository` | Appsmith image repository | `appsmith/appsmith-editor` | +| `image.tag` | Appsmith image tag | `latest` | +| `image.pullPolicy` | Appsmith image pull policy | `IfNotPresent` | + +### Appsmith deployment parameters +| Name | Description | Value | +| --------------------------- | --------------------------------------------------- | --------------- | +| `strategyType` | Appsmith deployment strategy type | `RollingUpdate` | +| `schedulerName` | Alternate scheduler | `""` | +| `podAnnotations` | Annotations for Appsmith pods | `{}` | +| `podSecurityContext` | Appsmith pods security context | `{}` | +| `securityContext` | Set security context | `{}` | +| `resources.limit` | The resources limits for the Appsmith container | `{}` | +| `resources.requests` | The requested resources for the Appsmith container | `{}` | +| `nodeSelector` | Node labels for pod assignment | `{}` | +| `tolerations` | Tolerations for pod assignment | `[]` | +| `affinity` | Affinity fod pod assignment | `{}` | + +### Appsmith service account parameters +| Name | Description | Value | +| ----------------------------- | ----------------------------------------------------------------------------------------------------------- | ------- | +| `serviceAccount.create` | Enable creation of `ServiceAccount` for Appsmith pods | `true` | +| `serviceAccount.name` | Name of the created `ServiceAccount` . If not set, a name is generated using the appsmith.fullname template | `""` | +| `serviceAccount.annotations` | Additional service account annotations | `{}` | + +### Traffic Exposure Parameters +| Name | Description | Value | +| ----------------------------------- | --------------------------------------------------------------------------------------- | ----------- | +| `service.type` | Appsmith service type | `ClusterIP` | +| `service.port` | Appsmith service port | `80` | +| `service.portName` | Appsmith service port name | `appsmith` | +| `service.clusterIP` | Appsmith service Cluster | `""` | +| `service.loadBalancerIP` | Appsmith service Load Balancer IP | `""` | +| `service.loadBalancerSourceRanges` | Appsmith service Load Balancer sources | `[]` | +| `service.annotations` | Additional custom annotations for Appsmith service | `{}` | +| `ingress.enabled` | Enable ingress record generation for Appsmith | `false` | +| `ingress.hosts` | An array of hosts to be covered with the ingress record | `[]` | +| `ingress.tls` | Enable TLS configuration for the hosts defined at `ingress.hosts` parameter | `false` | +| `ingress.secrets` | Custom TLS certificates as secrets | `[]` | +| `ingress.certManager` | Enable ingress to use TLS certificates provided by Cert Manager | `false` | +| `ingress.certManagerTls` | Specify TLS secret resources created by Cert Manager | `[]` | + +### Persistence parameters +| Name | Description | Value | +| ----------------------------------- | --------------------------------------------------------------------- | ------------------- | +| `persistence.enabled` | Enable persistence using Persistent Volume Claims | `true` | +| `persistence.storageClass` | Persistent Volume storage class | `""` | +| `persistence.localStorage` | Enable persistent volume using local storage | `false` | +| `persistence.storagePath` | Local storage path | `/tmp/hostpath_pv` | +| `persistence.localCluster` | Local running cluster to provide storage space | `[minikube]` | +| `persistence.accessModes` | Persistent Volume access modes | `[ReadWriteOnce]` | +| `persistence.size` | Persistent Volume size | `10Gi` | +| `storageClass.enabled` | Enable Storage Class configuration | `false` | +| `storageClass.defaultClass` | Create default Storage Class | `false` | +| `storageClass.bindingMode` | Binding mode for Persistent Volume Claims using Storage Class | `Immediate` | +| `storageClass.allowVolumeExpansion` | Allow expansion of Persistent Volume Claims using Storage Class | `true` | +| `storageClass.reclaimPolicy` | Configure the retention of the dynamically created Persistent Volume | `Delete` | +| `storageClass.provisioner` | Storage Class provisioner | `""` | +| `storageClass.annotations` | Additional storage class annotations | `{}` | +| `storageClass.mountOptions` | Mount options used by Persistent Volumes | `{}` | +| `storageClass.parameters` | Storage Class parameters | `{}` | + +### Auto update chart's image +| Name | Description | Value | +| ----------------------- | --------------------------------------------- | ------------- | +| `autoupdate.enabled` | Enable auto update Helm chart's image | `true` | +| `autoupdate.scheduler` | Schedule time to run cron job to update image | `"0 * * * *"` | + +Specify each parameter using `--set key=value[,key=value]` argument to helm install. For example: +``` +helm install appsmith \ +--set persistence.storageClass=appsmith-pv \ + deploy/helm +``` +The above command deploys Appsmith application and configure application to use storage class name `appsmith-pv` + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, +``` +helm install -f values.yaml appsmith/appsmith --generate-name +``` + +*Tip: You can use the default [values.yaml](https://github.com/appsmithorg/appsmith/blob/release/deploy/helm/values.yaml)* + +## Troubleshooting +If at any time you encounter an error during the installation process, reach out to support@appsmith.com or join our Discord Server + +If you know the error and would like to reinstall Appsmith, simply delete the installation folder and the templates folder and execute the script again \ No newline at end of file diff --git a/deploy/helm/Setup-https.md b/deploy/helm/Setup-https.md new file mode 100644 index 0000000000..31f2c4ddc7 --- /dev/null +++ b/deploy/helm/Setup-https.md @@ -0,0 +1,94 @@ +## Introduction +- Deploying Appsmith application on a Kubernetes cluster is easier with [Appsmith's Helm chart](). However, it is best practice to secure your web application with TLS certificates. + +- This guide will show you how to secure HTTP traffic with TLS and SSL certificates using [Cert Manager](https://cert-manager.io/). + +## Prerequisites +- You should have a Kubernetes cluster running with [Helm v3.x](https://helm.sh/docs/intro/install/) installed. +- Ensure `kubectl` is installed and configured to connect to your cluster: + - Install kubeclt: [kubernetes.io/vi/docs/tasks/tools/install-kubectl/](https://kubernetes.io/vi/docs/tasks/tools/install-kubectl/) + - Google Cloud Kubernetes: [Configuring cluster access for kubectl](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl) + * Aws EKS: [Create a kubeconfig for Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/create-kubeconfig.html) + +## Secure traffic with TLS and Let's Encrypt SSL certificates +The Appsmith Helm chart comes with built-in support for Ingress routes and certificate management through [cert-manager](https://github.com/jetstack/cert-manager). This makes it easy to configure TLS support using certificates from a variety of certificate providers, including [Let's Encrypt](https://letsencrypt.org/). + +The steps below explain how to use Ingress routes and cert-manager to configure TLS for your Appsmith deployment using a free Let's Encrypt certificate: + +- Begin by installing the NGINX Ingress controller with Helm: +```shell +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update + +helm install ingress-nginx ingress-nginx/ingress-nginx +``` +- Obtain the LoadBalancer IP address using the command below. Note this IP address as you will use it to configure DNS in a later step. +``` +kubectl get svc ingress-nginx-controller -o jsonpath="{.status.loadBalancer.ingress[0].hostname}" +``` +*Tip: It may take some time for the load balancer IP address to be assigned, so you may need to wait a few minutes before the command above returns any output.* +- Browse to the IP address and confirm that you see the default NGINX welcome page. This indicates that the NGINX Ingress controller is working. + +- Configure the DNS for your domain name by adding an A record pointing to the public IP address obtained in the previous steps. + +- Add the cert-manager repository, create a namespace and create CRDs: +``` +helm repo add jetstack https://charts.jetstack.io + +kubectl create namespace cert-manager +kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.5.3/cert-manager.crds.yaml +``` +*Tip: When executing these commands on Google Kubernetes Engine (GKE), you may encounter permission errors. [Refer to the official cert-manager documentation for notes on how to elevate your permissions](https://docs.cert-manager.io/en/latest/getting-started/install/kubernetes.html).* +- Create a ClusterIssuer resource for Let's Encrypt certificates. Create a file named letsencrypt-prod.yaml with the following content. Replace the EMAIL-ADDRESS placeholder with a valid email address. +```yaml +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + email: EMAIL-ADDRESS + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-prod + solvers: + - http01: + ingress: + class: nginx +``` +- Apply the changes to the cluster: +``` +kubectl apply -f letsencrypt-prod.yaml +``` +- Install cert-manager with Helm and configure Let's Encrypt as the default Certificate Authority (CA): +``` +helm install cert-manager --namespace cert-manager jetstack/cert-manager --version v1.5.3 +``` +- Install Appsmith using Helm chart with additional parameters to integrate with Ingress and cert-manager. Replace the DOMAIN placeholder with your domain name: +``` +helm install appsmith/appsmith --generate-name \ +--set service.type=ClusterIP \ +--set ingress.enabled=true \ +--set ingress.tls=true \ +--set ingress.certManager=true \ +--set ingress.annotations."kubernetes\.io/ingress\.class"=nginx \ +--set ingress.annotations."cert-manager\.io/cluster-issuer"=letsencrypt-prod \ +--set ingress.hosts[0].host=DOMAIN \ +--set ingress.hosts[0].paths[0].path=/ \ +--set ingress.hosts[0].paths[0].pathType=ImplementationSpecific \ +--set ingress.certManagerTls[0].hosts[0]=DOMAIN \ +--set ingress.certManagerTls[0].secretName=letsencrypt-prod +``` +After the deployment completes, visit the domain in your browser and you should see the Appsmith site over a secure TLS connection with a valid Let's Encrypt certificate. +

+ +

+ +## Useful links + +To learn more about the topics discussed in this guide, use the links below: +- [Appsmith Helm chart](https://github.com/appsmithorg/appsmith/blob/release/deploy/helm/README.md) +- [Get Started with Kubernetes](https://kubernetes.io/docs/setup/) +- [Kubernetes Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) +- [NGINX Ingress Controller documentation](https://github.com/kubernetes/ingress/tree/master/controllers/nginx) +- [Annotations supported by various Ingress controllers](https://github.com/kubernetes/ingress/blob/master/docs/annotations.md) \ No newline at end of file diff --git a/deploy/helm/charts/common-0.3.1.tgz b/deploy/helm/charts/common-0.3.1.tgz new file mode 100644 index 0000000000..72e4aba390 Binary files /dev/null and b/deploy/helm/charts/common-0.3.1.tgz differ diff --git a/deploy/helm/images/helm-ssl-config.png b/deploy/helm/images/helm-ssl-config.png new file mode 100644 index 0000000000..01a4cbcebd Binary files /dev/null and b/deploy/helm/images/helm-ssl-config.png differ diff --git a/deploy/helm/templates/NOTES.txt b/deploy/helm/templates/NOTES.txt new file mode 100644 index 0000000000..dd93c84575 --- /dev/null +++ b/deploy/helm/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "appsmith.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "appsmith.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "appsmith.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "appsmith.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/deploy/helm/templates/_helpers.tpl b/deploy/helm/templates/_helpers.tpl new file mode 100644 index 0000000000..e12d09be95 --- /dev/null +++ b/deploy/helm/templates/_helpers.tpl @@ -0,0 +1,84 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "appsmith.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "appsmith.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "appsmith.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "appsmith.labels" -}} +appsmith.sh/chart: {{ include "appsmith.chart" . }} +{{ include "appsmith.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "appsmith.selectorLabels" -}} +app.kubernetes.io/name: {{ include "appsmith.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "appsmith.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "appsmith.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts. +*/}} +{{- define "appsmith.namespace" -}} + {{- if .Values.global -}} + {{- if .Values.global.namespaceOverride }} + {{- .Values.global.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end }} +{{- end -}} + +{{/* +Return the appropriate apiVersion for the object +*/}} +{{- define "apiVersion" -}} +{{- default "storage.k8s.io/v1" .Values.apiVersion -}} +{{- end -}} \ No newline at end of file diff --git a/deploy/helm/templates/autoupdate.yaml b/deploy/helm/templates/autoupdate.yaml new file mode 100644 index 0000000000..4f563f5595 --- /dev/null +++ b/deploy/helm/templates/autoupdate.yaml @@ -0,0 +1,79 @@ +{{- if and .Values.autoupdate.enabled (ne .Values.autoupdate.scheduler "") }} +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: imago + namespace: {{ include "appsmith.namespace" . }} +spec: + schedule: {{ .Values.autoupdate.scheduler | quote }} + concurrencyPolicy: Forbid + jobTemplate: + spec: + template: + metadata: + labels: + k8s-app: imago + spec: + restartPolicy: Never + serviceAccount: imago + serviceAccountName: imago + containers: + - name: imago + image: philpep/imago + imagePullPolicy: Always + args: ["--update"] +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imago + namespace: {{ include "appsmith.namespace" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imago +rules: + - apiGroups: + - "" + - apps + resources: + - pods + - replicasets + - statefulsets + verbs: + - list + - apiGroups: + - "" + - batch + resources: + - cronjobs + verbs: + - get + - list + - update + - apiGroups: + - "" + - apps + resources: + - daemonsets + - deployments + - statefulsets + verbs: + - get + - list + - update +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: imago +roleRef: + kind: ClusterRole + name: imago + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: imago + namespace: {{ include "appsmith.namespace" . }} +{{- end }} diff --git a/deploy/helm/templates/deployment.yaml b/deploy/helm/templates/deployment.yaml new file mode 100644 index 0000000000..ee99fbd566 --- /dev/null +++ b/deploy/helm/templates/deployment.yaml @@ -0,0 +1,108 @@ +apiVersion: apps/v1 +kind: {{ if .Values.useStatefulSet }}StatefulSet{{- else }}Deployment{{- end }} +metadata: + name: {{ include "appsmith.fullname" . }} + namespace: {{ include "appsmith.namespace" . }} + labels: + {{- include "appsmith.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: 1 + {{- end }} + {{- if .Values.useStatefulSet }} + serviceName: {{ include "appsmith.fullname" . }} + updateStrategy: + {{- else }} + strategy: + {{- end }} + type: {{ .Values.strategyType }} + {{- if or (and (not .Values.useStatefulSet) (eq "Recreate" .Values.strategyType)) (and .Values.useStatefulSet (eq "OnDelete" .Values.strategyType)) }} + rollingUpdate: null + {{- end }} + selector: + matchLabels: + {{- include "appsmith.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "appsmith.selectorLabels" . | nindent 8 }} + spec: + {{- if .Values.schedulerName }} + schedulerName: {{ .Values.schedulerName | quote }} + {{- end }} + serviceAccountName: {{ template "appsmith.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Values.containerName }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + - name: https + containerPort: 443 + protocol: TCP + - name: supervisord + containerPort: 9001 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: data + mountPath: /appsmith-stacks + volumes: + {{- if not .Values.persistence.enabled }} + - name: data + emptyDir: {} + {{- else if not .Values.useStatefulSet }} + - name: data + persistentVolumeClaim: + claimName: {{ template "appsmith.fullname" . }} + {{- else }} + volumeClaimTemplates: + - metadata: + name: data + {{- if .Values.persistence.annotations }} + annotations: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.annotations "context" $) | nindent 10 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.volumeClaimTemplates.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.volumeClaimTemplates.selector "context" $) | nindent 10 }} + {{- end }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- end }} \ No newline at end of file diff --git a/deploy/helm/templates/ingress.yaml b/deploy/helm/templates/ingress.yaml new file mode 100644 index 0000000000..13afad5ced --- /dev/null +++ b/deploy/helm/templates/ingress.yaml @@ -0,0 +1,69 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "appsmith.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ include "appsmith.namespace" . }} + labels: + {{- include "appsmith.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.ingress.certManager }} + kubernetes.io/tls-acme: "true" + {{- end }} +spec: + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.secrets }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- range .Values.ingress.certManagerTls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deploy/helm/templates/namespace.yaml b/deploy/helm/templates/namespace.yaml new file mode 100644 index 0000000000..154a6de035 --- /dev/null +++ b/deploy/helm/templates/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: {{ include "appsmith.namespace" . }} \ No newline at end of file diff --git a/deploy/helm/templates/persistentVolume.yaml b/deploy/helm/templates/persistentVolume.yaml new file mode 100644 index 0000000000..5a07b1859a --- /dev/null +++ b/deploy/helm/templates/persistentVolume.yaml @@ -0,0 +1,27 @@ +{{- if and .Values.persistence.enabled .Values.persistence.localStorage }} +apiVersion: v1 +kind: PersistentVolume +metadata: + name: {{ include "appsmith.fullname" . }} + namespace: {{ include "appsmith.namespace" . }} +spec: + capacity: + storage: {{ .Values.persistence.size | quote }} + volumeMode: Filesystem # Mount volume into Pod as a directory. + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + persistentVolumeReclaimPolicy: Delete + storageClassName: {{ .Values.persistence.storageClass | quote }} + local: + path: {{ .Values.persistence.storagePath }} # Path to the directory this PV refers to. + nodeAffinity: # nodeAffinity is required when using local volumes. + required: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/hostname + operator: In + values: + {{- toYaml .Values.persistence.localCluster | nindent 12 }} +{{- end }} \ No newline at end of file diff --git a/deploy/helm/templates/persistentVolumeClaim.yaml b/deploy/helm/templates/persistentVolumeClaim.yaml new file mode 100644 index 0000000000..38db6ca337 --- /dev/null +++ b/deploy/helm/templates/persistentVolumeClaim.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.persistence.enabled ( not .Values.useStatefulSet) }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "appsmith.fullname" . }} + namespace: {{ include "appsmith.namespace" . }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} +{{- end }} \ No newline at end of file diff --git a/deploy/helm/templates/service.yaml b/deploy/helm/templates/service.yaml new file mode 100644 index 0000000000..3a6c2ba988 --- /dev/null +++ b/deploy/helm/templates/service.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "appsmith.fullname" . }} + namespace: {{ include "appsmith.namespace" . }} + labels: + {{- include "appsmith.labels" . | nindent 4 }} + {{- if or .Values.service.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.service.annotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.service.annotations "context" $) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "ClusterIP") .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if and (eq .Values.service.type "LoadBalancer") .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + ports: + - name: {{ .Values.service.portName }} + port: {{ .Values.service.port }} + targetPort: http + {{- if and (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- else if eq .Values.service.type "ClusterIP" }} + nodePort: null + {{- end }} + selector: + {{- include "appsmith.selectorLabels" . | nindent 4 }} diff --git a/deploy/helm/templates/serviceaccount.yaml b/deploy/helm/templates/serviceaccount.yaml new file mode 100644 index 0000000000..c22d0695cc --- /dev/null +++ b/deploy/helm/templates/serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "appsmith.serviceAccountName" . }} + namespace: {{ include "appsmith.namespace" . }} + labels: {{- include "appsmith.labels" . | nindent 4 }} + {{- if or .Values.serviceAccount.annotations .Values.commonAnnotations }} + annotations: + {{- if .Values.serviceAccount.annotations }} + {{ toYaml .Values.serviceAccount.annotations | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- end }} +secrets: + - name: {{ template "appsmith.fullname" . }} +{{- end }} \ No newline at end of file diff --git a/deploy/helm/templates/storageClass.yaml b/deploy/helm/templates/storageClass.yaml new file mode 100644 index 0000000000..fae96b8adc --- /dev/null +++ b/deploy/helm/templates/storageClass.yaml @@ -0,0 +1,39 @@ +{{- if and .Values.storageClass.enabled .Values.persistence.localStorage }} +apiVersion: {{ template "apiVersion" }} +kind: StorageClass +metadata: + name: {{ .Values.persistence.storageClass }} +provisioner: kubernetes.io/no-provisioner +volumeBindingMode: WaitForFirstConsumer +--- +{{- else if .Values.storageClass.enabled }} +apiVersion: {{ template "apiVersion" }} +kind: StorageClass +metadata: + name: {{ .Values.persistence.storageClass }} + {{- if or .Values.storageClass.annotations .Values.storageClass.defaultClass }} + annotations: + {{- end }} + {{- if .Values.storageClass.annotations }} + {{ toYaml .Values.storageClass.annotations | indent 4}} + {{- end }} + {{- if .Values.storageClass.defaultClass }} + storageclass.kubernetes.io/is-default-class: "true" + {{- end }} +volumeBindingMode: {{ .Values.storageClass.bindingMode }} +provisioner: {{ .Values.storageClass.provisioner }} +allowVolumeExpansion: {{ .Values.storageClass.allowVolumeExpansion }} +reclaimPolicy: {{ .Values.storageClass.reclaimPolicy }} +{{- if .Values.storageClass.parameters }} +parameters: +{{- range $key, $value := .Values.storageClass.parameters }} + {{ $key }}: {{ $value }} + {{- end }} +{{- end }} +{{- if .Values.storageClass.mountOptions }} +mountOptions: + {{- range .Values.storageClass.mountOptions }} + - {{ . }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/helm/templates/tls-secret.yaml b/deploy/helm/templates/tls-secret.yaml new file mode 100644 index 0000000000..1cd9529ab1 --- /dev/null +++ b/deploy/helm/templates/tls-secret.yaml @@ -0,0 +1,50 @@ +{{- if .Values.ingress.enabled }} +{{- if .Values.ingress.secrets }} +{{- range .Values.ingress.secrets }} +{{- if .certificate }} +{{- if .key }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-tls" .host }} + namespace: {{ include "appsmith.namespace" $ }} + labels: {{- include "common.labels.standard" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" $.Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" $.Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ .certificate | b64enc }} + tls.key: {{ .key | b64enc }} +--- +{{- end }} +{{- end }} +{{- if and .Values.ingress.tls (not .Values.ingress.certManager) }} +{{- range .Values.ingress.hosts }} +{{- $ca := genCA "appsmith-ca" 365 }} +{{- $cert := genSignedCert .host nil (list .host) 365 $ca }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-tls" .host }} + namespace: {{ include "appsmith.namespace" $ }} + labels: {{- include "common.labels.standard" $ | nindent 4 }} + {{- if $.Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if $.Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: kubernetes.io/tls +data: + tls.crt: {{ $cert.Cert | b64enc | quote }} + tls.key: {{ $cert.Key | b64enc | quote }} + ca.crt: {{ $ca.Cert | b64enc | quote }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/helm/values.yaml b/deploy/helm/values.yaml new file mode 100644 index 0000000000..3af97ee3a2 --- /dev/null +++ b/deploy/helm/values.yaml @@ -0,0 +1,260 @@ +## @section Global parameters +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## @param global.namespaceOverride Override the namespace for resource deployed by the chart, but can itself be overridden by the local namespaceOverride +## +global: + storageClass: "" + namespaceOverride: "appsmith" +## @param fullnameOverride String to fully override appsmith.fullname template +## +fullnameOverride: "" +## @param containerName specify running container name in a pod +## +containerName: "appsmith" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Common annotations to add to all Appsmith resources (sub-charts are not considered). Evaluated as a template +## +commonAnnotations: {} +## @param useStatefulSet Set to true to use a StatefulSet instead of a Deployment +## +useStatefulSet: true +## @param schedulerName Name of the scheduler (other than default) to dispatch pods +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +schedulerName: "" +## @param strategyType StrategyType for Appsmith® statefulset +## It can be set to RollingUpdate or Recreate by default. +## +strategyType: RollingUpdate +## Image +## +image: + registry: index.docker.io + repository: appsmith/appsmith-editor + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "latest" +## ServiceAccount +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + ## @param serviceAccount.create Enable creation of ServiceAccount for Appsmith; pods + ## + create: true + ## @param serviceAccount.name Name of the created serviceAccount + ## If not set and create is true, a name is generated using the appsmith.fullname template + ## + name: "" + ## @param serviceAccount.annotations Additional Service Account annotations + ## + annotations: {} + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + ## @param service.type Kubernetes Service type + ## + type: ClusterIP + ## @param service.port; service port + ## + port: 80 + ## @param service.portName Appsmith; service port name + ## + portName: appsmith + ## @param service.clusterIP Appsmith; service cluster IP + ## e.g: + ## clusterIP: None + ## + clusterIP: "" + ## @param service.loadBalancerIP loadBalancerIP for Appsmith® Service + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer + ## + loadBalancerIP: "" + ## @param service.loadBalancerSourceRanges Address(es) that are allowed when service is LoadBalancer + ## ref: https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + loadBalancerSourceRanges: [] + ## @param service.annotations Provide any additional annotations that may be required + ## + annotations: {} + +ingress: + ## @param ingress.enabled Enable ingress record generation for Ghost + ## + enabled: false + ## @param ingress.annotations Additional custom annotations for the ingress record + ## NOTE: If `ingress.certManager=true`, annotation `kubernetes.io/tls-acme: "true"` will automatically be added + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # cert-manager.io/cluster-issuer: "letsencrypt-prod" + # nginx.ingress.kubernetes.io/ssl-redirect: "true" + # nginx.ingress.kubernetes.io/force-ssl-redirect: "true" + hosts: [] + # - host: appsmith-domain.me + # paths: + # - path: / + # pathType: ImplementationSpecific + ## @param ingress.tls Enable TLS configuration for the host defined at `ingress.hosts` parameter + ## You can: + ## - Use the `ingress.secrets` parameter to create this TLS secret + ## - Relay on cert-manager to create it by setting `ingress.certManager=true` + ## - Relay on Helm to create self-signed certificates by setting `ingress.selfSigned=true` + ## + tls: false + ## @param ingress.secrets Custom TLS certificates as secrets + ## NOTE: 'key' and 'certificate' are expected in PEM format + ## NOTE: 'name' should line up with a 'secretName' set further up + ## If it is not set and you're using cert-manager, this is unneeded, as it will create a secret for you with valid certificates + ## If it is not set and you're NOT using cert-manager either, self-signed certificates will be created valid for 365 days + ## It is also possible to create and manage the certificates outside of this helm chart + ## Please see README.md for more information + ## e.g: + ## secrets: + ## - host: chart-example.local + ## key: |- + ## -----BEGIN RSA PRIVATE KEY----- + ## ... + ## -----END RSA PRIVATE KEY----- + ## certificate: |- + ## -----BEGIN CERTIFICATE----- + ## ... + ## -----END CERTIFICATE----- + ## + secrets: [] + ## @param ingress.certManager Enable ingress to use TLS certificates provided by Cert Manager + ## + certManager: false + ## @param ingress.certManagerTls Specify the TLS secret created by Cert Manager + ## e.g: + ## certManagerTls: + ## - hosts: + ## - appsmith-domain.me + ## secretName: appsmith-tls + certManagerTls: [] + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + limits: {} + requests: {} + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +persistence: + ## @param persistence.enabled - Enable data persistence using PVC + ## + enabled: true + ## @param persistence.storageClass PVC Storage Class + ## + storageClass: "" + ## @param persistence.localStorage - Use local storage for PVC + ## + localStorage: false + ## @param persistence.storagePath - local storage path + ## + storagePath: /tmp/hostpath_pv + ## @param persistence.localCluster + ## + localCluster: + - minikube + ## @param persistence.accessModes PV Access Mode + ## + accessModes: + - ReadWriteOnce + ## @param persistence.size PVC Storage Request + ## + size: 10Gi + ## Fine tuning for volumeClaimTemplates + ## + volumeClaimTemplates: + ## @param persistence.volumeClaimTemplates.selector A label query over volumes to consider for binding (e.g. when using local volumes) + ## A label query over volumes to consider for binding (e.g. when using local volumes) + ## See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#labelselector-v1-meta for more details + ## + selector: {} + ## @param persistence.volumeClaimTemplates.requests Custom PVC requests attributes + ## Sometime cloud providers use additional requests attributes to provision custom storage instance + ## See https://cloud.ibm.com/docs/containers?topic=containers-file_storage#file_dynamic_statefulset + ## + requests: {} + ## @param persistence.volumeClaimTemplates.dataSource Add dataSource to the VolumeClaimTemplate + ## + dataSource: {} +# tags: +# install-ingress-nginx: true +storageClass: + ## @param storageClass.enabled - Enable config storage class + ## + enabled: false + ## @param storageClass.bindingMode - the binding mode for PVCs using this storage class + ## + bindingMode: Immediate + ## @param storageClass.defaultClass - boolean to set annotation designating this object as the default storage class + ## + defaultClass: false + ## @param storageClass.allowVolumeExpansion - allow expansion of PVCs using this storage class + ## + allowVolumeExpansion: true + ## @param storageClass.reclaimPolicy - configures the retention of the PV when dynamically created using this class + ## + reclaimPolicy: Delete + ## @param storageClass.provisioner - storage class parameters used for volumes created with this storage class + ## + provisioner: "" + ## @param storageClass.annotations - annotations in yaml map format to be added to the object + ## + annotations: {} + ## @param storageClass.mountOptions - options used by volumes created by this storage class + ## + mountOptions: {} + ## @param storageClass.parameters - storage class parameters used for volumes created with this storage class + ## + parameters: {} + +autoupdate: + ## @param autoupdate.enabled - Enable config autoupdate + ## + enabled: true + ## @param autoupdate.scheduler - Schedule cron job to check & update Helm image + ## + scheduler: "0 * * * *" \ No newline at end of file