Optimize the mysql case by using sidecar for metrics exporter and fluent bit (#81)
diff --git a/deploy/platform/kubernetes/feature-mysql/fluent-bit.yaml b/deploy/platform/kubernetes/feature-mysql/fluent-bit.yaml
new file mode 100644
index 0000000..6a48c40
--- /dev/null
+++ b/deploy/platform/kubernetes/feature-mysql/fluent-bit.yaml
@@ -0,0 +1,172 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# @feature: slowsql-mysql; fluent bit log configurations
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: slowsql-mysql-fluent-bit
+ labels:
+ app: slowsql-mysql-fluent-bit
+data:
+ fluent-bit-conf: |
+ [SERVICE]
+ flush 1
+ log_level info
+ parsers_File fluent-bit-parser.conf
+ [INPUT]
+ name tail
+ path /data/slow.log
+ read_from_head true
+ multiline.parser my-log-format
+ [FILTER]
+ name grep
+ match *
+ exclude log mysqld, Version:.*
+ [FILTER]
+ name grep
+ match *
+ exclude log Tcp port: 0.*
+ [FILTER]
+ name grep
+ match *
+ exclude log Time .*
+ [FILTER]
+ name lua
+ match *
+ script fluent-bit-script.lua
+ call rewrite_body
+ [OUTPUT]
+ name stdout
+ match *
+ format json
+ [OUTPUT]
+ name http
+ match *
+ host oap
+ port 12800
+ uri /v3/logs
+ format json
+
+ fluent-bit-script-lua: |
+ function rewrite_body(tag, timestamp, record)
+ log = record["log"]
+ record["log"] = nil
+ record["date"] = nil
+ record["tags"] = {data={{key="LOG_KIND", value="SLOW_SQL"}}}
+ arr = split(log,"\n")
+ re1 = {}
+
+ time = string.sub(arr[1], 9)
+ time = string.sub(time,1,19)
+ time = string.gsub(time,"-","");
+ time = string.gsub(time,"T","");
+ time = string.gsub(time,":","");
+ y1 = string.sub(time,1,4)
+ m1 = string.sub(time,5,6)
+ d1 = string.sub(time,7,8)
+ h1 = string.sub(time,9,10)
+ min1 = string.sub(time,11,12)
+ s1 = string.sub(time,13,14)
+ re1["time"] = os.time()
+
+ re1["layer"] = "MYSQL"
+ record["layer"] = "MYSQL"
+ id1,_ = string.find(arr[2],"Id:")
+ service = "mysql::"..os.getenv("SW_SERVICE")
+ record["service"]=service
+ re1["service"]= service
+
+ f1,_ = string.find(arr[3],"Lock")
+ query_time = string.sub(arr[3],15,f1-3)
+ local qt,_ = math.modf(query_time*1000)
+ re1["query_time"] = qt
+ re1["statement"] = ""
+
+ re1["id"] = uuid()
+
+ for i=4,#arr,1 do
+ re1["statement"] = re1["statement"]..arr[i]
+ end
+ jsonstr = table2json(re1)
+ record["body"]={json={}}
+ record["body"]["json"]["json"] = jsonstr
+ return 1, timestamp, record
+ end
+ function split(input, delimiter)
+ input = tostring(input)
+ delimiter = tostring(delimiter)
+ if (delimiter == "") then return false end
+ local pos, arr = 0, {}
+ for st, sp in function() return string.find(input, delimiter, pos, true) end do
+ table.insert(arr, string.sub(input, pos, st - 1))
+ pos = sp + 1
+ end
+ table.insert(arr, string.sub(input, pos))
+ return arr
+ end
+
+ function uuid()
+ local seed={'e','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}
+ local tb={}
+ for i=1,32 do
+ table.insert(tb,seed[math.random(1,16)])
+ end
+ local sid=table.concat(tb)
+ return string.format('%s-%s-%s-%s-%s',
+ string.sub(sid,1,8),
+ string.sub(sid,9,12),
+ string.sub(sid,13,16),
+ string.sub(sid,17,20),
+ string.sub(sid,21,32)
+ )
+ end
+
+ function table2json(t)
+ local function serialize(tbl)
+ local tmp = {}
+ for k, v in pairs(tbl) do
+ local k_type = type(k)
+ local v_type = type(v)
+ local key = (k_type == "string" and '"' .. k .. '":') or (k_type == "number" and "")
+ local value =
+ (v_type == "table" and serialize(v)) or (v_type == "boolean" and tostring(v)) or
+ (v_type == "string" and '"' .. v .. '"') or
+ (v_type == "number" and v)
+ tmp[#tmp + 1] = key and value and tostring(key) .. tostring(value) or nil
+ end
+ if table.maxn(tbl) == 0 then
+ return "{" .. table.concat(tmp, ",") .. "}"
+ else
+ return "[" .. table.concat(tmp, ",") .. "]"
+ end
+ end
+ assert(type(t) == "table")
+ return serialize(t)
+ end
+
+ fluent-bit-parser-conf: |
+ [MULTILINE_PARSER]
+ name my-log-format
+ type regex
+ flush_timeout 1000
+ rule "start_state" "^(# Time: .*)" "second_state"
+ rule "second_state" "^(# User@Host.*)" "third_state"
+ rule "third_state" "^(# Query_time: .*)" "statement"
+ rule "statement" "^\w+.*" "statement"
diff --git a/deploy/platform/kubernetes/feature-mysql/mysql.yaml b/deploy/platform/kubernetes/feature-mysql/mysql.yaml
index 63f3677..795cdca 100644
--- a/deploy/platform/kubernetes/feature-mysql/mysql.yaml
+++ b/deploy/platform/kubernetes/feature-mysql/mysql.yaml
@@ -16,6 +16,25 @@
# under the License.
#
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: mysqld-config
+ labels:
+ app: mysqld-config
+data:
+ mysqld-config-file: |
+ [mysqld]
+ init_connect='SET NAMES utf8'
+ slow_query_log=ON
+ event_scheduler=ON
+ long_query_time=1
+ slow_query_log_file=/data/slow.log
+ [client]
+ default-character-set=utf8
+ [mysql]
+ default-character-set=utf8
+
---
apiVersion: v1
kind: ConfigMap
@@ -48,6 +67,10 @@
ON SCHEDULE EVERY 1 SECOND
DO COMMIT;
+ CREATE EVENT `event_5`
+ ON SCHEDULE EVERY 1 SECOND
+ DO SELECT SLEEP(3);
+
---
apiVersion: v1
kind: Service
@@ -59,6 +82,10 @@
ports:
- protocol: TCP
port: 3306
+ name: mysqld
+ - protocol: TCP
+ port: 9104
+ name: mysqld-exporter
---
apiVersion: apps/v1
@@ -80,46 +107,19 @@
sidecar.istio.io/inject: "false"
spec:
containers:
- - name: mysql
- image: mysql:8.0.30
+ - name: fluent-bit
+ image: fluent/fluent-bit:1.9
env:
- - name: MYSQL_ROOT_PASSWORD
- value: password
- ports:
- - containerPort: 3306
----
-apiVersion: v1
-kind: Service
-metadata:
- name: mysql-service
-spec:
- selector:
- app: mysql-service
- ports:
- - protocol: TCP
- port: 9104
-
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: mysql-service-deployment
- labels:
- app: mysql-service
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: mysql-service
- template:
- metadata:
- labels:
- app: mysql-service
- annotations:
- sidecar.istio.io/inject: "false"
- spec:
- containers:
- - name: mysql
+ - name: SW_SERVICE
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ volumeMounts:
+ - name: slowsql-mysql-fluent-bit
+ mountPath: /fluent-bit/etc/
+ - name: shared-data
+ mountPath: /data/
+ - name: mysqld-exporter
image: prom/mysqld-exporter:v0.14.0
env:
- name: DATA_SOURCE_NAME
@@ -131,6 +131,38 @@
ports:
- containerPort: 9104
name: metrics
+ - name: mysql
+ image: mysql:8.0.30
+ env:
+ - name: MYSQL_ROOT_PASSWORD
+ value: password
+ ports:
+ - containerPort: 3306
+ volumeMounts:
+ - name: mysqld-config
+ mountPath: /etc/mysql/conf.d/
+ - name: shared-data
+ mountPath: /data/
+ volumes:
+ - name: shared-data
+ emptyDir: {}
+ - name: slowsql-mysql-fluent-bit
+ configMap:
+ name: slowsql-mysql-fluent-bit
+ items:
+ - key: fluent-bit-conf
+ path: fluent-bit.conf
+ - key: fluent-bit-parser-conf
+ path: fluent-bit-parser.conf
+ - key: fluent-bit-script-lua
+ path: fluent-bit-script.lua
+ - name: mysqld-config
+ configMap:
+ name: mysqld-config
+ items:
+ - key: mysqld-config-file
+ path: config-file.cnf
+
---
apiVersion: batch/v1
kind: Job
diff --git a/deploy/platform/kubernetes/feature-mysql/open-telemetry.yaml b/deploy/platform/kubernetes/feature-mysql/open-telemetry.yaml
index f26b750..8ec063c 100644
--- a/deploy/platform/kubernetes/feature-mysql/open-telemetry.yaml
+++ b/deploy/platform/kubernetes/feature-mysql/open-telemetry.yaml
@@ -38,7 +38,7 @@
relabel_configs:
- source_labels: [__meta_kubernetes_pod_container_name, __meta_kubernetes_pod_container_port_name]
action: keep
- regex: mysql;metrics # @feature: mysql; reference the name of the metrics port
+ regex: mysqld-exporter;metrics # @feature: mysql; reference the name of the metrics port
- source_labels: [__meta_kubernetes_pod_name]
target_label: host_name
regex: (.+)
@@ -62,6 +62,7 @@
- batch
exporters:
- otlp
+ - logging
---
apiVersion: apps/v1
diff --git a/deploy/platform/kubernetes/feature-slowsql-mysql/fluent-bit.yaml b/deploy/platform/kubernetes/feature-slowsql-mysql/fluent-bit.yaml
deleted file mode 100644
index b2a6743..0000000
--- a/deploy/platform/kubernetes/feature-slowsql-mysql/fluent-bit.yaml
+++ /dev/null
@@ -1,330 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# @feature: slowsql-mysql; fluent bit log configurations
----
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: fluent-bit-slowsql-mysql
- labels:
- app: fluent-bit-slowsql-mysql
-data:
- fluent-bit-conf: |
- [SERVICE]
- flush 1
- log_level info
- parsers_File fluent-bit-parser.conf
- [INPUT]
- name tail
- path /data/slow.log
- read_from_head true
- multiline.parser my-log-format
- [FILTER]
- name grep
- match *
- exclude log mysqld, Version:.*
- [FILTER]
- name grep
- match *
- exclude log Tcp port: 0.*
- [FILTER]
- name grep
- match *
- exclude log Time .*
- [FILTER]
- name lua
- match *
- script fluent-bit-script.lua
- call rewrite_body
- [OUTPUT]
- name stdout
- match *
- format json
- [OUTPUT]
- name http
- match *
- host oap
- port 12800
- uri /v3/logs
- format json
-
- fluent-bit-script-lua: |
- function rewrite_body(tag, timestamp, record)
- log = record["log"]
- record["log"] = nil
- record["date"] = nil
- record["tags"] = {data={{key="LOG_KIND", value="SLOW_SQL"}}}
- arr = split(log,"\n")
- re1 = {}
-
- time = string.sub(arr[1], 9)
- time = string.sub(time,1,19)
- time = string.gsub(time,"-","");
- time = string.gsub(time,"T","");
- time = string.gsub(time,":","");
- y1 = string.sub(time,1,4)
- m1 = string.sub(time,5,6)
- d1 = string.sub(time,7,8)
- h1 = string.sub(time,9,10)
- min1 = string.sub(time,11,12)
- s1 = string.sub(time,13,14)
- re1["time"] = os.time()
-
- re1["layer"] = "MYSQL"
- record["layer"] = "MYSQL"
- id1,_ = string.find(arr[2],"Id:")
- service = os.getenv("SW_SERVICE")
- record["service"]=service
- re1["service"]= service
-
- f1,_ = string.find(arr[3],"Lock")
- query_time = string.sub(arr[3],15,f1-3)
- local qt,_ = math.modf(query_time*1000)
- re1["query_time"] = qt
- re1["statement"] = ""
-
- re1["id"] = uuid()
-
- for i=4,#arr,1 do
- re1["statement"] = re1["statement"]..arr[i]
- end
- jsonstr = table2json(re1)
- record["body"]={json={}}
- record["body"]["json"]["json"] = jsonstr
- return 1, timestamp, record
- end
- function split(input, delimiter)
- input = tostring(input)
- delimiter = tostring(delimiter)
- if (delimiter == "") then return false end
- local pos, arr = 0, {}
- for st, sp in function() return string.find(input, delimiter, pos, true) end do
- table.insert(arr, string.sub(input, pos, st - 1))
- pos = sp + 1
- end
- table.insert(arr, string.sub(input, pos))
- return arr
- end
-
- function uuid()
- local seed={'e','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}
- local tb={}
- for i=1,32 do
- table.insert(tb,seed[math.random(1,16)])
- end
- local sid=table.concat(tb)
- return string.format('%s-%s-%s-%s-%s',
- string.sub(sid,1,8),
- string.sub(sid,9,12),
- string.sub(sid,13,16),
- string.sub(sid,17,20),
- string.sub(sid,21,32)
- )
- end
-
- function table2json(t)
- local function serialize(tbl)
- local tmp = {}
- for k, v in pairs(tbl) do
- local k_type = type(k)
- local v_type = type(v)
- local key = (k_type == "string" and '"' .. k .. '":') or (k_type == "number" and "")
- local value =
- (v_type == "table" and serialize(v)) or (v_type == "boolean" and tostring(v)) or
- (v_type == "string" and '"' .. v .. '"') or
- (v_type == "number" and v)
- tmp[#tmp + 1] = key and value and tostring(key) .. tostring(value) or nil
- end
- if table.maxn(tbl) == 0 then
- return "{" .. table.concat(tmp, ",") .. "}"
- else
- return "[" .. table.concat(tmp, ",") .. "]"
- end
- end
- assert(type(t) == "table")
- return serialize(t)
- end
-
- fluent-bit-parser-conf: |
- [MULTILINE_PARSER]
- name my-log-format
- type regex
- flush_timeout 1000
- rule "start_state" "^(# Time: .*)" "second_state"
- rule "second_state" "^(# User@Host.*)" "third_state"
- rule "third_state" "^(# Query_time: .*)" "statement"
- rule "statement" "^\w+.*" "statement"
-
- mysqld-config-file: |
- [mysqld]
- init_connect='SET NAMES utf8'
- slow_query_log=ON
- event_scheduler=ON
- long_query_time=1
- slow_query_log_file=/data/slow.log
- [client]
- default-character-set=utf8
- [mysql]
- default-character-set=utf8
-
----
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: mock-sql-slowsql-mysql
- labels:
- app: mysql-load
-data:
- mock-sql: |
- CREATE DATABASE IF NOT EXISTS test;
- USE test;
- CREATE TABLE IF NOT EXISTS `t1`(
- `te1` VARCHAR(100) NOT NULL
- )ENGINE=InnoDB DEFAULT CHARSET=utf8;
- SET GLOBAL event_scheduler = 1;
-
- CREATE EVENT `event_1`
- ON SCHEDULE EVERY 1 SECOND
- DO INSERT INTO t1 values('test');
-
- CREATE EVENT `event_2`
- ON SCHEDULE EVERY 1 SECOND
- DO UPDATE t1 SET `te1` = 1;
-
- CREATE EVENT `event_3`
- ON SCHEDULE EVERY 1 SECOND
- DO DELETE FROM t1;
-
- CREATE EVENT `event_4`
- ON SCHEDULE EVERY 1 SECOND
- DO COMMIT;
-
- CREATE EVENT `event_5`
- ON SCHEDULE EVERY 1 SECOND
- DO SELECT SLEEP(3);
-
----
-apiVersion: v1
-kind: Service
-metadata:
- name: slowsql-mysql
-spec:
- selector:
- app: slowsql-mysql
- ports:
- - protocol: TCP
- port: 3306
-
----
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: slowsql-mysql
- labels:
- app: slowsql-mysql
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: slowsql-mysql
- template:
- metadata:
- labels:
- app: slowsql-mysql
- annotations:
- sidecar.istio.io/inject: "false"
- spec:
- containers:
- - name: fluent-bit
- image: fluent/fluent-bit:1.9
- env:
- - name: SW_SERVICE
- valueFrom:
- fieldRef:
- fieldPath: metadata.name
- volumeMounts:
- - name: fluent-bit-slowsql-mysql
- mountPath: /fluent-bit/etc/
- - name: shared-data
- mountPath: /data/
- - name: mysql
- image: mysql:8.0.30
- env:
- - name: MYSQL_ROOT_PASSWORD
- value: password
- ports:
- - containerPort: 3306
- volumeMounts:
- - name: mysqld-config
- mountPath: /etc/mysql/conf.d/
- - name: shared-data
- mountPath: /data/
- volumes:
- - name: shared-data
- emptyDir: {}
- - name: fluent-bit-slowsql-mysql
- configMap:
- name: fluent-bit-slowsql-mysql
- items:
- - key: fluent-bit-conf
- path: fluent-bit.conf
- - key: fluent-bit-parser-conf
- path: fluent-bit-parser.conf
- - key: fluent-bit-script-lua
- path: fluent-bit-script.lua
- - name: mysqld-config
- configMap:
- name: fluent-bit-slowsql-mysql
- items:
- - key: mysqld-config-file
- path: config-file.cnf
----
-apiVersion: batch/v1
-kind: Job
-metadata:
- name: slowsql-mysql-load-generator # @feature: slowsql-mysql; set up job to trigger mysql slow commands, you don't need this in production env.
-spec:
- template:
- metadata:
- name: mysql-load-deployment-slowsql
- annotations:
- sidecar.istio.io/inject: "false"
- spec:
- restartPolicy: Never
- initContainers:
- - name: wait-for-mysql
- image: busybox
- command: ["sh", "-c", "until nc -z slowsql-mysql 3306 > /dev/null; do echo Waiting for slowsql-mysql.; sleep 2; done;"]
- containers:
- - name: mysql-load-slowsql
- image: mysql:8.0.30
- command:
- - bash
- - -c
- - mysql -hslowsql-mysql -uroot -ppassword < /conf/mock.sql
- volumeMounts:
- - name: mock-sql-vol-slowsql-mysql
- mountPath: /conf
- volumes:
- - name: mock-sql-vol-slowsql-mysql
- configMap:
- name: mock-sql-slowsql-mysql
- items:
- - key: mock-sql
- path: mock.sql
diff --git a/docs/readme.md b/docs/readme.md
index f1de27d..d502676 100644
--- a/docs/readme.md
+++ b/docs/readme.md
@@ -97,8 +97,7 @@
| `function` | Deploy [OpenFunction](https://openfunction.dev/) and export trace to SkyWalking. | Command [ofn](https://github.com/OpenFunction/cli) is required to run this feature. |
| `trace-profiling` | Deploy tools to submit trace profiling tasks. | Only support deployment with SkyWalking agents installed, currently Java agent and Python agent support trace profiling. |
| `rover` | Deploy SkyWalking Rover and detect the processes in the Kubernetes environment. | Only support deployment in the Kubernetes environment, docker is not supported. |
-| `mysql` | Start a MySQL server, execute the sample SQLs periodically, and export their metrics to SkyWalking. | |
-| `slowsql-mysql` | Start a MySQL server and load generator to execute the sample SQLs periodically; set up fluent bit to fetch slow logs and export to OAP. | |
+| `mysql` | Start a MySQL server and load generator to execute the sample SQLs periodically, set up fluent bit to fetch slow logs and export to OAP, and export their metrics to SkyWalking. | |
| `postgresql` | Start a PostgreSQL server, execute the sample SQLs periodically, and export their metrics to SkyWalking. | |
### Kubernetes