在上一个项目,我们在短时间内从单一的单体后端服务发展成为一个微服务集群!我们发现自己需要一个强大的解决方案来取代现有的反向代理,而我们基本需求清单中最重要的几点是:

  1. 单一事实来源;维护身份验证和安全标准应该易于实现。
  2. 简化的入口创建;新服务的加入应该轻而易举!
  3. 模块化可扩展性;异常并不例外,需要进行大量的自定义添加。

在本文中,我们将构建一个小型的概念验证,它将满足上述所有标准,并为读者提供一个已配置的 Kong 实例,以便进一步扩展和定制,以适应他们自己的微服务集群。

要求

  • Helm v3
  • 本地 Kubernetes:例如 minikube、kind、microk8s。

本文将使用 minikube,但任何平台均可!
虽然本文面向完全不熟悉 Kong 的开发者,但它并非涵盖所有工具的教程。拥有 Kubernetes 和 Helm 使用经验的读者将受益匪浅。

什么是 Kong Gateway?


Kong 是一个开源的、多平台的 RESTful API 反向代理,我们将其部署到 上一个项目AWS EKS集群中,因为它使我们能够实现上述所有目标:

无数据库配置使我们能够实现 Kong 的代码配置。

Kong Kubernetes Ingress Controller (KIC) 使服务启动变得非常简单,只需编写一个小型的 Kubernetes 清单,Kong 便会使用它通过 URL 路径路由用户的请求。

捆绑和自定义插件支持使我们能够通过操控传入/传出请求和响应来配置 Kong 作为后端网关的行为。

部署minikube 

ninjamac@ip-192-168-1-95 ~ % minikube start --cpus=4 --memory=4g
😄  Darwin 15.3.1 (arm64) 上的 minikube v1.33.1
✨  自动选择 docker 驱动。其他选项:parallels, qemu2, vmware, ssh
📌  使用具有 root 权限的 Docker Desktop 驱动程序
👍  Starting "minikube" primary control-plane node in "minikube" cluster
🚜  Pulling base image v0.0.44 ...
🔥  Creating docker container (CPUs=4, Memory=4096MB) ...
🐳  正在 Docker 26.1.1 中准备 Kubernetes v1.30.0…
    ▪ 正在生成证书和密钥...
    ▪ 正在启动控制平面...
    ▪ 配置 RBAC 规则 ...
🔗  配置 bridge CNI (Container Networking Interface) ...
🔎  正在验证 Kubernetes 组件...
    ▪ 正在使用镜像 gcr.io/k8s-minikube/storage-provisioner:v5
🌟  启用插件: storage-provisioner, default-storageclass
🏄  完成!kubectl 现在已配置,默认使用"minikube"集群和"default"命名空间

 安装kic ingress controller

  1. 创建命令空间:kong
  2. 添加kong 的helm repo
  3. 创建kic.yaml value 文件
  4. 使用helm install命令安装kong ingress controller
ninjamac@ip-192-168-1-95 ~ % kubectl create namespace kong
namespace/kong created
ninjamac@ip-192-168-1-95 ~ % helm repo add kong https://charts.konghq.com
"kong" has been added to your repositories
ninjamac@ip-192-168-1-95 ~ % vim kic.yaml
image:
  repository: kong/kong
  tag: "3.4"

env:
  prefix: /kong_prefix/
  database: "off"

ingressController:
  enabled: true
ninjamac@ip-192-168-1-95 ~ % helm install kic kong/kong -n kong -f kic.yaml

安装成功后,你可以看到下面的结果:

NAME: kic
LAST DEPLOYED: Sat Apr 12 10:45:51 2025
NAMESPACE: kong
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
To connect to Kong, please execute the following commands:

