Skip to content

Instantly share code, notes, and snippets.

@631068264
Last active November 4, 2021 02:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 631068264/67877ff618fcfcd0894cbc7d74340ca1 to your computer and use it in GitHub Desktop.
Save 631068264/67877ff618fcfcd0894cbc7d74340ca1 to your computer and use it in GitHub Desktop.
mysqlha_helm
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ template "fullname" . }}-master
labels:
app: {{ template "fullname" . }}-master
chart: "{{ template "mysqlha.chart" . }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
serviceName: {{ template "fullname" . }}-master
replicas: 1
selector:
matchLabels:
fullname: {{ template "fullname" . }}
app: {{ template "fullname" . }}-master
template:
metadata:
labels:
fullname: {{ template "fullname" . }}
app: {{ template "fullname" . }}-master
{{- if .Values.mysqlha.podAnnotations }}
annotations:
{{ toYaml .Values.mysqlha.podAnnotations | indent 8 }}
{{- end }}
spec:
{{- if .Values.schedulerName }}
schedulerName: "{{ .Values.schedulerName }}"
{{- end }}
initContainers:
- name: init-mysql
image: {{ .Values.mysqlImage }}
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
command: ["/bin/bash"]
args:
- "-c"
- |
set -ex
# Generate mysql server-id from pod ordinal index.
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
# Copy server-id.conf adding offset to avoid reserved server-id=0 value.
cat /mnt/config-map/server-id.cnf | sed s/@@SERVER_ID@@/$((99 + $ordinal))/g > /mnt/conf.d/server-id.cnf
# Copy appropriate conf.d files from config-map to config mount.
cp -f /mnt/config-map/master.cnf /mnt/conf.d/
# Copy replication user script
cp -f /mnt/config-map/create-replication-user.sh /mnt/scripts/create-replication-user.sh
chmod 700 /mnt/scripts/create-replication-user.sh
volumeMounts:
- name: conf
mountPath: /mnt/conf.d
- name: config-map
mountPath: /mnt/config-map
- name: scripts
mountPath: /mnt/scripts
containers:
- name: mysql
image: {{ .Values.mysqlImage }}
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
env:
- name: MYSQL_DATABASE
value: {{ default "" .Values.mysqlha.mysqlDatabase | quote }}
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-root-password
- name: MYSQL_REPLICATION_USER
value: {{ .Values.mysqlha.mysqlReplicationUser }}
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-replication-password
{{ if .Values.mysqlha.mysqlUser }}
- name: MYSQL_USER
value: {{ .Values.mysqlha.mysqlUser | quote }}
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-password
{{ end }}
ports:
- name: mysql
containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
resources:
requests:
cpu: {{ .Values.resources.requests.cpu }}
memory: {{ .Values.resources.requests.memory }}
livenessProbe:
exec:
command:
- /bin/sh
- "-c"
- mysqladmin ping -h 127.0.0.1 -u root -p${MYSQL_ROOT_PASSWORD}
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
# Check we can execute queries over TCP (skip-networking is off).
command:
- /bin/sh
- "-c"
- MYSQL_PWD="${MYSQL_ROOT_PASSWORD}"
- mysql -h 127.0.0.1 -u root -e "SELECT 1"
initialDelaySeconds: 10
timeoutSeconds: 1
- name: xtrabackup
image: {{ .Values.xtraBackupImage }}
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
env:
- name: MYSQL_PWD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-root-password
- name: MYSQL_REPLICATION_USER
value: {{ .Values.mysqlha.mysqlReplicationUser }}
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-replication-password
ports:
- name: xtrabackup
containerPort: 3307
command: ["/bin/bash"]
args:
- "-c"
- |
set -ex
echo "Waiting for mysqld to be ready (accepting connections)"
until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 5; done
# Create replication user
cd /mnt/scripts
# file exists and is not empty with -s
if [[ -s create-replication-user.sh ]]; then
ls -la
./create-replication-user.sh
fi
cd /var/lib/mysql
# Determine binlog position of cloned data, if any.
if [[ -f xtrabackup_slave_info ]]; then
# XtraBackup already generated a partial "CHANGE MASTER TO" query
# because we're cloning from an existing slave.
cp xtrabackup_slave_info change_master_to.sql.in
elif [[ -f xtrabackup_binlog_info ]]; then
# We're cloning directly from master. Parse binlog position.
[[ $(cat xtrabackup_binlog_info) =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
fi
# Check if we need to complete a clone by starting replication.
if [[ -f change_master_to.sql.in ]]; then
# In case of container restart, attempt this at-most-once.
cp change_master_to.sql.in change_master_to.sql.orig
mysql -h 127.0.0.1 --verbose<<EOF
STOP SLAVE IO_THREAD;
$(<change_master_to.sql.orig),
MASTER_HOST='{{ template "fullname" . }}-master-0.{{ template "fullname" . }}-master',
MASTER_USER='${MYSQL_REPLICATION_USER}',
MASTER_PASSWORD='${MYSQL_REPLICATION_PASSWORD}',
MASTER_CONNECT_RETRY=10;
START SLAVE;
EOF
fi
# Start a server to send backups when requested by peers.
exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
"xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=${MYSQL_REPLICATION_USER} --password=${MYSQL_REPLICATION_PASSWORD}"
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
- name: scripts
mountPath: /mnt/scripts
resources:
requests:
cpu: 100m
memory: 100Mi
{{- if .Values.metrics.enabled }}
- name: metrics
image: "{{ .Values.metrics.image }}:{{ .Values.metrics.imageTag }}"
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
{{- if .Values.mysqlha.mysqlAllowEmptyPassword }}
command: ['sh', '-c', 'DATA_SOURCE_NAME="root@(localhost:3306)/" /bin/mysqld_exporter' ]
{{- else }}
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-root-password
command: [ 'sh', '-c', 'DATA_SOURCE_NAME="root:$MYSQL_ROOT_PASSWORD@(localhost:3306)/" /bin/mysqld_exporter' ]
{{- end }}
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" . }}
- name: scripts
emptyDir: {}
{{- 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 }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ template "fullname" . }}-salve
labels:
app: {{ template "fullname" . }}-salve
chart: "{{ template "mysqlha.chart" . }}"
release: "{{ .Release.Name }}"
heritage: "{{ .Release.Service }}"
spec:
serviceName: {{ template "fullname" . }}-salve
replicas: {{ sub .Values.mysqlha.replicaCount 1 }}
selector:
matchLabels:
fullname: {{ template "fullname" . }}
app: {{ template "fullname" . }}-salve
template:
metadata:
labels:
fullname: {{ template "fullname" . }}
app: {{ template "fullname" . }}-salve
{{- if .Values.mysqlha.podAnnotations }}
annotations:
{{ toYaml .Values.mysqlha.podAnnotations | indent 8 }}
{{- end }}
spec:
{{- if .Values.schedulerName }}
schedulerName: "{{ .Values.schedulerName }}"
{{- end }}
initContainers:
- name: clone-mysql
image: {{ .Values.xtraBackupImage }}
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
command:
- bash
- "-c"
- |
set -ex
# Skip the clone on master (ordinal index 0).
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
# If data already exists, delete and proceed to clone.
[[ -d /var/lib/mysql/mysql ]] && rm -fr /var/lib/mysql/*
# Clone data from previous peer.
ncat --recv-only {{ template "fullname" . }}-master-0.{{ template "fullname" . }}-master 3307 | xbstream -x -C /var/lib/mysql
# Prepare the backup.
xtrabackup --prepare --user=${MYSQL_REPLICATION_USER} --password=${MYSQL_REPLICATION_PASSWORD} --target-dir=/var/lib/mysql
env:
- name: MYSQL_REPLICATION_USER
value: {{ .Values.mysqlha.mysqlReplicationUser }}
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-replication-password
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
- name: init-mysql
image: {{ .Values.mysqlImage }}
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
command: ["/bin/bash"]
args:
- "-c"
- |
set -ex
# Generate mysql server-id from pod ordinal index.
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
# 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/slave.cnf /mnt/conf.d/
volumeMounts:
- name: conf
mountPath: /mnt/conf.d
- name: config-map
mountPath: /mnt/config-map
- name: scripts
mountPath: /mnt/scripts
containers:
- name: mysql
image: {{ .Values.mysqlImage }}
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
env:
- name: MYSQL_DATABASE
value: {{ default "" .Values.mysqlha.mysqlDatabase | quote }}
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-root-password
- name: MYSQL_REPLICATION_USER
value: {{ .Values.mysqlha.mysqlReplicationUser }}
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-replication-password
{{ if .Values.mysqlha.mysqlUser }}
- name: MYSQL_USER
value: {{ .Values.mysqlha.mysqlUser | quote }}
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-password
{{ end }}
ports:
- name: mysql
containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
resources:
requests:
cpu: {{ .Values.resources.requests.cpu }}
memory: {{ .Values.resources.requests.memory }}
livenessProbe:
exec:
command:
- /bin/sh
- "-c"
- mysqladmin ping -h 127.0.0.1 -u root -p${MYSQL_ROOT_PASSWORD}
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
# Check we can execute queries over TCP (skip-networking is off).
command:
- /bin/sh
- "-c"
- MYSQL_PWD="${MYSQL_ROOT_PASSWORD}"
- mysql -h 127.0.0.1 -u root -e "SELECT 1"
initialDelaySeconds: 10
timeoutSeconds: 1
- name: xtrabackup
image: {{ .Values.xtraBackupImage }}
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
env:
- name: MYSQL_PWD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-root-password
- name: MYSQL_REPLICATION_USER
value: {{ .Values.mysqlha.mysqlReplicationUser }}
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-replication-password
ports:
- name: xtrabackup
containerPort: 3307
command: ["/bin/bash"]
args:
- "-c"
- |
set -ex
echo "Waiting for mysqld to be ready (accepting connections)"
until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 5; done
# Create replication user
cd /mnt/scripts
# file exists and is not empty with -s
if [[ -s create-replication-user.sh ]]; then
ls -la
./create-replication-user.sh
fi
cd /var/lib/mysql
# Determine binlog position of cloned data, if any.
if [[ -f xtrabackup_slave_info ]]; then
# XtraBackup already generated a partial "CHANGE MASTER TO" query
# because we're cloning from an existing slave.
cp xtrabackup_slave_info change_master_to.sql.in
elif [[ -f xtrabackup_binlog_info ]]; then
# We're cloning directly from master. Parse binlog position.
[[ $(cat xtrabackup_binlog_info) =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
fi
# Check if we need to complete a clone by starting replication.
if [[ -f change_master_to.sql.in ]]; then
# In case of container restart, attempt this at-most-once.
cp change_master_to.sql.in change_master_to.sql.orig
mysql -h 127.0.0.1 --verbose<<EOF
STOP SLAVE IO_THREAD;
$(<change_master_to.sql.orig),
MASTER_HOST='{{ template "fullname" . }}-master-0.{{ template "fullname" . }}-master',
MASTER_USER='${MYSQL_REPLICATION_USER}',
MASTER_PASSWORD='${MYSQL_REPLICATION_PASSWORD}',
MASTER_CONNECT_RETRY=10;
START SLAVE;
EOF
fi
# Start a server to send backups when requested by peers.
exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
"xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=${MYSQL_REPLICATION_USER} --password=${MYSQL_REPLICATION_PASSWORD}"
volumeMounts:
- name: data
mountPath: /var/lib/mysql
subPath: mysql
- name: conf
mountPath: /etc/mysql/conf.d
- name: scripts
mountPath: /mnt/scripts
resources:
requests:
cpu: 100m
memory: 100Mi
{{- if .Values.metrics.enabled }}
- name: metrics
image: "{{ .Values.metrics.image }}:{{ .Values.metrics.imageTag }}"
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
{{- if .Values.mysqlha.mysqlAllowEmptyPassword }}
command: ['sh', '-c', 'DATA_SOURCE_NAME="root@(localhost:3306)/" /bin/mysqld_exporter' ]
{{- else }}
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-root-password
command: [ 'sh', '-c', 'DATA_SOURCE_NAME="root:$MYSQL_ROOT_PASSWORD@(localhost:3306)/" /bin/mysqld_exporter' ]
{{- end }}
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" . }}
- name: scripts
emptyDir: {}
{{- 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 }}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment