<p>For the <a href="https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack" rel="nofollow noreferrer">kube-prometheus-stack</a> we added more and more dashboards config to <code>/grafana/dashboards</code> folder to have more and more provisioned dashboards.</p>
<p>And then in one day we've done this:</p>
<pre><code>kube-prometheus-stack&gt;helm -n monitoring upgrade prometheus ./ -f ./values-core.yaml 
</code></pre>
<p>and got:</p>
<pre><code>Error: UPGRADE FAILED: create: failed to create: Secret &quot;sh.helm.release.v1.prometheus.v16&quot; is invalid: data: Too long: must have at most 1048576 bytes
</code></pre>
<p>What is the designed way to overrun these limitations? There is a need to add more and more provisioned dashboards to the chart.</p>
<pre><code>kubectl version
Client Version: version.Info{Major:&quot;1&quot;, Minor:&quot;19&quot;, GitVersion:&quot;v1.19.0&quot;, GitCommit:&quot;e19964183377d0ec2052d1f1fa930c4d7575bd50&quot;, GitTreeState:&quot;clean&quot;, BuildDate:&quot;2020-08-26T14:30:33Z&quot;, GoVersion:&quot;go1.15&quot;, Compiler:&quot;gc&quot;, Platform:&quot;windows/amd64&quot;}
Server Version: version.Info{Major:&quot;1&quot;, Minor:&quot;21&quot;, GitVersion:&quot;v1.21.5&quot;, GitCommit:&quot;aea7bbadd2fc0cd689de94a54e5b7b758869d691&quot;, GitTreeState:&quot;clean&quot;, BuildDate:&quot;2021-09-15T21:04:16Z&quot;, GoVersion:&quot;go1.16.8&quot;, Compiler:&quot;gc&quot;, Platform:&quot;linux/amd64&quot;}
</code></pre>

<p>As we can get information from <a href="https://helm.sh/docs/topics/advanced/#storage-backends" rel="nofollow noreferrer">doc</a>, the purpose of auto generated secret is for recording release information. In k8s <a href="https://kubernetes.io/docs/concepts/configuration/secret/#restriction-data-size" rel="nofollow noreferrer">design</a>, Individual secrets are limited to 1MiB in size. Based on the above information, the secret size is the hard limitation of k8s, and the actual release secret size should be positively correlated with the size of the helm chart.</p>
<p>In this use case, the main reason for the large helm chart is that you use grafana's dashboardProvider to automatically deploy the ready-made dashboard JSON file. The provider will load all JSON file to kube-prometheus-stack for creating dashboard configmaps. And then in one day when you add new dashboard and it makes release secret finally hit the limitation you will get the error.</p>
<p>If you don't want to change k8s storage backend type, there is alternative way to work around with. The main idea is to separat tasks of creating dashboard configmap from grafana dashboardProvider and create dashboard configmap by our own.</p>
<p><strong>First</strong>, we can abandon this kind of declaration in kube-prometheus-stack</p>
<pre><code>    dashboardProviders:
      dashboardproviders.yaml:
          apiVersion: 1
          providers:
              - name: 'default'
              orgId: 1
              folder: 'default'
              type: file
              disableDeletion: true
              editable: true
              options:
                  path: /var/lib/grafana/dashboards/default
      dashboards:
        default:
        {{- range $_, $file := ( exec &quot;bash&quot; (list &quot;-c&quot; &quot;echo -n dashboards/default/*.json&quot;) | splitList &quot; &quot; ) }}
        {{ trimSuffix (ext $file) (base $file) }}:
            json: |
              {{- readFile $file }}
        {{- end }}
</code></pre>
<p><strong>Then</strong>, we create another helm chart configmap</p>
<p>Helm chart template</p>
<pre><code>{{- range $config, $data := .Values.configs }}
 ---
 apiVersion: v1
 kind: ConfigMap
 metadata:
   name: grafana-dashboard-{{ $config }}
   labels:
     grafana_dashboard: &quot;1&quot;
   annotations:
     grafana_folder: {{ $config }}
 data:
   {{ range $key, $val := $data }}
     {{ $key }}.json: |
       {{ mustToJson $val }}
   {{ end }}
{{- end }}
</code></pre>
<p>Helm values, read dashboard json file and convert to golang string</p>
<pre><code>configs:
 default:
 {{- range $_, $file := ( exec &quot;bash&quot; ( list &quot;-c&quot; (printf &quot;echo -n dashboards/default/*.json&quot;)) | splitList &quot; &quot;) }}
 {{ trimSuffix (ext $file) (base $file) }}:
     {{ readFile $file }}
 {{- end}}
</code></pre>
<p>At this time, when we deploy this separated dashboard helm chart, it should generate all configmaps which contain dashboard json value automatically.</p>
<p><strong>Finally</strong>, the last step, we can go to setup Grafana sidecar configurations to make it scrape dashboard from configmaps.</p>
<pre><code>grafana:
 defaultDashboardsEnabled: false
 sidecar:
   dashboards:
     enabled: true
     label: grafana_dashboard
     annotations:
       grafana_folder: &quot;Default&quot;
     folder: /tmp/dashboards
     folderAnnotation: grafana_folder
     provider:
       foldersFromFilesStructure: true
</code></pre>
<p>After update kube-prometheus-stack and waiting for a while, or you can monitoring on Grafana sidecar pod logs. You will see the dashboard configmaps are loading to pod and ADD to dashboard.</p>
