部署安装
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm search repo grafana/pyroscope
kubectl create namespace pyroscope-test
helm -n pyroscope-test install pyroscope grafana/pyroscope
[root@master-1 keda]#kubectl get po -n pyroscope-test
NAME READY STATUS RESTARTS AGE
pyroscope-0 1/1 Running 0 97m
pyroscope-alloy-0 2/2 Running 0 97m
侵入式
GO代码引入
package main
import (
...
"github.com/grafana/pyroscope-go"
...
)
func initPyroScope() {
runtime.SetMutexProfileFraction(5)
runtime.SetBlockProfileRate(5)
_, _ = pyroscope.Start(pyroscope.Config{
ApplicationName: "tcp_backend", // 应用名称
ServerAddress: "http://pyroscope.pyroscope-test.svc.cluster.local.:4040", // 上报地址
Logger: pyroscope.StandardLogger,
Tags: map[string]string{"hostname": os.Getenv("HOSTNAME")},
ProfileTypes: []pyroscope.ProfileType{
pyroscope.ProfileCPU,
pyroscope.ProfileAllocObjects,
pyroscope.ProfileAllocSpace,
pyroscope.ProfileInuseObjects,
pyroscope.ProfileInuseSpace,
pyroscope.ProfileGoroutines,
pyroscope.ProfileMutexCount,
pyroscope.ProfileMutexDuration,
pyroscope.ProfileBlockCount,
pyroscope.ProfileBlockDuration,
},
})
}
func main() {
initPyroScope()
.....
}
部署验证
apiVersion: apps/v1
kind: Deployment
metadata:
name: tcp-backend
namespace: default
labels:
app: tcp-backend
spec:
replicas: 1
selector:
matchLabels:
app: tcp-backend
template:
metadata:
labels:
app: tcp-backend
spec:
containers:
- name: tcp-backend
image: registry.cn-zhangjiakou.aliyuncs.com/tanghao-public/k8s-tcp-test:v0.3
imagePullPolicy: IfNotPresent
ports:
- name: tcp
containerPort: 8080
protocol: TCP
- name: metrics
containerPort: 9090
protocol: TCP
readinessProbe:
tcpSocket:
port: tcp
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: tcp
initialDelaySeconds: 15
periodSeconds: 20
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: tcp-backend
namespace: default
labels:
app: tcp-backend
spec:
type: ClusterIP
selector:
app: tcp-backend
ports:
- name: tcp
port: 8080
targetPort: tcp
protocol: TCP
- name: metrics
port: 9090
targetPort: metrics
protocol: TCP
查看收集的数据
半侵入式
GO 代码引入
import _ "net/http/pprof"
go func() {
http.ListenAndServe(":6060", nil)
}()
部署验证
apiVersion: apps/v1
kind: Deployment
metadata:
name: tcp-backend
namespace: default
labels:
app: tcp-backend
spec:
replicas: 1
selector:
matchLabels:
app: tcp-backend
template:
metadata:
annotations:
profiles.grafana.com/memory.scrape: "true"
profiles.grafana.com/memory.port: "6060"
profiles.grafana.com/cpu.scrape: "true"
profiles.grafana.com/cpu.port: "6060"
profiles.grafana.com/goroutine.scrape: "true"
profiles.grafana.com/goroutine.port: "6060"
labels:
app: tcp-backend
spec:
containers:
- name: tcp-backend
image: registry.cn-zhangjiakou.aliyuncs.com/tanghao-public/k8s-tcp-test:v0.4
imagePullPolicy: IfNotPresent
ports:
- name: tcp
containerPort: 8080
protocol: TCP
- name: metrics
containerPort: 9090
protocol: TCP
- name: pprof
containerPort: 6060
protocol: TCP
readinessProbe:
tcpSocket:
port: tcp
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: tcp
initialDelaySeconds: 15
periodSeconds: 20
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
---
apiVersion: v1
kind: Service
metadata:
name: tcp-backend
namespace: default
labels:
app: tcp-backend
spec:
type: ClusterIP
selector:
app: tcp-backend
ports:
- name: tcp
port: 8080
targetPort: tcp
protocol: TCP
- name: metrics
port: 9090
targetPort: metrics
protocol: TCP
查看收集的数据
无侵入式
部署单独的alloy
配置
[root@master-1 pyroscope]# helm pull grafana/alloy --version=1.5.2
[root@master-1 pyroscope]#tar xf alloy-1.5.2.tgz
[root@master-1 alloy]#cat values.yaml | grep -v '#'
nameOverride: null
namespaceOverride: null
fullnameOverride: null
global:
image:
registry: ""
pullSecrets: []
podSecurityContext: {}
crds:
create: true
alloy:
configMap:
create: true
content: ''
name: null
key: null
clustering:
enabled: false
name: ""
portName: http
stabilityLevel: "generally-available"
storagePath: /tmp/alloy
enableHttpServerPort: true
listenAddr: 0.0.0.0
listenPort: 12345
listenScheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 1
uiPathPrefix: /
enableReporting: true
extraEnv: []
envFrom: []
extraArgs: []
extraPorts: []
hostAliases: []
mounts:
varlog: false
dockercontainers: false
extra:
- name: proc
mountPath: /proc
readOnly: true
securityContext:
privileged: true
resources: {}
lifecycle: {}
livenessProbe: {}
image:
registry: "docker.io"
repository: grafana/alloy
tag: null
digest: null
pullPolicy: IfNotPresent
pullSecrets: []
rbac:
create: true
namespaces: []
rules:
- apiGroups: ["", "discovery.k8s.io", "networking.k8s.io"]
resources: ["endpoints", "endpointslices", "ingresses", "pods", "services"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods", "pods/log", "namespaces"]
verbs: ["get", "list", "watch"]
- apiGroups: ["monitoring.grafana.com"]
resources: ["podlogs"]
verbs: ["get", "list", "watch"]
- apiGroups: ["monitoring.coreos.com"]
resources: ["prometheusrules"]
verbs: ["get", "list", "watch"]
- apiGroups: ["monitoring.coreos.com"]
resources: ["alertmanagerconfigs"]
verbs: ["get", "list", "watch"]
- apiGroups: ["monitoring.coreos.com"]
resources: ["podmonitors", "servicemonitors", "probes", "scrapeconfigs"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps", "extensions"]
resources: ["replicasets"]
verbs: ["get", "list", "watch"]
clusterRules:
- apiGroups: [""]
resources: ["nodes", "nodes/proxy", "nodes/metrics"]
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
serviceAccount:
create: true
additionalLabels: {}
annotations: {}
name: null
automountServiceAccountToken: true
configReloader:
enabled: true
image:
registry: "quay.io"
repository: prometheus-operator/prometheus-config-reloader
tag: v0.81.0
digest: ""
customArgs: []
resources:
requests:
cpu: "10m"
memory: "50Mi"
securityContext:
privileged: true
controller:
type: 'daemonset'
replicas: 1
extraLabels: {}
extraAnnotations: {}
parallelRollout: true
minReadySeconds: 10
hostNetwork: true
hostPID: true
dnsPolicy: ClusterFirst
terminationGracePeriodSeconds: null
updateStrategy: {}
nodeSelector: {}
tolerations: []
topologySpreadConstraints: []
priorityClassName: ''
podAnnotations: {}
podLabels: {}
podDisruptionBudget:
enabled: false
minAvailable: null
maxUnavailable: null
enableStatefulSetAutoDeletePVC: false
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 5
targetCPUUtilizationPercentage: 0
targetMemoryUtilizationPercentage: 80
scaleDown:
policies: []
selectPolicy: Max
stabilizationWindowSeconds: 300
scaleUp:
policies: []
selectPolicy: Max
stabilizationWindowSeconds: 0
horizontal:
enabled: false
minReplicas: 1
maxReplicas: 5
targetCPUUtilizationPercentage: 0
targetMemoryUtilizationPercentage: 80
scaleDown:
policies: []
selectPolicy: Max
stabilizationWindowSeconds: 300
scaleUp:
policies: []
selectPolicy: Max
stabilizationWindowSeconds: 0
vertical:
enabled: false
recommenders: []
resourcePolicy:
containerPolicies:
- containerName: alloy
controlledResources:
- cpu
- memory
controlledValues: "RequestsAndLimits"
maxAllowed: {}
minAllowed: {}
updatePolicy:
affinity: {}
volumes:
extra:
- name: proc
hostPath:
path: /proc
volumeClaimTemplates: []
initContainers: []
extraContainers: []
networkPolicy:
enabled: false
flavor: kubernetes
policyTypes:
- Ingress
- Egress
ingress:
- {}
egress:
- {}
service:
enabled: true
type: ClusterIP
nodePort: 31128
clusterIP: ''
internalTrafficPolicy: Cluster
annotations: {}
serviceMonitor:
enabled: false
additionalLabels: {}
interval: ""
metricRelabelings: []
tlsConfig: {}
relabelings: []
ingress:
enabled: false
annotations:
{}
labels: {}
path: /
faroPort: 12347
pathType: Prefix
hosts:
- chart-example.local
extraPaths: []
tls: []
extraObjects: []
[root@master-1 alloy]#cat config/example.alloy
// =========================
// 全局日志
// =========================
logging {
level = "info"
}
// =========================
// Pyroscope 写入端
// =========================
pyroscope.write "default" {
endpoint {
url = "http://10.96.153.34:4040"
}
}
// =========================
// 1. Kubernetes 服务发现
// =========================
discovery.kubernetes "k8s_pods" {
role = "pod"
// 命名空间过滤
namespaces {
names = ["default"]
}
}
// =========================
// 2. 必须增加:过滤本机 Pod (防止重复采集)
// =========================
// 如果 Alloy 是以 DaemonSet 运行的,必须只处理本节点的 Pod
// 否则集群里 10 个 Alloy 会同时采集同一个 Pod 10 次
discovery.relabel "k8s_pods_local" {
targets = discovery.kubernetes.k8s_pods.targets
rule {
source_labels = ["__meta_kubernetes_pod_node_name"]
target_label = "__host__" // 仅作临时对比用
}
// 这里的 HOSTNAME 必须是 Alloy Pod 里的环境变量 (通常 DaemonSet 会注入 spec.nodeName)
// 如果你没有注入 HOSTNAME 环境变量,需要去 DaemonSet yaml 里加一下
// 1. 必须保留:过滤本机 Pod
rule {
source_labels = ["__meta_kubernetes_pod_node_name"]
regex = sys.env("HOSTNAME")
action = "keep"
}
// 2. 映射 Namespace (这样你就能在 Pyroscope 面板看到 namespace 标签了)
rule {
source_labels = ["__meta_kubernetes_namespace"]
target_label = "namespace"
}
// 3. 映射 Pod Name
rule {
source_labels = ["__meta_kubernetes_pod_name"]
target_label = "pod"
}
// 4. 映射 Container Name
rule {
source_labels = ["__meta_kubernetes_pod_container_name"]
target_label = "container"
}
rule {
source_labels = ["__meta_kubernetes_pod_label_app"]
target_label = "service_name"
}
}
// =========================
// 3. eBPF Profiling
// =========================
pyroscope.ebpf "kubernetes" {
forward_to = [pyroscope.write.default.receiver]
// 使用经过 relabel 过滤后的 targets (只包含本节点的 Pod)
targets = discovery.relabel.k8s_pods_local.output
sample_rate = 97
}
部署
[root@master-1 alloy]# helm upgrade alloy --namespace alloy .
查看数据
目前只能采集 CPU 信息






文章评论