diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md index 42019ef1..4889a315 100644 --- a/README.md +++ b/README.md @@ -1 +1,26 @@ -# krypton-helm \ No newline at end of file +# krypton-helm + +## Overview + +[krypton](https://github.com/radondb/krypton) is an open-source, high-available, cloud-native cluster solution based on [MySQL](https://MySQL.org). By using the Raft protocol, krypton can fast failover with no lost transactions. + +## Charts + +- [简体中文](docs/zh-cn/charts.md) +- [English](charts/README.md) + +## Dockerfile + +### Krypton + +- [简体中文](docs/zh-cn/krypton.md) +- [English](dockerfile/krypton/README.md) + +### MySQL + +- [简体中文](docs/zh-cn/mysql.md) +- [English](dockerfile/mysql/README.md) + +## License + +Krypton-helm is under the Apache 2.0 license. See the [LICENSE](./LICENSE) file for details. diff --git a/charts/.helmignore b/charts/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/.helmignore @@ -0,0 +1,23 @@ +# 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 +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/Chart.yaml b/charts/Chart.yaml new file mode 100644 index 00000000..36a5853f --- /dev/null +++ b/charts/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +name: krypton +description: Fast, reliable, scalable, and easy to use open-source relational database system. +home: https://github.com/radondb/krypton + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: beta0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "5.7.33" diff --git a/charts/README.md b/charts/README.md new file mode 100644 index 00000000..4db8eb61 --- /dev/null +++ b/charts/README.md @@ -0,0 +1,149 @@ +# Introduction + +This chart bootstraps a single master and multiple slave krypton deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +# Prerequisites + +- Kubernetes 1.10+ with Beta APIs enabled +- PV provisioner support in the underlying infrastructure +- Helm 2.11+ or Helm 3.0-beta3+ + +# Installing the Chart + +To install the chart with the release name `my-release`: + +```bash +## For Helm v2 +$ cd charts +$ helm install . --name my-release + +## For Helm v3 +$ cd charts +$ helm install --name my-release . +``` + +The command deploys krypton cluster on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. + +# Uninstall + +To uninstall/delete the `my-release` deployment: + +```bash +$ helm delete my-release +``` +The command removes all the Kubernetes components associated with the chart and deletes the release completely. + +# Configuration + +The following table lists the configurable parameters of the krypton chart and their default values. + + +| Parameter | Description | Default | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------- | +| `imagePullPolicy` | Image pull policy | `IfNotPresent` | +| `fullnameOverride` | Custom fullname override for the chart | | +| `nameOverride` | Custom name override for the chart | | +| `replicaCount` | The number of pods | `3` | +| `busybox.image` | `busybox` image repository. | `busybox` | +| `busybox.tag` | `busybox` image tag. | `1.32` | +| `mysql.image` | `mysql` image repository. | `zhyass/percona57` | +| `mysql.tag` | `mysql` image tag. | `beta0.1.0` | +| `mysql.mysqlReplicationPassword` | Password for the `qc_repl` user. | `Repl_123`, random 12 characters if not set | +| `mysql.mysqlUser` | Username of new user to create. | `qingcloud` | +| `mysql.mysqlPassword` | Password for the new user. | `Qing@123`, random 12 characters if not set | +| `mysql.mysqlDatabase` | Name for new database to create. | `qingcloud` | +| `mysql.initTokudb` | Install tokudb engine. | `false` | +| `mysql.uuid` | Server_uuid of the mysql. | Generated by uuidv4 function | +| `mysql.args` | Additional arguments to pass to the MySQL container. | `[]` | +| `mysql.livenessProbe.initialDelaySeconds` | Delay before mysql liveness probe is initiated | 30 | +| `mysql.livenessProbe.periodSeconds` | How often to perform the mysql probe | 10 | +| `mysql.livenessProbe.timeoutSeconds` | When the mysql probe times out | 5 | +| `mysql.livenessProbe.successThreshold` | Minimum consecutive successes for the mysql probe to be considered successful after having failed.| 1 | +| `mysql.livenessProbe.failureThreshold` | Minimum consecutive failures for the mysql probe to be considered failed after having succeeded. | 3 | +| `mysql.readinessProbe.initialDelaySeconds` | Delay before mysql readiness probe is initiated | 10 | +| `mysql.readinessProbe.periodSeconds` | How often to perform the mysql probe | 10 | +| `mysql.readinessProbe.timeoutSeconds` | When the mysql probe times out | 1 | +| `mysql.readinessProbe.successThreshold` | Minimum consecutive successes for the mysql probe to be considered successful after having failed.| 1 | +| `mysql.readinessProbe.failureThreshold` | Minimum consecutive failures for the mysql probe to be considered failed after having succeeded. | 3 | +| `mysql.extraEnvVars` | Additional environment variables as a string to be passed to the `tpl` function | | +| `mysql.resources` | CPU/Memory resource requests/limits for mysql. | Memory: `256Mi`, CPU: `100m` | +| `krypton.image` | `krypton` image repository. | `zhyass/krypton` | +| `krypton.tag` | `krypton` image tag. | `beta0.1.0` | +| `krypton.args` | Additional arguments to pass to the krypton container. | `[]` | +| `krypton.extraEnvVars` | Additional environment variables as a string to be passed to the `tpl` function | | +| `krypton.livenessProbe.initialDelaySeconds` | Delay before krypton liveness probe is initiated | 30 | +| `krypton.livenessProbe.periodSeconds` | How often to perform the krypton probe | 10 | +| `krypton.livenessProbe.timeoutSeconds` | When the krypton probe times out | 5 | +| `krypton.livenessProbe.successThreshold` | Minimum consecutive successes for krypton probe to be considered successful after having failed. | 1 | +| `krypton.livenessProbe.failureThreshold` | Minimum consecutive failures for the krypton probe to be considered failed after having succeeded.| 3 | +| `krypton.readinessProbe.initialDelaySeconds` | Delay before krypton readiness probe is initiated | 10 | +| `krypton.readinessProbe.periodSeconds` | How often to perform the krypton probe | 10 | +| `krypton.readinessProbe.timeoutSeconds` | When the krypton probe times out | 1 | +| `krypton.readinessProbe.successThreshold` | Minimum consecutive successes for krypton probe to be considered successful after having failed. | 1 | +| `krypton.readinessProbe.failureThreshold` | Minimum consecutive failures for the krypton probe to be considered failed after having succeeded.| 3 | +| `krypton.resources` | CPU/Memory resource requests/limits for krypton. | Memory: `128Mi`, CPU: `50m` | +| `metrics.enabled` | Start a side-car prometheus exporter | `true` | +| `metrics.image` | Exporter image | `prom/mysqld-exporter` | +| `metrics.tag` | Exporter image | `v0.12.1` | +| `metrics.annotations` | Exporter annotations | `{}` | +| `metrics.livenessProbe.initialDelaySeconds` | Delay before metrics liveness probe is initiated | 15 | +| `metrics.livenessProbe.timeoutSeconds` | When the probe times out | 5 | +| `metrics.readinessProbe.initialDelaySeconds` | Delay before metrics readiness probe is initiated | 5 | +| `metrics.readinessProbe.timeoutSeconds` | When the probe times out | 1 | +| `metrics.resources` | Exporter resource requests/limit | Memory: `32Mi`, CPU: `10m` | +| `service.annotations` | Kubernetes annotations for service | {} | +| `service.type` | Kubernetes service type | NodePort | +| `service.loadBalancerIP` | The service loadBalancer IP | `""` | +| `service.nodePort` | The service nodePort | `""` | +| `service.clusterIP` | The service clusterIP | `""` | +| `service.port` | The service port | `3306` | +| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | +| `priorityClassName` | Set pod priorityClassName | `{}` | +| `statefulsetAnnotations` | Map of annotations for statefulset | `{}` | +| `podAnnotations` | Map of annotations to add to the pods | `{}` | +| `podLabels` | Map of labels to add to the pods | `{}` | +| `persistence.enabled` | Create a volume to store data | true | +| `persistence.size` | Size of persistent volume claim | 10Gi | +| `persistence.storageClass` | Type of persistent volume claim | nil | +| `persistence.accessMode` | ReadWriteOnce or ReadOnly | ReadWriteOnce | +| `persistence.annotations` | Persistent Volume annotations | {} | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```bash +$ cd charts +$ helm install my-release \ + --set mysql.mysqlUser=my-user,mysql.mysqlPassword=my-password,mysql.database=my-database . +``` + +The above command creates a standard database user named `my-user`, with the password `my-password`, who has access to a database named `my-database`. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```bash +$ cd charts +$ helm install my-release -f values.yaml . +``` + +# Persistence + +The [MySQL](https://hub.docker.com/repository/docker/zhyass/percona57) image stores the MySQL data and configurations at the `/var/lib/mysql` path of the container. + +By default, the PersistentVolumeClaim is disabled. In order to enable this functionality you can change the values.yaml to enable persistence, and then a PersistentVolumeClaim can be created and mounted into the directory. + +> *"An emptyDir volume is first created when a Pod is assigned to a Node, and exists as long as that Pod is running on that node. When a Pod is removed from a node for any reason, the data in the emptyDir is deleted forever."* + +**Notice**: You may need to increase the value of `livenessProbe.initialDelaySeconds` when enabling persistence by using PersistentVolumeClaim from PersistentVolume with varying properties. Since its IO performance has impact on the database initialization performance. The default limit for database initialization is `60` seconds (`livenessProbe.initialDelaySeconds` + `livenessProbe.periodSeconds` * `livenessProbe.failureThreshold`). Once such initialization process takes more time than this limit, kubelet will restart the database container, which will interrupt database initialization then causing persisent data in an unusable state. + +# Custom MySQL configuration + +You can add or modify the mysql configuration in [node.cnf](./files/node.cnf). + +``` +[mysqld] +default_storage_engine=InnoDB +max_connections=65535 + +# custom mysql configuration. +expire_logs_days=7 +``` diff --git a/charts/files/node.cnf b/charts/files/node.cnf new file mode 100644 index 00000000..a3eab30c --- /dev/null +++ b/charts/files/node.cnf @@ -0,0 +1,3 @@ +[mysqld] +default_storage_engine=InnoDB +max_connections=65535 diff --git a/charts/templates/NOTE.txt b/charts/templates/NOTE.txt new file mode 100644 index 00000000..e69de29b diff --git a/charts/templates/_helpers.tpl b/charts/templates/_helpers.tpl new file mode 100644 index 00000000..688a432d --- /dev/null +++ b/charts/templates/_helpers.tpl @@ -0,0 +1,35 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "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). +*/}} +{{- define "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 "krypton.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "mysql.uuid" -}} +{{ .Values.mysql.uuid | default uuidv4 }} +{{- end -}} diff --git a/charts/templates/configmap.yaml b/charts/templates/configmap.yaml new file mode 100644 index 00000000..fe2fb777 --- /dev/null +++ b/charts/templates/configmap.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "fullname" . }} + chart: {{ template "krypton.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +data: + node.cnf: |- +{{ .Files.Get "files/node.cnf" | indent 4 }} + server-id.cnf: | + [mysqld] + server-id=@@SERVER_ID@@ + create-peers.sh: | + #!/bin/bash + i=0 + while [ $i -lt {{ .Values.replicaCount }} ] + do + if [ $i = 0 ] + then + echo -n "{{ template "fullname" . }}-${i}.{{ template "fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:8801" + else + echo -n ",{{ template "fullname" . }}-${i}.{{ template "fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:8801" + fi + let i++ + done + diff --git a/charts/templates/secrets.yaml b/charts/templates/secrets.yaml new file mode 100644 index 00000000..9695c035 --- /dev/null +++ b/charts/templates/secrets.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "fullname" . }} + chart: {{ template "krypton.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +type: Opaque +data: +# {{ if not .Values.mysql.allowEmptyRootPassword }} +# {{- if .Values.mysql.mysqlRootPassword }} +# mysql-root-password: {{ .Values.mysql.mysqlRootPassword | b64enc | quote }} +# {{- end }} +# {{- else }} +# mysql-root-password: {{ randAlphaNum 12 | b64enc | quote }} +# {{- end }} + {{- if and .Values.mysql.mysqlUser (and (ne .Values.mysql.mysqlUser "qc_repl") (ne .Values.mysql.mysqlUser "root"))}} + {{- if .Values.mysql.mysqlPassword }} + mysql-password: {{ .Values.mysql.mysqlPassword | b64enc | quote }} + {{- else }} + mysql-password: {{ randAlphaNum 12 | b64enc | quote }} + {{- end }} + {{- end }} + {{- if .Values.mysql.mysqlReplicationPassword }} + mysql-replication-password: {{ .Values.mysql.mysqlReplicationPassword | b64enc | quote }} + {{- else }} + mysql-replication-password: {{ randAlphaNum 12 | b64enc | quote }} + {{- end }} diff --git a/charts/templates/statefulset.yaml b/charts/templates/statefulset.yaml new file mode 100644 index 00000000..25250551 --- /dev/null +++ b/charts/templates/statefulset.yaml @@ -0,0 +1,261 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ template "fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "fullname" . }} + chart: {{ template "krypton.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +{{- with .Values.statefulsetAnnotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + +spec: + serviceName: {{ template "fullname" . }} + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ template "fullname" . }} + release: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ template "fullname" . }} + release: {{ .Release.Name }} +{{- with .Values.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} +{{- with .Values.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} + initContainers: + - name: init-mysql + image: "{{ .Values.busybox.image }}:{{ .Values.busybox.tag }}" + imagePullPolicy: {{ .Values.imagePullPolicy | quote }} + command: ['sh','-c'] + args: + - | + # Generate mysql server-id from pod ordinal index. + ordinal=$(echo $(hostname) | tr -cd "[0-9]") + # Copy server-id.conf adding offset to avoid reserved server-id=0 value. + cat /mnt/config-map/server-id.cnf | sed s/@@SERVER_ID@@/$((100 + $ordinal))/g > /mnt/conf.d/server-id.cnf + # Copy appropriate conf.d files from config-map to config mount. + cp -f /mnt/config-map/node.cnf /mnt/conf.d/ + {{- if .Values.mysql.initTokudb }} + # For install tokudb. + printf '\nloose_tokudb_directio = ON\n' >> /mnt/conf.d/node.cnf + echo never > /host-sys/kernel/mm/transparent_hugepage/enabled + {{- end }} + volumeMounts: + - name: conf + mountPath: /mnt/conf.d + - name: config-map + mountPath: /mnt/config-map + {{- if .Values.mysql.initTokudb }} + - name: host-sys + mountPath: /host-sys + {{- end }} + containers: + - name: mysql + image: "{{ .Values.mysql.image }}:{{ .Values.mysql.tag }}" + imagePullPolicy: {{ .Values.imagePullPolicy | quote }} + {{- with .Values.mysql.args }} + args: + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} + resources: +{{ toYaml .Values.mysql.resources | indent 10 }} + env: +# {{- if .Values.mysql.allowEmptyRootPassword }} +# - name: MYSQL_ALLOW_EMPTY_ROOT_PASSWORD +# value: "true" +# {{- else }} +# - name: MYSQL_ROOT_PASSWORD +# valueFrom: +# secretKeyRef: +# name: {{ template "fullname" . }} +# key: mysql-root-password +# {{- end }} + - name: MYSQL_REPL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "fullname" . }} + key: mysql-replication-password + {{- if .Values.mysql.database }} + - name: MYSQL_DATABASE + value: {{ .Values.mysql.database | quote }} + {{- end }} + {{- if .Values.mysql.mysqlUser }} + - name: MYSQL_USER + value: {{ .Values.mysql.mysqlUser | quote }} + - name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "fullname" . }} + key: mysql-password + {{- end }} + {{- if .Values.mysql.initTokudb }} + - name: INIT_TOKUDB + value: "1" + {{- end }} + - name: SERVER_UUID + value: {{ template "mysql.uuid" . }} + {{- if .Values.mysql.extraEnvVars }} +{{ tpl .Values.mysql.extraEnvVars . | indent 8 }} + {{- end }} + ports: + - name: mysql + containerPort: 3306 + volumeMounts: + - name: data + mountPath: /var/lib/mysql + - name: conf + mountPath: /etc/mysql/conf.d + livenessProbe: + exec: + command: + - /bin/sh + - "-c" + - mysqladmin ping -h 127.0.0.1 -u root + initialDelaySeconds: {{ .Values.mysql.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.mysql.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.mysql.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.mysql.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.mysql.livenessProbe.failureThreshold }} + readinessProbe: + exec: + command: + - /bin/sh + - "-c" + - mysql -h 127.0.0.1 -u root -e "SELECT 1" + initialDelaySeconds: {{ .Values.mysql.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.mysql.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.mysql.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.mysql.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.mysql.readinessProbe.failureThreshold }} + - name: krypton + image: "{{ .Values.krypton.image }}:{{ .Values.krypton.tag }}" + imagePullPolicy: {{ .Values.imagePullPolicy | quote }} + {{- with .Values.krypton.args }} + args: + {{- range . }} + - {{ . | quote }} + {{- end }} + {{- end }} + lifecycle: + postStart: + exec: + command: ['sh', '-c', 'until /krypton/kryptoncli xenon ping > /dev/null 2>&1; do sleep 2; done && /krypton/kryptoncli mysql stopmonitor && /krypton/kryptoncli cluster add "$(/bin/bash /create-peers.sh)"'] + resources: +{{ toYaml .Values.krypton.resources | indent 10 }} + volumeMounts: + - name: config-map + mountPath: /create-peers.sh + subPath: create-peers.sh + env: + - name: MYSQL_REPL_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "fullname" . }} + key: mysql-replication-password + - name: HOST_SUFFIX + value: {{ template "fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + {{- if .Values.krypton.extraEnvVars }} +{{ tpl .Values.krypton.extraEnvVars . | indent 8 }} + {{- end }} + ports: + - name: krypton + containerPort: 8801 + livenessProbe: + exec: + command: + - pgrep + - krypton + initialDelaySeconds: {{ .Values.krypton.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.krypton.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.krypton.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.krypton.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.krypton.livenessProbe.failureThreshold }} + readinessProbe: + exec: + command: + - sh + - -c + - "/krypton/kryptoncli xenon ping" + initialDelaySeconds: {{ .Values.krypton.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.krypton.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.krypton.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.krypton.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.krypton.readinessProbe.failureThreshold }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: "{{ .Values.metrics.image }}:{{ .Values.metrics.tag }}" + imagePullPolicy: {{ .Values.imagePullPolicy | quote }} + command: ['sh', '-c', 'DATA_SOURCE_NAME="root@(localhost:3306)/" /bin/mysqld_exporter' ] + ports: + - name: metrics + containerPort: 9104 + livenessProbe: + httpGet: + path: / + port: metrics + initialDelaySeconds: {{ .Values.metrics.livenessProbe.initialDelaySeconds }} + timeoutSeconds: {{ .Values.metrics.livenessProbe.timeoutSeconds }} + readinessProbe: + httpGet: + path: / + port: metrics + initialDelaySeconds: {{ .Values.metrics.readinessProbe.initialDelaySeconds }} + timeoutSeconds: {{ .Values.metrics.readinessProbe.timeoutSeconds }} + resources: +{{ toYaml .Values.metrics.resources | indent 10 }} + {{- end }} + volumes: + - name: conf + emptyDir: {} + - name: config-map + configMap: + name: {{ template "fullname" . }} + {{- if .Values.mysql.initTokudb }} + - name: host-sys + hostPath: + path: /sys + {{- end }} +{{- if .Values.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + annotations: + {{- range $key, $value := .Values.persistence.annotations }} + {{ $key }}: {{ $value }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.storageClass }} + {{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.persistence.storageClass }}" + {{- end }} + {{- end }} +{{- else }} + - name: data + emptyDir: {} +{{- end }} diff --git a/charts/templates/svc.yaml b/charts/templates/svc.yaml new file mode 100644 index 00000000..78330062 --- /dev/null +++ b/charts/templates/svc.yaml @@ -0,0 +1,38 @@ +# Headless service for stable DNS entries of StatefulSet members. +apiVersion: v1 +kind: Service +metadata: + name: {{ template "fullname" . }} + labels: + app: {{ template "fullname" . }} + chart: {{ template "krypton.chart" . }} + release: {{ .Release.Name | quote }} + heritage: {{ .Release.Service | quote }} +{{- if .Values.service.annotations }} +{{ toYaml .Values.service.annotations | indent 4 }} +{{- end }} +{{- if and (.Values.metrics.enabled) (.Values.metrics.annotations) }} +{{ toYaml .Values.metrics.annotations | indent 4 }} +{{- end }} +spec: + type: {{ .Values.service.type }} + {{- if (and (eq .Values.service.type "ClusterIP") (not (empty .Values.service.clusterIP))) }} + clusterIP: {{ .Values.service.clusterIP }} + {{- end }} + {{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP))) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + ports: + - name: mysql + port: {{ .Values.service.port }} + targetPort: mysql + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + port: 9104 + targetPort: metrics + {{- end }} + selector: + app: {{ template "fullname" . }} diff --git a/charts/values.yaml b/charts/values.yaml new file mode 100644 index 00000000..9b63af3d --- /dev/null +++ b/charts/values.yaml @@ -0,0 +1,182 @@ +# Default values for krypton. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +## Specify an imagePullPolicy (Required) +## It's recommended to change this to 'Always' if the image tag is 'latest' +## ref: http://kubernetes.io/docs/user-guide/images/#updating-images +## Always IfNotPresent NEVER +imagePullPolicy: Always + +## String to partially override orangehrm.fullname template (will maintain the release name) +## +# nameOverride: "" +## String to fully override orangehrm.fullname template +## +# fullnameOverride: "" + +replicaCount: 3 + +busybox: + image: "busybox" + tag: "1.32" + +mysql: + image: zhyass/percona57 + tag: beta0.1.0 + + mysqlReplicationPassword: Repl_123 + + mysqlUser: qingcloud + mysqlPassword: Qing@123 + database: qingcloud + + initTokudb: false + uuid: "" + ## Additionnal arguments that are passed to the MySQL container. + ## For example use --default-authentication-plugin=mysql_native_password if older clients need to + ## connect to a MySQL 8 instance. + args: [] + + livenessProbe: + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + + readinessProbe: + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + + ## A string to add extra environment variables + # extraEnvVars: | + # - name: EXTRA_VAR + # value: "extra" + + ## Configure resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + requests: + memory: 256Mi + cpu: 100m + limits: + memory: 1Gi + cpu: 500m + +krypton: + image: zhyass/krypton + tag: beta0.1.0 + args: [] + + ## A string to add extra environment variables + # extraEnvVars: | + # - name: EXTRA_VAR + # value: "extra" + + ## Configure resource requests and limits + ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + livenessProbe: + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + successThreshold: 1 + failureThreshold: 3 + + readinessProbe: + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + + resources: + requests: + memory: 128Mi + cpu: 50m + limits: + memory: 256Mi + cpu: 100m + +metrics: + enabled: true + image: prom/mysqld-exporter + tag: v0.12.1 + annotations: {} + + livenessProbe: + initialDelaySeconds: 15 + timeoutSeconds: 5 + readinessProbe: + initialDelaySeconds: 5 + timeoutSeconds: 1 + resources: + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 10m + memory: 32Mi + +## Configure the service +## ref: http://kubernetes.io/docs/user-guide/services/ +service: + annotations: {} + ## Specify a service type, NodePort|ClusterIP|LoadBalancer + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types + type: NodePort + # clusterIP: None + port: 3306 + # nodePort: 32000 + # loadBalancerIP: + +# create pv for test persistence +#apiVersion: v1 +#kind: PersistentVolume +#metadata: +# name: lzz-pv1 +#spec: +# capacity: +# storage: 1Gi +# persistentVolumeReclaimPolicy: Recycle +# accessModes: +# - ReadWriteOnce +# hostPath: +# path: "/pv/lzz-pv1" + +## Enable persistence using Persistent Volume Claims +## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +## +persistence: + enabled: true + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, azure-disk on + ## Azure, standard on GKE, AWS & OpenStack) + ## + # storageClass: "-" + accessModes: + - ReadWriteOnce + size: 10Gi + annotations: {} + +## Set pod priorityClassName +# priorityClassName: {} + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + +# statefulset Annotations +statefulsetAnnotations: {} + +# To be added to the database server pod(s) +podAnnotations: {} +podLabels: {} diff --git a/dockerfile/krypton/Dockerfile b/dockerfile/krypton/Dockerfile new file mode 100644 index 00000000..006f8378 --- /dev/null +++ b/dockerfile/krypton/Dockerfile @@ -0,0 +1,37 @@ +# Builder image +FROM golang:1.13-buster as builder + +ARG KRYPTON_BRANCH=feature_adapt_k8s +RUN set -ex; \ + mkdir -p /go/src/github.com/andyli029; \ + cd /go/src/github.com/andyli029; \ + git clone --branch $KRYPTON_BRANCH https://github.com/andyli029/krypton.git; \ + cd krypton; \ + make build + +FROM ubuntu:focal + +RUN set -ex; \ + groupadd --gid 999 --system mysql; \ + useradd \ + --uid 999 \ + --system \ + --home-dir /var/lib/mysql \ + --no-create-home \ + --gid mysql \ + mysql; \ + mkdir -p /krypton /etc/krypton /var/log/krypton /var/lib/krypton; \ + echo "/etc/krypton/krypton.json" > /krypton/config.path; \ + # allow to change config files + chown -R mysql:mysql /krypton /etc/krypton /var/log/krypton /var/lib/krypton + +VOLUME ["/var/lib/krypton", "/var/log/krypton"] + +COPY --from=builder --chown=mysql:mysql /go/src/github.com/andyli029/krypton/bin/xenon /krypton/krypton +COPY --from=builder --chown=mysql:mysql /go/src/github.com/andyli029/krypton/bin/xenoncli /krypton/kryptoncli +COPY krypton-entry.sh /docker-entrypoint.sh +ENTRYPOINT ["/docker-entrypoint.sh"] + +USER mysql +EXPOSE 8801 +CMD ["/krypton/krypton", "-c", "/etc/krypton/krypton.json"] diff --git a/dockerfile/krypton/README.md b/dockerfile/krypton/README.md new file mode 100644 index 00000000..940a76c3 --- /dev/null +++ b/dockerfile/krypton/README.md @@ -0,0 +1,23 @@ +# Introduction + +The [krypton](https://hub.docker.com/repository/docker/zhyass/krypton) image has been pushed into docker hub. The available versions are: + + zhyass/krypton (tag: beta0.1.0) + +Images are updated when new releases are published. + +# Environment Variables + +## `MYSQL_REPL_PASSWORD` + +This variable specifies a replication password that will be set in the configuration file `krypton.json`, the default is `Repl_123`. + +## `HOST_SUFFIX` + +This variable is used to specify the endpoint in the kubenetes cluster, default is nil. + +# Build Image + +``` +docker build -t krypton:v1.0 . +``` diff --git a/dockerfile/krypton/krypton-entry.sh b/dockerfile/krypton/krypton-entry.sh new file mode 100755 index 00000000..a4325057 --- /dev/null +++ b/dockerfile/krypton/krypton-entry.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +host=$(hostname) + +file_env 'HOST_SUFFIX' '' + +if [ -n "$HOST_SUFFIX" ]; then + host=$host.$HOST_SUFFIX +fi + +file_env 'MYSQL_REPL_PASSWORD' 'Repl_123' + +printf '{ + "log": { + "level": "INFO" + }, + "server": { + "endpoint": "%s:8801" + }, + "replication": { + "passwd": "%s", + "user": "qc_repl" + }, + "rpc": { + "request-timeout": 2000 + }, + "mysql": { + "admit-defeat-ping-count": 3, + "admin": "root", + "basedir": "/usr", + "defaults-file": "/etc/mysql/my.cnf", + "ping-timeout": 2000, + "passwd": "", + "host": "localhost", + "version": "mysql57", + "master-sysvars": "tokudb_fsync_log_period=default;sync_binlog=default;innodb_flush_log_at_trx_commit=default", + "slave-sysvars": "tokudb_fsync_log_period=1000;sync_binlog=1000;innodb_flush_log_at_trx_commit=1", + "port": 3306 + }, + "raft": { + "election-timeout": 10000, + "admit-defeat-hearbeat-count": 5, + "heartbeat-timeout": 2000, + "meta-datadir": "/var/lib/krypton/", + "leader-start-command": "", + "leader-stop-command": "", + "semi-sync-degrade": true, + "purge-binlog-disabled": true, + "super-idle": false + } +}' $host $MYSQL_REPL_PASSWORD > /etc/krypton/krypton.json + +chown -R mysql:mysql /etc/krypton/krypton.json + +exec "$@" \ No newline at end of file diff --git a/dockerfile/mysql/Dockerfile b/dockerfile/mysql/Dockerfile new file mode 100644 index 00000000..36de38b8 --- /dev/null +++ b/dockerfile/mysql/Dockerfile @@ -0,0 +1,65 @@ +FROM ubuntu:focal + +RUN set -ex; \ + groupadd --gid 999 --system mysql; \ + useradd \ + --uid 999 \ + --system \ + --home-dir /var/lib/mysql \ + --no-create-home \ + --gid mysql \ + mysql; \ + apt-get update; \ + if ! which gpg; then \ + apt-get install -y --no-install-recommends gnupg; \ + fi; \ + if ! gpg --version | grep -q '^gpg (GnuPG) 1\.'; then \ + apt-get install -y --no-install-recommends dirmngr; \ + fi; \ + rm -rf /var/lib/apt/lists/* + +ARG XTRABACKUP_PKG=percona-xtrabackup-24 +RUN set -ex; \ + key='9334A25F8507EFA5'; \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver keys.gnupg.net --recv-keys "$key"; \ + gpg --batch --export $key > /etc/apt/trusted.gpg.d/mysql.gpg; \ + command -v gpgconf > /dev/null && gpgconf --kill all || :; \ + rm -r "$GNUPGHOME"; \ + apt-key list > /dev/null; \ + echo "deb http://repo.percona.com/apt focal main\ndeb-src http://repo.percona.com/apt focal main">> /etc/apt/sources.list.d/mysql.list; \ + apt-get update; \ + export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true; \ + { \ + echo percona-server-server-5.7 percona-server-server-5.7/root-pass password ''; \ + echo percona-server-server-5.7 percona-server-server-5.7/re-root-pass password ''; \ + echo tzdata tzdata/Areas select Asia; \ + echo tzdata tzdata/Zones/Asia select Shanghai; \ + } | debconf-set-selections; \ + # install "tzdata" for /usr/share/zoneinfo/ + apt-get install -y --no-install-recommends libjemalloc1 libmecab2 tzdata; \ + apt-get install -y --no-install-recommends \ + percona-server-server-5.7 \ + percona-server-common-5.7 \ + percona-server-tokudb-5.7 \ + ${XTRABACKUP_PKG}; \ + # TokuDB modifications + echo "LD_PRELOAD=/usr/lib64/libjemalloc.so.1" >> /etc/default/mysql; \ + echo "THP_SETTING=never" >> /etc/default/mysql; \ + \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /var/lib/mysql /etc/alternatives/my.cnf /etc/mysql/*; \ + mkdir -p /var/lib/mysql /var/log/mysql /var/run/mysqld /etc/mysql/conf.d; \ + # allow to change config files + chown -R mysql:mysql /var/lib/mysql /var/log/mysql /var/run/mysqld /etc/mysql; \ + # ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime + chmod 1777 /var/run/mysqld + +VOLUME ["/var/lib/mysql", "/var/log/mysql"] + +COPY mysql-entry.sh /docker-entrypoint.sh +COPY --chown=mysql:mysql my.cnf /etc/mysql/my.cnf +ENTRYPOINT ["/docker-entrypoint.sh"] + +EXPOSE 3306 +CMD ["mysqld"] \ No newline at end of file diff --git a/dockerfile/mysql/README.md b/dockerfile/mysql/README.md new file mode 100644 index 00000000..45cd755a --- /dev/null +++ b/dockerfile/mysql/README.md @@ -0,0 +1,41 @@ +# Introduction + +The [mysql](https://hub.docker.com/repository/docker/zhyass/percona57) image has been pushed into docker hub. The available versions are: + + zhyass/percona57 (tag: beta0.1.0) + +Images are updated when new releases are published. + +# Environment Variables + +## `MYSQL_REPL_PASSWORD` + +This variable specifies a replication password that will be set for the replication account, the default is `Repl_123`. + +## `INIT_TOKUDB` + +Set to `1` to allow the container to be started with enabled TOKUDB engine. + +## `MYSQL_INITDB_SKIP_TZINFO` + +Skip import time zone information into MySQL when the variable is set. + +## `MYSQL_DATABASE` + +This variable is optional. It allows you to specify the name of a database to be created on image startup. If a user/password was supplied (see below) then that user will be granted superuser access (corresponding to GRANT ALL) to this database. + +## `MYSQL_USER`, `MYSQL_PASSWORD` + +These variables are optional, used in conjunction to create a new user and set that user's password. This user will be granted superuser permissions (see above) for the database specified by the `MYSQL_DATABASE` variable. Both variables are required for a user to be created. + +Do note that there is no need to use this mechanism to create the `root` superuser or `qc_repl` replication user, that user gets created by default with the password set by either of the mechanisms (given or generated) discussed above. + +## `SERVER_UUID` + +The variable is a mysql parameter configured in `auto.cnf`, used to provide UUID when mysql is started for the first time. + +# Build Image + +``` +docker build -t mysql:v1.0 . +``` diff --git a/dockerfile/mysql/my.cnf b/dockerfile/mysql/my.cnf new file mode 100644 index 00000000..c99d3de7 --- /dev/null +++ b/dockerfile/mysql/my.cnf @@ -0,0 +1,63 @@ +[client] +socket = /var/run/mysqld/mysqld.sock + +[mysqld] +federated +skip-host-cache +skip-name-resolve + +server-id = 9527 +user = mysql +port = 3306 +basedir = /usr +datadir = /var/lib/mysql/ + +# log-error = /var/log/mysql/mysql-error.log +slow_query_log_file = /var/log/mysql/mysql-slow.log + +read_only = ON +binlog_format = row +log-bin-index=/var/log/mysql/mysql-bin.index +log-bin=/var/log/mysql/mysql-bin +core-file + +log-timestamps=SYSTEM + +#ssl +ssl-ca=/var/lib/mysql/ca.pem +ssl-cert=/var/lib/mysql/server-cert.pem +ssl-key=/var/lib/mysql/server-key.pem + +##semi-sync +plugin-load="semisync_master.so;semisync_slave.so;audit_log.so" +rpl_semi_sync_master_enabled=OFF +rpl_semi_sync_slave_enabled=ON +rpl_semi_sync_master_wait_no_slave=ON +rpl_semi_sync_master_timeout=1000000000000000000 + +##repl +skip-slave-start +gtid-mode = ON +enforce-gtid-consistency = ON +slave_parallel_type = LOGICAL_CLOCK +slave_parallel_workers=0 +log-slave-updates + +#relay log +relay_log=/var/log/mysql/mysql-relay-bin +relay_log_index=/var/log/mysql/mysql-relay-bin.index + +master_info_repository=TABLE +relay_log_info_repository=TABLE + +#fixed config +slow_query_log=1 +tmp_table_size=32M +tmpdir=/var/lib/mysql + +# audit log +audit_log_file = /var/log/mysql/mysql-audit.log +audit_log_exclude_accounts = "root@localhost,root@127.0.0.1,qc_repl@%" +audit_log_buffer_size = 16M + +!includedir /etc/mysql/conf.d diff --git a/dockerfile/mysql/mysql-entry.sh b/dockerfile/mysql/mysql-entry.sh new file mode 100755 index 00000000..f2f0c9c2 --- /dev/null +++ b/dockerfile/mysql/mysql-entry.sh @@ -0,0 +1,157 @@ +#!/bin/bash + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +# usage: process_init_file FILENAME MYSQLCOMMAND... +# ie: process_init_file foo.sh mysql -uroot +# (process a single initializer file, based on its extension. we define this +# function here, so that initializer scripts (*.sh) can use the same logic, +# potentially recursively, or override the logic used in subsequent calls) +process_init_file() { + local f="$1"; shift + local mysql=( "$@" ) + + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;; + *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo +} + +# Fetch value from server config +# We use mysqld --verbose --help instead of my_print_defaults because the +# latter only show values present in config files, and not server defaults +_get_config() { + local conf="$1"; + "mysqld" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null \ + | awk '$1 == "'"$conf"'" && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }' + # match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)" +} + +if [ -n "$INIT_TOKUDB" ]; then + export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 +fi +# Get config +DATADIR="$(_get_config 'datadir')" + +if [ ! -d "$DATADIR/mysql" ]; then + mkdir -p "$DATADIR" + + echo 'Initializing database' + mysqld --initialize-insecure --skip-ssl + echo 'Database initialized' + + if command -v mysql_ssl_rsa_setup > /dev/null && [ ! -e "$DATADIR/server-key.pem" ]; then + # https://github.com/mysql/mysql-server/blob/23032807537d8dd8ee4ec1c4d40f0633cd4e12f9/packaging/deb-in/extra/mysql-systemd-start#L81-L84 + echo 'Initializing certificates' + mysql_ssl_rsa_setup --datadir="$DATADIR" + echo 'Certificates initialized' + fi + + SOCKET="$(_get_config 'socket')" + "mysqld" --skip-networking --socket="${SOCKET}" & + pid="$!" + + mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" --password="" ) + + for i in {120..0}; do + if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then + break + fi + echo 'MySQL init process in progress...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 'MySQL init process failed.' + exit 1 + fi + + if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then + # sed is for https://bugs.mysql.com/bug.php?id=20545 + mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql + fi + + # install TokuDB engine + if [ -n "$INIT_TOKUDB" ]; then + ps-admin --docker --enable-tokudb -u root + fi + + "${mysql[@]}" <<-EOSQL + -- What's done in this file shouldn't be replicated + -- or products like mysql-fabric won't work + SET @@SESSION.SQL_LOG_BIN=0; + DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'root') OR host NOT IN ('localhost') ; + CREATE USER 'root'@'127.0.0.1' IDENTIFIED BY '' ; + GRANT ALL ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION ; + DROP DATABASE IF EXISTS test ; + FLUSH PRIVILEGES ; + EOSQL + + file_env 'MYSQL_REPL_PASSWORD' 'Repl_123' + echo "GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* to 'qc_repl'@'%' IDENTIFIED BY '$MYSQL_REPL_PASSWORD' ;" | "${mysql[@]}" + echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" + + file_env 'MYSQL_USER' 'qingcloud' + echo "MySQL USER: $MYSQL_USER" + if [ $MYSQL_USER = "root" -o $MYSQL_USER = "qc_repl" ]; then + echo >&2 'Donot set MYSQL_USER as root or qc_repl.' + exit 1 + fi + + file_env 'MYSQL_PASSWORD' 'qingcloud' + + file_env 'MYSQL_DATABASE' + if [ "$MYSQL_DATABASE" ]; then + echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" + mysql+=( "$MYSQL_DATABASE" ) + fi + + echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}" + if [ "$MYSQL_DATABASE" ]; then + echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}" + fi + echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" + echo 'reset master;' | "${mysql[@]}" + + if ! kill -s TERM "$pid" || ! wait "$pid"; then + echo >&2 'MySQL init process failed.' + exit 1 + fi + + sed -i '/server-id/d' /etc/mysql/my.cnf + rm /var/log/mysql/error.log + rm /var/lib/mysql/auto.cnf + + uuid=$(cat /proc/sys/kernel/random/uuid) + file_env 'SERVER_UUID' $uuid + printf '[auto]\nserver_uuid=%s' $SERVER_UUID > a + chown -R mysql:mysql "$DATADIR" + + echo + echo 'MySQL init process done.' + echo +fi + +exec "$@" diff --git a/docs/zh-cn/charts.md b/docs/zh-cn/charts.md new file mode 100644 index 00000000..433aeb03 --- /dev/null +++ b/docs/zh-cn/charts.md @@ -0,0 +1,3 @@ +# Krypton Charts + +## 简介 diff --git a/docs/zh-cn/krypton.md b/docs/zh-cn/krypton.md new file mode 100644 index 00000000..e76a0dc1 --- /dev/null +++ b/docs/zh-cn/krypton.md @@ -0,0 +1,3 @@ +# Krypton Dockerfile + +## 简介 diff --git a/docs/zh-cn/mysql.md b/docs/zh-cn/mysql.md new file mode 100644 index 00000000..89c5a438 --- /dev/null +++ b/docs/zh-cn/mysql.md @@ -0,0 +1,3 @@ +# MySQL Dockerfile + +## 简介