How Easegress Functions as a Kubernetes Ingress Controller: Architecture and Deployment Guide

Easegress operates as a fully-functional Kubernetes Ingress Controller by watching Ingress, Service, Endpoints, and Secret resources via Kubernetes informers and dynamically translating them into internal HTTPServer and Pipeline objects that handle traffic routing, load balancing, and mTLS termination.

Easegress is a comprehensive cloud-native traffic orchestration system that can function as a Kubernetes Ingress Controller when deployed inside a cluster. According to the megaease/easegress source code, the implementation resides in the meshcontroller/ingresscontroller package, where it synchronizes Kubernetes API state with Easegress traffic management objects to provide advanced routing capabilities including canary releases and mutual TLS.

Core Architecture of the Ingress Controller

The controller follows a stateless, highly-available design where each pod instance watches the Kubernetes API and reconciles internal state through a dedicated traffic reload pipeline.

Controller Initialization and Resource Watching

The entry point in pkg/object/meshcontroller/ingresscontroller/ingresscontroller.go creates the controller via the New function (lines 62-70). This function registers Kubernetes informers that watch four critical resource types:

  • Ingress objects for routing rules
  • Service specs for backend definitions
  • ServiceInstance specs for endpoint health
  • Ingress-controller certificates for TLS configuration

Each informer callback triggers a traffic reload through methods like ic.informer.OnAllIngressSpecs() and ic.informer.OnIngressControllerCert() (lines 101-118).

The Traffic Reload Pipeline

When Kubernetes resources change, the reloadTraffic function (lines 18-25) acquires a lock and executes a three-phase reconciliation:

  1. _reloadIngress: Iterates stored Ingress objects and rewrites each path.Backend to reference the pipeline name that will serve that service (lines 27-45).
  2. _reloadPipelines: Removes stale pipelines and creates new ones for active backends, gathering service-instance specs, counting healthy instances, and building pipeline specifications via IngressControllerPipelineSpec (lines 46-73).
  3. _reloadHTTPServer: Generates a shared HTTP server using IngressControllerHTTPServerSpec, aggregating all IngressRules into a single traffic gate (lines 304-311).

Translating Kubernetes Resources to Easegress Objects

The controller instantiates two primary object types in a dedicated mesh namespace to avoid conflicts with user-defined configurations.

Shared HTTPServer Generation

For every observed Ingress resource, the controller creates one shared HTTPServer that receives all external traffic on a configurable port. The specification is built by IngressControllerHTTPServerSpec in pkg/object/meshcontroller/spec/ingresscontroller.go (lines 41-85), which renders a YAML-style configuration combining all IngressRules into unified routing rules.

Per-Backend Pipeline Creation

Each backend service referenced in an Ingress gets its own Pipeline that performs load balancing and traffic management. The _reloadPipelines function constructs these via IngressControllerPipelineSpec (lines 87-101 in the spec file), which assembles a JSON specification containing:

  • A mesh adaptor for service discovery
  • A proxy filter with canary release support
  • Optional mTLS configuration

Mutual TLS (mTLS) Implementation

When spec.Admin.EnablemTLS() returns true, the controller enhances pipeline security by fetching the controller-instance certificate and root certificate during the _reloadPipelines phase (lines 58-64). These certificates are passed to the pipeline generation logic, enabling each proxy to terminate TLS connections from external clients while maintaining encrypted communication with backend pods.

High Availability and Scaling Characteristics

The implementation is stateless and highly-available by design. Scaling the Deployment launches identical pods where each instance:

  1. Registers itself in the service registry via PutIngressControllerInstanceSpec
  2. Runs the same informer watches and reload logic
  3. Relies on the traffic controller to deduplicate pipelines across instances

This architecture allows horizontal scaling without session affinity or leader election complexity.

Practical Deployment Guide

Deploying Easegress as an Ingress Controller involves creating the controller specification, deploying the server, and defining standard Kubernetes Ingress resources.

Step 1: Configure the Controller

Create a ConfigMap containing the Easegress server configuration and IngressController specification:

apiVersion: v1
kind: ConfigMap
metadata:
  name: easegress-cm
  namespace: default
data:
  easegress-server.yaml: |
    name: ingress-easegress
    cluster-name: easegress-ingress-controller
    api-addr: 0.0.0.0:2381
    data-dir: /opt/easegress/data
    log-dir: /opt/easegress/log
  controller.yaml: |
    kind: IngressController
    name: ingress-controller
    namespaces: ["default"]
    ingressClass: easegress
    httpServer:
      port: 8080
      https: false
      keepAlive: true

Step 2: Deploy the Controller Pod

Apply a Deployment that mounts the ConfigMap and initializes both the server and controller:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: easegress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: easegress-ingress
  template:
    metadata:
      labels:
        app: easegress-ingress
    spec:
      serviceAccountName: easegress-ingress-controller
      containers:
      - name: easegress-primary
        image: megaease/easegress:latest
        command: ["/bin/sh"]
        args:
        - -c
        - |
          /opt/easegress/bin/easegress-server \
            -f /opt/eg-config/easegress-server.yaml \
            --initial-object-config-files /opt/eg-config/controller.yaml
        volumeMounts:
        - name: easegress-cm
          mountPath: /opt/eg-config/easegress-server.yaml
          subPath: easegress-server.yaml
        - name: easegress-cm
          mountPath: /opt/eg-config/controller.yaml
          subPath: controller.yaml
      volumes:
      - name: easegress-cm
        configMap:
          name: easegress-cm

Step 3: Expose the Traffic Gate

Create a NodePort Service to expose the shared HTTP server:

apiVersion: v1
kind: Service
metadata:
  name: easegress-public
spec:
  type: NodePort
  selector:
    app: easegress-ingress
  ports:
  - name: http
    port: 8080
    nodePort: 30080

Step 4: Define Backend Services and Ingress Rules

Deploy a backend Service and Ingress resource using the easegress ingress class:

apiVersion: v1
kind: Service
metadata:
  name: hello-service
spec:
  selector:
    app: hello
  ports:
  - name: v1
    port: 60001
    targetPort: 50001
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: hello-ingress
spec:
  ingressClassName: easegress
  rules:
  - host: www.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: hello-service
            port:
              number: 60001

Test the deployment:

curl http://<NODE_IP>:30080/ -H "Host: www.example.com"

Summary

  • Easegress implements a Kubernetes Ingress Controller through the meshcontroller/ingresscontroller package, translating K8s resources into native HTTPServer and Pipeline objects.
  • Dynamic reconciliation occurs via the reloadTraffic function, which locks the controller and sequentially rebuilds ingress mappings, pipelines, and HTTP server configurations.
  • Namespace isolation prevents conflicts by storing all generated objects in a dedicated mesh namespace.
  • mTLS support is available through certificate watching and pipeline injection when enabled via spec.Admin.EnablemTLS().
  • Stateless architecture enables horizontal scaling without leader election, as each instance registers itself and the traffic controller deduplicates configuration.

Frequently Asked Questions

How does Easegress differ from other Kubernetes Ingress Controllers like NGINX or Traefik?

Unlike traditional controllers that generate static configuration files, Easegress maintains a live object model where IngressControllerHTTPServerSpec and IngressControllerPipelineSpec dynamically build YAML and JSON specifications that feed directly into Easegress's runtime traffic controller. This enables native support for canary releases and advanced load balancing strategies without external dependencies.

Can Easegress handle multiple IngressClasses or namespaces simultaneously?

Yes. The controller accepts a list of namespaces in its configuration (namespaces: ["default", "production"]) and respects the ingressClassName field in Ingress resources. Multiple controller instances can coexist in a cluster by specifying different ingressClass values in their respective configurations.

How does the controller handle backend pod health changes?

The _reloadPipelines function continuously monitors ServiceInstance specs through Kubernetes informers. When healthy instance counts change, the function regenerates the pipeline specification with updated upstream targets without requiring a full controller restart, ensuring zero-downtime backend transitions.

Is mutual TLS mandatory, or can I run the controller without it?

mTLS is optional. The controller checks spec.Admin.EnablemTLS() during pipeline generation. If disabled, pipelines operate without certificate termination, allowing plain HTTP communication between the ingress gateway and backend services.

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 →