Cuando se utiliza OpenTelemetry eBPF Instrumentation (OBI) para enviar datos de trazas a Application Real-Time Monitoring Service (ARMS) de forma no intrusiva, ARMS comienza a monitorear las aplicaciones. Desde ahí es posible consultar la topología de la aplicación, las trazas de llamadas, las transacciones anómalas, las transacciones lentas, el análisis de SQL y otros datos de monitoreo. En este tema se describe cómo usar OBI para monitorear aplicaciones y reportar datos.
Requisitos previos
Si encuentra algún problema al usar OpenTelemetry eBPF, contáctenos mediante el grupo de preguntas y respuestas de DingTalk (número de grupo: 159215000379).
-
Prepare un servidor Linux (una instancia de Elastic Compute Service (ECS) o un entorno local) que cumpla con los siguientes requisitos.
Requisito
Rango compatible
Versión del kernel
Linux 5.8 o posterior. Las distribuciones basadas en RHEL (con parches backport de eBPF) admiten como mínimo Linux 4.18.
BTF
El kernel debe exponer la información de BTF (BPF Type Format).
Arquitectura de CPU
amd64 (x86_64), arm64 (aarch64).
Permisos
Permisos de root.
NotaAlibaba Cloud Linux 3 y Alibaba Cloud Linux 4 cumplen de forma predeterminada con los requisitos anteriores.
Para comprobar si su servidor cumple con los requisitos, ejecute los siguientes comandos:
# Check the kernel version (must be >= 5.8, or >= 4.18 for RHEL-based distributions) uname -r # Check the CPU architecture (must be amd64 or arm64) uname -m # Check whether BTF is available (the file exists if supported) ls /sys/kernel/btf/vmlinux # Check whether you have root permissions whoami
Contexto
OBI es un componente de instrumentación automática basado en eBPF diseñado para la observability en Kubernetes. Se despliega como un DaemonSet en los nodos del clúster y recopila automáticamente datos de métricas y trazas de las aplicaciones, sin necesidad de modificar el código ni de inyectar sidecars. OBI detecta de forma automática protocolos principales como HTTP, gRPC, SQL, Redis y Kafka, entre otros. Además, extrae de manera profunda los cuerpos de solicitud y respuesta para escenarios de GenAI (OpenAI, Anthropic, Qwen, MCP, Embedding, Rerank y más). Los datos de telemetría recopilados se exportan mediante el protocolo OTLP y se integran sin problemas con plataformas de observability como ARMS. Esto le permite lograr una observability de pila completa, sin intrusiones y con baja sobrecarga.
Métodos de coincidencia para el descubrimiento de aplicaciones
OBI descubre y asocia los procesos que va a monitorear mediante la sección de configuración discovery.instrument. A continuación se muestran los métodos de coincidencia compatibles. Todas las condiciones utilizan lógica AND, por lo que deben cumplirse en su totalidad para que exista una coincidencia:
|
Campo YAML |
Tipo |
Descripción |
Ejemplo |
|
open_ports |
Número o rango de puertos |
Números de puerto en los que escucha el proceso. Admite valores separados por comas y rangos. |
8080, 80,443, 8000-8999 |
|
exe_path |
Patrón Glob |
Coincide con la ruta completa del archivo ejecutable del proceso. |
/java, /nginx, myapp |
|
cmd_args |
Patrón Glob |
Coincide con los argumentos de línea de comandos del proceso (sin incluir el nombre del archivo ejecutable). |
petclinic, --config=prod |
|
languages |
Patrón Glob |
Coincide automáticamente según el lenguaje de programación (go/java/python/ruby/nodejs/rust/dotnet/php/cpp). |
java, {go,rust} |
|
target_pids |
Lista de PID |
Especifica directamente los PID de los procesos. |
[12345, 67890] |
|
container_name |
Patrón Glob |
Coincide con los nombres de contenedores OCI (aplicable a despliegues de Docker). |
my-container-* |
|
containers_only |
Booleano |
Coincide únicamente con los procesos que se ejecutan dentro de contenedores. |
true |
|
name |
Cadena |
Nombre de la aplicación que se muestra en la consola de ARMS. |
my-app |
|
namespace |
Cadena |
Espacio de nombres del servicio. |
production |
|
exports |
Lista de señales |
Controla los tipos de señales exportadas (metrics/traces/logs). Una matriz vacía deshabilita todas las exportaciones. |
[metrics, traces] |
|
sampler |
Configuración de muestreo |
Muestrea las trazas por proporción para reducir el volumen de datos. |
name: traceidratio, arg: "0.5" |
Ejemplos de configuración para escenarios comunes
Escenario 1: coincidencia por número de puerto. Este método es el más sencillo y funciona con cualquier tipo de aplicación web.
discovery:
instrument:
- name: my-web-app
open_ports: 8080
Escenario 2: aplicación Java (exe_path + cmd_args). Localiza el proceso mediante el ejecutable de Java y el nombre del archivo JAR.
discovery:
instrument:
- name: my-java-app
exe_path: "*/java"
cmd_args: "*petclinic*"
Escenario 3: descubrimiento automático por lenguaje de programación. Detecta de forma automática todos los procesos del lenguaje especificado.
discovery:
instrument:
- name: go-services
languages: go
- name: python-services
languages: "{python,nodejs}"
Escenario 4: coincidencia por ruta del archivo ejecutable. Recomendado cuando se trabaja con archivos binarios compilados manualmente.
discovery:
instrument:
- name: my-binary
exe_path: "*/my-server"
Escenario 5: coincidencia por nombre de contenedor de Docker. Diseñado para despliegues de Docker en ECS.
discovery:
instrument:
- name: my-container-app
container_name: "my-container-*"
Escenario 6: varios rangos de puertos. Monitorea los servicios que operan dentro de un rango de puertos determinado.
discovery:
instrument:
- name: microservices
open_ports: 8080-8090,9090
Escenario 7: especificar PID para depuración temporal. Indica directamente los PID de los procesos que desea monitorear.
discovery:
instrument:
- name: debug-target
target_pids: [12345]
Escenario 8: solo procesos de contenedor con muestreo. Monitorea exclusivamente los procesos de contenedor y aplica un muestreo de trazas del 50 %.
discovery:
instrument:
- name: container-apps
containers_only: true
open_ports: 8080
sampler:
name: traceidratio
arg: "0.5"
Escenario 9: varias aplicaciones con reglas de exclusión. Monitorea múltiples aplicaciones y excluye procesos específicos.
discovery:
instrument:
- name: api-gateway
open_ports: 80,443
- name: backend-java
exe_path: "*/java"
cmd_args: "*backend*"
- name: worker
exe_path: "*/python*"
cmd_args: "*celery*"
exclude_instrument:
- exe_path: "{obi,prometheus,otelcol*}"
Escenario 10: control de señales exportadas. Exporta únicamente métricas, sin incluir trazas.
discovery:
instrument:
- name: high-qps-app
open_ports: 8080
exports: [metrics]
Procedimiento
Descripción general del procedimiento: instalar y desplegar (obtener la información del endpoint > descargar OBI > redactar el archivo de configuración > desplegar el servicio) > comprobar los datos de monitoreo.
Instalar y desplegar
Existen dos métodos de despliegue: el despliegue con script de un solo clic (recomendado) y el despliegue manual paso a paso.
Método 1: despliegue con script de un solo clic (recomendado)
Todos los pasos se agrupan en un único script obi-setup.sh que admite modos interactivo y no interactivo.
#!/bin/bash
# ============================================================================
# OBI (OpenTelemetry eBPF Instrumentation) one-click deployment script
# Combines the complete flow of environment check, download, configuration generation, and service installation
#
# Usage:
# sudo bash obi-setup.sh install — Interactive installation (binary + systemd)
# sudo bash obi-setup.sh docker — Deploy with Docker
# sudo bash obi-setup.sh check — Perform environment check only
# sudo bash obi-setup.sh uninstall — Uninstall the OBI service
# sudo bash obi-setup.sh status — View the running status and logs
#
# Non-interactive deployment (using environment variables):
# export OTLP_ENDPOINT="http://xxx:4318"
# export OTLP_HEADERS="Authentication=xxx"
# export APP_NAME="my-app"
# export APP_MATCH_TYPE="port" # port|cmd|exe|lang|container|pid
# export APP_MATCH_VALUE="8080"
# sudo -E bash obi-setup.sh install
# ============================================================================
set -euo pipefail
# ========================= Global Variables =========================
VERSION="0.10.0"
SERVICE_NAME="obi"
INSTALL_DIR="/opt/obi"
CONFIG_FILE="${INSTALL_DIR}/config.yaml"
OBI_BINARY="${INSTALL_DIR}/obi"
DOCKER_IMAGE="registry.cn-hangzhou.aliyuncs.com/private-mesh/obi:${VERSION}"
OSS_BASE="https://arms-apm-cn-hangzhou-pre.oss-cn-hangzhou.aliyuncs.com/obi-agent/${VERSION}"
# Colors
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
# Application list (array)
declare -a APP_ENTRIES=()
# Exclusion pattern
EXCLUDE_PATTERN=""
# ========================= Utility Functions =========================
info() { echo -e "${CYAN}[INFO]${NC} $*"; }
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
fail() { echo -e "${RED}[FAIL]${NC} $*"; }
die() { fail "$*"; exit 1; }
prompt_input() {
local var_name="$1" prompt_msg="$2" default_val="${3:-}"
local current_val="${!var_name:-}"
if [[ -n "$current_val" ]]; then
info "Using environment variable ${var_name}=${current_val}"
return
fi
if [[ -n "$default_val" ]]; then
read -rp "$(echo -e "${BOLD}${prompt_msg} [${default_val}]: ${NC}")" input
eval "$var_name=\"${input:-$default_val}\""
else
while true; do
read -rp "$(echo -e "${BOLD}${prompt_msg}: ${NC}")" input
if [[ -n "$input" ]]; then
eval "$var_name=\"$input\""
return
fi
warn "This field is required"
done
fi
}
prompt_yesno() {
local prompt_msg="$1" default="${2:-n}"
local yn
read -rp "$(echo -e "${BOLD}${prompt_msg} [y/N]: ${NC}")" yn
case "${yn:-$default}" in
[Yy]*) return 0 ;;
*) return 1 ;;
esac
}
# ========================= Environment Check =========================
check_root() {
if [[ "$EUID" -ne 0 ]]; then
die "Please run with root permissions: sudo bash $0 $*"
fi
ok "Root permissions"
}
check_env() {
echo ""
echo -e "${BOLD}========== Environment Check ==========${NC}"
local kernel_ver major minor
kernel_ver=$(uname -r)
major=$(echo "$kernel_ver" | cut -d. -f1)
minor=$(echo "$kernel_ver" | cut -d. -f2)
local is_rhel=false
if [[ -f /etc/redhat-release ]] || grep -qi 'rhel\|centos\|rocky\|alma\|anolis\|alinux' /etc/os-release 2>/dev/null; then
is_rhel=true
fi
if [[ "$major" -gt 5 ]] || { [[ "$major" -eq 5 ]] && [[ "$minor" -ge 8 ]]; }; then
ok "Kernel version: ${kernel_ver} (>= 5.8)"
elif $is_rhel && { [[ "$major" -gt 4 ]] || { [[ "$major" -eq 4 ]] && [[ "$minor" -ge 18 ]]; }; }; then
ok "Kernel version: ${kernel_ver} (RHEL-based, >= 4.18)"
else
fail "Kernel version: ${kernel_ver} (Minimum requirement: 5.8, or 4.18 for RHEL-based systems)"
return 1
fi
local arch
arch=$(uname -m)
case "$arch" in
x86_64|amd64) ok "CPU architecture: ${arch} (amd64)" ;;
aarch64|arm64) ok "CPU architecture: ${arch} (arm64)" ;;
*) fail "CPU architecture: ${arch} (unsupported)"; return 1 ;;
esac
if [[ -f /sys/kernel/btf/vmlinux ]]; then
ok "BTF: Available"
else
fail "BTF: /sys/kernel/btf/vmlinux does not exist"
return 1
fi
echo -e "${GREEN}========== Environment Check Passed ==========${NC}"
echo ""
return 0
}
detect_arch() {
local arch
arch=$(uname -m)
case "$arch" in
x86_64|amd64) echo "amd64" ;;
aarch64|arm64) echo "arm64" ;;
*) die "Unsupported CPU architecture: ${arch}" ;;
esac
}
# ========================= Collect Single Application Configuration =========================
collect_one_app() {
local app_name match_type
local entry=""
prompt_input app_name "Application name (display name in the Cloud Monitor 2.0 console)" "my-app"
echo ""
echo -e " ${BOLD}Select application matching method:${NC}"
echo -e " 1) Match by port number — open_ports, such as 8080, 80,443, or 8000-8999"
echo -e " 2) Match by command line — exe_path + cmd_args, suitable for scenarios like java -jar"
echo -e " 3) Match by executable file path — exe_path, suitable for self-compiled binaries"
echo -e " 4) Auto-discover by programming language — languages, auto-detects go, java, python, nodejs, etc."
echo -e " 5) Match by Docker container name — container_name, suitable for running Docker on ECS"
echo -e " 6) Specify by PID — target_pids, for temporary debugging"
read -rp "$(echo -e "${BOLD}Select [1-6, default 1]: ${NC}")" match_choice
entry=" - name: ${app_name}"
case "${match_choice:-1}" in
1)
local ports
prompt_input ports "Listening port number (e.g., 8080, 80,443, 8000-8999)" "8080"
entry="${entry}
open_ports: ${ports}"
;;
2)
local exe_path cmd_args
prompt_input exe_path "Executable file path Glob (e.g., */java)" "*/java"
prompt_input cmd_args "Command line argument Glob (e.g., *petclinic*)"
entry="${entry}
exe_path: \"${exe_path}\"
cmd_args: \"${cmd_args}\""
;;
3)
local exe_path
prompt_input exe_path "Executable file path Glob (e.g., */my-server, */nginx)"
entry="${entry}
exe_path: \"${exe_path}\""
;;
4)
local lang
echo -e " Supported languages: go, java, python, ruby, nodejs, rust, dotnet, php, cpp"
echo -e " For multiple languages, use braces: {go,rust} or {python,nodejs}"
prompt_input lang "Programming language" "java"
entry="${entry}
languages: \"${lang}\""
;;
5)
local cname
prompt_input cname "Docker container name Glob (e.g., my-container-*)"
entry="${entry}
container_name: \"${cname}\""
;;
6)
local pids
prompt_input pids "PID list, comma-separated (e.g., 12345,67890)"
local pid_array
pid_array=$(echo "$pids" | tr ',' '\n' | sed 's/^[[:space:]]*//' | awk '{printf " - %s\n", $0}')
entry="${entry}
target_pids:
${pid_array}"
;;
*)
local ports
prompt_input ports "Listening port number" "8080"
entry="${entry}
open_ports: ${ports}"
;;
esac
# Optional: Container processes only
if [[ "${match_choice:-1}" != "5" ]]; then
if prompt_yesno "Match only processes inside containers (containers_only)?"; then
entry="${entry}
containers_only: true"
fi
fi
# Optional: Sampling
if prompt_yesno "Configure Traces sampling (to reduce data volume)?"; then
echo -e " Samplers: always_on, always_off, traceidratio, parentbased_traceidratio"
local sampler_name sampler_arg
prompt_input sampler_name "Sampler name" "traceidratio"
prompt_input sampler_arg "Sampler argument (e.g., 0.5 for 50% sampling)" "1.0"
entry="${entry}
sampler:
name: ${sampler_name}
arg: \"${sampler_arg}\""
fi
APP_ENTRIES+=("$entry")
ok "Added application: ${app_name}"
}
# ========================= Collect Full Configuration =========================
collect_config() {
echo -e "${BOLD}========== Configuration Information ==========${NC}"
echo ""
info "Please obtain the following information from the Cloud Monitor Integration Center:"
info " Cloud Monitor 2.0 console -> Integration Center -> OpenTelemetry card -> Click to get LicenseKey"
echo ""
prompt_input OTLP_ENDPOINT "OTEL_EXPORTER_OTLP_ENDPOINT (e.g., http://xxx:4318)"
prompt_input OTLP_HEADERS "OTEL_EXPORTER_OTLP_HEADERS (e.g., Authentication=xxx)"
echo ""
echo -e "${BOLD}========== Application Configuration ==========${NC}"
# Non-interactive mode: Build a single app from environment variables
if [[ -n "${APP_MATCH_TYPE:-}" ]]; then
local entry=" - name: ${APP_NAME:-my-app}"
case "$APP_MATCH_TYPE" in
port)
entry="${entry}
open_ports: ${APP_MATCH_VALUE:-8080}" ;;
cmd)
entry="${entry}
exe_path: \"${APP_EXE_PATH:-*/java}\"
cmd_args: \"${APP_CMD_ARGS}\"" ;;
exe)
entry="${entry}
exe_path: \"${APP_MATCH_VALUE}\"" ;;
lang)
entry="${entry}
languages: \"${APP_MATCH_VALUE}\"" ;;
container)
entry="${entry}
container_name: \"${APP_MATCH_VALUE}\"" ;;
pid)
local pid_array
pid_array=$(echo "${APP_MATCH_VALUE}" | tr ',' '\n' | sed 's/^[[:space:]]*//' | awk '{printf " - %s\n", $0}')
entry="${entry}
target_pids:
${pid_array}" ;;
*)
die "Unknown APP_MATCH_TYPE: ${APP_MATCH_TYPE} (Supported: port|cmd|exe|lang|container|pid)" ;;
esac
APP_ENTRIES+=("$entry")
ok "Added application: ${APP_NAME:-my-app} (${APP_MATCH_TYPE})"
return
fi
# Interactive mode: Loop to add applications
while true; do
echo ""
collect_one_app
echo ""
if ! prompt_yesno "Add another application?"; then
break
fi
done
# Optional: Exclusion rules
echo ""
if prompt_yesno "Configure exclusion rules (exclude_instrument)?"; then
echo -e " Enter the executable file path Glob to exclude"
echo -e " Example: {obi,prometheus,otelcol*,node_exporter}"
local exclude_val
prompt_input exclude_val "Exclusion path Glob"
EXCLUDE_PATTERN="$exclude_val"
ok "Added exclusion rule: ${exclude_val}"
fi
}
# ========================= Generate Configuration File =========================
generate_config() {
local endpoint_metrics="${OTLP_ENDPOINT}/v1/metrics"
# Concatenate the instrument section
local instrument_yaml=""
for entry in "${APP_ENTRIES[@]}"; do
instrument_yaml="${instrument_yaml}
${entry}"
done
# Concatenate the exclude section
local exclude_yaml=""
if [[ -n "$EXCLUDE_PATTERN" ]]; then
exclude_yaml="
exclude_instrument:
- exe_path: \"${EXCLUDE_PATTERN}\""
fi
cat > "${CONFIG_FILE}" <<YAML
log_level: WARN
otel_metrics_export:
endpoint: ${endpoint_metrics}
metrics:
features:
- application
- network
- stats_tcp_rtt
routes:
unmatched: low-cardinality
max_path_segment_cardinality: 500
ebpf:
context_propagation: all
track_request_headers: true
payload_extraction:
http:
genai:
openai:
enabled: true
anthropic:
enabled: true
jsonrpc:
enabled: true
mcp:
enabled: true
qwen:
enabled: true
rerank:
enabled: true
embedding:
enabled: true
gemini:
enabled: true
buffer_sizes:
http: 262144
otel_traces_export:
endpoint: ${OTLP_ENDPOINT}
batch_timeout: 10s
batch_max_size: 512
queue_size: 4096
backoff_initial_interval: 5s
backoff_max_interval: 15s
backoff_max_elapsed_time: 2m
instrumentations:
- http
- grpc
- sql
- redis
- kafka
- mqtt
- mongo
- couchbase
- memcached
- genai
nodejs:
enabled: true
discovery:
min_process_age: 30s
instrument:${instrument_yaml}${exclude_yaml}
YAML
ok "Configuration file generated: ${CONFIG_FILE}"
}
# ========================= Download OBI =========================
download_obi() {
local arch
arch=$(detect_arch)
local url="${OSS_BASE}/obi-linux-${arch}"
info "Downloading OBI v${VERSION} (${arch})..."
mkdir -p "${INSTALL_DIR}"
if command -v wget &>/dev/null; then
wget -q --show-progress "${url}" -O "${OBI_BINARY}"
elif command -v curl &>/dev/null; then
curl -fL --progress-bar "${url}" -o "${OBI_BINARY}"
else
die "Neither wget nor curl is available"
fi
chmod +x "${OBI_BINARY}"
ok "OBI downloaded to ${OBI_BINARY}"
}
# ========================= Systemd Service =========================
install_systemd() {
info "Creating systemd service..."
cat > "/etc/systemd/system/${SERVICE_NAME}.service" <<EOF
[Unit]
Description=OBI eBPF Instrumentation Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=${INSTALL_DIR}
Environment="OTEL_EBPF_CONFIG_PATH=${CONFIG_FILE}"
Environment="OTEL_EXPORTER_OTLP_HEADERS=${OTLP_HEADERS}"
ExecStart=${OBI_BINARY}
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=${SERVICE_NAME}
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "${SERVICE_NAME}" --quiet
ok "Systemd service created and enabled on boot"
}
start_service() {
info "Starting OBI service..."
systemctl start "${SERVICE_NAME}"
sleep 2
if systemctl is-active --quiet "${SERVICE_NAME}"; then
ok "OBI service started successfully!"
else
fail "Failed to start OBI service. The error log is as follows:"
journalctl -u "${SERVICE_NAME}" -n 30 --no-pager
exit 1
fi
}
# ========================= Docker Deployment =========================
deploy_docker() {
if ! command -v docker &>/dev/null; then
die "Docker is not installed"
fi
collect_config
mkdir -p "${INSTALL_DIR}"
generate_config
info "Pulling Docker image: ${DOCKER_IMAGE}"
docker pull "${DOCKER_IMAGE}"
if docker ps -a --format '{{.Names}}' | grep -q "^${SERVICE_NAME}$"; then
warn "Removing existing container..."
docker rm -f "${SERVICE_NAME}" >/dev/null 2>&1
fi
info "Starting OBI container..."
docker run -d \
--name "${SERVICE_NAME}" \
--pid=host \
--privileged \
--restart=always \
-v "${CONFIG_FILE}:/config/config.yaml:ro" \
-e "OTEL_EXPORTER_OTLP_HEADERS=${OTLP_HEADERS}" \
-e "OTEL_EXPORTER_OTLP_ENDPOINT=${OTLP_ENDPOINT}" \
"${DOCKER_IMAGE}" \
--config=/config/config.yaml
sleep 2
if docker ps --format '{{.Names}}' | grep -q "^${SERVICE_NAME}$"; then
ok "OBI container started successfully!"
else
fail "Failed to start container:"
docker logs "${SERVICE_NAME}" --tail 30
exit 1
fi
echo ""
echo -e "${BOLD}Docker Management Commands:${NC}"
echo " View logs: docker logs -f ${SERVICE_NAME}"
echo " Stop container: docker stop ${SERVICE_NAME}"
echo " Remove container: docker rm -f ${SERVICE_NAME}"
echo ""
}
# ========================= Uninstall =========================
uninstall() {
echo -e "${BOLD}========== Uninstall OBI ==========${NC}"
if systemctl is-active --quiet "${SERVICE_NAME}" 2>/dev/null; then
systemctl stop "${SERVICE_NAME}"
fi
if [[ -f "/etc/systemd/system/${SERVICE_NAME}.service" ]]; then
systemctl disable "${SERVICE_NAME}" --quiet 2>/dev/null || true
rm -f "/etc/systemd/system/${SERVICE_NAME}.service"
systemctl daemon-reload
ok "Systemd service removed"
fi
if command -v docker &>/dev/null && docker ps -a --format '{{.Names}}' | grep -q "^${SERVICE_NAME}$"; then
docker rm -f "${SERVICE_NAME}" >/dev/null 2>&1
ok "Docker container removed"
fi
if [[ -d "${INSTALL_DIR}" ]]; then
rm -rf "${INSTALL_DIR}"
ok "Installation directory cleaned up"
fi
ok "OBI has been completely uninstalled"
}
# ========================= Show Status =========================
show_status() {
echo -e "${BOLD}========== OBI Running Status ==========${NC}"
if [[ -f "/etc/systemd/system/${SERVICE_NAME}.service" ]]; then
echo -e "\n${CYAN}[Systemd Service]${NC}"
systemctl status "${SERVICE_NAME}" --no-pager 2>/dev/null || true
echo -e "\n${CYAN}[Recent Logs]${NC}"
journalctl -u "${SERVICE_NAME}" -n 20 --no-pager 2>/dev/null || true
fi
if command -v docker &>/dev/null && docker ps -a --format '{{.Names}}' | grep -q "^${SERVICE_NAME}$"; then
echo -e "\n${CYAN}[Docker Container]${NC}"
docker ps -f "name=${SERVICE_NAME}"
echo -e "\n${CYAN}[Recent Logs]${NC}"
docker logs "${SERVICE_NAME}" --tail 20 2>&1 || true
fi
if [[ -f "${CONFIG_FILE}" ]]; then
echo -e "\n${CYAN}[Configuration File: ${CONFIG_FILE}]${NC}"
cat "${CONFIG_FILE}"
fi
}
# ========================= Binary Installation Main Flow =========================
install_binary() {
check_env || die "Environment check failed"
collect_config
download_obi
generate_config
install_systemd
start_service
echo ""
echo -e "${GREEN}============================================${NC}"
echo -e "${GREEN} OBI deployment complete!${NC}"
echo -e "${GREEN}============================================${NC}"
echo ""
echo -e "${BOLD}Installation directory:${NC} ${INSTALL_DIR}"
echo -e "${BOLD}Configuration file:${NC} ${CONFIG_FILE}"
echo ""
echo -e "Common commands:"
echo " View status: sudo systemctl status ${SERVICE_NAME}"
echo " View logs: sudo journalctl -u ${SERVICE_NAME} -f"
echo " Restart service: sudo systemctl restart ${SERVICE_NAME}"
echo " Uninstall: sudo bash $0 uninstall"
echo ""
}
# ========================= Entry Point =========================
print_usage() {
echo ""
echo -e "${BOLD}OBI One-Click Deployment Script v${VERSION}${NC}"
echo ""
echo "Usage: sudo bash $0 <command>"
echo ""
echo "Commands:"
echo " install Install as a binary (managed by systemd)"
echo " docker Deploy with Docker"
echo " check Perform environment check only"
echo " status View running status and logs"
echo " uninstall Uninstall OBI"
echo ""
echo "Application matching methods (APP_MATCH_TYPE):"
echo " port Match by port number (open_ports)"
echo " cmd Match by command line (exe_path + cmd_args)"
echo " exe Match by executable file path (exe_path)"
echo " lang Auto-discover by programming language (languages)"
echo " container Match by Docker container name (container_name)"
echo " pid Specify by PID (target_pids)"
echo ""
}
main() {
local action="${1:-}"
case "$action" in
install) check_root "$@"; install_binary ;;
docker) check_root "$@"; check_env || die "Environment check failed"; deploy_docker ;;
check) check_root "$@"; check_env ;;
uninstall) check_root "$@"; uninstall ;;
status) check_root "$@"; show_status ;;
*) print_usage; exit 1 ;;
esac
}
main "$@"
Paso 1: obtener la información del endpoint
Inicie sesión en la consola de ARMS. En el panel de navegación izquierdo, haga clic en Integration Center. En la sección de aplicaciones del lado del servidor, haga clic en la tarjeta OpenTelemetry y obtenga los dos valores siguientes:
OTEL_EXPORTER_OTLP_ENDPOINT(por ejemplo,http://xxx:4318)OTEL_EXPORTER_OTLP_HEADERS(por ejemplo,Authentication=xxx)
Paso 2: descargar y preparar el script
chmod +x obi-setup.sh
Paso 3: instalación interactiva (archivo binario + systemd)
sudo bash obi-setup.sh install
El script ejecuta de forma secuencial los siguientes pasos: comprobación del entorno > recopilación del endpoint y los encabezados > selección del método de coincidencia de la aplicación (admite 6 escenarios) > incorporación de varias aplicaciones > configuración opcional de reglas de exclusión, muestreo y control de exportación > detección automática de la arquitectura de CPU y descarga de OBI > generación del archivo config.yaml > creación e inicio de un servicio de systemd.
Paso 4: despliegue con Docker
sudo bash obi-setup.sh docker
Paso 5: despliegue no interactivo (escenarios por lotes)
Pase los parámetros mediante variables de entorno para omitir las solicitudes interactivas. Se admiten los siguientes tipos de coincidencia:
# Match by port
export OTLP_ENDPOINT="http://xxx:4318"
export OTLP_HEADERS="Authentication=xxx"
export APP_NAME="my-app"
export APP_MATCH_TYPE="port"
export APP_MATCH_VALUE="8080"
sudo -E bash obi-setup.sh install
# Java application (exe_path + cmd_args)
export APP_MATCH_TYPE="cmd"
export APP_EXE_PATH="*/java"
export APP_CMD_ARGS="*petclinic*"
# Match by programming language
export APP_MATCH_TYPE="lang"
export APP_MATCH_VALUE="java"
# Match by executable file path
export APP_MATCH_TYPE="exe"
export APP_MATCH_VALUE="*/my-server"
# Match by Docker container name
export APP_MATCH_TYPE="container"
export APP_MATCH_VALUE="my-container-*"
# Match by PID
export APP_MATCH_TYPE="pid"
export APP_MATCH_VALUE="12345,67890"
Paso 6: otros comandos
sudo bash obi-setup.sh check # Run environment checks only
sudo bash obi-setup.sh status # View running status and logs
sudo bash obi-setup.sh uninstall # Uninstall OBI
Método 2: despliegue manual paso a paso
Si necesita un control más detallado de cada paso, siga estas instrucciones manuales.
Paso 1: obtener la información del endpoint
Siga el mismo proceso que en el método anterior. Obtenga OTEL_EXPORTER_OTLP_ENDPOINT y OTEL_EXPORTER_OTLP_HEADERS desde la consola de ARMS.
Paso 2: descargar OBI
# amd64 architecture
wget https://arms-apm-cn-hangzhou-pre.oss-cn-hangzhou.aliyuncs.com/obi-agent/0.10.0/obi-linux-amd64 -O obi
# arm64 architecture
wget https://arms-apm-cn-hangzhou-pre.oss-cn-hangzhou.aliyuncs.com/obi-agent/0.10.0/obi-linux-arm64 -O obi
chmod +x obi
Paso 3: redactar el archivo de configuración
Cree un archivo config.yaml. Reemplace <OTLP_ENDPOINT> con el valor real y modifique la sección discovery.instrument según su aplicación. Consulte la sección "Métodos de coincidencia para el descubrimiento de aplicaciones" de este documento para ver las configuraciones adecuadas:
log_level: WARN
otel_metrics_export:
endpoint: <OTLP_ENDPOINT>/v1/metrics
metrics:
features:
- application
- network
- stats_tcp_rtt
routes:
unmatched: low-cardinality
max_path_segment_cardinality: 500
ebpf:
context_propagation: all
track_request_headers: true
payload_extraction:
http:
genai:
openai:
enabled: true
anthropic:
enabled: true
jsonrpc:
enabled: true
mcp:
enabled: true
qwen:
enabled: true
rerank:
enabled: true
embedding:
enabled: true
gemini:
enabled: true
buffer_sizes:
http: 262144
otel_traces_export:
endpoint: <OTLP_ENDPOINT>
instrumentations:
- http
- grpc
- sql
- redis
- kafka
- mqtt
- mongo
- couchbase
- memcached
- genai
nodejs:
enabled: true
discovery:
instrument:
- name: my-app
open_ports: 8080
Paso 4: desplegar el servicio
Despliegue de archivo binario (administrado por systemd):
Cree un archivo de servicio de systemd en /etc/systemd/system/obi.service:
[Unit]
Description=OBI eBPF Instrumentation Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/path/to/obi-dir
Environment="OTEL_EBPF_CONFIG_PATH=config.yaml"
Environment="OTEL_EXPORTER_OTLP_HEADERS=<Replace with actual value>"
ExecStart=/path/to/obi-dir/obi
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=obi
[Install]
WantedBy=multi-user.target
Inicie el servicio:
sudo systemctl daemon-reload
sudo systemctl enable obi
sudo systemctl start obi
sudo systemctl status obi
Despliegue con Docker:
docker pull registry.cn-hangzhou.aliyuncs.com/private-mesh/obi:0.10.0
docker run -d \
--name obi \
--pid=host \
--privileged \
--restart=always \
-v $(pwd)/config.yaml:/config/config.yaml:ro \
-e OTEL_EXPORTER_OTLP_HEADERS="<Replace with actual value>" \
-e OTEL_EXPORTER_OTLP_ENDPOINT="<Replace with actual value>" \
registry.cn-hangzhou.aliyuncs.com/private-mesh/obi:0.10.0 \
--config=/config/config.yaml
Comprobar los datos de monitoreo
Inicie sesión en la consola de ARMS. En el panel de navegación izquierdo, haga clic en Application Monitoring. Busque el nombre de la aplicación que configuró en la lista de aplicaciones y haga clic en él para consultar los detalles de monitoreo, como la topología, las trazas y las anomalías.
Comandos comunes de operación y mantenimiento
|
Operación |
Método con systemd |
Método con Docker |
|
Consultar el estado |
sudo systemctl status obi |
docker ps -f name=obi |
|
Consultar los registros |
sudo journalctl -u obi -f |
docker logs -f obi |
|
Reiniciar |
sudo systemctl restart obi |
docker restart obi |
|
Detener |
sudo systemctl stop obi |
docker stop obi |
|
Desinstalar |
sudo bash obi-setup.sh uninstall |
docker rm -f obi |