Skip to content

Commit 9344a5f

Browse files
ayleishuijing198799
authored andcommitted
Support slow log tailing sidcar for tidb instance (pingcap#290)
* Support slow log tailing sidcar for tidb instance
1 parent 4b91c46 commit 9344a5f

File tree

11 files changed

+200
-53
lines changed

11 files changed

+200
-53
lines changed

charts/tidb-cluster/templates/scripts/_start_tidb.sh.tpl

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ then
3434
ARGS="${ARGS} --enable-binlog=true"
3535
fi
3636

37+
if [[ ! -z "${SLOW_LOG_FILE}" ]]
38+
then
39+
ARGS="${ARGS} --log-slow-query=${SLOW_LOG_FILE:-}"
40+
fi
41+
3742
echo "start tidb-server ..."
3843
echo "/tidb-server ${ARGS}"
3944
exec /tidb-server ${ARGS}

charts/tidb-cluster/templates/tidb-cluster.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,10 @@ spec:
7676
{{- end }}
7777
binlogEnabled: {{ .Values.binlog.pump.create | default false }}
7878
maxFailoverCount: {{ .Values.tidb.maxFailoverCount | default 3 }}
79+
separateSlowLog: {{ .Values.tidb.separateSlowLog | default false }}
80+
slowLogTailer:
81+
image: {{ .Values.tidb.slowLogTailer.image }}
82+
imagePullPolicy: {{ .Values.tidb.slowLogTailer.imagePullPolicy | default "IfNotPresent" }}
83+
{{- if .Values.tidb.slowLogTailer.resources }}
84+
{{ toYaml .Values.tidb.slowLogTailer.resources | indent 6 }}
85+
{{- end }}

charts/tidb-cluster/values.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,16 @@ tidb:
175175
exposeStatus: true
176176
# annotations:
177177
# cloud.google.com/load-balancer-type: Internal
178+
# separateSlowLog: true
179+
slowLogTailer:
180+
image: busybox:1.26.2
181+
resources:
182+
limits:
183+
cpu: 100m
184+
memory: 50Mi
185+
requests:
186+
cpu: 20m
187+
memory: 5Mi
178188

179189
# mysqlClient is used to set password for TiDB
180190
mysqlClient:

docs/operation-guide.md

+27
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,33 @@ Then open your browser at http://localhost:3000 The default username and passwor
131131

132132
The Grafana service is exposed as `NodePort` by default, you can change it to `LoadBalancer` if the underlining Kubernetes has load balancer support. And then view the dashboard via load balancer endpoint.
133133

134+
### View TiDB Slow Query Log
135+
136+
For default setup, tidb is configured to export slow query log to STDOUT along with normal server logs. You can obtain the slow query log by `grep` the keyword `SLOW_QUERY`:
137+
138+
```shell
139+
$ kubectl logs -n ${namespace} ${tidbPodName} | grep SLOW_QUERY
140+
```
141+
142+
Optionally, you can output slow query log in a separate sidecar by enabling `separateSlowLog`:
143+
144+
```yaml
145+
# Uncomment the following line to enable separate output of the slow query log
146+
# separateSlowLog: true
147+
```
148+
149+
Run `helm upgrade` to apply the change, then you can obtain the slow query log from the sidecar named `slowlog`:
150+
151+
```shell
152+
$ kubectl logs -n ${namespace} ${tidbPodName} -c slowlog
153+
```
154+
155+
To retrieve logs from multiple pods, [`stern`](https://github.com/wercker/stern) is recommended.
156+
157+
```shell
158+
$ stern -n ${namespace} tidb -c slowlog
159+
```
160+
134161
## Backup
135162

136163
Currently, TiDB Operator supports two kinds of backup: incremental backup via binlog and full backup(scheduled or ad-hoc) via [Mydumper](https://github.com/maxbube/mydumper).

images/tidb-operator-e2e/tidb-cluster-values.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ tidb:
143143
exposeStatus: true
144144
# annotations:
145145
# cloud.google.com/load-balancer-type: Internal
146+
separateSlowLog: true
146147

147148
# mysqlClient is used to set password for TiDB
148149
mysqlClient:

pkg/apis/pingcap.com/v1alpha1/types.go

+17-8
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ const (
4242
TiDBMemberType MemberType = "tidb"
4343
// TiKVMemberType is tikv container type
4444
TiKVMemberType MemberType = "tikv"
45-
//PushGatewayMemberType is pushgateway container type
45+
// PushGatewayMemberType is pushgateway container type
4646
PushGatewayMemberType MemberType = "pushgateway"
47+
// SlowLogTailerMemberType is tidb log tailer container type
48+
SlowLogTailerMemberType MemberType = "slowlog"
4749
// UnknownMemberType is unknown container type
4850
UnknownMemberType MemberType = "unknown"
4951
)
@@ -117,13 +119,20 @@ type PDSpec struct {
117119
// TiDBSpec contains details of PD member
118120
type TiDBSpec struct {
119121
ContainerSpec
120-
Replicas int32 `json:"replicas"`
121-
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
122-
NodeSelectorRequired bool `json:"nodeSelectorRequired,omitempty"`
123-
StorageClassName string `json:"storageClassName,omitempty"`
124-
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
125-
BinlogEnabled bool `json:"binlogEnabled,omitempty"`
126-
MaxFailoverCount int32 `json:"maxFailoverCount,omitempty"`
122+
Replicas int32 `json:"replicas"`
123+
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
124+
NodeSelectorRequired bool `json:"nodeSelectorRequired,omitempty"`
125+
StorageClassName string `json:"storageClassName,omitempty"`
126+
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
127+
BinlogEnabled bool `json:"binlogEnabled,omitempty"`
128+
MaxFailoverCount int32 `json:"maxFailoverCount,omitempty"`
129+
SeparateSlowLog bool `json:"separateSlowLog,omitempty"`
130+
SlowLogTailer TiDBSlowLogTailerSpec `json:"slowLogTailer,omitempty"`
131+
}
132+
133+
// TiDBSlowLogTailerSpec represents an optional log tailer sidecar with TiDB
134+
type TiDBSlowLogTailerSpec struct {
135+
ContainerSpec
127136
}
128137

129138
// TiKVSpec contains details of PD member

pkg/apis/pingcap.com/v1alpha1/zz_generated.deepcopy.go

+18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controller/controller_utils.go

+9
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ var (
3636
const (
3737
// defaultPushgatewayImage is default image of pushgateway
3838
defaultPushgatewayImage = "prom/pushgateway:v0.3.1"
39+
// defaultTiDBSlowLogImage is default image of tidb log tailer
40+
defaultTiDBLogTailerImage = "busybox:1.26.2"
3941
)
4042

4143
// RequeueError is used to requeue the item, this error type should't be considered as a real error
@@ -129,6 +131,13 @@ func GetPushgatewayImage(cluster *v1alpha1.TidbCluster) string {
129131
return defaultPushgatewayImage
130132
}
131133

134+
func GetSlowLogTailerImage(cluster *v1alpha1.TidbCluster) string {
135+
if img := cluster.Spec.TiDB.SlowLogTailer.Image; img != "" {
136+
return img
137+
}
138+
return defaultTiDBLogTailerImage
139+
}
140+
132141
// PDMemberName returns pd member name
133142
func PDMemberName(clusterName string) string {
134143
return fmt.Sprintf("%s-pd", clusterName)

pkg/controller/controller_utils_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ func TestGetPushgatewayImage(t *testing.T) {
157157
g.Expect(GetPushgatewayImage(tc)).To(Equal("image-1"))
158158
}
159159

160+
func TestGetSlowLogTailerImage(t *testing.T) {
161+
g := NewGomegaWithT(t)
162+
163+
tc := &v1alpha1.TidbCluster{}
164+
g.Expect(GetSlowLogTailerImage(tc)).To(Equal(defaultTiDBLogTailerImage))
165+
tc.Spec.TiDB.SlowLogTailer.Image = "image-1"
166+
g.Expect(GetSlowLogTailerImage(tc)).To(Equal("image-1"))
167+
}
168+
160169
func TestPDMemberName(t *testing.T) {
161170
g := NewGomegaWithT(t)
162171
g.Expect(PDMemberName("demo")).To(Equal("demo-pd"))

pkg/manager/member/tidb_member_manager.go

+85-45
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package member
1515

1616
import (
17+
"fmt"
1718
"strconv"
1819

1920
"github.com/pingcap/tidb-operator/pkg/apis/pingcap.com/v1alpha1"
@@ -30,6 +31,12 @@ import (
3031
corelisters "k8s.io/client-go/listers/core/v1"
3132
)
3233

34+
const (
35+
slowQueryLogVolumeName = "slowlog"
36+
slowQueryLogDir = "/var/log/tidb"
37+
slowQueryLogFile = slowQueryLogDir + "/slowlog"
38+
)
39+
3340
type tidbMemberManager struct {
3441
setControl controller.StatefulSetControlInterface
3542
svcControl controller.ServiceControlInterface
@@ -240,6 +247,83 @@ func (tmm *tidbMemberManager) getNewTiDBSetForTidbCluster(tc *v1alpha1.TidbClust
240247
},
241248
}
242249

250+
var containers []corev1.Container
251+
if tc.Spec.TiDB.SeparateSlowLog {
252+
// mount a shared volume and tail the slow log to STDOUT using a sidecar.
253+
vols = append(vols, corev1.Volume{
254+
Name: slowQueryLogVolumeName,
255+
VolumeSource: corev1.VolumeSource{
256+
EmptyDir: &corev1.EmptyDirVolumeSource{},
257+
},
258+
})
259+
volMounts = append(volMounts, corev1.VolumeMount{Name: slowQueryLogVolumeName, MountPath: slowQueryLogDir})
260+
containers = append(containers, corev1.Container{
261+
Name: v1alpha1.SlowLogTailerMemberType.String(),
262+
Image: controller.GetSlowLogTailerImage(tc),
263+
ImagePullPolicy: tc.Spec.TiDB.SlowLogTailer.ImagePullPolicy,
264+
Resources: util.ResourceRequirement(tc.Spec.TiDB.SlowLogTailer.ContainerSpec),
265+
VolumeMounts: []corev1.VolumeMount{
266+
{Name: slowQueryLogVolumeName, MountPath: slowQueryLogDir},
267+
},
268+
Command: []string{
269+
"sh",
270+
"-c",
271+
fmt.Sprintf("touch %s; tail -n0 -F %s;", slowQueryLogFile, slowQueryLogFile),
272+
},
273+
})
274+
}
275+
276+
envs := []corev1.EnvVar{
277+
{
278+
Name: "CLUSTER_NAME",
279+
Value: tc.GetName(),
280+
},
281+
{
282+
Name: "TZ",
283+
Value: tc.Spec.Timezone,
284+
},
285+
{
286+
Name: "BINLOG_ENABLED",
287+
Value: strconv.FormatBool(tc.Spec.TiDB.BinlogEnabled),
288+
},
289+
}
290+
if tc.Spec.TiDB.SeparateSlowLog {
291+
envs = append(envs, corev1.EnvVar{
292+
Name: "SLOW_LOG_FILE",
293+
Value: slowQueryLogFile,
294+
})
295+
}
296+
containers = append(containers, corev1.Container{
297+
Name: v1alpha1.TiDBMemberType.String(),
298+
Image: tc.Spec.TiDB.Image,
299+
Command: []string{"/bin/sh", "/usr/local/bin/tidb_start_script.sh"},
300+
ImagePullPolicy: tc.Spec.TiDB.ImagePullPolicy,
301+
Ports: []corev1.ContainerPort{
302+
{
303+
Name: "server",
304+
ContainerPort: int32(4000),
305+
Protocol: corev1.ProtocolTCP,
306+
},
307+
{
308+
Name: "status", // pprof, status, metrics
309+
ContainerPort: int32(10080),
310+
Protocol: corev1.ProtocolTCP,
311+
},
312+
},
313+
VolumeMounts: volMounts,
314+
Resources: util.ResourceRequirement(tc.Spec.TiDB.ContainerSpec),
315+
Env: envs,
316+
ReadinessProbe: &corev1.Probe{
317+
Handler: corev1.Handler{
318+
HTTPGet: &corev1.HTTPGetAction{
319+
Path: "/status",
320+
Port: intstr.FromInt(10080),
321+
},
322+
},
323+
InitialDelaySeconds: int32(10),
324+
},
325+
})
326+
243327
tidbLabel := label.New().Instance(instanceName).TiDB()
244328
tidbSet := &apps.StatefulSet{
245329
ObjectMeta: metav1.ObjectMeta{
@@ -264,51 +348,7 @@ func (tmm *tidbMemberManager) getNewTiDBSetForTidbCluster(tc *v1alpha1.TidbClust
264348
label.New().Instance(instanceName).TiDB(),
265349
tc.Spec.TiDB.NodeSelector,
266350
),
267-
Containers: []corev1.Container{
268-
{
269-
Name: v1alpha1.TiDBMemberType.String(),
270-
Image: tc.Spec.TiDB.Image,
271-
Command: []string{"/bin/sh", "/usr/local/bin/tidb_start_script.sh"},
272-
ImagePullPolicy: tc.Spec.TiDB.ImagePullPolicy,
273-
Ports: []corev1.ContainerPort{
274-
{
275-
Name: "server",
276-
ContainerPort: int32(4000),
277-
Protocol: corev1.ProtocolTCP,
278-
},
279-
{
280-
Name: "status", // pprof, status, metrics
281-
ContainerPort: int32(10080),
282-
Protocol: corev1.ProtocolTCP,
283-
},
284-
},
285-
VolumeMounts: volMounts,
286-
Resources: util.ResourceRequirement(tc.Spec.TiDB.ContainerSpec),
287-
Env: []corev1.EnvVar{
288-
{
289-
Name: "CLUSTER_NAME",
290-
Value: tc.GetName(),
291-
},
292-
{
293-
Name: "TZ",
294-
Value: tc.Spec.Timezone,
295-
},
296-
{
297-
Name: "BINLOG_ENABLED",
298-
Value: strconv.FormatBool(tc.Spec.TiDB.BinlogEnabled),
299-
},
300-
},
301-
ReadinessProbe: &corev1.Probe{
302-
Handler: corev1.Handler{
303-
HTTPGet: &corev1.HTTPGetAction{
304-
Path: "/status",
305-
Port: intstr.FromInt(10080),
306-
},
307-
},
308-
InitialDelaySeconds: int32(10),
309-
},
310-
},
311-
},
351+
Containers: containers,
312352
RestartPolicy: corev1.RestartPolicyAlways,
313353
Tolerations: tc.Spec.TiDB.Tolerations,
314354
Volumes: vols,

pkg/manager/member/tidb_member_manager_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,18 @@ func TestTiDBMemberManagerSyncUpdate(t *testing.T) {
209209
g.Expect(err).NotTo(HaveOccurred())
210210
},
211211
},
212+
{
213+
name: "enable separate slowlog on the fly",
214+
modify: func(tc *v1alpha1.TidbCluster) {
215+
tc.Spec.TiDB.SeparateSlowLog = true
216+
},
217+
errWhenUpdateStatefulSet: false,
218+
err: false,
219+
expectStatefulSetFn: func(g *GomegaWithT, set *apps.StatefulSet, err error) {
220+
g.Expect(err).NotTo(HaveOccurred())
221+
g.Expect(set.Spec.Template.Spec.Containers).To(HaveLen(2))
222+
},
223+
},
212224
}
213225

214226
for i := range tests {

0 commit comments

Comments
 (0)