From 8a9194d5814ec776e8dfd4765e86f7a0b0e087be Mon Sep 17 00:00:00 2001 From: amecea Date: Mon, 18 Feb 2019 17:32:51 +0200 Subject: [PATCH] Add a cluster chart and documentation of how to use it --- .drone.yml | 6 ++ docs/integrate-operator.md | 84 +++++++++++++++++-- hack/charts/mysql-cluster/.helmignore | 21 +++++ hack/charts/mysql-cluster/Chart.yaml | 5 ++ .../mysql-cluster/templates/_helpers.tpl | 49 +++++++++++ .../templates/backup-secret.yaml | 16 ++++ .../mysql-cluster/templates/cluster.yaml | 40 +++++++++ .../mysql-cluster/templates/secret.yaml | 16 ++++ hack/charts/mysql-cluster/values.yaml | 35 ++++++++ 9 files changed, 266 insertions(+), 6 deletions(-) create mode 100644 hack/charts/mysql-cluster/.helmignore create mode 100644 hack/charts/mysql-cluster/Chart.yaml create mode 100644 hack/charts/mysql-cluster/templates/_helpers.tpl create mode 100644 hack/charts/mysql-cluster/templates/backup-secret.yaml create mode 100644 hack/charts/mysql-cluster/templates/cluster.yaml create mode 100644 hack/charts/mysql-cluster/templates/secret.yaml create mode 100644 hack/charts/mysql-cluster/values.yaml diff --git a/.drone.yml b/.drone.yml index bf9750242..9923b893b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -109,6 +109,12 @@ pipeline: - helm package mysql-operator - CHART="$(basename *.tgz)" ; MESSAGE="Publish $(basename $CHART .tgz)" - /usr/local/bin/gh put --skip-existing -m "$MESSAGE" "$CHART" "presslabs/charts/docs/" + - rm *.tgz + # publish cluster chart + - (cd mysql-cluster && helm dep build) + - helm package mysql-cluster + - CHART="$(basename *.tgz)" ; MESSAGE="Publish $(basename $CHART .tgz)" + - /usr/local/bin/gh put --skip-existing -m "$MESSAGE" "$CHART" "presslabs/charts/docs/" secrets: - GH_PASSWORD when: diff --git a/docs/integrate-operator.md b/docs/integrate-operator.md index e7912fa58..e2c397b17 100644 --- a/docs/integrate-operator.md +++ b/docs/integrate-operator.md @@ -1,5 +1,5 @@ --- -title: Integration of the MySQL Operator +title: Integrating mysql clusters into your own helm charts linktitle: MySQL Operator Integration description: How to integrate the MySQL operator with your application. categories: [mysql operator] @@ -13,14 +13,86 @@ aliases: [] toc: true --- -After cluster creation, you can update the provided secret with a new field named `DB_CONNECT_URL` that contains a [DSN](https://en.wikipedia.org/wiki/Data_source_name) to connect to the writable cluster endpoint. You can check the `_helper.tpl` file for more insights. +After cluster creation, you can update the provided secret with a new field named `DB_CONNECT_URL` +that contains a [DSN](https://en.wikipedia.org/wiki/Data_source_name) to connect to the writable +cluster endpoint. You can check the `_helper.tpl` file for more insights. The MySQL operator provides 3 services to access the nodes: - * `-mysql-master` is the service that points to the master node and this endpoint should be used for writes. This service is usually used to construct the DSN. + * `-mysql-master` is the service that points to the master node and this endpoint + should be used for writes. This service is usually used to construct the DSN. - * `-mysql` is the service that routes traffic to all the _healthy_ nodes from the cluster. You should use this endpoint for reads. + * `-mysql` is the service that routes traffic to all the _healthy_ nodes from the + cluster. You should use this endpoint for reads. - * `-mysql-nodes` is the service used internally to access nodes. You can use this service to access a specific node (e.g. `-mysql-0.-mysql-nodes.default`) + * `-mysql-nodes` is the service used internally to access nodes. You can use this + service to access a specific node (e.g. + `-mysql-0.-mysql-nodes.default`) -We use helm to deploy our application into Kubernetes, so we updated our charts to use the MySQL operator to provide one cluster per application. +We use helm to deploy our application into Kubernetes, so we updated our charts to use the MySQL +operator to provide one cluster per application. + + +## Using Helm + +Usually a cluster of MySQL is needed alongside with an application, that's why we provide a Helm +chart for easy deployment of a MySQL cluster. The chart can be found in `presslabs` chart repository and +installed like the operator. Below is illustrated how this chart can be integrated with your +application to provision a MySQL cluster. + + +### Add MySQL Cluster chart as dependency +In your chart add in `requirements.yaml` under `dependencies` section the following: +```yaml +dependencies: + - name: mysql-cluster + version: 0.1.0 + repository: https://presslabs.github.io/charts + condition: mysql.enabled + alias: mysql + +``` + +Once dependencies are configured run `helm dependency update` to fetch related charts. + +More information about chart requirements can be found in the official +[documentation](https://docs.helm.sh/developing_charts/#managing-dependencies-with-requirements-yaml). + +### Configure your chart's values.yaml file +You can configure the cluster by providing values under the `mysql` key. A comprehensive description +can be found in the chart +[`values.yaml`](https://github.com/presslabs/mysql-operator/blob/master/hack/charts/mysql-cluster/values.yaml) +file. + +```yaml +mysql: + enabled: true + rootPassword: + appUser: + appPassword: + appDatabase: +``` + +### Use into your application +In your deployment add an environment variable that point to the `DB_CONNECT_URL` field from cluster +secret named `{{ include "mysql-cluster.secretName" . }}`. + +For example in the `deployment.yaml`: +```yaml +spec: + replicas: {{ .Values.replicaCount }} + template: + spec: + containers: + - name: {{ .Chart.Name }} + ... + env: + - name: DB_CONNECT_URL + valueFrom: + secretKeyRef: + name: {{ include "mysql-cluster.secretName" . }} + key: DB_CONNECT_URL +``` + +Now just modify your app to connect to the DSN that is provided into `DB_CONNECT_URL` environment +variable. diff --git a/hack/charts/mysql-cluster/.helmignore b/hack/charts/mysql-cluster/.helmignore new file mode 100644 index 000000000..f0c131944 --- /dev/null +++ b/hack/charts/mysql-cluster/.helmignore @@ -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 diff --git a/hack/charts/mysql-cluster/Chart.yaml b/hack/charts/mysql-cluster/Chart.yaml new file mode 100644 index 000000000..192e31de8 --- /dev/null +++ b/hack/charts/mysql-cluster/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart for easy deployment of a MySQL cluster with MySQL operator. +name: mysql-cluster +version: 0.1.0 diff --git a/hack/charts/mysql-cluster/templates/_helpers.tpl b/hack/charts/mysql-cluster/templates/_helpers.tpl new file mode 100644 index 000000000..e3b0c1ceb --- /dev/null +++ b/hack/charts/mysql-cluster/templates/_helpers.tpl @@ -0,0 +1,49 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "mysql-cluster.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 "mysql-cluster.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 "mysql-cluster.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "mysql-cluster.dbConnectURL" -}} +mysql://{{- urlquery .Values.appUser -}}:{{- urlquery .Values.appPassword -}}@ +{{- include "mysql-cluster.clusterName" . -}}-mysql-master:3306/{{- .Values.appDatabase -}} +{{- end -}} + +{{- define "mysql-cluster.clusterName" -}} +{{- printf "%s-db" (include "mysql-cluster.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "mysql-cluster.secretName" -}} +{{- printf "%s-db" (include "mysql-cluster.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "mysql-cluster.backupSecretName" -}} +{{- printf "%s-db-backup" (include "mysql-cluster.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end -}} \ No newline at end of file diff --git a/hack/charts/mysql-cluster/templates/backup-secret.yaml b/hack/charts/mysql-cluster/templates/backup-secret.yaml new file mode 100644 index 000000000..d6f59e123 --- /dev/null +++ b/hack/charts/mysql-cluster/templates/backup-secret.yaml @@ -0,0 +1,16 @@ +{{- if .Values.backupCredentials }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "mysql-cluster.backupSecretName" . }} + labels: + app: {{ template "mysql-cluster.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +type: Opaque +data: + {{- range $key, $value := .Values.backupCredentials }} + {{ $key | upper }}: {{ $value | b64enc | quote }} + {{ end }} +{{- end -}} diff --git a/hack/charts/mysql-cluster/templates/cluster.yaml b/hack/charts/mysql-cluster/templates/cluster.yaml new file mode 100644 index 000000000..ec3f9d65f --- /dev/null +++ b/hack/charts/mysql-cluster/templates/cluster.yaml @@ -0,0 +1,40 @@ +apiVersion: mysql.presslabs.org/v1alpha1 +kind: MysqlCluster +metadata: + name: {{ include "mysql-cluster.clusterName" . }} + labels: + app: {{ template "mysql-cluster.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: {{ .Values.replicas }} + secretName: {{ include "mysql-cluster.secretName" . }} + + {{- if .Values.backupSecretName }} + backupSecretName: {{ .Values.backupSecretName }} + {{- else if .Values.backupCredentials }} + backupSecretName: {{ include "mysql-cluster.backupSecretName" . }} + {{- else if .Values.backupSchedule }} + {{ required "One of .mysql.backupBucketSecretName and .mysql.backupCredentails should be specified" "" }} + {{- end }} + + {{- if .Values.backupSchedule }} + backupSchedule: {{ .Values.backupSchedule }} + backupURL: {{ required ".mysql.backupURL is missing" .Values.backupURL }} + {{- end }} + + {{- if .Values.mysqlConfig }} + mysqlConf: + {{ toYaml .Values.mysqlConf | nindent 4 }} + {{- end }} + + {{- if .Values.podSpec }} + podSpec: + {{ toYaml .Values.podSpec | nindent 4 }} + {{- end }} + + {{- if .Values.volumeSpec }} + volumeSpec: + {{ toYaml .Values.volumeSpec | nindent 4 }} + {{- end }} diff --git a/hack/charts/mysql-cluster/templates/secret.yaml b/hack/charts/mysql-cluster/templates/secret.yaml new file mode 100644 index 000000000..ddf0fd84c --- /dev/null +++ b/hack/charts/mysql-cluster/templates/secret.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "mysql-cluster.secretName" . }} + labels: + app: {{ template "mysql-cluster.name" . }} + chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +type: Opaque +data: + ROOT_PASSWORD: {{ required ".rootPassword is missing" .Values.rootPassword | b64enc | quote }} + USER: {{ required ".appUser is missing" .Values.appUser | b64enc | quote }} + PASSWORD: {{ required ".appPassword is missing" .Values.appPassword | b64enc | quote }} + DATABASE: {{ required ".appDatabase is missing" .Values.appDatabase | b64enc | quote }} + DB_CONNECT_URL: {{ include "mysql-cluster.dbConnectURL" . | b64enc | quote }} diff --git a/hack/charts/mysql-cluster/values.yaml b/hack/charts/mysql-cluster/values.yaml new file mode 100644 index 000000000..3d565705a --- /dev/null +++ b/hack/charts/mysql-cluster/values.yaml @@ -0,0 +1,35 @@ +# Default values for mysql-cluster. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +## The cluster number of nodes +replicas: 1 + +## MySQL connect credentials, thoses credentials will be provisioned in the cluster +# rootPassword: +# appUser: +# appPassword: +# appDatabase: + +podSpec: +mysqlConf: +volumeSpec: + +backupSchedule: +backupURL: +backupSecretName: +backupCredentials: + # AWS_ACCESS_KEY_ID: ? + # AWS_SECRET_KEY: ? + # AWS_REGION: us-east-1 + # AWS_ACL: ? + + # GCS_SERVICE_ACCOUNT_JSON_KEY: ? + # GCS_PROJECT_ID: ? + # GCS_OBJECT_ACL: ? + # GCS_BUCKET_ACL: ? + # GCS_LOCATION: ? + # GCS_STORAGE_CLASS: MULTI_REGIONAL + + # HTTP_URL: ? +