常用服务docker安装

常用服务

pg, mysql, redis 等服务

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
docker run -d \
--name=postgres \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_USER=postgres \
-e POSTGRES_DB=postgres \
-v ./postgres/data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres

docker run -d \
--name=mysql \
-e MYSQL_ROOT_PASSWORD=yourrootpassword \
-e MYSQL_DATABASE=yourdatabase \
-e MYSQL_USER=yourusername \
-e MYSQL_PASSWORD=yourpassword \
-v ./mysql/data:/var/lib/mysql \
-p 3306:3306 \
mysql



docker run -d \
--name=redis \
-v ./redis/data:/data \
-p 6379:6379 \
redis

prometheus, grafana, nodeexport 等服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

docker run -d \
--name=prometheus \
-v ./prometheus/config/prometheus.yml:/etc/prometheus/prometheus.yml \
-v ./prometheus/data:/prometheus \
-p 9090:9090 \
prom/prometheus



docker run -p 3000:3000 --name grafana \
-v /opt/prometheus/grafana/data:/var/lib/grafana \
-e "GF_SECURITY_ADMIN_PASSWORD=grafana123" \
-itd grafana/grafana

# -v ./prometheus/grafana/grafana.ini:/etc/grafana/grafana.ini # 按需设置

docker run -d --name node-exporter --restart=always -p 9100:9100 -v "/proc:/host/proc:ro" -v "/sys:/host/sys:ro" -v "/:/rootfs:ro" prom/node-exporter

Pyroscope

Pyroscope 是一个开源的性能剖析工具,可以帮助开发者对应用程序进行性能分析、热点诊断,并提供对性能问题的可视化支持。它支持多种语言和运行时环境(如 Go、Python、Ruby、Java 等),可以在生产环境中对应用程序进行低开销的性能剖析

安装

1
docker run -it --net=host -e "PYROSCOPE_SERVER_HTTP_ADDRESS=0.0.0.0:4040" grafana/pyroscope

使用 pyroscope-test.py

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
#  pip install pyroscope-io
import pyroscope
import time
import random

# 配置 Pyroscope
pyroscope.configure(
application_name="my2.python.app",
server_address="http://localhost:4040",
# 可选:设置更多参数
# sample_rate=100, # 每秒采样次数
# detect_subprocesses=True, # 检测子进程
# gil_only=False # 是否只分析持有 GIL 的线程
)

def cpu_intensive_task():
"""模拟 CPU 密集型任务"""
result = 0
for _ in range(10000):
result += random.randint(1, 100) ** 2
return result

def main():
try:
while True:
cpu_intensive_task()
time.sleep(0.1) # 控制执行频率
except KeyboardInterrupt:
print("性能分析结束")

if __name__ == "__main__":
main()

验证

pyroscope-py-test

集成到 grafana

grafana 里运行
grafana-cli plugins install pyroscope-datasource

grafana-pyroscope-datasource

grafana-pyroscope-explore

使用 alloy 搭配

alloy 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
logging {
level = "info"
format = "logfmt"
}

pyroscope.scrape "local" {
targets = array.concat([
{"__address__" = "pyroscope:4040", "service_name"="pyroscope"},
{"__address__" = "localhost:12345", "service_name"="alloy"},
])

forward_to = [pyroscope.write.local.receiver]
}

pyroscope.write "local" {
endpoint {
url = "http://pyroscope:4040"
}
}

alloy 安装 (k8s helm)

1
2
3
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm install --namespace pyroscope alloy2 grafana/alloy

默认生成的配置文件

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
# Source: alloy/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: alloy2
labels:
helm.sh/chart: alloy-0.10.0
app.kubernetes.io/name: alloy
app.kubernetes.io/instance: alloy2

app.kubernetes.io/version: "v1.5.0"
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/part-of: alloy
app.kubernetes.io/component: config
data:
config.alloy: |-

logging {
level = "info"
format = "logfmt"
}

profiling {
enabled = true
endpoint = "http://pyroscope:4040"
application_name = "alloy"
}


discovery.kubernetes "pods" {
role = "pod"
}

discovery.kubernetes "nodes" {
role = "node"
}

discovery.kubernetes "services" {
role = "service"
}

discovery.kubernetes "endpoints" {
role = "endpoints"
}

discovery.kubernetes "endpointslices" {
role = "endpointslice"
}

discovery.kubernetes "ingresses" {
role = "ingress"
}

使用 values.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
alloy:
configMap:
create: true
content: |
discovery.kubernetes "all_pods" {
role = "pod"
selectors {
field = "spec.nodeName=" + env("HOSTNAME")
role = "pod"
}
}

discovery.relabel "local_pods" {
targets = discovery.kubernetes.all_pods.targets
rule {
action = "drop"
regex = "Succeeded|Failed"
source_labels = ["__meta_kubernetes_pod_phase"]
}
rule {
action = "replace"
regex = "(.*)@(.*)"
replacement = "ebpf/${1}/${2}"
separator = "@"
source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
target_label = "service_name"
}
rule {
action = "labelmap"
regex = "__meta_kubernetes_pod_label_(.+)"
}
rule {
action = "replace"
source_labels = ["__meta_kubernetes_namespace"]
target_label = "namespace"
}
rule {
action = "replace"
source_labels = ["__meta_kubernetes_pod_name"]
target_label = "pod"
}
rule {
action = "replace"
source_labels = ["__meta_kubernetes_node_name"]
target_label = "node"
}
rule {
action = "replace"
source_labels = ["__meta_kubernetes_pod_container_name"]
target_label = "container"
}
}
pyroscope.ebpf "local_pods" {
forward_to = [ pyroscope.write.endpoint.receiver ]
targets = discovery.relabel.local_pods.output
}

pyroscope.write "endpoint" {
endpoint {
url = "http://pyroscope:4040"
}
}
securityContext:
privileged: true
runAsGroup: 0
runAsUser: 0

controller:
hostPID: true

生成的配置文件

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
apiVersion: v1
kind: ConfigMap
metadata:
name: alloy2
namespace: common-infra-prod
data:
config.alloy: |-
discovery.kubernetes "all_pods" {
role = "pod"
selectors {
field = "spec.nodeName=" + env("HOSTNAME")
role = "pod"
}
}

discovery.relabel "local_pods" {
targets = discovery.kubernetes.all_pods.targets
rule {
action = "drop"
regex = "Succeeded|Failed"
source_labels = ["__meta_kubernetes_pod_phase"]
}
rule {
action = "replace"
regex = "(.*)@(.*)"
replacement = "ebpf/${1}/${2}"
separator = "@"
source_labels = ["__meta_kubernetes_namespace", "__meta_kubernetes_pod_container_name"]
target_label = "service_name"
}
rule {
action = "labelmap"
regex = "__meta_kubernetes_pod_label_(.+)"
}
rule {
action = "replace"
source_labels = ["__meta_kubernetes_namespace"]
target_label = "namespace"
}
rule {
action = "replace"
source_labels = ["__meta_kubernetes_pod_name"]
target_label = "pod"
}
rule {
action = "replace"
source_labels = ["__meta_kubernetes_node_name"]
target_label = "node"
}
rule {
action = "replace"
source_labels = ["__meta_kubernetes_pod_container_name"]
target_label = "container"
}
}
pyroscope.ebpf "local_pods" {
forward_to = [ pyroscope.write.endpoint.receiver ]
targets = discovery.relabel.local_pods.output
}

pyroscope.write "endpoint" {
endpoint {
url = "http://pyroscope:4040"
}
}