Statefulset
1 实践
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ template "fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "fullname" . }}
chart: {{ template "xdb.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 }}
role: candidate
{{- 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 }}
serviceAccountName: {{ template "serviceAccountName" . }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
affinity:
{{- if .Values.affinity }}
{{ toYaml .Values.affinity | indent 8 }}
{{- end }}
# 这里的反亲和性控制数据库服务绝对不调度到同机器上
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "release"
operator: In
values:
- {{ .Release.Name }}
- key: app
operator: In
values:
- {{ template "fullname" . }}
topologyKey: "kubernetes.io/hostname"
initContainers:
- name: init-mysql
image: "{{ .Values.mysql.image }}:{{ .Values.mysql.tag }}"
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
resources:
{{ toYaml .Values.resources | indent 10 }}
command: ['sh','-c']
args:
- |
# Workaround for kylin4/10's docker start with umask 027.
umask 0022
# Generate mysql server-id from pod ordinal index.
ordinal=$(echo $(hostname) | tr -cd "[1-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/
cp -f /mnt/config-map/*.sh /mnt/scripts/
chmod +x /mnt/scripts/*
/init-container.sh {{ .Release.Name }}
{{- if .Values.persistence.enabled }}
# remove lost+found.
rm -rf /mnt/data/lost+found
{{- end }}
volumeMounts:
- name: conf
mountPath: /mnt/conf.d
- name: scripts
mountPath: /mnt/scripts
- name: config-map
mountPath: /mnt/config-map
{{- if .Values.persistence.enabled }}
- name: data
mountPath: /mnt/data
{{- end }}
containers:
- name: mysql
image: "{{ .Values.mysql.image }}:{{ .Values.mysql.tag }}"
imagePullPolicy: {{ .Values.imagePullPolicy | quote }}
lifecycle:
preStop:
exec:
command:
- sh
- -c
- /mysql/bin/mysqladmin --defaults-file=/mysql/etc/user.root.cnf shutdown && sleep 10
command:
- sh
- -c
- umask 0022 && sleep 30 && /docker-entrypoint.sh mysqld {{ .Release.Name }}
{{- with .Values.mysql.args }}
args:
{{- range . }}
- {{ . | quote }}
{{- end }}
{{- end }}
resources:
{{ toYaml .Values.mysql.resources | indent 10 }}
env:
# namespace
- name: {{ (print $.Release.Name "_NAMESPACE") }}
value: {{ .Release.Namespace }}
# HAStrategy
- name: {{ (print $.Release.Name "_SQL_RUNNING_ABNORMAL_JOIN_TOPO") }}
{{- if not .Values.mysql.HAStrategy.sqlRunningAbnormalJoinTopo }}
value: "true"
{{- else }}
value: {{ .Values.mysql.HAStrategy.sqlRunningAbnormalJoinTopo | quote }}
{{- end }}
- name: {{ (print $.Release.Name "_GTID_ABNORMAL_JOIN_TOPO") }}
{{- if not .Values.mysql.HAStrategy.gtidAbnormalJoinTopo }}
value: "true"
{{- else }}
value: {{ .Values.mysql.HAStrategy.gtidAbnormalJoinTopo | quote }}
{{- end }}
- name: {{ (print $.Release.Name "_NOT_IN_TOPO_JOIN_EXCHANGE") }}
{{- if not .Values.mysql.HAStrategy.notInTopoJoinExchange }}
value: "true"
{{- else }}
value: {{ .Values.mysql.HAStrategy.notInTopoJoinExchange | quote }}
{{- end }}
- name: {{ (print $.Release.Name "_MASTER_SWITCH_TO_SLAVE_KILL_SESSION") }}
{{- if not .Values.mysql.HAStrategy.masterSwitchToSlaveKillSession }}
value: "false"
{{- else }}
value: {{ .Values.mysql.HAStrategy.masterSwitchToSlaveKillSession | quote }}
{{- end }}
# resource params
- name: {{ (print $.Release.Name "_CPU_LIMIT") }}
{{- if not .Values.mysql.resources.limits }}
value: "0"
{{- else if not .Values.mysql.resources.limits.cpu }}
value: "0"
{{- else }}
value: {{ .Values.mysql.resources.limits.cpu }}
{{- end }}
- name: {{ (print $.Release.Name "_MEMORY_LIMIT") }}
{{- if not .Values.mysql.resources.limits }}
value: "0"
{{- else if not .Values.mysql.resources.limits.memory }}
value: "0"
{{- else }}
value: {{ .Values.mysql.resources.limits.memory }}
{{- end }}
- name: {{ (print $.Release.Name "_DISK_LIMIT") }}
{{- if not .Values.persistence.enabled }}
value: "0"
{{- else if not .Values.persistence.size }}
value: "0"
{{- else }}
value: {{ .Values.persistence.size }}
{{- end }}
{{- if .Values.timezone }}
- name: TZ
value: {{ .Values.timezone }}
{{- end }}
{{- if .Values.mysql.extraEnvVars }}
{{ tpl .Values.mysql.extraEnvVars . | indent 8 }}
{{- end }}
- name: {{ (print $.Release.Name "_MYSQL_ROOT_PASSWORD") }}
valueFrom:
secretKeyRef:
name: {{ template "fullname" . }}
key: mysql-root-password
# backup env params
- name: {{ (print $.Release.Name "_BACKUP_ENABLED") }}
value: {{ .Values.backup.enabled | quote }}
- name: {{ (print $.Release.Name "_SCHEDULE") }}
value: {{ .Values.backup.cronjob.schedule | quote }}
- name: {{ (print $.Release.Name "_LOCAL_ENABLED") }}
{{- if .Values.backup.storage.hostPath.enabled }}
value: "true"
{{- else }}
value: "false"
{{- end }}
- name: {{ (print $.Release.Name "_LOCAL_PATH") }}
value: "/data/backup"
- name: {{ (print $.Release.Name "_LOCAL_SAVE_HOURS") }}
{{- if .Values.backup.storage.hostPath.enabled }}
value: {{ .Values.backup.storage.hostPath.saveHours | quote }}
{{- else if .Values.backup.storage.persistence.enabled }}
value: {{ .Values.backup.storage.persistence.saveHours | quote }}
{{- else }}
value: "0"
{{- end}}
- name: {{ (print $.Release.Name "_S3_ENABLED") }}
{{- if or .Values.backup.storage.s3.enabled}}
value: "true"
{{- else }}
value: "false"
{{- end }}
- name: {{ (print $.Release.Name "_S3_ADDRESS") }}
value: {{ .Values.backup.storage.s3.address | quote }}
- name: {{ (print $.Release.Name "_S3_BUCKET") }}
value: {{ .Values.backup.storage.s3.bucket | quote }}
- name: {{ (print $.Release.Name "_S3_PATH") }}
value: {{ .Release.Name }}
- name: {{ (print $.Release.Name "_S3_AK") }}
value: {{ .Values.backup.storage.s3.accessKey | quote }}
- name: {{ (print $.Release.Name "_S3_SK") }}
value: {{ .Values.backup.storage.s3.secretKey | quote }}
- name: {{ (print $.Release.Name "_S3_SAVE_HOURS") }}
value: {{ .Values.backup.storage.s3.saveHours | quote }}
ports:
- name: mysql
containerPort: 3306
- name: xagent
containerPort: 8500
- name: xagent-sync
containerPort: 8501
volumeMounts:
- name: data
mountPath: /mysql
- name: conf
mountPath: /etc/mysql/conf.d
- name: logs
mountPath: /var/log/mysql
{{- if .Values.mysql.initializationFiles }}
- name: initialization
mountPath: /docker-entrypoint-initdb.d
{{- end }}
{{- if and .Values.backup.enabled }}
- name: backup-data
mountPath: /data/backup
{{- end }}
livenessProbe:
exec:
command:
{{- if .Values.mysql.allowEmptyRootPassword }}
- sh
- -c
- /mysql/bin/mysqladmin --defaults-file=/mysql/etc/user.root.cnf ping
{{- else }}
- sh
- -c
- /mysql/bin/mysqladmin --defaults-file=/mysql/etc/user.root.cnf ping
{{- end }}
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:
{{- if .Values.mysql.allowEmptyRootPassword }}
- sh
- -c
- /mysql/bin/mysql --defaults-file=/mysql/etc/user.root.cnf -e "SELECT 1"
{{- else }}
- sh
- -c
- /mysql/bin/mysql --defaults-file=/mysql/etc/user.root.cnf -e "SELECT 1"
{{- end }}
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 }}
volumes:
- name: conf
emptyDir: {}
- name: scripts
emptyDir: {}
- name: logs
emptyDir: {}
- name: config-map
configMap:
name: {{ template "fullname" . }}
{{- if and .Values.persistence.enabled .Values.persistence.hostPath }}
- name: data
hostPath:
path: {{ (print .Values.persistence.hostPath "/" $.Release.Name) }}
type: DirectoryOrCreate
{{- else if not .Values.persistence.enabled }}
- name: data
emptyDir: {}
{{- end }}
{{- if and .Values.backup.enabled }}
- name: backup-data
{{- if .Values.backup.storage.hostPath.enabled }}
hostPath:
path: {{ (print $.Values.backup.storage.hostPath.hostPath "/" $.Release.Name) }}
type: DirectoryOrCreate
{{- else if not .Values.backup.storage.persistence.enabled }}
emptyDir: {}
{{- end }}
{{- end }}
volumeClaimTemplates:
{{- if and .Values.persistence.enabled (not .Values.persistence.hostPath) }}
- 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 }}
{{- end }}
{{- if and .Values.backup.enabled .Values.backup.storage.persistence.enabled }}
- metadata:
name: backup-data
spec:
accessModes:
{{- range .Values.backup.storage.persistence.accessModes }}
- {{ . | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.backup.storage.persistence.size }}
storageClassName: {{ .Values.backup.storage.persistence.storageClass }}
{{- end }}1.1 元数据 (Metadata)
1.2 StatefulSet 核心配置
1.3 容器配置
1.3.1 初始化容器 (InitContainers)
1.3.2 主容器 (MySQL)
1.3.3 Volumes
1.4 存储配置
1.5 关键功能
Last updated