Understanding the Architecture of the Easegress Agent: Sidecar Observability Deep Dive

The Easegress Agent (EaseAgent) is a Java-based sidecar that instruments applications via bytecode enhancement, exposing a local HTTP API on port 9900 to receive configuration from the Easegress control plane and push JMX-based metrics, logs, and traces.

The architecture of the Easegress agent forms the backbone of Easegress's service mesh observability capabilities. Implemented in the easegress-io/easegress repository, this sidecar component runs alongside service instances to provide metrics, logging, and distributed tracing without requiring modifications to application code.

Core Components of the Easegress Agent Architecture

The Easegress Agent architecture consists of three logical parts that work together to form a complete control-plane to data-plane observability loop.

Agent Process (Java Side-Car)

The Agent Process is the Java-based sidecar that runs within the same pod or host as the service instance. According to the source analysis, this component:

  • Instruments the application using bytecode enhancement to capture metrics and traces without code changes
  • Exposes a minimal HTTP API on localhost:9900 with endpoints /config and /agent-info
  • Collects JMX-based metrics from the Java application and pushes them to the configured reporter endpoint
  • Handles TLS configuration for secure communication with the observability backend

The agent type is declared in the ServiceInstanceSpec via the AgentType field, which can be set to EaseAgent, GoSDK, or empty (None) as defined in pkg/object/meshcontroller/spec/spec.go.

Agent Client (jmxtool)

The Agent Client is a Go HTTP client implemented in pkg/util/jmxtool/agent_controller.go that enables the mesh controller to communicate with the Java sidecar:

  • Serializes AgentConfig structures containing service specifications, header whitelists, and reporter TLS settings
  • Issues HTTP PUT requests to http://host:port/config to push configuration updates
  • Queries GET /agent-info to retrieve the agent version and type (EaseAgent or GoSDK) for health checks and upgrade validation

The client handles the protocol translation between the Go-based control plane and the Java-based agent.

Observability Manager

The Observability Manager resides in the mesh controller worker and orchestrates the agent lifecycle:

  • Creates the AgentClient targeting localhost:9900 as implemented in pkg/object/meshcontroller/worker/observability.go
  • Builds AgentConfig from the current ServiceSpec and canary rules, including the comma-separated list of headers that must be forwarded
  • Periodically pushes updates every 30 seconds via worker.updateAgentConfig() (lines 283-327 in pkg/object/meshcontroller/worker/worker.go)
  • Retrieves health information to monitor agent connectivity and version compatibility

Control-Plane to Data-Plane Communication Flow

The architecture of the Easegress agent implements a complete configuration and telemetry loop between the control plane and the sidecar:

  1. Mesh Controller Worker loads the ServiceSpec from pkg/object/meshcontroller/spec/spec.go, including AgentType, sidecar image name, and canary headers.

  2. Worker initializes ObservabilityManager, which creates an AgentClient configured to communicate with localhost:9900.

  3. ObservabilityManager builds AgentConfig containing the full service definition, header whitelist (e.g., x-demo-header,authorization), and optional AgentReporter configuration with TLS credentials.

  4. AgentClient pushes configuration via HTTP PUT to /config. The Java sidecar unmarshals the JSON, updates its internal JMX exporter, and begins pushing metrics to the configured reporter endpoint.

  5. EaseAgent streams telemetry through its reporter (e.g., OpenTelemetry collector) back to the Easegress observability stack for display in the portal or external monitoring systems.

  6. Health monitoring occurs when the control plane queries GET /agent-info to fetch agent type and version, enabling automatic upgrade checks and compatibility validation.

Key Implementation Details

Several critical implementation details govern how the Easegress agent architecture handles configuration and security:

  • AgentType Declaration: The ServiceInstanceSpec struct defines AgentType to distinguish between EaseAgent, GoSDK, or None, determining which instrumentation mechanism to activate.

  • TLS Credential Handling: Reporter TLS certificates are stored base64-encoded in the mesh spec and decoded at runtime via decodeBase64 before being passed to the agent configuration.

  • Configuration Refresh Cycle: The worker invokes updateAgentConfig() every 30 seconds (as seen in worker.go lines 260-317), ensuring that changes to canary headers or mTLS settings propagate without requiring sidecar restarts.

  • Localhost Binding: The agent HTTP API binds to localhost:9900 by default, ensuring that only local processes (the mesh controller worker) can access the configuration endpoints.