HOST=$(kubectl get svc --namespace kong kic-kong-proxy -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
PORT=$(kubectl get svc --namespace kong kic-kong-proxy -o jsonpath='{.spec.ports[0].port}')
export PROXY_IP=${HOST}:${PORT}
curl $PROXY_IP

Once installed, please follow along the getting started guide to start using
Kong: https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/getting-started/

WARNING: Kong Manager will not be functional because the Admin API is not
enabled. Setting both .admin.enabled and .admin.http.enabled and/or
.admin.tls.enabled to true to enable the Admin API over HTTP/TLS.

大约过一两分钟后,你可以看到kong ingress controller 的pod 已经运行起来:

ninjamac@ip-192-168-1-95 ~ % kubectl get pods -n kong
NAME                        READY   STATUS    RESTARTS   AGE
kic-kong-65f7b7d49d-f2srq   2/2     Running   0          116s

运行下面的命令来启用本地端口8000到pod的8000端口转发:

ninjamac@ip-192-168-1-95 ~ % kubectl port-forward kic-kong-65f7b7d49d-f2srq -n kong 8000:8000
Forwarding from 127.0.0.1:8000 -> 8000
Forwarding from [::1]:8000 -> 8000
Handling connection for 8000
Handling connection for 8000
Handling connection for 8000

部署后端服务

Kong 的强大之处在于其服务上线的便捷性。目前,Kong 已在您的项目仓库中配置完毕,但它尚未为任何后端应用程序提供服务;为了将整个项目保持为一个完整的单元,我们将在 Kong Helm Chart 中定义一项服务。

在实际场景中,您更有可能将后端服务与 Kong 分开部署。只要网关和服务最终位于同一个集群中,对 Kong 来说就完全一样!

我们将在集群中部署一个 echo-server 来演示其便捷的上线方式。您可以查看此步骤:

  1. 部署后端服务和deployment
apiVersion: v1
kind: Service
metadata:
  labels:
    app: echo
  name: echo
spec:
  ports:
  - port: 1025
    name: tcp
    protocol: TCP
    targetPort: 1025
  - port: 1026
    name: udp
    protocol: TCP
    targetPort: 1026
  - port: 1027
    name: http
    protocol: TCP
    targetPort: 1027
  selector:
    app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: echo
  name: echo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: echo
    spec:
      containers:
      - image: kong/go-echo:latest
        name: echo
        ports:
        - containerPort: 1027
        env:
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
        resources: {}

     2.  部署ingress 对象

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echo
  annotations:
    konghq.com/strip-path: 'true'
spec:
  ingressClassName: kong
  rules:
  - host: kong.example
    http:
      paths:
      - path: /echo
        pathType: ImplementationSpecific
        backend:
          service:
            name: echo
            port:
              number: 1027

验证 ingress 

ninjamac@ip-192-168-1-95 kong % curl -i http://kong.example:8000/echo --resolve kong.example:8000:127.0.0.1
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 134
Connection: keep-alive
Date: Sat, 12 Apr 2025 02:54:15 GMT
X-Kong-Upstream-Latency: 8
X-Kong-Proxy-Latency: 1
Via: kong/3.4.2

Welcome, you are connected to node minikube.
Running on Pod echo-77d6dc75f6-fb48t.
In namespace default.
With IP address 10.244.0.4.

添加模块化插件


我们如此喜欢 Kong 的主要原因是它对模块化插件和集成的强大支持。Kong Hub 拥有大量现成的实用插件;应用捆绑插件就像路由应用程序一样简单。

在本演示中,我们将对所有进入 Kong 的请求应用一个限速插件,其速率可由人工控制:5 个请求/分钟。

我们将在项目中添加一个新文件

apiVersion: configuration.konghq.com/v1
kind: KongClusterPlugin
metadata:
  name: global-rate-limiting
  annotations:
    kubernetes.io/ingress.class: kong
  labels:
    global: "true"
config: 
  minute: 5
  policy: local
plugin: rate-limiting

 通过一个for循环来运行前面的命令

for i in {1..100}; do curl -i http://kong.example:8000/echo --resolve kong.example:8000:127.0.0.1; done

你会看到下面的信息,前五个请求都可以正常返回,后面的请求都返回下面的错误信息

{
  "message":"API rate limit exceeded"
}HTTP/1.1 429 Too Many Requests

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 134
Connection: keep-alive
RateLimit-Reset: 31
X-RateLimit-Limit-Minute: 5
X-RateLimit-Remaining-Minute: 0
RateLimit-Limit: 5
RateLimit-Remaining: 0
Date: Sun, 13 Apr 2025 08:43:29 GMT
X-Kong-Upstream-Latency: 0
X-Kong-Proxy-Latency: 1
Via: kong/3.4.2

Welcome, you are connected to node minikube.
Running on Pod echo-77d6dc75f6-fb48t.
In namespace default.
With IP address 10.244.0.4.

HTTP/1.1 429 Too Many Requests
Date: Sun, 13 Apr 2025 08:43:29 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
RateLimit-Reset: 31
X-RateLimit-Limit-Minute: 5
Retry-After: 31
X-RateLimit-Remaining-Minute: 0
RateLimit-Limit: 5
RateLimit-Remaining: 0
Content-Length: 41
X-Kong-Response-Latency: 1
Server: kong/3.4.2

{
  "message":"API rate limit exceeded"
}HTTP/1.1 429 Too Many Requests

结论


通过本教程,我们成功地将 Kong 网关实例部署到集群中,并使用配置即代码的方式,代理受全局速率限制的后端服务。而且,我们用不到 100 行代码,以完全可复制的方式完成了这一切!

对于网关而言,这是一个不错的开端,其发展潜力可能远远超出这个简单的示例!身份验证和自定义路由都只需一些基本的清单即可实现,并且由于整个配置都保存为一组 Kubernetes 清单,因此运行此网关的本地实例非常轻松。

    Logo

    开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

    更多推荐