diff --git a/changelogs/unreleased/sh-support-grafana.yml b/changelogs/unreleased/sh-support-grafana.yml new file mode 100644 index 0000000000000000000000000000000000000000..096a4ad5ae9c24a3df47457479afdd42fc107ef6 --- /dev/null +++ b/changelogs/unreleased/sh-support-grafana.yml @@ -0,0 +1,5 @@ +--- +title: Added Grafana support into chart install +merge_request: 789 +author: Gerard Hickey +type: added diff --git a/charts/gitlab/charts/gitlab-grafana/Chart.yaml b/charts/gitlab/charts/gitlab-grafana/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..68529444c05652b7c1e81a31f695e563d5958f0b --- /dev/null +++ b/charts/gitlab/charts/gitlab-grafana/Chart.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: v1 +name: gitlab-grafana +version: 0.1.0 +description: Adapt the Grafana chart to interface to the GitLab App +keywords: +- gitlab +- grafana +home: https://about.gitlab.com/ +icon: https://gitlab.com/gitlab-com/gitlab-artwork/raw/master/logo/logo-square.svg +sources: +- https://gitlab.com/charts/gitlab/tree/master/charts/gitlab/charts/gitlab-grafana +- https://gitlab.com/gitlab-org/build/CNG/tree/master/gitlab-grafana +maintainers: +- name: GitLab Inc. + email: support@gitlab.com diff --git a/charts/gitlab/charts/gitlab-grafana/templates/_import-secret.sh b/charts/gitlab/charts/gitlab-grafana/templates/_import-secret.sh new file mode 100644 index 0000000000000000000000000000000000000000..5ad8814b66e0403eb452df2911dd441a2a632d00 --- /dev/null +++ b/charts/gitlab/charts/gitlab-grafana/templates/_import-secret.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +PW_FILE='/tmp/initial/password' + +# If the password file exists, set the admin password using the contents +if [ -r "$PW_FILE" ]; then + echo "GitLab shim: Setting admin username to root" + export GF_SECURITY_ADMIN_USER="root" + + read -r line < "$PW_FILE" + echo "GitLab shim: Setting admin password in environment" + export GF_SECURITY_ADMIN_PASSWORD="$line" +fi + +# Start up the full grafana service +exec /run.sh diff --git a/charts/gitlab/charts/gitlab-grafana/templates/datasource-configmap.yaml b/charts/gitlab/charts/gitlab-grafana/templates/datasource-configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6b13e75938feeec3e9adba14a5c583c3910c61a7 --- /dev/null +++ b/charts/gitlab/charts/gitlab-grafana/templates/datasource-configmap.yaml @@ -0,0 +1,24 @@ +{{- if .Values.global.grafana.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "fullname" . }}-datasource + namespace: {{ .Release.Namespace }} + labels: + gitlab_grafana_datasource: "true" +{{ include "gitlab.standardLabels" . | indent 4 }} +data: + gitlab.yaml: | + apiVersion: 1 + deleteDatasources: + - name: GitLab installed Prometheus + orgId: 1 + datasources: + - name: GitLab installed Prometheus + type: prometheus + orgId: 1 + url: "http://{{ .Release.Name }}-prometheus-server" + access: proxy + isDefault: true + editable: false +{{- end }} diff --git a/charts/gitlab/charts/gitlab-grafana/templates/import-secret-configmap.yaml b/charts/gitlab/charts/gitlab-grafana/templates/import-secret-configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e8b9fbc3da14b909380103a0cde61efc54aa4da3 --- /dev/null +++ b/charts/gitlab/charts/gitlab-grafana/templates/import-secret-configmap.yaml @@ -0,0 +1,12 @@ +{{- if .Values.global.grafana.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitlab-grafana-import-secret + namespace: {{ .Release.Namespace }} + labels: +{{ include "gitlab.standardLabels" . | indent 4 }} +data: + import-secret.sh: |- +{{ include (print $.Template.BasePath "/_import-secret.sh") . | indent 4 }} +{{- end }} diff --git a/charts/gitlab/charts/gitlab-grafana/templates/ingress.yaml b/charts/gitlab/charts/gitlab-grafana/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dbabf73f69828f8dcedfdc8d565400a707fdf0ff --- /dev/null +++ b/charts/gitlab/charts/gitlab-grafana/templates/ingress.yaml @@ -0,0 +1,39 @@ +{{- if .Values.global.grafana.enabled -}} +{{- $gitlabHostname := include "gitlab.gitlab.hostname" . -}} +{{- $tlsSecret := include "unicorn.tlsSecret" . -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-grafana + namespace: {{ $.Release.Namespace }} + labels: +{{ include "gitlab.standardLabels" . | indent 4 }} + annotations: + kubernetes.io/ingress.class: "{{ template "gitlab.ingressclass" . }}" + kubernetes.io/ingress.provider: nginx + nginx.ingress.kubernetes.io/proxy-body-size: {{ .Values.ingress.proxyBodySize | quote }} + nginx.ingress.kubernetes.io/proxy-read-timeout: {{ .Values.ingress.proxyReadTimeout | quote }} + nginx.ingress.kubernetes.io/proxy-connect-timeout: {{ .Values.ingress.proxyConnectTimeout | quote }} + nginx.ingress.kubernetes.io/rewrite-target: / + {{ include "gitlab.certmanager_annotations" . }} + {{- range $key, $value := merge .Values.ingress.annotations .Values.global.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} +spec: + rules: + - host: {{ $gitlabHostname }} + http: + paths: + - backend: + serviceName: {{ .Release.Name }}-grafana + servicePort: 80 + path: /-/grafana + {{- if (and $tlsSecret (eq (include "gitlab.ingress.tls.enabled" $) "true" )) }} + tls: + - hosts: + - {{ $gitlabHostname }} + secretName: {{ $tlsSecret }} + {{- else }} + tls: [] + {{- end }} +{{- end -}} \ No newline at end of file diff --git a/charts/gitlab/charts/gitlab-grafana/values.yaml b/charts/gitlab/charts/gitlab-grafana/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..81a92724e24c0bea142cf9b4473561ec49bf0848 --- /dev/null +++ b/charts/gitlab/charts/gitlab-grafana/values.yaml @@ -0,0 +1,16 @@ +## GitLab Grafana configuration +## If enabled, we will deploy a secured Grafana + +# This chart is controlled by `global.grafana.enabled` +global: {} + +# We supply an Ingress resource that locates Grafana under /-/grafana +# NOTE: these values are placeholders for template functionality. +ingress: + tls: {} + annotations: {} + proxyBodySize: "0" + # Setting longer read timeout in case there is a lot of data coming back + proxyReadTimeout: 180 + proxyConnectTimeout: 15 + diff --git a/charts/gitlab/values.yaml b/charts/gitlab/values.yaml index 72d12591f20dc6a3b123fa0ceb7d69eda77470da..890462588d67914d7ee60237167a026bb4052a93 100644 --- a/charts/gitlab/values.yaml +++ b/charts/gitlab/values.yaml @@ -35,3 +35,4 @@ global: gitlab-runner: enabled: false + diff --git a/charts/shared-secrets/templates/_generate_secrets.sh b/charts/shared-secrets/templates/_generate_secrets.sh index 591c68b618fa3f05d0234e386e324ad139469ebc..84efedd921843a3486df747ae3625471de2371dd 100644 --- a/charts/shared-secrets/templates/_generate_secrets.sh +++ b/charts/shared-secrets/templates/_generate_secrets.sh @@ -123,3 +123,9 @@ generate_secret_if_needed {{ template "gitlab.workhorse.secret" . }} --from-lite # Registry http.secret secret generate_secret_if_needed {{ template "gitlab.registry.httpSecret.secret" . }} --from-literal={{ template "gitlab.registry.httpSecret.key" . }}=$(gen_random 'a-z0-9' 128 | base64 -w 0) + +{{ if .Values.global.grafana.enabled -}} +# Grafana password +generate_secret_if_needed "gitlab-grafana-initial-password" --from-literal=password=$(gen_random 'a-zA-Z0-9' 64) +{{ end }} + diff --git a/doc/charts/gitlab/gitlab-grafana/index.md b/doc/charts/gitlab/gitlab-grafana/index.md new file mode 100644 index 0000000000000000000000000000000000000000..bf2769dd13165a5714507cd588177bc467a8ff30 --- /dev/null +++ b/doc/charts/gitlab/gitlab-grafana/index.md @@ -0,0 +1,66 @@ +# Using the gitlab-grafana chart + +The `gitlab-grafana` subchart adapts the [stable/grafana][] chart to operate +correctly with the same level of configuration as the Omnibus +GitLab install. In addition, the installation of Grafana allows additional +dashboards to be installed by the end user and be incorporated with the +GitLab supplied dashboards. + +[stable/grafana]: https://github.com/helm/charts/tree/master/stable/grafana + +## Requirements + +This chart depends on the `stable/grafana` chart which is usually installed +by the `GitLab` meta chart. In addition, Kubernetes ingress support is +needed to properly route the Grafana requests using the `/-/grafana` path. + +## Design Choices + +Because of Helm limitations it is not possible to configure the Grafana +chart with knowledge of a dynamic name for the initial password Secret. +As a result a statically named Secret is created to contain the initial +password. This Secret is named `gitlab-grafana-initial-password`. + +The same issue exists for the ConfigMap that contains the script that +is used to inject the initial password into the Grafana container. That +ConfigMap is named `gitlab-grafana-import-secret`. + +Both the initial password Secret and the import script ConfigMap are +mounted into the Grafana container (`/tmp/initial` and `/tmp/scripts` +respectively) and the container command line is augmented to use both +of these objects to securely expose the initial password to the +Grafana server. Modification of the container command line will +generally prevent the initial password from being injected into the +Grafana server environment. + +## Configuration + +There are no required settings, it should work out of the box if you deploy +all of the charts together. The administrator credentials are created by +the `shared-secrets` chart and the administrator username is set to `root`. + +## Installation command line options + +| Parameter | Default | Description | +|---------------------|---------|----------------------------------------------------------------------| +| ingress.tls | `{}` | Hash of Ingress TLS settings if GitLab cert manager is not installed | +| ingress.annotations | `{}` | Additional annotations to add to Grafana Ingress resource | + +## Dashboard Support + +Grafana dashboards are automatically discovered from the ConfigMaps in +the deployed namespace. If a ConfigMap has been created with the +`gitlab_grafana_dashboard` label set to `true`, then the JSON encoded +dashboard in the ConfigMap will be imported into Grafana. This mechanism +does not allow any updates to the dashboard to be written back to the +ConfigMap containing the JSON encoded dashboard. + +The end user may supply their own dashboards utilizing the same mechanism +by supplying the `gitlab_grafana_dashboard` label and managing the +ConfigMap themselves. + +## Datasource Support + +Datasources may be created in the same manner as the dashboards by adding +the `gitlab_grafana_datasource` label. This chart will add a ConfigMap +to direct Grafana to use the embedded Prometheus metrics. diff --git a/doc/charts/globals.md b/doc/charts/globals.md index b23632276ec0915edc55c307b6229e2446e57ec2..75eb210ea7907080d54db304a208646a49de0b67 100644 --- a/doc/charts/globals.md +++ b/doc/charts/globals.md @@ -11,6 +11,7 @@ for more information on how the global variables work. - [GitLab Version](#gitlab-version) - [PostgreSQL](#configure-postgresql-settings) - [Redis](#configure-redis-settings) +- [Grafana](#configure-grafana-integration) - [Registry](#configure-registry-settings) - [Gitaly](#configure-gitaly-settings) - [Minio](#configure-minio-settings) @@ -165,6 +166,14 @@ global: key: redis-password ``` +## Configure Grafana integration + +The GitLab global grafana settings are located under `global.grafana`. At this time, the only setting available is `global.grafana.enabled`. + +When set to `true`, the GitLab chart will deploy the [Grafana chart](https://github.com/helm/helm/tree/master/stable/grafana), expose it under `/-/grafana` of the GitLab Ingress, and pre-configure it with a secure random password. The generated password can be found in the Secret named `gitlab-grafana-initial-root-password`. + +The GitLab chart connects to the deployed Prometheus instance. + ## Configure Registry settings The global Registry settings are located under the `global.registry` key. For more diff --git a/doc/installation/secrets.md b/doc/installation/secrets.md index baab5731d2ed4fee98d9388dce9e94ee5ef9faff..ef0b789faebcf191087ec4b56f102eb73f56c477 100644 --- a/doc/installation/secrets.md +++ b/doc/installation/secrets.md @@ -40,6 +40,7 @@ documentation. - [Postgres password](#postgresql-password) - [Minio secret](#minio-secret) - [Registry HTTP secret](#registry-http-secret) + - [Grafana password](#grafana-password) - [External Services](#external-services) - [Unicorn Omniauth](#unicorn-omniauth) - [LDAP Password](#ldap-password) @@ -191,6 +192,14 @@ the name of the release. kubectl create secret generic -postgresql-password --from-literal=postgres-password=$(head -c 512 /dev/urandom | LC_CTYPE=C tr -cd 'a-zA-Z0-9' | head -c 64) ``` +### Grafana password + +If configuring [Grafana integration](../charts/globals.md#configure-grafana-integration), generate a random 64 character alpha-numeric password. + +``` +generate_secret_if_needed "gitlab-grafana-initial-password" --from-literal=password=$(gen_random 'a-zA-Z0-9' 64) +``` + ### Registry HTTP secret Generate a random 64 character alpha-numeric key shared by all registry pods. diff --git a/requirements.yaml b/requirements.yaml index 3618835926e7f9d3e616a99024da339bceab48a1..e39d01da40a2da518d57340ee244db826428d044 100644 --- a/requirements.yaml +++ b/requirements.yaml @@ -16,3 +16,7 @@ dependencies: version: 0.7.0 repository: https://charts.gitlab.io/ condition: gitlab-runner.install +- name: grafana + version: 3.5.12 + repository: https://kubernetes-charts.storage.googleapis.com/ + condition: global.grafana.enabled diff --git a/values.yaml b/values.yaml index 41d1eeb7d80ced1441d5e8d834fcf369a0cb4d66..e3348cc54dc52a4bf0c9983d2ef772a7c8e2dae5 100644 --- a/values.yaml +++ b/values.yaml @@ -96,6 +96,10 @@ global: credentials: {} # secret: + ## doc/charts/globals.md#configure-grafana-integration + grafana: + enabled: false + ## doc/charts/globals.md#configure-appconfig-settings ## Rails based portions of this chart share many settings appConfig: @@ -463,6 +467,49 @@ gitlab-runner: s3CachePath: gitlab-runner s3CacheInsecure: false + +## Installation & configuration of stable/grafana +## See requirements.yaml for current version +## Controlled by `global.grafana.enabled` +grafana: + ## Override and provide "bogus" administation secrets + ## gitlab/gitlab-grafana provides overrides via shared-secrets + admin: + existingSecret: bogus + env: + GF_SECURITY_ADMIN_USER: bogus + GF_SECURITY_ADMIN_PASSWORD: bogus + ## This override allows gitlab/gitlab-grafana to completely override the secret + ## handling behavior of the upstream chart in combination with the above. + command: [ "sh", "-x", "/tmp/scripts/import-secret.sh" ] + ## The following settings allow Grafana to dynamically create + ## dashboards and datasources from configmaps. See + ## https://github.com/helm/charts/tree/master/stable/grafana#sidecar-for-dashboards + sidecar: + dashboards: + enabled: true + label: gitlab_grafana_dashboard + datasources: + enabled: true + label: gitlab_grafana_datasource + ## We host Grafana as a sub-url of GitLab + grafana.ini: + server: + root_url: http://localhost/-/grafana/ + ## We generate and provide random passwords + ## NOTE: the Secret & ConfigMap names are hard coded! + extraSecretMounts: + - name: initial-password + mountPath: /tmp/initial + readOnly: true + secretName: gitlab-grafana-initial-password + defaultMode: 400 + extraConfigmapMounts: + - name: import-secret + mountPath: /tmp/scripts + configMap: gitlab-grafana-import-secret + readOnly: true + ## Settings for individual sub-charts under GitLab ## Note: Many of these settings are configurable via globals # gitlab: @@ -481,3 +528,5 @@ gitlab-runner: ## doc/charts/gitlab/gitlab-shell # gitlab-shell: # enabled: false +## doc/charts/gitlab/gitlab-grafana +# gitlab-grafana: