Kubernetes Gateway API
The GatewayController
is an implementation of
Kubernetes Gateway API, it watches
Kubernetes Gateway, HTTPRoute, Service, and Secrets then translates them to
Easegress HTTP server and pipelines.
Note the currenct GatewayController
is an experimental implementation, NOT all the features of the Kubernetes Gateway API
features are supported.
Prerequisites
- K8s cluster : v1.23+
- Gateway API: following https://gateway-api.sigs.k8s.io/guides/#installing-gateway-api to install.
Getting Started
Role Based Access Control configuration
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:
---
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"]
---
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
Note the name of the ServiceAccount we just created is easegress-gateway-controller
,
it will be used later.
Config Map
Let’s use ConfigMap to store Easegress server configuration and Easegress gateway configuration. This ConfigMap is used later in Deployment.
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: []
The easegress-server.yaml
creates Easegress instance named easegress-gateway-controller
and controller.yaml
defines GatewayController object for Easegress.
Deploy Easegress GatewayController
To deploy the GatewayController, we will create a Deployment and a Service as below:
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
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.
Deploy Backend Services
Apply below YAML configuration to Kubernetes:
---
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
Deploy Gateway API Objects
Please refer https://gateway-api.sigs.k8s.io/ for the detailed information of Gateway Class, Gateway and HTTPRoute configuration. Up to now, the Easegress GatewayController only support HTTP & HTTPS listeners.
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
name: example-gateway-class
spec:
controllerName: "megaease.com/gateway-controller"
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: example-gateway
spec:
gatewayClassName: example-gateway-class
listeners:
- protocol: HTTP
port: 8080
name: example-listener
---
apiVersion: gateway.networking.k8s.io/v1beta1
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/v1beta1
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
Expose The Listener Port
Create service to forward the incoming traffic to Listener in Easegress.
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
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.
Verification
Once all configurations are applied, we can leverage the command below to access
both versions of the hello
application:
$ curl http://127.0.0.1:30080/1
Hello, world!
Version: 2.0.0
Hostname: hello-deployment-7855bc9747-n4qsx
$ curl http://127.0.0.1:30080/2 -i
HTTP/1.1 404 Not Found
Date: Wed, 19 Jul 2023 06:59:07 GMT
Content-Length: 0
Connection: close
$ curl http://127.0.0.1:30080/2 -H Host:megaease.com
Hello, world!
Version: 2.0.0
Hostname: hello-deployment-7855bc9747-n4qsx