Permalink
Browse files

Deploy Grafana using our new helm strategy

Deploy the grafana via the helm strategy with which I'll eventually
deploy all my applications on Kubernetes. Note, I will stop the password
being stored in source control in a later commit. Its not pressing for
now because the service is not exposed publicly.
  • Loading branch information...
mattjmcnaughton committed Dec 23, 2018
1 parent c2924ee commit b74a4502e294ca6caef0d6633151a5fc9a288273
@@ -1,7 +1,6 @@
replicaCount: 2

image:

repository: docker.io/mattjmcnaughton/blog
tag: 0b805208794fce961d21cc540290127df97742ed

@@ -0,0 +1,21 @@
# 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
*~
# Various IDEs
.project
.idea/
*.tmproj
@@ -0,0 +1,4 @@
apiVersion: v1
description: A Helm chart for my Grafana deployment.
name: grafana
version: 0.0.1
@@ -0,0 +1,32 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "grafana.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 "grafana.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 "grafana.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
@@ -4,7 +4,12 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-config
name: {{ include "grafana.name" . }}-config
labels:
app.kubernetes.io/name: {{ include "grafana.name" . }}-config
app.kubernetes.io/environment: {{ .Values.environment }}
helm.sh/chart: {{ include "grafana.chart" . }}
namespace: {{ .Values.namespace }}
data:
# Responsible for the Grafana's base configuration.
grafana.ini: |-
@@ -4,7 +4,12 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-dashboards
name: {{ include "grafana.name" . }}-dashboards
labels:
app.kubernetes.io/name: {{ include "grafana.name" . }}-dashboards
app.kubernetes.io/environment: {{ .Values.environment }}
helm.sh/chart: {{ include "grafana.chart" . }}
namespace: {{ .Values.namespace }}
data:
# This configuration file is responsible for the dashboard visualizing our
# adherence with our blog's SLO.
@@ -1,45 +1,39 @@
---
# This manifest declares the Deployment responsible for managing the Pods which
# run Grafana.
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: grafana
name: {{ include "grafana.name" . }}
labels:
app.kubernetes.io/name: {{ include "grafana.name" . }}
app.kubernetes.io/environment: {{ .Values.environment }}
helm.sh/chart: {{ include "grafana.chart" . }}
namespace: {{ .Values.namespace }}
spec:
replicas: 2
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: grafana
app.kubernetes.io/name: {{ include "grafana.name" . }}
app.kubernetes.io/environment: {{ .Values.environment }}
template:
metadata:
labels:
app: grafana
app.kubernetes.io/name: {{ include "grafana.name" . }}
app.kubernetes.io/environment: {{ .Values.environment }}
spec:
# Ensure we use the `grafana` service account we created for RBAC
# purposes.
serviceAccountName: grafana
serviceAccountName: {{ include "grafana.name" . }}
containers:
- name: grafana
# Need to use `grafana>=5.x` so that we can provision dashboards and
# datasources via configuration files.
image: docker.io/grafana/grafana:5.3.2
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- name: http
containerPort: 3000
protocol: TCP
resources:
requests:
cpu: "100m"
memory: "100Mi"
limits:
cpu: "100m"
memory: "100Mi"
{{ toYaml .Values.resources | indent 10 }}
env:
# @TODO(mattjmcnaughton) Long term, this password should certainly not
# be plain text nor `password`. For now, it doesn't matter as the
# service is not accessible from the public internet.
- name: GF_SECURITY_ADMIN_PASSWORD
value: password
value: {{ .Values.unencryptedAdminPassword }}
# Mount the volumes containing all of the config files from our
# ConfigMaps into the proper location.
volumeMounts:
@@ -1,15 +1,19 @@
---
# This manifest declares a RoleBinding binding the Grafana role to the Grafana
# This manifest declares a RoleBinding binding the grafana role to the grafana
# ServiceAccount.
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: grafana
name: {{ include "grafana.name" . }}
labels:
app.kubernetes.io/name: {{ include "grafana.name" . }}
app.kubernetes.io/environment: {{ .Values.environment }}
helm.sh/chart: {{ include "grafana.chart" . }}
namespace: {{ .Values.namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: grafana
name: {{ include "grafana.name" . }}
subjects:
- kind: ServiceAccount
name: grafana
name: {{ include "grafana.name" . }}

@@ -1,13 +1,18 @@
---
# This manifest declares the Role under which our Grafana pod will run.
# This manifest declares the Role under which our grafana pod will run.
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: grafana
# Our Grafana application never needs to access the Kubernetes API, so it has no
name: {{ include "grafana.name" . }}
labels:
app.kubernetes.io/name: {{ include "grafana.name" . }}
app.kubernetes.io/environment: {{ .Values.environment }}
helm.sh/chart: {{ include "grafana.chart" . }}
namespace: {{ .Values.namespace }}
# Our grafana application never needs to access the Kubernetes API, so it has no
# permissions.
#
# @TODO(mattjmcnaughton) Long term, should we create (or utilize if it already
# exists) a single role specifying the ServiceAccount should not interact with
# the Kubernetes API.
rules: []

@@ -1,6 +1,11 @@
---
# This manifest declares the ServiceAccount with which our Grafana pod will run.
# This manifest declares the ServiceAccount with which our grafana pods will run.
apiVersion: v1
kind: ServiceAccount
metadata:
name: grafana
name: {{ include "grafana.name" . }}
labels:
app.kubernetes.io/name: {{ include "grafana.name" . }}
app.kubernetes.io/environment: {{ .Values.environment }}
helm.sh/chart: {{ include "grafana.chart" . }}
namespace: {{ .Values.namespace }}

@@ -1,22 +1,24 @@
---
# This manifest declares the Service for accessing our Grafana application.
# The template for the Service which allows access to our grafana.
apiVersion: v1
kind: Service
metadata:
name: grafana
name: {{ include "grafana.name" . }}
labels:
app: grafana
app.kubernetes.io/name: {{ include "grafana.name" . }}
app.kubernetes.io/environment: {{ .Values.environment }}
helm.sh/chart: {{ include "grafana.chart" . }}
namespace: {{ .Values.namespace }}
spec:
# @TODO(mattjmcnaughton) We temporarily use a ClusterIP, because we don't want this externally accessible
# from the internet until we have some form of authentication. We can't have
# some form of meaningful authentication until we have https. We can access it
# from our local machine using port forwarding. Once we have `https` and
# authentication, we can make it a `LoadBalancer`.
type: ClusterIP
selector:
app: grafana
{{- if eq .Values.environment "production" }}
type: {{ .Values.service.productionType }}
{{- else }}
type: {{ .Values.service.developmentType }}
{{- end }}
ports:
- name: http
port: 3000
targetPort: 3000
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: {{ include "grafana.name" . }}
app.kubernetes.io/environment: {{ .Values.environment }}
@@ -0,0 +1,33 @@
replicaCount: 2

image:
repository: docker.io/grafana/grafana
# Need to use `grafana>=5.x` so that we can provision dashboards and
# datasources via configuration files.
tag: 5.3.2

resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi

service:
# @TODO(mattjmcnaughton) We temporarily use a ClusterIP, because we don't want this externally accessible
# from the internet until we have some form of authentication. We can't have
# some form of meaningful authentication until we have https. We can access it
# from our local machine using port forwarding. Once we have `https` and
# authentication, we can make it a `LoadBalancer` (or expose via an ingress).
productionType: ClusterIP
developmentType: ClusterIP
port: 3000

# @TODO(mattjmcnaughton) Long term, this password should certainly not
# be plain text nor `password`. For now, it doesn't matter as the
# service is not accessible from the public internet.
#
# Once it is a true secret, we will store it in secret-values.yaml according to
# our typical secrets workflow.
unencryptedAdminPassword: password

0 comments on commit b74a450

Please sign in to comment.