Code Example: Configuring the Agent

The following Go example demonstrates how the mesh controller creates a client and pushes configuration to the Easegress Agent, mirroring the logic found in worker.updateAgentConfig():

// Create a client that talks to the side-car running on the same host.
client := jmxtool.NewAgentClient("localhost", "9900")

// Build the AgentConfig – normally the Mesh controller fills these
// fields from the ServiceSpec.
cfg := &jmxtool.AgentConfig{
    Service: spec.Service{
        Name:          "my-service",
        RegisterTenant: "default",
        Sidecar: &spec.Sidecar{
            Address:      "10.1.2.3",
            IngressPort:  9900,
            EgressPort:   9901,
        },
    },
    Headers: "x-demo-header,authorization",
    Reporter: &jmxtool.AgentReporter{
        ReporterTLS: &jmxtool.AgentReporterTLS{
            Enable: true,
            CACert: "base64-ca",
            Cert:   "base64-cert",
            Key:    "base64-key",
        },
        AppendType:      "http",
        BootstrapServer: "http://observability:9090",
        Username:        "agent",
        Password:        "s3cr3t",
    },
}

// Push the configuration to the side-car.
if err := client.UpdateAgentConfig(cfg); err != nil {
    logger.Errorf("failed to update agent config: %v", err)
}

This implementation references the actual source in pkg/object/meshcontroller/worker/worker.go (lines 283-327), where the worker constructs the AgentConfig from the current service specification and canary rules before pushing updates every 30 seconds.

Summary

The architecture of the Easegress agent implements a robust sidecar observability pattern through three integrated components:

  • Java-based Agent Process runs alongside service instances, instrumenting applications via bytecode enhancement and exposing a local HTTP API on port 9900 for configuration and health checks.
  • Go-based Agent Client (jmxtool) enables the mesh controller to serialize and push AgentConfig structures containing service specifications, header whitelists, and TLS reporter settings to the sidecar.
  • Observability Manager orchestrates the control-plane loop, refreshing agent configuration every 30 seconds and retrieving health information without requiring sidecar restarts.

Together, these components form a complete telemetry pipeline that streams JMX-based metrics, logs, and traces from the data plane to the Easegress observability stack.

Frequently Asked Questions

What port does the Easegress Agent use for communication?

The Easegress Agent exposes its HTTP API on port 9900 by default, binding to localhost. This port handles PUT /config requests for configuration updates and GET /agent-info requests for health and version checks. The AgentClient in pkg/util/jmxtool/agent_controller.go targets this port when communicating with the sidecar.

How does the Easegress Agent instrument applications?

The agent uses bytecode enhancement to instrument Java applications without requiring code changes. As a Java sidecar, it attaches to the application process and modifies bytecode at runtime to capture metrics, logs, and traces. This approach allows the EaseAgent type (specified in the ServiceInstanceSpec.AgentType field) to collect JMX-based metrics transparently from the running service.

What is the refresh interval for agent configuration updates?

The mesh controller worker pushes configuration updates to the Easegress Agent every 30 seconds. This refresh cycle, implemented in pkg/object/meshcontroller/worker/worker.go (lines 260-317), ensures that changes to canary headers, mTLS settings, or service specifications propagate to the sidecar without requiring a restart. The updateAgentConfig() function handles this periodic synchronization.

How are TLS credentials handled in the Easegress Agent architecture?

TLS credentials for the agent's reporter are stored base64-encoded in the mesh specification and decoded at runtime before being passed to the agent configuration. The AgentReporter structure in the AgentConfig includes AgentReporterTLS fields for CACert, Cert, and Key, all handled as base64 strings in pkg/object/meshcontroller/spec/spec.go. This ensures secure transmission of certificate data from the control plane to the sidecar's observability reporter.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →