ProxySQL Helm Chart 部署

ProxySQL 官方的 Helm Chart 长期未更新,为了方便在 Kuberneters 中部署,重新编写了 ProxySQL Helm Chart。功能包括:

  • 支持将 ProxySQL 的配置存储到 PV 中
  • 支持以 NodePort 的形式暴露 ProxySQL 服务,用于跨集群访问

Chart

Chart 文件目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
├── Chart.yaml
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── configmap.yaml
│ ├── statefuleset.yaml
│ ├── svc-headless.yaml
│ ├── svc.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml

Chart.yaml

1
2
3
4
5
6
7
apiVersion: v2
name: proxysql
description: ProxySQL Helm Chart for Kubernetes

type: application
version: 0.1.0
appVersion: "1.16.0"

_helpers.tpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{{/*
Expand the name of the chart.
*/}}
{{- define "proxysql.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "proxysql.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 "proxysql.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "proxysql.labels" -}}
helm.sh/chart: {{ include "proxysql.chart" . }}
{{ include "proxysql.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "proxysql.selectorLabels" -}}
app.kubernetes.io/name: {{ include "proxysql.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

statefulset.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ template "proxysql.fullname" . }}
labels: {{- include "proxysql.labels" . | nindent 4 }}
spec:
selector:
matchLabels: {{- include "proxysql.selectorLabels" . | nindent 6 }}
serviceName: {{ template "proxysql.fullname" . }}-headless
replicas: {{ .Values.replicaCount }}
minReadySeconds: 5
template:
metadata:
labels: {{- include "proxysql.selectorLabels" . | nindent 8 }}
spec:
terminationGracePeriodSeconds: 10
containers:
- name: proxysql
image: {{ .Values.image }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
resources:
{{- toYaml .Values.resources | nindent 10 }}
ports:
- name: admin
containerPort: 6032
protocol: TCP
- name: proxysql
containerPort: 6033
protocol: TCP
volumeMounts:
- name: proxysql-data
mountPath: /var/lib/proxysql
- name: proxysql-config
mountPath: /etc/proxysql.cnf
subPath: proxysql.cnf
livenessProbe:
tcpSocket:
port: admin
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
readinessProbe:
tcpSocket:
port: admin
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
startupProbe:
tcpSocket:
port: admin
initialDelaySeconds: 10
periodSeconds: 3
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
volumes:
- name: proxysql-config
configMap:
name: {{ include "proxysql.fullname" . }}-config
volumeClaimTemplates:
- metadata:
name: proxysql-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
storageClassName: {{ .Values.storageClassName }}

svc-headless

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: v1
kind: Service
metadata:
name: {{ include "proxysql.fullname" . }}-headless
labels:
{{- include "proxysql.labels" . | nindent 4 }}
spec:
type: ClusterIP
clusterIP: None
ports:
- name: admin
port: 6032
targetPort: admin
protocol: TCP
- name: proxysql
port: 6033
targetPort: proxysql
protocol: TCP
selector:
{{- include "proxysql.selectorLabels" . | nindent 4 }}

svc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Service
metadata:
name: {{ include "proxysql.fullname" . }}
labels:
{{- include "proxysql.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- name: proxysql
port: 6033
targetPort: 6033
{{- if and .Values.service.nodePort (eq .Values.service.type "NodePort") }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
protocol: TCP
selector:
{{- include "proxysql.selectorLabels" . | nindent 4 }}

config map

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "proxysql.fullname" . }}-config
labels:
{{- include "proxysql.labels" . | nindent 4 }}
data:
proxysql.cnf: |-
{{ .Values.configuration | nindent 4 }}

values

数据库连接账户、转发规则暂未通过配置文件的形式初始化进数据库。需待 proxysql Pod 运行起来后,通过命令行的形式导入内置的 sqlite,数据会自动同步到其他 Pod

1
2
3
4
5
6
7
8
9
10
11
12
mycli -u proxyadmin -P6032
> INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES (1, 1, '\/\*FORCE_MASTER\*\/', 1, 1);
> INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES (2, 1, '\/\*FORCE_SLAVE\*\/', 2, 1);
> INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES (10, 1, '^SELECT .* FOR UPDATE$', 1, 1);
> INSERT INTO mysql_query_rules (rule_id, active, match_digest, destination_hostgroup, apply) VALUES (11, 1, '^SELECT .*', 2, 1);
> LOAD MYSQL QUERY RULES TO RUNTIME;
> SAVE MYSQL QUERY RULES TO DISK;

> INSERT INTO mysql_users (username, password, default_hostgroup, default_schema, transaction_persistent, max_connections) VALUES ('', '', 1, 'bbl_keycloak', 1, 200);
> ...
> LOAD MYSQL USERS TO RUNTIME;
> SAVE MYSQL USERS TO DISK;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# Default values for proxysql.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 3

image: "proxysql/proxysql:2.5.5"
imagePullPolicy: IfNotPresent
storageClassName: ""
configuration: |-
admin_variables =
{
admin_credentials="proxyadmin:proxyadmin"
cluster_username="proxyadmin"
cluster_password="proxyadmin"
restapi_enabled=true
restapi_port=6070
prometheus_memory_metrics_interval=60
}

mysql_variables =
{
query_digests_keep_comment=true
default_charset="utf8mb4"
default_collation_connection="utf8mb4_0900_ai_ci"
show_processlist_extended=1
server_version="8.0.33"
monitor_username="monitor"
monitor_password="monitor"
monitor_connect_interval=60000
monitor_ping_interval=5000
monitor_read_only_interval=2000
wait_timeout=28800000
set_parser_algorithm=2
long_query_time=1000
max_connections=1000
}

mysql_servers =
(
{ hostname="", port=3306, hostgroup_id=1, max_connections=1000, comment="" },
{ hostname="", port=3306, hostgroup_id=1, max_connections=1000, comment="" },
)

mysql_replication_hostgroups =
(
{ writer_hostgroup=1, reader_hostgroup=2, comment="mysql cluster" }
)

proxysql_servers =
(
{ hostname="proxysql-0.proxysql-headless", port=6032, weight=0, comment="proxysql 0" },
{ hostname="proxysql-1.proxysql-headless", port=6032, weight=0, comment="proxysql 1" },
{ hostname="proxysql-2.proxysql-headless", port=6032, weight=0, comment="proxysql 2" },
)

nameOverride: ""
fullnameOverride: ""

ingress:
enabled: false

autoscaling:
enabled: false

service:
type: ClusterIP

resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 100m
memory: 512Mi

build image

在官方镜像中增加一些调试工具

1
2
3
4
5
6
7
FROM proxysql/proxysql:2.5.4

RUN sed -i "s@http://\(deb\|security\).debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list \
&& apt update -y \
&& apt dist-upgrade -y \
&& apt install -y --no-install-recommends curl mycli dnsutils iputils-ping \
&& rm -rf /var/lib/apt/lists/*