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:9900with endpoints/configand/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
AgentConfigstructures containing service specifications, header whitelists, and reporter TLS settings - Issues HTTP
PUTrequests tohttp://host:port/configto push configuration updates - Queries
GET /agent-infoto retrieve the agent version and type (EaseAgentorGoSDK) 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
AgentClienttargetinglocalhost:9900as implemented inpkg/object/meshcontroller/worker/observability.go - Builds
AgentConfigfrom the currentServiceSpecand 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 inpkg/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:
-
Mesh Controller Worker loads the
ServiceSpecfrompkg/object/meshcontroller/spec/spec.go, includingAgentType, sidecar image name, and canary headers. -
Worker initializes ObservabilityManager, which creates an
AgentClientconfigured to communicate withlocalhost:9900. -
ObservabilityManager builds AgentConfig containing the full service definition, header whitelist (e.g.,
x-demo-header,authorization), and optionalAgentReporterconfiguration with TLS credentials. -
AgentClient pushes configuration via HTTP
PUTto/config. The Java sidecar unmarshals the JSON, updates its internal JMX exporter, and begins pushing metrics to the configured reporter endpoint. -
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.
-
Health monitoring occurs when the control plane queries
GET /agent-infoto 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
ServiceInstanceSpecstruct definesAgentTypeto distinguish betweenEaseAgent,GoSDK, orNone, 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
decodeBase64before being passed to the agent configuration. -
Configuration Refresh Cycle: The worker invokes
updateAgentConfig()every 30 seconds (as seen inworker.golines 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:9900by 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 pushAgentConfigstructures 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →