Grafana: support multiple replicas and data persistance

This PS adds support for multiple replicas of Grafana to be
deployed, and adds MySQL based data persistance to the chart.

Change-Id: Ife44985a6d5024cc2074346340fba1d8efdecbfa
This commit is contained in:
portdirect 2018-01-11 00:51:48 -05:00
parent 85011f9c48
commit 21dc4f8af8
14 changed files with 477 additions and 22 deletions

View File

@ -0,0 +1,71 @@
#!/usr/bin/env python
# Creates db and user for an OpenStack Service:
# Set ROOT_DB_CONNECTION and DB_CONNECTION environment variables to contain
# SQLAlchemy strings for the root connection to the database and the one you
# wish the service to use. Alternatively, you can use an ini formatted config
# at the location specified by OPENSTACK_CONFIG_FILE, and extract the string
# from the key OPENSTACK_CONFIG_DB_KEY, in the section specified by
# OPENSTACK_CONFIG_DB_SECTION.
import os
import sys
import ConfigParser
import logging
from sqlalchemy import create_engine
# Create logger, console handler and formatter
logger = logging.getLogger('OpenStack-Helm DB Init')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# Set the formatter and add the handler
ch.setFormatter(formatter)
logger.addHandler(ch)
# Get the connection string for the service db
if "DB_CONNECTION" in os.environ:
user_db_conn = os.environ['DB_CONNECTION']
logger.info('Got config from DB_CONNECTION env var')
else:
logger.critical('Could not get db config, either from config file or env var')
sys.exit(1)
# User DB engine
try:
user_engine = create_engine(user_db_conn)
# Get our user data out of the user_engine
database = user_engine.url.database
user = user_engine.url.username
password = user_engine.url.password
host = user_engine.url.host
port = user_engine.url.port
logger.info('Got user db config')
except:
logger.critical('Could not get user database config')
raise
# Test connection
try:
connection = user_engine.connect()
connection.close()
logger.info("Tested connection to DB @ {0}:{1}/{2} as {3}".format(
host, port, database, user))
except:
logger.critical('Could not connect to database as user')
raise
# Create Table
try:
user_engine.execute('''CREATE TABLE IF NOT EXISTS `session` (
`key`CHAR(16) NOT NULL,
`data` BLOB,
`expiry` INT(11) UNSIGNED NOT NULL,
PRIMARY KEY (`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;''')
logger.info('Created table for session cache')
except:
logger.critical('Could not create table for session cache')
raise

View File

@ -22,6 +22,10 @@ kind: ConfigMap
metadata:
name: grafana-bin
data:
db-init.py: |
{{- include "helm-toolkit.scripts.db_init" . | indent 4 }}
db-session-sync.py: |
{{ tuple "bin/_db-session-sync.py.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
image-repo-sync.sh: |+
{{- include "helm-toolkit.scripts.image_repo_sync" . | indent 4 }}
datasource.sh: |

View File

@ -16,6 +16,19 @@ limitations under the License.
{{- if .Values.manifests.configmap_etc }}
{{- $envAll := . }}
{{- if and (empty .Values.conf.grafana.database.url) (not (eq .Values.conf.grafana.database.type "sqlite3") ) -}}
{{- tuple "oslo_db" "internal" "user" "mysql" . | include "helm-toolkit.endpoints.authenticated_endpoint_uri_lookup" | replace "mysql+pymysql://" "mysql://" | set .Values.conf.grafana.database "url" | quote | trunc 0 -}}
{{- end -}}
{{- if empty .Values.conf.grafana.session.provider_config -}}
{{- $user := .Values.endpoints.oslo_db_session.auth.user.username }}
{{- $pass := .Values.endpoints.oslo_db_session.auth.user.password }}
{{- $host_port := tuple "oslo_db_session" "internal" "mysql" . | include "helm-toolkit.endpoints.host_and_port_endpoint_uri_lookup" }}
{{- $path := .Values.endpoints.oslo_db_session.path }}
{{- printf "%s:%s%s(%s)%s" $user $pass "@tcp" $host_port $path | set .Values.conf.grafana.session "provider_config" | quote | trunc 0 -}}
{{- end -}}
---
apiVersion: v1
kind: ConfigMap

View File

@ -43,6 +43,8 @@ spec:
configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }}
spec:
serviceAccountName: {{ $serviceAccountName }}
nodeSelector:
{{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
initContainers:
{{ tuple $envAll .Values.pod_dependency list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
containers:

View File

@ -30,9 +30,7 @@ kind: Ingress
metadata:
name: {{ $ingressName }}
annotations:
kubernetes.io/ingress.class: "nginx"
ingress.kubernetes.io/rewrite-target: /
ingress.kubernetes.io/proxy-body-size: {{ .Values.network.grafana.ingress.proxy_body_size }}
{{ toYaml .Values.network.grafana.ingress.annotations | indent 4 }}
spec:
rules:
{{ if ne $hostNameNamespaced $hostNameFull }}

View File

@ -0,0 +1,67 @@
{{/*
Copyright 2017 The Openstack-Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
{{- if .Values.manifests.job_db_init_session }}
{{- $envAll := . }}
{{- $dependencies := .Values.dependencies.db_init_session }}
{{- $serviceAccountName := "grafana-db-init-session" }}
{{ tuple $envAll $dependencies $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: grafana-db-init-session
spec:
template:
metadata:
labels:
{{ tuple $envAll "grafana" "db-init" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
spec:
serviceAccountName: {{ $serviceAccountName }}
restartPolicy: OnFailure
nodeSelector:
{{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
initContainers:
{{ tuple $envAll $dependencies list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
containers:
- name: grafana-db-init-session
{{ tuple $envAll "db_init" | include "helm-toolkit.snippets.image" | indent 10 }}
{{ tuple $envAll $envAll.Values.pod.resources.jobs.db_init_session | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
env:
- name: ROOT_DB_CONNECTION
valueFrom:
secretKeyRef:
name: {{ .Values.secrets.oslo_db_session.admin }}
key: DB_CONNECTION
- name: DB_CONNECTION
valueFrom:
secretKeyRef:
name: {{ .Values.secrets.oslo_db_session.user }}
key: DB_CONNECTION
command:
- /tmp/db-init.py
volumeMounts:
- name: grafana-bin
mountPath: /tmp/db-init.py
subPath: db-init.py
readOnly: true
volumes:
- name: grafana-bin
configMap:
name: grafana-bin
defaultMode: 0555
{{- end }}

View File

@ -0,0 +1,67 @@
{{/*
Copyright 2017 The Openstack-Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
{{- if .Values.manifests.job_db_init }}
{{- $envAll := . }}
{{- $dependencies := .Values.dependencies.db_init }}
{{- $serviceAccountName := "grafana-db-init" }}
{{ tuple $envAll $dependencies $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: grafana-db-init
spec:
template:
metadata:
labels:
{{ tuple $envAll "grafana" "db-init" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
spec:
serviceAccountName: {{ $serviceAccountName }}
restartPolicy: OnFailure
nodeSelector:
{{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
initContainers:
{{ tuple $envAll $dependencies list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
containers:
- name: grafana-db-init
{{ tuple $envAll "db_init" | include "helm-toolkit.snippets.image" | indent 10 }}
{{ tuple $envAll $envAll.Values.pod.resources.jobs.db_init | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
env:
- name: ROOT_DB_CONNECTION
valueFrom:
secretKeyRef:
name: {{ .Values.secrets.oslo_db.admin }}
key: DB_CONNECTION
- name: DB_CONNECTION
valueFrom:
secretKeyRef:
name: {{ .Values.secrets.oslo_db.user }}
key: DB_CONNECTION
command:
- /tmp/db-init.py
volumeMounts:
- name: grafana-bin
mountPath: /tmp/db-init.py
subPath: db-init.py
readOnly: true
volumes:
- name: grafana-bin
configMap:
name: grafana-bin
defaultMode: 0555
{{- end }}

View File

@ -0,0 +1,62 @@
{{/*
Copyright 2017 The Openstack-Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
{{- if .Values.manifests.job_db_session_sync }}
{{- $envAll := . }}
{{- $dependencies := .Values.dependencies.db_session_sync }}
{{- $serviceAccountName := "grafana-db-session-sync" }}
{{ tuple $envAll $dependencies $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: grafana-db-session-sync
spec:
template:
metadata:
labels:
{{ tuple $envAll "grafana" "db-session-sync" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
spec:
serviceAccountName: {{ $serviceAccountName }}
restartPolicy: OnFailure
nodeSelector:
{{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
initContainers:
{{ tuple $envAll $dependencies list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
containers:
- name: grafana-db-session-sync
{{ tuple $envAll "grafana_db_session_sync" | include "helm-toolkit.snippets.image" | indent 10 }}
{{ tuple $envAll $envAll.Values.pod.resources.jobs.db_session_sync | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
env:
- name: DB_CONNECTION
valueFrom:
secretKeyRef:
name: {{ .Values.secrets.oslo_db_session.user }}
key: DB_CONNECTION
command:
- /tmp/db-session-sync.py
volumeMounts:
- name: grafana-bin
mountPath: /tmp/db-session-sync.py
subPath: db-session-sync.py
readOnly: true
volumes:
- name: grafana-bin
configMap:
name: grafana-bin
defaultMode: 0555
{{- end }}

View File

@ -34,7 +34,7 @@ spec:
serviceAccountName: {{ $serviceAccountName }}
restartPolicy: OnFailure
nodeSelector:
{{ .Values.labels.jobs.node_selector_key }}: {{ .Values.labels.jobs.node_selector_value }}
{{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
initContainers:
{{ tuple $envAll .Values.pod_dependency list | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
containers:

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/}}
{{- if .Values.manifests.secret_admin }}
{{- if .Values.manifests.secret_admin_creds }}
{{- $envAll := . }}
---
apiVersion: v1

View File

@ -0,0 +1,30 @@
{{/*
Copyright 2017 The Openstack-Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
{{- if .Values.manifests.secret_db_session }}
{{- $envAll := . }}
{{- range $key1, $userClass := tuple "admin" "user" }}
{{- $secretName := index $envAll.Values.secrets.oslo_db_session $userClass }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ $secretName }}
type: Opaque
data:
DB_CONNECTION: {{ tuple "oslo_db_session" "internal" $userClass "mysql" $envAll | include "helm-toolkit.endpoints.authenticated_endpoint_uri_lookup" | b64enc -}}
{{- end }}
{{- end }}

View File

@ -0,0 +1,30 @@
{{/*
Copyright 2017 The Openstack-Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
{{- if .Values.manifests.secret_db }}
{{- $envAll := . }}
{{- range $key1, $userClass := tuple "admin" "user" }}
{{- $secretName := index $envAll.Values.secrets.oslo_db $userClass }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ $secretName }}
type: Opaque
data:
DB_CONNECTION: {{ tuple "oslo_db" "internal" $userClass "mysql" $envAll | include "helm-toolkit.endpoints.authenticated_endpoint_uri_lookup" | b64enc -}}
{{- end }}
{{- end }}

View File

@ -21,6 +21,8 @@ images:
grafana: docker.io/grafana/grafana:4.5.2
datasource: docker.io/kolla/ubuntu-source-heat-engine:3.0.3
dep_check: quay.io/stackanetes/kubernetes-entrypoint:v0.2.1
db_init: docker.io/kolla/ubuntu-source-heat-engine:3.0.3
grafana_db_session_sync: docker.io/kolla/ubuntu-source-heat-engine:3.0.3
image_repo_sync: docker.io/docker:17.07.0
pull_policy: IfNotPresent
local_registry:
@ -30,17 +32,16 @@ images:
- image_repo_sync
labels:
jobs:
node_selector_key: openstack-control-plane
node_selector_value: enabled
node_selector_key: openstack-control-plane
node_selector_value: enabled
pod:
affinity:
anti:
type:
default: preferredDuringSchedulingIgnoredDuringExecution
topologyKey:
default: kubernetes.io/hostname
anti:
type:
default: preferredDuringSchedulingIgnoredDuringExecution
topologyKey:
default: kubernetes.io/hostname
mounts:
grafana:
init_container: null
@ -75,6 +76,27 @@ pod:
limits:
memory: "1024Mi"
cpu: "2000m"
db_init:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "1024Mi"
cpu: "2000m"
db_init_session:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "1024Mi"
cpu: "2000m"
grafana_db_session_sync:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "1024Mi"
cpu: "2000m"
grafana:
requests:
memory: "128Mi"
@ -85,6 +107,42 @@ pod:
endpoints:
cluster_domain_suffix: cluster.local
oslo_db:
namespace: null
auth:
admin:
username: root
password: password
user:
username: grafana
password: password
hosts:
default: mariadb
host_fqdn_override:
default: null
path: /grafana
scheme: mysql+pymysql
port:
mysql:
default: 3306
oslo_db_session:
namespace: null
auth:
admin:
username: root
password: password
user:
username: grafana_session
password: password
hosts:
default: mariadb
host_fqdn_override:
default: null
path: /grafana_session
scheme: mysql+pymysql
port:
mysql:
default: 3306
grafana:
name: grafana
namespace: null
@ -122,13 +180,31 @@ endpoints:
public: 80
dependencies:
register_datasource:
jobs:
db_init:
services:
- service: grafana
endpoint: internal
- service: oslo_db
endpoint: internal
db_init_session:
services:
- service: oslo_db
endpoint: internal
db_session_sync:
jobs:
- grafana-db-init-session
services:
- service: oslo_db
endpoint: internal
register_datasource:
services:
- service: grafana
endpoint: internal
grafana:
services: null
jobs:
- grafana-db-init
- grafana-db-session-sync
services:
- service: oslo_db
endpoint: internal
image_repo_sync:
services:
- service: local_image_registry
@ -150,8 +226,17 @@ network:
port: 30902
ingress:
public: true
proxy_body_size: 1024M
annotations:
kubernetes.io/ingress.class: "nginx"
ingress.kubernetes.io/rewrite-target: /
secrets:
oslo_db:
admin: grafana-db-admin
user: grafana-db-user
oslo_db_session:
admin: grafana-session-db-admin
user: grafana-session-db-user
manifests:
configmap_bin: true
@ -159,9 +244,14 @@ manifests:
configmap_etc: true
deployment: true
ingress: true
job_db_init: true
job_db_init_session: true
job_db_session_sync: true
job_datasource: true
job_image_repo_sync: true
secret_admin: true
secret_db: true
secret_db_session: true
secret_admin_creds: true
service: true
service_ingress: true
@ -179,9 +269,11 @@ conf:
server:
protocol: http
http_port: 3000
database:
type: mysql
session:
provider: file
provider_config: sessions
provider: mysql
provider_config: null
cookie_name: grafana_sess
cookie_secure: false
session_life_time: 86400

View File

@ -155,6 +155,25 @@ charts:
timeout: 300
output: false
values:
dependencies:
grafana:
jobs: null
services: null
manifests:
ingress: false
job_db_init: false
job_db_init_session: false
job_db_session_sync: false
secret_db: false
secret_db_session: false
service_ingress: false
conf:
grafana:
database:
type: sqlite3
session:
provider: file
provider_config: sessions
network:
grafana:
ingress: