├── Dockerfile ├── LICENSE.txt ├── README.md ├── entrypoint.sh ├── functions.sh ├── helm ├── .helmignore ├── Chart.yaml ├── README.md ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── pvc.yaml │ ├── secrets.yaml │ ├── statefulset.yaml │ └── svc.yaml └── values.yaml └── kubernetes └── percona-galera-xtradb.yaml /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM percona/percona-xtradb-cluster:5.7.19 2 | 3 | COPY entrypoint.sh /entrypoint.sh 4 | COPY functions.sh /functions.sh 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2017 Paul Czarkowski (pczarkowski@pivotal.io) 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # k8s-percona-pxc 2 | 3 | Extends the official [Percona XtraDB Cluster image](https://github.com/percona/percona-docker/tree/master/pxc-57) to work natively in Kubernetes. 4 | 5 | The Percona image supports specifying a peer to join or ETCD as service discovery. However etcd is unecessary with Kubernetes as Kubernetes already knows enough about what is running to provide similar functionality. 6 | 7 | # How does it work? 8 | 9 | If the environment variable `DISCOVERY_SERVICE` is set to `kubernetes` it simply exploits the nature of the Kubernetes **StatefulSet** and headless **Service** resources to determine if there is already 10 | a primary MySQL server to cluster to. 11 | 12 | There is an example [Kubernetes manifest](kubernetes/percona-galera-xtradb.yaml) included that is written to be as compatible as possible 13 | so it doesn't do any volume mapping or fancy. If you want to use it for real workloads you'll want 14 | to spend some time making the manifest production ready. 15 | 16 | # Demo 17 | 18 | This assumes you already have kubernetes running. 19 | 20 | Deploy a 3 node Percona XtraDB Cluster: 21 | 22 | ``` 23 | $ kubectl create -f kubernetes 24 | ``` 25 | 26 | Wait a few minute and then check that all three pods are running: 27 | 28 | ``` 29 | $ kubectl get pods 30 | NAME READY STATUS RESTARTS AGE 31 | percona-galera-0 1/1 Running 4 5m 32 | percona-galera-1 1/1 Running 4 3m 33 | percona-galera-2 1/1 Running 4 1m 34 | ``` 35 | 36 | Check that they have clustered correctly: 37 | 38 | ``` 39 | $ kubectl exec -ti percona-galera-0 -- \ 40 | mysql -pnot-a-secure-password -e "SHOW GLOBAL STATUS LIKE 'wsrep_cluster_size'" 41 | mysql: [Warning] Using a password on the command line interface can be insecure. 42 | +--------------------+-------+ 43 | | Variable_name | Value | 44 | +--------------------+-------+ 45 | | wsrep_cluster_size | 3 | 46 | +--------------------+-------+ 47 | ``` 48 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [[ -n "${DEBUG}" ]]; then 5 | set -x 6 | fi 7 | 8 | . /functions.sh 9 | 10 | ipaddr=$(hostname -i | awk ' { print $1 } ') 11 | hostname=$(hostname) 12 | echo "I AM $hostname - $ipaddr" 13 | 14 | # if command starts with an option, prepend mysqld 15 | if [ "${1:0:1}" = '-' ]; then 16 | CMDARG="$@" 17 | fi 18 | 19 | cluster_join=$(resolveip -s "${K8S_SERVICE_NAME}" || echo "") 20 | if [[ -z "${cluster_join}" ]]; then 21 | echo "I am the Primary Node" 22 | init_mysql 23 | write_password_file 24 | exec mysqld --user=mysql --wsrep_cluster_name=$CLUSTER_NAME --wsrep_node_name=$hostname \ 25 | --wsrep_cluster_address=gcomm:// --wsrep_sst_method=xtrabackup-v2 \ 26 | --wsrep_sst_auth="xtrabackup:$XTRABACKUP_PASSWORD" \ 27 | --wsrep_node_address="$ipaddr" $CMDARG 28 | else 29 | echo "I am not the Primary Node" 30 | write_password_file 31 | exec mysqld --user=mysql --wsrep_cluster_name=$CLUSTER_NAME --wsrep_node_name=$hostname \ 32 | --wsrep_cluster_address="gcomm://$cluster_join" --wsrep_sst_method=xtrabackup-v2 \ 33 | --wsrep_sst_auth="xtrabackup:$XTRABACKUP_PASSWORD" \ 34 | --wsrep_node_address="$ipaddr" $CMDARG 35 | fi 36 | -------------------------------------------------------------------------------- /functions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | write_password_file() { 4 | if [[ -n "${MYSQL_ROOT_PASSWORD}" ]]; then 5 | cat < /root/.my.cnf 6 | [client] 7 | user=root 8 | password=${MYSQL_ROOT_PASSWORD} 9 | EOF 10 | fi 11 | } 12 | 13 | init_mysql() { 14 | DATADIR=/var/lib/mysql 15 | # if we have CLUSTER_JOIN - then we do not need to perform datadir initialize 16 | # the data will be copied from another node 17 | if [ ! -e "$DATADIR/mysql" ]; then 18 | if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" -a -z "$MYSQL_ROOT_PASSWORD_FILE" ]; then 19 | echo >&2 'error: database is uninitialized and password option is not specified ' 20 | echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ROOT_PASSWORD_FILE, MYSQL_ALLOW_EMPTY_PASSWORD or MYSQL_RANDOM_ROOT_PASSWORD' 21 | exit 1 22 | fi 23 | 24 | if [ ! -z "$MYSQL_ROOT_PASSWORD_FILE" -a -z "$MYSQL_ROOT_PASSWORD" ]; then 25 | MYSQL_ROOT_PASSWORD=$(cat $MYSQL_ROOT_PASSWORD_FILE) 26 | fi 27 | mkdir -p "$DATADIR" 28 | 29 | echo "Running --initialize-insecure on $DATADIR" 30 | ls -lah $DATADIR 31 | mysqld --initialize-insecure 32 | chown -R mysql:mysql "$DATADIR" 33 | chown mysql:mysql /var/log/mysqld.log 34 | echo 'Finished --initialize-insecure' 35 | 36 | mysqld --user=mysql --datadir="$DATADIR" --skip-networking & 37 | pid="$!" 38 | 39 | mysql=( mysql --protocol=socket -uroot ) 40 | 41 | for i in {30..0}; do 42 | if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then 43 | break 44 | fi 45 | echo 'MySQL init process in progress...' 46 | sleep 1 47 | done 48 | if [ "$i" = 0 ]; then 49 | echo >&2 'MySQL init process failed.' 50 | exit 1 51 | fi 52 | 53 | # sed is for https://bugs.mysql.com/bug.php?id=20545 54 | mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql 55 | if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then 56 | MYSQL_ROOT_PASSWORD="$(pwmake 128)" 57 | echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" 58 | fi 59 | "${mysql[@]}" <<-EOSQL 60 | -- What's done in this file shouldn't be replicated 61 | -- or products like mysql-fabric won't work 62 | SET @@SESSION.SQL_LOG_BIN=0; 63 | CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; 64 | GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; 65 | ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; 66 | CREATE USER 'xtrabackup'@'localhost' IDENTIFIED BY '$XTRABACKUP_PASSWORD'; 67 | GRANT RELOAD,PROCESS,LOCK TABLES,REPLICATION CLIENT ON *.* TO 'xtrabackup'@'localhost'; 68 | GRANT REPLICATION CLIENT ON *.* TO monitor@'%' IDENTIFIED BY 'monitor'; 69 | GRANT PROCESS ON *.* TO monitor@localhost IDENTIFIED BY 'monitor'; 70 | DROP DATABASE IF EXISTS test ; 71 | FLUSH PRIVILEGES ; 72 | EOSQL 73 | if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then 74 | mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) 75 | fi 76 | 77 | if [ "$MYSQL_DATABASE" ]; then 78 | echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" 79 | mysql+=( "$MYSQL_DATABASE" ) 80 | fi 81 | 82 | if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then 83 | echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" | "${mysql[@]}" 84 | 85 | if [ "$MYSQL_DATABASE" ]; then 86 | echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" | "${mysql[@]}" 87 | fi 88 | 89 | echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" 90 | fi 91 | 92 | if [ ! -z "$MYSQL_ONETIME_PASSWORD" ]; then 93 | "${mysql[@]}" <<-EOSQL 94 | ALTER USER 'root'@'%' PASSWORD EXPIRE; 95 | EOSQL 96 | fi 97 | if ! kill -s TERM "$pid" || ! wait "$pid"; then 98 | echo >&2 'MySQL init process failed.' 99 | exit 1 100 | fi 101 | 102 | echo 103 | echo 'MySQL init process done. Ready for start up.' 104 | echo 105 | #mv /etc/my.cnf $DATADIR 106 | fi 107 | 108 | } 109 | -------------------------------------------------------------------------------- /helm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | name: percona 2 | version: 0.3.0 3 | description: free, fully compatible, enhanced, open source drop-in replacement for 4 | MySQL 5 | keywords: 6 | - mysql 7 | - percona 8 | - database 9 | - sql 10 | home: https://www.percona.com/ 11 | icon: https://www.percona.com/sites/all/themes/percona2015/logo.png 12 | sources: 13 | - https://github.com/kubernetes/charts 14 | - https://github.com/docker-library/percona 15 | maintainers: 16 | - name: Patrick Galbraith 17 | email: patg@patg.net 18 | engine: gotpl 19 | -------------------------------------------------------------------------------- /helm/README.md: -------------------------------------------------------------------------------- 1 | # Percona 2 | 3 | [Percona Server](https://MySQL.org) for MySQL® is a free, fully compatible, enhanced, open source drop-in replacement for MySQL that provides superior performance, scalability and instrumentation. With over 3,000,000 downloads, Percona Server for MySQL's self-tuning algorithms and support for extremely high-performance hardware delivers excellent performance and reliability. 4 | 5 | Notable users include Netflix, Amazon Web Services, Alcatel-Lucent, and Smug Mug. 6 | 7 | ## Introduction 8 | 9 | This chart, based off of the MySQL chart, bootstraps a single node Percona Server deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. 10 | 11 | ## Prerequisites 12 | 13 | - Kubernetes 1.6+ with Beta APIs enabled 14 | - PV provisioner support in the underlying infrastructure 15 | 16 | ## Installing the Chart 17 | 18 | To install the chart with the release name `my-release`: 19 | 20 | ```bash 21 | $ helm install --name my-release stable/percona 22 | ``` 23 | 24 | The command deploys Percona Server on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. 25 | 26 | By default a random password will be generated for the root user. If you'd like to set your own password change the perconaRootPassword 27 | in the values.yaml. 28 | 29 | You can retrieve your root password by running the following command. Make sure to replace [YOUR_RELEASE_NAME]: 30 | 31 | printf $(printf '\%o' `kubectl get secret [YOUR_RELEASE_NAME]-percona -o jsonpath="{.data.mysql-root-password[*]}"`) 32 | 33 | > **Tip**: List all releases using `helm list` 34 | 35 | ## Uninstalling the Chart 36 | 37 | To uninstall/delete the `my-release` deployment: 38 | 39 | ```bash 40 | $ helm delete my-release 41 | ``` 42 | 43 | The command removes all the Kubernetes components associated with the chart and deletes the release. 44 | 45 | ## Configuration 46 | 47 | The following tables lists the configurable parameters of the Percona chart and their default values. 48 | 49 | | Parameter | Description | Default | 50 | | ----------------------- | ---------------------------------- | ---------------------------------------------------------- | 51 | | `imageTag` | `percona` image tag. | Most recent release | 52 | | `imagePullPolicy` | Image pull policy | `IfNotPresent` | 53 | | `perconaRootPassword` | Password for the `root` user. | `nil` | 54 | | `perconaUser` | Username of new user to create. | `nil` | 55 | | `perconaPassword` | Password for the new user. | `nil` | 56 | | `perconaDatabase` | Name for new database to create. | `nil` | 57 | | `persistence.enabled` | Create a volume to store data | false | 58 | | `persistence.size` | Size of persistent volume claim | 8Gi RW | 59 | | `persistence.storageClass` | Type of persistent volume claim | nil (uses alpha storage class annotation) | 60 | | `persistence.accessMode` | ReadWriteOnce or ReadOnly | ReadWriteOnce | 61 | | `resources` | CPU/Memory resource requests/limits | Memory: `256Mi`, CPU: `100m` | 62 | 63 | Some of the parameters above map to the env variables defined in the [Percona Server DockerHub image](https://hub.docker.com/_/percona/). 64 | 65 | Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, 66 | 67 | ```bash 68 | $ helm install --name my-release \ 69 | --set mysqlLRootPassword=secretpassword,mysqlUser=my-user,mysqlPassword=my-password,mysqlDatabase=my-database \ 70 | stable/percona 71 | ``` 72 | 73 | The above command sets the MySQL `root` account password to `secretpassword`. Additionally it creates a standard database user named `my-user`, with the password `my-password`, who has access to a database named `my-database`. 74 | 75 | Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, 76 | 77 | ```bash 78 | $ helm install --name my-release -f values.yaml stable/percona 79 | ``` 80 | 81 | > **Tip**: You can use the default [values.yaml](values.yaml) 82 | 83 | ## Persistence 84 | 85 | The [Percona Server](https://hub.docker.com/_/percona/) image stores the MySQL data and configurations at the `/var/lib/mysql` path of the container. 86 | 87 | By default, an emptyDir volume is mounted at that location. 88 | 89 | > *"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."* 90 | 91 | You can change the values.yaml to enable persistence and use a PersistentVolumeClaim instead. 92 | -------------------------------------------------------------------------------- /helm/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Percona can be accessed via port 3306 on the following DNS name from within your cluster: 2 | {{ template "percona.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local 3 | 4 | To get your root password run: 5 | 6 | kubectl get secret --namespace {{ .Release.Namespace }} {{ template "percona.fullname" . }} -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo 7 | 8 | To connect to your database: 9 | 10 | 1. Run a percona pod that you can use as a client: 11 | 12 | kubectl run -i --tty percona-client --image=percona:5.7 --restart=Never -- bash -il 13 | 14 | 2. Connect using the mysql cli, then provide your password: 15 | $ mysql -h {{ template "percona.fullname" . }} -p 16 | 17 | -------------------------------------------------------------------------------- /helm/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 5 | */}} 6 | {{- define "percona.name" -}} 7 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 8 | {{- end -}} 9 | 10 | {{/* 11 | Create a default fully qualified app name. 12 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 13 | */}} 14 | {{- define "percona.fullname" -}} 15 | {{- $name := default .Chart.Name .Values.nameOverride -}} 16 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 17 | {{- end -}} 18 | -------------------------------------------------------------------------------- /helm/templates/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.persistence.enabled }} 2 | kind: PersistentVolumeClaim 3 | apiVersion: v1 4 | metadata: 5 | name: {{ template "percona.fullname" . }} 6 | labels: 7 | app: {{ template "percona.fullname" . }} 8 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 9 | release: "{{ .Release.Name }}" 10 | heritage: "{{ .Release.Service }}" 11 | spec: 12 | accessModes: 13 | - {{ .Values.persistence.accessMode | quote }} 14 | resources: 15 | requests: 16 | storage: {{ .Values.persistence.size | quote }} 17 | {{- if .Values.persistence.storageClass }} 18 | {{- if (eq "-" .Values.persistence.storageClass) }} 19 | storageClassName: "" 20 | {{- else }} 21 | storageClassName: "{{ .Values.persistence.storageClass }}" 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | -------------------------------------------------------------------------------- /helm/templates/secrets.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ template "percona.fullname" . }} 5 | labels: 6 | app: {{ template "percona.fullname" . }} 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | release: "{{ .Release.Name }}" 9 | heritage: "{{ .Release.Service }}" 10 | type: Opaque 11 | data: 12 | {{ if .Values.mysqlRootPassword }} 13 | mysql-root-password: {{ .Values.mysqlRootPassword | b64enc | quote }} 14 | {{ else }} 15 | mysql-root-password: {{ randAlphaNum 10 | b64enc | quote }} 16 | {{ end }} 17 | {{ if .Values.mysqlPassword }} 18 | mysql-password: {{ .Values.mysqlPassword | b64enc | quote }} 19 | {{ else }} 20 | mysql-password: {{ randAlphaNum 10 | b64enc | quote }} 21 | {{ end }} 22 | -------------------------------------------------------------------------------- /helm/templates/statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta2 2 | kind: StatefulSet 3 | metadata: 4 | name: {{ template "percona.fullname" . }} 5 | labels: 6 | app: {{ template "percona.fullname" . }} 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | release: "{{ .Release.Name }}" 9 | heritage: "{{ .Release.Service }}" 10 | spec: 11 | replicas: {{ .Values.replicas }} 12 | selector: 13 | matchLabels: 14 | app: {{ template "percona.fullname" . }} 15 | serviceName: {{ template "percona.fullname" . }} 16 | template: 17 | metadata: 18 | labels: 19 | app: {{ template "percona.fullname" . }} 20 | spec: 21 | initContainers: 22 | - name: "remove-lost-found" 23 | image: "busybox:1.25.0" 24 | imagePullPolicy: {{ .Values.imagePullPolicy | quote }} 25 | command: 26 | - "rm" 27 | - "-fr" 28 | - "/var/lib/mysql/lost+found" 29 | volumeMounts: 30 | - name: data 31 | mountPath: /var/lib/mysql 32 | containers: 33 | - name: {{ template "percona.fullname" . }} 34 | image: "{{ .Values.imageRepo }}:{{ .Values.imageTag }}" 35 | imagePullPolicy: {{ .Values.imagePullPolicy | quote }} 36 | resources: 37 | {{ toYaml .Values.resources | indent 10 }} 38 | env: 39 | {{- if .Values.mysqlAllowEmptyPassword }} 40 | - name: MYSQL_ALLOW_EMPTY_PASSWORD 41 | value: "true" 42 | {{- else }} 43 | - name: MYSQL_ROOT_PASSWORD 44 | valueFrom: 45 | secretKeyRef: 46 | name: {{ template "percona.fullname" . }} 47 | key: mysql-root-password 48 | - name: MYSQL_PASSWORD 49 | valueFrom: 50 | secretKeyRef: 51 | name: {{ template "percona.fullname" . }} 52 | key: mysql-password 53 | {{- end }} 54 | - name: MYSQL_USER 55 | value: {{ default "" .Values.mysqlUser | quote }} 56 | - name: MYSQL_DATABASE 57 | value: {{ default "" .Values.mysqlDatabase | quote }} 58 | - name: CLUSTER_NAME 59 | value: {{ template "percona.fullname" . }} 60 | - name: K8S_SERVICE_NAME 61 | value: {{ template "percona.fullname" . }}-xtradb-cluster 62 | - name: DEBUG 63 | value: "true" 64 | ports: 65 | - name: mysql 66 | containerPort: 3306 67 | - name: galera-repl 68 | containerPort: 4567 69 | - name: state-transfer 70 | containerPort: 4568 71 | - name: state-snapshot 72 | containerPort: 4444 73 | livenessProbe: 74 | exec: 75 | command: 76 | - mysqladmin 77 | - ping 78 | initialDelaySeconds: 30 79 | timeoutSeconds: 2 80 | readinessProbe: 81 | exec: 82 | command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"] 83 | initialDelaySeconds: 30 84 | timeoutSeconds: 2 85 | volumeMounts: 86 | - name: data 87 | mountPath: /var/lib/mysql 88 | volumes: 89 | - name: data 90 | {{- if .Values.persistence.enabled }} 91 | persistentVolumeClaim: 92 | claimName: {{ template "percona.fullname" . }} 93 | {{- else }} 94 | emptyDir: {} 95 | {{- end -}} 96 | -------------------------------------------------------------------------------- /helm/templates/svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ template "percona.fullname" . }} 5 | labels: 6 | app: {{ template "percona.fullname" . }} 7 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 8 | release: "{{ .Release.Name }}" 9 | heritage: "{{ .Release.Service }}" 10 | spec: 11 | ports: 12 | - name: mysql 13 | port: 3306 14 | targetPort: mysql 15 | selector: 16 | app: {{ template "percona.fullname" . }} 17 | --- 18 | apiVersion: v1 19 | kind: Service 20 | metadata: 21 | name: "{{ template "percona.fullname" . }}-xtradb-cluster" 22 | labels: 23 | app: {{ template "percona.fullname" . }} 24 | chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 25 | release: "{{ .Release.Name }}" 26 | heritage: "{{ .Release.Service }}" 27 | spec: 28 | clusterIP: None 29 | ports: 30 | - name: galera 31 | port: 4567 32 | - name: state-xfer 33 | port: 4568 34 | - name: state-snap 35 | port: 4444 36 | selector: 37 | app: {{ template "percona.fullname" . }} 38 | -------------------------------------------------------------------------------- /helm/values.yaml: -------------------------------------------------------------------------------- 1 | ## percona image version 2 | ## ref: https://hub.docker.com/r/library/percona/tags/ 3 | ## 4 | imageRepo: "paulczar/percona-xtradb-cluster" 5 | imageTag: "5.7.19" 6 | replicas: 2 7 | ## Specify password for root user 8 | ## 9 | ## Default: random 10 character string 10 | #mysqlRootPassword: 11 | ## Create a database user 12 | ## 13 | mysqlUser: test 14 | mysqlPassword: test 15 | 16 | ## Allow unauthenticated access, uncomment to enable 17 | ## 18 | #mysqlAllowEmptyPassword: true 19 | 20 | ## Create a database 21 | ## 22 | mysqlDatabase: test 23 | 24 | ## Specify an imagePullPolicy (Required) 25 | ## It's recommended to change this to 'Always' if the image tag is 'latest' 26 | ## ref: http://kubernetes.io/docs/user-guide/images/#updating-images 27 | ## 28 | imagePullPolicy: Always 29 | 30 | ## Persist data to a persitent volume 31 | persistence: 32 | enabled: false 33 | ## percona data Persistent Volume Storage Class 34 | ## If defined, storageClassName: 35 | ## If set to "-", storageClassName: "", which disables dynamic provisioning 36 | ## If undefined (the default) or set to null, no storageClassName spec is 37 | ## set, choosing the default provisioner. (gp2 on AWS, standard on 38 | ## GKE, AWS & OpenStack) 39 | ## 40 | # storageClass: "-" 41 | accessMode: ReadWriteOnce 42 | size: 8Gi 43 | 44 | ## Configure resource requests and limits 45 | ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ 46 | ## 47 | resources: 48 | requests: 49 | memory: 256Mi 50 | cpu: 100m 51 | -------------------------------------------------------------------------------- /kubernetes/percona-galera-xtradb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1beta2 2 | kind: StatefulSet 3 | metadata: 4 | labels: 5 | app: percona-galera 6 | name: percona-galera 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: percona-galera 12 | serviceName: percona-galera 13 | template: 14 | metadata: 15 | labels: 16 | app: percona-galera 17 | spec: 18 | containers: 19 | - name: percona-galera 20 | imagePullPolicy: Always 21 | image: paulczar/percona-xtradb-cluster:5.7.19 22 | env: 23 | - name: CLUSTER_NAME 24 | value: percona-galera 25 | - name: MYSQL_ROOT_PASSWORD 26 | value: not-a-secure-password 27 | - name: K8S_SERVICE_NAME 28 | value: percona-galera-xtradb 29 | - name: LOG_TO_STDOUT 30 | value: "true" 31 | - name: DEBUG 32 | value: "true" 33 | livenessProbe: 34 | exec: 35 | command: ["mysqladmin", "-p$(MYSQL_ROOT_PASSWORD)", "ping"] 36 | initialDelaySeconds: 60 37 | periodSeconds: 10 38 | timeoutSeconds: 5 39 | readinessProbe: 40 | exec: 41 | command: ["mysql", "-h", "127.0.0.1", "-p$(MYSQL_ROOT_PASSWORD)", "-e", "SELECT 1"] 42 | initialDelaySeconds: 60 43 | periodSeconds: 10 44 | timeoutSeconds: 5 45 | --- 46 | apiVersion: v1 47 | kind: Service 48 | metadata: 49 | labels: 50 | app: percona-galera 51 | name: percona-galera-xtradb 52 | spec: 53 | clusterIP: None 54 | ports: 55 | - name: galera-replication 56 | port: 4567 57 | - name: state-transfer 58 | port: 4568 59 | - name: state-snapshot 60 | port: 4444 61 | selector: 62 | app: percona-galera 63 | --- 64 | apiVersion: v1 65 | kind: Service 66 | metadata: 67 | labels: 68 | app: percona-galera 69 | name: percona-galera 70 | spec: 71 | type: NodePort 72 | ports: 73 | - name: mysql 74 | port: 3306 75 | selector: 76 | app: percona-galera 77 | --------------------------------------------------------------------------------