Skip to content

Commit

Permalink
Gateway api (#1042)
Browse files Browse the repository at this point in the history
* upgrade k8s to v0.27.3

* nearly done, but still WIP

* fix some issues, now work for simplest cases

* documentation

* fix bugs

* update supported k8s version
  • Loading branch information
localvar authored Aug 4, 2023
1 parent 2c1b4f0 commit 31d6188
Show file tree
Hide file tree
Showing 11 changed files with 1,763 additions and 24 deletions.
10 changes: 10 additions & 0 deletions build/package/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,19 @@ WORKDIR /opt/easegress
COPY build/package/entrypoint.sh /
COPY build/bin/egctl build/bin/easegress-server /opt/easegress/bin/

# If the following apk command takes too much time or failed because of
# network issues, we can setup a proxy for it.
#
# ENV http_proxy 'http://192.168.1.1:7890'
# ENV https_proxy 'http://192.168.1.1:7890'

RUN apk --no-cache add tini tzdata && \
chmod +x /entrypoint.sh /opt/easegress/bin/*

# If we setup a proxy for the apk command, we must unset it
# ENV http_proxy=
# ENV https_proxy=

ENV PATH /opt/easegress/bin:$PATH

ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"]
344 changes: 344 additions & 0 deletions doc/reference/gatewaycontroller.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
# GatewayController

The GatewayController is an implementation of
[Kubernetes Gateway API](https://gateway-api.sigs.k8s.io/), 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

1. K8s cluster : **v1.23+**
2. 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:

```yaml
---
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.

```yaml
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:

```yaml
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:

```yaml
---
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.

```yaml
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.

```yaml
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:

```bash
$ 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
```
2 changes: 1 addition & 1 deletion doc/reference/ingresscontroller.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ data:
maxConnections: 10240
```

The `easegress-serverl` creates Easegress instance named *easegress-ingress-controller* and `controller.yaml` defines IngressController object for Easegress.
The `easegress-server.yaml` creates Easegress instance named *easegress-ingress-controller* and `controller.yaml` defines IngressController object for Easegress.

### Deploy Easegress IngressController

Expand Down
2 changes: 1 addition & 1 deletion doc/reference/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ whether a request/response is a stream, for example:
refer [Proxy](./filters.md#proxy) for more information.

As we have mentioned above, the payload of a stream-based request/response
cannot be read once, so some features are not possible for these
can only be read once, so some features are not possible for these
requests/responses, including:

* In the `template` of `RequestBuilder` or `ResponseBuilder`, you cannot
Expand Down
Loading

0 comments on commit 31d6188

Please sign in to comment.