How to setup GatewayAPI on Kubernetes cluster

Here in this article we will try to setup GatewayAPI implementation Easegress to provide traffic routing capability to the backend kubernetes services.
Test Environment
Kubernetes cluster v1.32.0
What is Gateway API
Gateway API is an add-on containing API kinds that provide dynamic infrastructure provisioning and advanced traffic routing features. Gateway API is a set of specifications that are defined as custom resources and are supported by many implementations.
Gateway API Resources
Gateway API has three stable API kinds:
- GatewayClass: Defines a set of gateways with common configuration and managed by a controller that implements the class.
- Gateway: Defines an instance of traffic handling infrastructure, such as cloud load balancer.
- HTTPRoute: Defines HTTP-specific rules for mapping traffic from a Gateway listener to a representation of backend network endpoints. These endpoints are often represented as a Service.
What is Easegress
Easegress is a Cloud Native traffic orchestration system. It can function as a sophisticated modern gateway, a robust distributed cluster, a flexible traffic orchestrator, or even an accessible service mesh. Easegress currently supports Gateway API v1beta1 version of the specification by GatewayController.
Procedure
Step1: Install Gateway API CRD’s
A Gateway API bundle represents the set of CRDs associated with a version of Gateway API. The standard release channel includes all resources that have graduated to GA or beta, including GatewayClass, Gateway, HTTPRoute, and ReferenceGrant. To install this channel, run the following kubectl command.
admin@kubemaster:~$ kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created
Step2: Authorize Easegress GatewayController for using the Kubernetes API
If your cluster is configured with RBAC, first you will need to authorize Easegress GatewayController for using the Kubernetes API. Below is an example configuration. Here we are creating a service account “easegress-gateway-controller” and binding a clusterrole to the serivce account using clusterrolebinding as shown below.
Gateway controller watches a Kubernetes API for Gateway API resources and reconciles Load Balancing resources to implement the networking behavior specified by the Gateway resources.
File: easegress_rbac.yml
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: easegress-gateway-controller
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["services", "secrets", "endpoints", "namespaces"]
verbs: ["get", "watch", "list"]
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["gatewayclasses", "httproutes", "gateways"]
verbs: ["get", "watch", "list"]
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["gatewayclasses/status", "gateways/status"]
verbs: ["update"]
# used for extensions
- apiGroups: ["easegress.megaease.com"]
resources: ["filterspecs"]
verbs: ["get", "watch", "list"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: easegress-gateway-controller
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: easegress-gateway-controller
subjects:
- kind: ServiceAccount
name: easegress-gateway-controller
namespace: default
roleRef:
kind: ClusterRole
name: easegress-gateway-controller
apiGroup: rbac.authorization.k8s.io
admin@kubemaster:~$ kubectl apply -f easegress_rbac.yml
clusterrole.rbac.authorization.k8s.io/easegress-gateway-controller created
serviceaccount/easegress-gateway-controller created
clusterrolebinding.rbac.authorization.k8s.io/easegress-gateway-controller created
Step3: Create ConfigMap to store Easegress server configuration and Easegress gateway configuration
Here we are going to create a ConfigMap to store Easegress server configuration and Easegress gateway configuration. The easegress-server.yaml creates Easegress instance named easegress-gateway-controller and controller.yaml defines GatewayController object for Easegress.
File: easegress_cm.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: easegress-cm
namespace: default
data:
easegress-server.yaml: |
name: gateway-easegress
cluster-name: easegress-gateway-controller
cluster-role: primary
api-addr: 0.0.0.0:2381
data-dir: /opt/easegress/data
log-dir: /opt/easegress/log
debug: false
controller.yaml: |
kind: GatewayController
name: gateway-controller-example
kubeConfig:
masterURL:
namespaces: []
admin@kubemaster:~$ kubectl apply -f easegress_cm.yml
configmap/easegress-cm created
admin@kubemaster:~$ kubectl get cm
NAME DATA AGE
easegress-cm 2 5s
Step4: Deploy Easegress GatewayController
To deploy the GatewayController, we will create a Deployment and a Service as below.
The GatewayController is created via the command line argument initial-object-config-files of easegress-server. Note that Easegress logs and data are stored to emptyDir called gateway-data-volume inside the pod as GatewayController is stateless so we can restart new pods without preserving previous state.
File: easegress_deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: easegress-gateway
name: easegress
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: easegress-gateway
template:
metadata:
labels:
app: easegress-gateway
spec:
serviceAccountName: easegress-gateway-controller
containers:
- args:
- -c
- |-
/opt/easegress/bin/easegress-server \
-f /opt/eg-config/easegress-server.yaml \
--initial-object-config-files /opt/eg-config/controller.yaml \
--initial-cluster $(EG_NAME)=http://localhost:2380
command:
- /bin/sh
env:
- name: EG_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
image: megaease/easegress:latest
imagePullPolicy: IfNotPresent
name: easegress-primary
resources:
limits:
cpu: 1200m
memory: 2Gi
requests:
cpu: 100m
memory: 256Mi
volumeMounts:
- mountPath: /opt/eg-config/easegress-server.yaml
name: easegress-cm
subPath: easegress-server.yaml
- mountPath: /opt/eg-config/controller.yaml
name: easegress-cm
subPath: controller.yaml
- mountPath: /opt/easegress/data
name: gateway-data-volume
- mountPath: /opt/easegress/log
name: gateway-data-volume
restartPolicy: Always
volumes:
- emptyDir: {}
name: gateway-data-volume
- configMap:
defaultMode: 420
items:
- key: easegress-server.yaml
path: easegress-server.yaml
- key: controller.yaml
path: controller.yaml
name: easegress-cm
name: easegress-cm
admin@kubemaster:~$ kubectl apply -f easegress_deployment.yml
deployment.apps/easegress created
admin@kubemaster:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
easegress-576cdb7f9b-bcnzp 1/1 Running 0 77s
Step5: Deploy Backend Services
Here we are going to deploy sample application exposed as service on NodePort as shown below.
File: easegress_application.yml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-deployment
spec:
selector:
matchLabels:
app: products
department: sales
replicas: 2
template:
metadata:
labels:
app: products
department: sales
spec:
containers:
- name: hello-v1
image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0"
env:
- name: "PORT"
value: "50001"
- name: hello-v2
image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
env:
- name: "PORT"
value: "50002"
---
apiVersion: v1
kind: Service
metadata:
name: hello-service
spec:
type: NodePort
selector:
app: products
department: sales
ports:
- name: port-v1
protocol: TCP
port: 60001
targetPort: 50001
- name: port-v2
protocol: TCP
port: 60002
targetPort: 50002
admin@kubemaster:~$ kubectl apply -f easegress_application.yml
deployment.apps/hello-deployment created
service/hello-service created
Step6: Deploy Gateway API Objects
Gateways can be implemented by different controllers, often with different configurations. A Gateway must reference a GatewayClass that contains the name of the controller that implements the class.
A Gateway describes an instance of traffic handling infrastructure. It defines a network endpoint that can be used for processing traffic, i.e. filtering, balancing, splitting, etc. for backends such as a Service. For example, a Gateway may represent a cloud load balancer or an in-cluster proxy server that is configured to accept HTTP traffic.
The HTTPRoute kind specifies routing behaviour of HTTP requests from a Gateway listener to backend network endpoints.
File: easegress_gateway_objects.yml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: example-gateway-class
spec:
controllerName: "megaease.com/gateway-controller"
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-gateway
spec:
gatewayClassName: example-gateway-class
listeners:
- protocol: HTTP
port: 8080
name: example-listener
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-route
spec:
parentRefs:
- kind: Gateway
name: example-gateway
sectionName: example-listener
rules:
- matches:
- path:
value: /1
backendRefs:
- name: hello-service
port: 60001
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-route-2
spec:
parentRefs:
- kind: Gateway
name: example-gateway
sectionName: example-listener
hostnames:
- megaease.com
rules:
- matches:
- path:
value: /2
backendRefs:
- name: hello-service
port: 60002
admin@kubemaster:~$ kubectl apply -f easegress_gateway_objects.yml
gatewayclass.gateway.networking.k8s.io/example-gateway-class created
gateway.gateway.networking.k8s.io/example-gateway created
httproute.gateway.networking.k8s.io/example-route created
httproute.gateway.networking.k8s.io/example-route-2 created
admin@kubemaster:~$ kubectl get gatewayclass
NAME CONTROLLER ACCEPTED AGE
example-gateway-class megaease.com/gateway-controller True 54m
admin@kubemaster:~$ kubectl get gateway
NAME CLASS ADDRESS PROGRAMMED AGE
example-gateway example-gateway-class 54m
admin@kubemaster:~$ kubectl get httproute
NAME HOSTNAMES AGE
example-route 54m
example-route-2 ["megaease.com"] 54m
Step7: Expose The Listener Port
Create service to forward the incoming traffic to Listener in Easegress. The port web is to receive external HTTP requests from port 30080 and forward them to the HTTP server created according to the Listener configuration of the Gateway.
File: easegress_listener_service.yml
apiVersion: v1
kind: Service
metadata:
name: easegress-public
namespace: default
spec:
ports:
- name: web
protocol: TCP
port: 8080
nodePort: 30080
selector:
app: easegress-gateway
type: NodePort
admin@kubemaster:~$ kubectl apply -f easegress_listener_service.yml
service/easegress-public created
Step8: Validate Application access
Here we can validate our two endpoints by access them as shown below.
admin@kubemaster:~$ curl http://127.0.0.1:30080/1
Hello, world!
Version: 2.0.0
Hostname: hello-deployment-569c6f9545-qncjr
admin@kubemaster:~$ curl http://127.0.0.1:30080/2 -i
HTTP/1.1 404 Not Found
Date: Fri, 31 Jan 2025 09:11:31 GMT
Content-Length: 0
Connection: close
admin@kubemaster:~$ curl http://127.0.0.1:30080/2 -H Host:megaease.com
Hello, world!
Version: 2.0.0
Hostname: hello-deployment-569c6f9545-qncjr
NOTE: The example-route-2 will forward the request to backend service only when it receives the request with host header as megaease.com
Hope you enjoyed reading this article. Thank you..
Leave a Reply
You must be logged in to post a comment.