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:
_reloadIngress: Iterates stored Ingress objects and rewrites eachpath.Backendto reference the pipeline name that will serve that service (lines 27-45)._reloadPipelines: Removes stale pipelines and creates new ones for active backends, gathering service-instance specs, counting healthy instances, and building pipeline specifications viaIngressControllerPipelineSpec(lines 46-73)._reloadHTTPServer: Generates a shared HTTP server usingIngressControllerHTTPServerSpec, 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:
- Registers itself in the service registry via
PutIngressControllerInstanceSpec - Runs the same informer watches and reload logic
- 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/ingresscontrollerpackage, translating K8s resources into native HTTPServer and Pipeline objects. - Dynamic reconciliation occurs via the
reloadTrafficfunction, 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →