Skip to content

Commit 1a4294d

Browse files
authored
K8SPS-163: add PMM support for HAProxy (#380)
https://jira.percona.com/browse/K8SPS-163
1 parent 2008ee3 commit 1a4294d

File tree

12 files changed

+472
-210
lines changed

12 files changed

+472
-210
lines changed

api/v1alpha1/perconaservermysql_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ func (cr *PerconaServerMySQL) InternalSecretName() string {
793793
}
794794

795795
func (cr *PerconaServerMySQL) PMMEnabled(secret *corev1.Secret) bool {
796-
if cr.Spec.PMM != nil && cr.Spec.PMM.Enabled && secret.Data != nil {
796+
if cr.Spec.PMM != nil && cr.Spec.PMM.Enabled && secret != nil && secret.Data != nil {
797797
return cr.Spec.PMM.HasSecret(secret)
798798
}
799799
return false

build/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,6 @@ COPY build/haproxy_liveness_check.sh /opt/percona-server-mysql-operator/haproxy_
101101
COPY build/haproxy_readiness_check.sh /opt/percona-server-mysql-operator/haproxy_readiness_check.sh
102102
COPY build/haproxy.cfg /opt/percona-server-mysql-operator/haproxy.cfg
103103
COPY build/haproxy-global.cfg /opt/percona-server-mysql-operator/haproxy-global.cfg
104+
COPY build/pmm-prerun.sh /opt/percona-server-mysql-operator/pmm-prerun.sh
104105

105106
USER 2

build/haproxy-global.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@
2525
mode tcp
2626
option clitcpka
2727
default_backend mysql-replicas
28+
29+
frontend stats
30+
bind *:8404
31+
mode http
32+
http-request use-service prometheus-exporter if { path /metrics }

build/pmm-prerun.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
5+
pmm_args=()
6+
7+
read -ra PMM_ADMIN_CUSTOM_PARAMS_ARRAY <<<"$PMM_ADMIN_CUSTOM_PARAMS"
8+
pmm_args+=(
9+
"${PMM_ADMIN_CUSTOM_PARAMS_ARRAY[@]}"
10+
)
11+
12+
if [[ $DB_TYPE != "haproxy" ]]; then
13+
pmm_args+=(
14+
--service-name="$PMM_AGENT_SETUP_NODE_NAME"
15+
--host="$POD_NAME"
16+
--port="$DB_PORT"
17+
)
18+
fi
19+
20+
if [[ $DB_TYPE == "mysql" ]]; then
21+
read -ra DB_ARGS_ARRAY <<<"$DB_ARGS"
22+
pmm_args+=(
23+
"${DB_ARGS_ARRAY[@]}"
24+
)
25+
fi
26+
27+
if [[ $DB_TYPE == "haproxy" ]]; then
28+
pmm_args+=(
29+
"$PMM_AGENT_SETUP_NODE_NAME"
30+
)
31+
fi
32+
33+
pmm-admin status --wait=10s
34+
pmm-admin add "$DB_TYPE" --skip-connection-check --metrics-mode="$PMM_AGENT_SETUP_METRICS_MODE" --username="$DB_USER" --password="$DB_PASSWORD" --cluster="$CLUSTER_NAME" "${pmm_args[@]}"
35+
pmm-admin annotate --service-name="$PMM_AGENT_SETUP_NODE_NAME" 'Service restarted'

build/ps-init-entrypoint.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "${OPERATORDIR}/haproxy_liveness_
3232
install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "${OPERATORDIR}/haproxy_readiness_check.sh" "${BINDIR}/haproxy_readiness_check.sh"
3333
install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "${OPERATORDIR}/haproxy.cfg" "${BINDIR}/haproxy.cfg"
3434
install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "${OPERATORDIR}/haproxy-global.cfg" "${BINDIR}/haproxy-global.cfg"
35+
36+
install -o "$(id -u)" -g "$(id -g)" -m 0755 -D "${OPERATORDIR}/pmm-prerun.sh" "${BINDIR}/pmm-prerun.sh"

e2e-tests/tests/monitoring/02-assert.yaml

Lines changed: 165 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,7 @@ spec:
7474
- name: PMM_AGENT_SETUP_NODE_TYPE
7575
value: container
7676
- name: PMM_AGENT_PRERUN_SCRIPT
77-
value: |-
78-
pmm-admin status --wait=10s;
79-
pmm-admin add ${DB_TYPE} ${PMM_ADMIN_CUSTOM_PARAMS} --skip-connection-check --metrics-mode=${PMM_AGENT_SETUP_METRICS_MODE} --username=${DB_USER} --password=${DB_PASSWORD} --cluster=${CLUSTER_NAME} --service-name=${PMM_AGENT_SETUP_NODE_NAME} --host=${POD_NAME} --port=${DB_PORT} ${DB_ARGS};
80-
pmm-admin annotate --service-name=${PMM_AGENT_SETUP_NODE_NAME} 'Service restarted'
77+
value: /opt/percona/pmm-prerun.sh
8178
- name: PMM_AGENT_SIDECAR
8279
value: "true"
8380
- name: PMM_AGENT_SIDECAR_SLEEP
@@ -135,3 +132,167 @@ status:
135132
size: 3
136133
state: ready
137134
state: ready
135+
---
136+
apiVersion: apps/v1
137+
kind: StatefulSet
138+
metadata:
139+
name: monitoring-haproxy
140+
spec:
141+
template:
142+
spec:
143+
containers:
144+
- name: haproxy
145+
- name: mysql-monit
146+
- name: pmm-client
147+
env:
148+
- name: POD_NAME
149+
valueFrom:
150+
fieldRef:
151+
apiVersion: v1
152+
fieldPath: metadata.name
153+
- name: POD_NAMESPACE
154+
valueFrom:
155+
fieldRef:
156+
apiVersion: v1
157+
fieldPath: metadata.namespace
158+
- name: CLUSTER_NAME
159+
value: monitoring
160+
- name: CLIENT_PORT_LISTEN
161+
value: "7777"
162+
- name: CLIENT_PORT_MIN
163+
value: "30100"
164+
- name: CLIENT_PORT_MAX
165+
value: "30105"
166+
- name: PMM_AGENT_SERVER_ADDRESS
167+
value: monitoring-service
168+
- name: PMM_AGENT_SERVER_USERNAME
169+
value: api_key
170+
- name: PMM_AGENT_SERVER_PASSWORD
171+
valueFrom:
172+
secretKeyRef:
173+
key: pmmserverkey
174+
name: internal-monitoring
175+
- name: PMM_SERVER
176+
value: monitoring-service
177+
- name: PMM_USER
178+
value: api_key
179+
- name: PMM_PASSWORD
180+
valueFrom:
181+
secretKeyRef:
182+
key: pmmserverkey
183+
name: internal-monitoring
184+
- name: PMM_AGENT_LISTEN_PORT
185+
value: "7777"
186+
- name: PMM_AGENT_PORTS_MIN
187+
value: "30100"
188+
- name: PMM_AGENT_PORTS_MAX
189+
value: "30105"
190+
- name: PMM_AGENT_CONFIG_FILE
191+
value: /usr/local/percona/pmm2/config/pmm-agent.yaml
192+
- name: PMM_AGENT_SERVER_INSECURE_TLS
193+
value: "1"
194+
- name: PMM_AGENT_LISTEN_ADDRESS
195+
value: 0.0.0.0
196+
- name: PMM_AGENT_SETUP_NODE_NAME
197+
value: $(POD_NAMESPACE)-$(POD_NAME)
198+
- name: PMM_AGENT_SETUP_METRICS_MODE
199+
value: push
200+
- name: PMM_AGENT_SETUP
201+
value: "1"
202+
- name: PMM_AGENT_SETUP_FORCE
203+
value: "1"
204+
- name: PMM_AGENT_SETUP_NODE_TYPE
205+
value: container
206+
- name: PMM_AGENT_PRERUN_SCRIPT
207+
value: /opt/percona/pmm-prerun.sh
208+
- name: PMM_AGENT_SIDECAR
209+
value: "true"
210+
- name: PMM_AGENT_SIDECAR_SLEEP
211+
value: "5"
212+
- name: DB_CLUSTER
213+
value: monitoring
214+
- name: DB_TYPE
215+
value: haproxy
216+
- name: DB_HOST
217+
value: localhost
218+
- name: DB_PORT
219+
value: "33062"
220+
- name: DB_USER
221+
value: monitor
222+
- name: DB_PASSWORD
223+
valueFrom:
224+
secretKeyRef:
225+
key: monitor
226+
name: internal-monitoring
227+
- name: DB_ARGS
228+
value: --query-source=perfschema
229+
- name: PMM_ADMIN_CUSTOM_PARAMS
230+
value: --listen-port=8404
231+
image: perconalab/pmm-client:dev-latest
232+
imagePullPolicy: Always
233+
ports:
234+
- containerPort: 7777
235+
protocol: TCP
236+
- containerPort: 30100
237+
protocol: TCP
238+
- containerPort: 30101
239+
protocol: TCP
240+
- containerPort: 30102
241+
protocol: TCP
242+
- containerPort: 30103
243+
protocol: TCP
244+
- containerPort: 30104
245+
protocol: TCP
246+
- containerPort: 30105
247+
protocol: TCP
248+
- containerPort: 8404
249+
protocol: TCP
250+
resources:
251+
requests:
252+
cpu: 300m
253+
memory: 150M
254+
terminationMessagePath: /dev/termination-log
255+
terminationMessagePolicy: File
256+
volumeMounts:
257+
- mountPath: /opt/percona
258+
name: bin
259+
dnsPolicy: ClusterFirst
260+
initContainers:
261+
- command:
262+
- /opt/percona-server-mysql-operator/ps-init-entrypoint.sh
263+
imagePullPolicy: Always
264+
name: haproxy-init
265+
resources: {}
266+
terminationMessagePath: /dev/termination-log
267+
terminationMessagePolicy: File
268+
volumeMounts:
269+
- mountPath: /opt/percona
270+
name: bin
271+
restartPolicy: Always
272+
schedulerName: default-scheduler
273+
securityContext: {}
274+
terminationGracePeriodSeconds: 30
275+
volumes:
276+
- emptyDir: {}
277+
name: bin
278+
- emptyDir: {}
279+
name: haproxy-config
280+
- name: users
281+
secret:
282+
defaultMode: 420
283+
secretName: internal-monitoring
284+
- name: tls
285+
secret:
286+
defaultMode: 420
287+
secretName: test-ssl
288+
updateStrategy:
289+
rollingUpdate:
290+
partition: 0
291+
type: RollingUpdate
292+
status:
293+
availableReplicas: 3
294+
currentReplicas: 3
295+
observedGeneration: 1
296+
readyReplicas: 3
297+
replicas: 3
298+
updatedReplicas: 3

e2e-tests/tests/monitoring/02-create-cluster.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ commands:
1010
get_cr \
1111
| yq eval '.spec.mysql.clusterType="async"' - \
1212
| yq eval '.spec.pmm.enabled = true' - \
13+
| yq eval '.spec.proxy.haproxy.enabled = true' - \
14+
| yq eval '.spec.proxy.haproxy.expose.type = "LoadBalancer"' - \
1315
| kubectl -n "${NAMESPACE}" apply -f -
1416
timeout: 10

e2e-tests/tests/monitoring/03-check-metrics.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,11 @@ commands:
1717
sleep 90 # wait for QAN
1818
1919
get_qan20_values monitoring-mysql-0 api_key:$API_KEY
20+
21+
haproxy_svc=$(get_service_ip "monitoring-haproxy")
22+
http_code=$(curl -s -o /dev/null -w "%{http_code}" http://${haproxy_svc}:8404/metrics)
23+
if [[ $http_code != 200 ]]; then
24+
echo "Error: http code is $http_code"
25+
exit 1
26+
fi
2027
timeout: 120

pkg/controller/ps/controller.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,14 @@ func (r *PerconaServerMySQLReconciler) reconcileHAProxy(ctx context.Context, cr
719719
return errors.Wrap(err, "get init image")
720720
}
721721

722-
if err := k8s.EnsureObjectWithHash(ctx, r.Client, cr, haproxy.StatefulSet(cr, initImage), r.Scheme); err != nil {
722+
internalSecret := new(corev1.Secret)
723+
nn = types.NamespacedName{Name: cr.InternalSecretName(), Namespace: cr.Namespace}
724+
err = r.Client.Get(ctx, nn, internalSecret)
725+
if client.IgnoreNotFound(err) != nil {
726+
return errors.Wrapf(err, "get Secret/%s", nn.Name)
727+
}
728+
729+
if err := k8s.EnsureObjectWithHash(ctx, r.Client, cr, haproxy.StatefulSet(cr, initImage, internalSecret), r.Scheme); err != nil {
723730
return errors.Wrap(err, "reconcile StatefulSet")
724731
}
725732

@@ -736,8 +743,15 @@ func (r *PerconaServerMySQLReconciler) reconcileServices(ctx context.Context, cr
736743
return errors.Wrap(err, "reconcile Orchestrator services")
737744
}
738745
if cr.HAProxyEnabled() {
746+
internalSecret := new(corev1.Secret)
747+
nn := types.NamespacedName{Name: cr.InternalSecretName(), Namespace: cr.Namespace}
748+
err := r.Client.Get(ctx, nn, internalSecret)
749+
if client.IgnoreNotFound(err) != nil {
750+
return errors.Wrapf(err, "get Secret/%s", nn.Name)
751+
}
752+
739753
expose := cr.Spec.Proxy.HAProxy.Expose
740-
if err := k8s.EnsureService(ctx, r.Client, cr, haproxy.Service(cr), r.Scheme, expose.SaveOldMeta()); err != nil {
754+
if err := k8s.EnsureService(ctx, r.Client, cr, haproxy.Service(cr, internalSecret), r.Scheme, expose.SaveOldMeta()); err != nil {
741755
return errors.Wrap(err, "reconcile HAProxy svc")
742756
}
743757
}
@@ -894,7 +908,7 @@ func (r *PerconaServerMySQLReconciler) cleanupOutdatedServices(ctx context.Conte
894908
log := logf.FromContext(ctx).WithName("cleanupOutdatedServices")
895909

896910
if !cr.HAProxyEnabled() || cr.Spec.Proxy.HAProxy.Size == 0 {
897-
svc := haproxy.Service(cr)
911+
svc := haproxy.Service(cr, nil)
898912
if err := r.Client.Delete(ctx, svc); err != nil && !k8serrors.IsNotFound(err) {
899913
return errors.Wrapf(err, "delete HAProxy svc %s", svc.Name)
900914
}
@@ -942,7 +956,7 @@ func (r *PerconaServerMySQLReconciler) cleanupOutdatedStatefulSets(ctx context.C
942956
}
943957
}
944958
if !cr.HAProxyEnabled() {
945-
if err := r.Delete(ctx, haproxy.StatefulSet(cr, "")); err != nil && !k8serrors.IsNotFound(err) {
959+
if err := r.Delete(ctx, haproxy.StatefulSet(cr, "", nil)); err != nil && !k8serrors.IsNotFound(err) {
946960
return errors.Wrap(err, "failed to delete haproxy statefulset")
947961
}
948962
}

0 commit comments

Comments
 (0)