Лучшие практики трассировки производительности для Linux
Это перевод оригинальной статьи Expert Guide to BPF Performance Monitoring in Linux
Перевод сделан специально для телеграм-канала Мониторим ИТ. Подписывайтесь! Там еще больше полезных постов о мониторинге.
Подробные примеры кода для превосходной трассировки
Для эффективного профилирования использования CPU на работающем сервере Linux, незаменимым инструментом является perf. Приведённый ниже пример собирает данные для flame graph в течение 30 секунд, фиксируя стеки вызовов с целью выявления "горячих точек" в приложении или ядре:
sudo perf record -F 99 -a -g -- sleep 30 sudo perf script > out.perf # To generate a flame graph, one would typically use Brendan Gregg's stackcollapse-perf.pl and flamegraph.pl scripts. # For example: # stackcollapse-perf.pl out.perf | flamegraph.pl > perf-flamegraph.svg
Для более глубокого анализа системных вызовов можно использовать strace или ltrace. При мониторинге критически важного сервиса понимание взаимодействия с системными вызовами даёт важный контекст. Ниже показано, как отследить системные вызовы, выполняемые процессом с определённым идентификатором (PID), и регистрировать их:
sudo strace -p <PID_OF_SERVICE> -o /var/log/service_strace.log -yy -f -T # -p specifies the PID # -o redirects output to a file # -yy prints path for FDs and sockets # -f traces child processes # -T shows time spent in system calls
Этот вывод помогает диагностировать взаимоблокировки, проблемы с правами доступа к файлам или непредвиденные сетевые взаимодействия.
В средах Kubernetes агенты на основе eBPF обеспечивают контроль производительности узлов и контейнеров, без вмешательств в код приложения. С помощью DaemonSet можно развернуть агент трассировки на базе eBPF на всех узлах кластера. Ниже представлен манифест для развертывания гипотетического контейнера с агентом eBPF:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ebpf-tracing-agent
namespace: kube-system
spec:
selector:
matchLabels:
app: ebpf-tracing-agent
template:
metadata:
labels:
app: ebpf-tracing-agent
spec:
hostPID: true
hostNetwork: true
containers:
- name: agent
image: your_registry/ebpf-tracing-agent:latest
securityContext:
privileged: true
volumeMounts:
- name: sys-kernel-debug
mountPath: /sys/kernel/debug
- name: lib-modules
mountPath: /lib/modules
- name: usr-src
mountPath: /usr/src
volumes:
- name: sys-kernel-debug
hostPath:
path: /sys/kernel/debug
- name: lib-modules
hostPath:
path: /lib/modules
- name: usr-src
hostPath:
path: /usr/srcТакой агент предоставляет метрики производительности на уровне узлов, включая сетевую задержку, частоту системных вызовов и загрузку процессора, что критически важно для диагностики проблем в распределённой системе и повышения наблюдаемости. Однако существуют риски, связанные с предоставлением привилегированного доступа, поэтому строгая защита образов и регулярное сканирование на уязвимости крайне важны.
Для контейнеризированных приложений Dockerfile позволяет интегрировать библиотеки трассировки или агенты непосредственно в образ. Это обеспечивает единообразную настройку трассировки во всех экземплярах. Здесь продемонстрировано добавление SDK OpenTelemetry в контейнер приложения Python:
# Use a slim base image for security and size optimization
FROM python:3.9-slim-buster
WORKDIR /app
# Install OpenTelemetry SDK
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt \
opentelemetry-sdk \
opentelemetry-exporter-otlp
COPY . .
# Set environment variables for OpenTelemetry collector endpoint
ENV OTEL_EXPORTER_OTLP_ENDPOINT="http://opentelemetry-collector:4317"
ENV OTEL_RESOURCE_ATTRIBUTES="service.name=my-app,environment=production"
CMD ["python", "app.py"]Этот Dockerfile создает неизменяемый компонент инфраструктуры, в который трассировка встроена с момента создания, поддерживая распределенную трассировку и упрощая интеграцию наблюдаемости для безопасности выполнения контейнера и проверки производительности.
Автоматизировать сбор и анализ данных о производительности на экземплярах AWS EC2 можно с помощью AWS CLI или SDK. В этом примере показана установка perf В этом примере показана установка perf и сбор короткой трассировки на экземпляре:
#!/bin/bash # Script to install perf and collect basic CPU profile on an EC2 instance sudo yum update -y # For Amazon Linux 2 # For Debian/Ubuntu based systems: sudo apt update && sudo apt install -y linux-tools-$(uname -r) sudo yum install -y perf echo "Collecting perf data for 10 seconds..." sudo perf record -F 99 -a -g -- sleep 10 echo "Generating perf report..." sudo perf report > /tmp/perf_report.txt # Optionally, upload the report to S3 for centralized analysis # aws s3 cp /tmp/perf_report.txt s3://your-perf-data-bucket/ec2-$(hostname)-$(date +%Y%m%d%H%M%S)_perf_report.txt
Этот сценарий обеспечивает автоматизированный сбор данных, что бесценно для реагирования на инциденты и непрерывного мониторинга производительности в автоматизированной инфраструктуре.
Python можно использовать для обработки данных perf или взаимодействия с инструментами BPF для пользовательского анализа. В этом примере показано, как с помощью pyroute2 взаимодействовать с eBPF-программами (требует предварительно загруженной eBPF-программы):
from pyroute2 import IPRoute
import socket
# This is a conceptual example for interacting with BPF programs.
# A real scenario would involve loading a BPF program (e.g., via bcc or libbpf)
# and then potentially using pyroute2 to attach/detach or query maps.
def interact_with_bpf_map(map_id, key):
with IPRoute() as ip:
# Example: Get a BPF map by ID
# map_info = ip.bpf_map_get(map_id=map_id)
# print(f"BPF Map Info: {map_info}")
# Example: Lookup a key in a BPF map
# This requires knowing the map's type and structure.
# For demonstration, let's assume a basic map interaction.
print(f"Attempting to interact with BPF map ID: {map_id}")
print(f"Looking up key: {key}")
# In a real scenario, you'd use specific library functions to
# query the map, e.g., via bcc.BPF().get_table("map_name")
# Example usage (replace with actual map ID and key)
# Assuming a map with ID 123 and a key 'some_value'
interact_with_bpf_map(123, b"some_value")Это взаимодействие с Python демонстрирует, как продвинутые инженеры могут программно запрашивать карты eBPF, собирая пользовательские метрики и осуществлять динамический контроль над агентами трассировки, легко интегрируясь в конвейеры наблюдения.
Наконец, с помощью Terraform можно управлять развертыванием компонентов инфраструктуры распределённой трассировки, таких как OpenTelemetry Collector в AWS. Это гарантирует применение принципов IaC к системам наблюдаемости:
resource "kubernetes_deployment" "otel_collector" {
metadata {
name = "otel-collector"
namespace = "observability"
}
spec {
replicas = 2
selector {
match_labels = {
app = "otel-collector"
}
}
template {
metadata {
labels = {
app = "otel-collector"
}
}
spec {
container {
name = "collector"
image = "otel/opentelemetry-collector-contrib:latest"
args = [ "--config=/etc/otel-collector-config.yaml" ]
port {
container_port = 4317 # OTLP gRPC
name = "otlp-grpc"
}
port {
container_port = 4318 # OTLP HTTP
name = "otlp-http"
}
volume_mount {
name = "otel-config"
mount_path = "/etc/otel-collector-config.yaml"
sub_path = "otel-collector-config.yaml"
}
}
volume {
name = "otel-config"
config_map {
name = "otel-collector-config"
}
}
}
}
}
}
resource "kubernetes_config_map" "otel_collector_config" {
metadata {
name = "otel-collector-config"
namespace = "observability"
}
data = {
"otel-collector-config.yaml" = <<-EOT
receivers:
otlp:
protocols:
grpc:
http:
exporters:
logging:
loglevel: debug
# Add your preferred exporter (e.g., Jaeger, Prometheus, AWS CloudWatch)
processors:
batch:
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [logging]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [logging]
logs:
receivers: [otlp]
processors: [batch]
exporters: [logging]
EOT
}
}Такая конфигурация Terraform гарантирует, что сборщик OpenTelemetry, являющийся важной частью любой распределенной системы трассировки, будет последовательно развернут и настроен в Kubernetes, следуя принципам «инфраструктура как код» и обеспечивая бесперебойный прием данных из различных источников трассировки.
Этот Bash-скрипт демонстрирует автоматизированный сбор данных perf для определенных процессов в часы пик с загрузкой результатов в контейнер S3. Этот шаблон упрощает проактивный мониторинг и анализ аварийных ситуаций для обеспечения надежности распределенной системы.
#!/bin/bash
# Automated perf collection script for critical services
SERVICE_NAME="my_critical_service_process" # Replace with actual process name or pattern
S3_BUCKET="s3://your-enterprise-perf-bucket"
HOSTNAME=$(hostname -s)
TIMESTAMP=$(date +%Y%m%d%H%M%S)
OUTPUT_DIR="/tmp/perf_data"
REPORT_FILE="${OUTPUT_DIR}/${HOSTNAME}_${SERVICE_NAME}_${TIMESTAMP}_perf_report.txt"
PERF_DATA_FILE="${OUTPUT_DIR}/${HOSTNAME}_${SERVICE_NAME}_${TIMESTAMP}_perf.data"
mkdir -p "$OUTPUT_DIR"
# Find PIDs of the critical service
PIDS=$(pgrep -d ',' -f "$SERVICE_NAME")
if [ -z "$PIDS" ]; then
echo "No processes found for service: $SERVICE_NAME"
exit 1
fi
echo "Collecting perf data for PIDs: $PIDS for 60 seconds..."
sudo perf record -F 99 -p "$PIDS" -g --output "$PERF_DATA_FILE" -- sleep 60
echo "Generating perf report..."
sudo perf report -i "$PERF_DATA_FILE" > "$REPORT_FILE"
echo "Uploading perf report to S3..."
aws s3 cp "$REPORT_FILE" "$S3_BUCKET/" --region us-east-1
echo "Cleaning up local files..."
rm -rf "$OUTPUT_DIR"
echo "Perf data collection and upload complete."С помощью Python можно реализовать парсинг собранных логов или метрик и передачи их в централизованную систему отчётности. Этот фрагмент кода демонстрирует взаимодействие с клиентом Prometheus:
from prometheus_client import Gauge, start_http_server
import random
import time
# Metrics for tracing compliance
tracing_agent_status = Gauge('tracing_agent_status', 'Status of tracing agent (0=down, 1=up)', ['hostname', 'service'])
tracing_data_ingestion_rate = Gauge('tracing_data_ingestion_rate', 'Rate of tracing data ingestion (spans/sec)', ['hostname', 'service'])
def update_compliance_metrics():
# In a real scenario, this would query an actual tracing system or parse logs
# For demonstration, we'll simulate data.
host = "web-server-01"
svc = "frontend-api"
# Simulate agent status (e.g., check process or endpoint)
status = random.choice([0, 1])
tracing_agent_status.labels(hostname=host, service=svc).set(status)
# Simulate ingestion rate
ingestion_rate = random.uniform(50.0, 500.0)
tracing_data_ingestion_rate.labels(hostname=host, service=svc).set(ingestion_rate)
print(f"Updated metrics for {host}/{svc}: Agent Status={status}, Ingestion Rate={ingestion_rate}")
if __name__ == '__main__':
start_http_server(8000)
print("Prometheus metrics server started on port 8000")
while True:
update_compliance_metrics()
time.sleep(30) # Update every 30 secondsВ этом примере Python показано, как предоставить показатели производительности с помощью Prometheus, поддерживая мониторинг, ориентированный на наблюдаемость.
Для обеспечения безопасного выполнения контейнера Dockerfile можно задать более строгие привилегии пользователя для агентов трассировки, придерживаясь принципа наименьших привилегий, что особенно важно в среде нулевого доверия.
FROM ubuntu:22.04
RUN apt update && apt install -y \
procps \
iproute2 \
strace \
# Install minimal tools required for tracing, avoid full perf/bcc for small agents unless needed
# libcap-ng-utils # For capsh if needed to drop capabilities at runtime
&& rm -rf /var/lib/apt/lists/*
# Create a non-root user for the agent
RUN useradd -ms /bin/bash tracinguser
# Copy agent binaries/scripts
COPY tracing_agent.sh /opt/tracing_agent.sh
RUN chown tracinguser:tracinguser /opt/tracing_agent.sh
RUN chmod +x /opt/tracing_agent.sh
# Switch to the non-root user
USER tracinguser
# Define entrypoint or command to run the agent
ENTRYPOINT ["/opt/tracing_agent.sh"]В этом Dockerfile особое внимание уделяется безопасности выполнения контейнера за счет запуска агента трассировки от имени пользователя, не являющегося пользователем root, что является фундаментальной практикой для снижения рисков безопасности, связанных с привилегированными контейнерами.
Подписывайтесь на телеграм-канал Мониторим ИТ, там еще больше полезной информации о мониторинге!