企業級網關 Kong 部署 Spring Boot 項目實戰

1. 概述

在本教程中,我們將演示使用 Kong Ingress Controller (KIC) 在 Kubernetes 上部署 Spring Boot 應用程序。通過爲應用程序實現一個簡單的速率限制器來演示 KIC 的高級使用,而無需任何編碼。

2. 改進的安全和訪問控制

現代應用程序部署,尤其是 API,需要應對許多挑戰,例如:隱私法(例如 GPDR)、安全問題 (DDOS) 和使用跟蹤(例如 API 配額和速率限制)。在這種情況下,現代應用程序和 API 需要額外的保護級別來應對這些挑戰,例如防火牆、反向代理、速率限制器等。

儘管 K8s 環境保護應用程序免受其中許多威脅,但我們仍然需要採取一些措施來進一步確保應用程序安全。這些措施之一是部署入口控制器並設置其對應用程序的訪問規則。

Ingress 是一個對象,它通過向部署的應用程序公開 HTTP / HTTPS 路由並強制執行訪問規則來管理對 K8s 集羣及其上部署的應用程序的外部訪問。爲了暴露應用程序以允許外部訪問,我們需要定義入口規則並使用入口控制器,它是一個專門的反向代理和負載平衡器。通常,ingress controller 由第三方公司提供,功能各不相同,例如:本文使用的 Kong Ingress Controller

https://docs.konghq.com/kubernetes-ingress-controller/latest/

3. 搭建環境

爲了演示 Kong Ingress Controller (KIC) 與 Spring Boot 應用程序的結合使用,需要訪問 K8s 集羣,因此可以使用 minikube 創建一個示例 K8s 集羣。啓動 K8s 環境後,需要在集羣上部署 Kong Ingress Controller 。

https://docs.konghq.com/kubernetes-ingress-controller/2.7.x/guides/getting-started/

Kong 公開了一個外部 IP,需要使用它來訪問應用程序,因此最好使用該地址創建一個環境變量:

export PROXY_IP=$(minikube service -n kong kong-proxy --url | head -1)

如果 Kong Ingress Controller 已安裝,我們就可以通過訪問該 PROXY_IP 來測試它是否正在運行:

curl -i $PROXY_IP

響應應該是 404 錯誤,這是正常的,因爲我們還沒有部署任何應用程序,所以應該說沒有與之匹配的路由。現在是時候創建一個示例應用程序了,爲了將我們的應用程序部署到 K8s,我們需要創建容器鏡像,我們可以使用 Docker 來做到這一點。所以需要提前安裝 docker。

4. 創建示例 Spring Boot 應用程序

現在我們需要一個 Spring Boot 應用程序並將其部署到 K8s 集羣。要生成具有至少一個公開 Web 資源的簡單 HTTP 服務器應用程序,我們可以這樣做:

curl https://start.spring.io/starter.tgz -d dependencies=webflux,actuator -d type=maven-project | tar -xzvf -

一件重要的事情是選擇默認的 Java 版本。如果我們需要使用舊版本,則需要執行 javaVersion 屬性:

curl https://start.spring.io/starter.tgz -d dependencies=webflux,actuator -d type=maven-project -d javaVersion=11 | tar -xzvf -

在這個示例應用程序中,我們選擇了 webflux,它使用 Spring WebFlux 和 Netty 生成一個響應式 Web 應用程序。

https://www.baeldung.com/spring-webflux

以及添加了另一個重要的依賴項:actuator

https://www.baeldung.com/spring-boot-actuators

這是一個 Spring 應用的監控工具,已經暴露了一些 web 資源,這正是我們需要用 Kong 測試的。這樣,應用程序已經公開了可以使用的 Web API。現在開始構建它:

./mvnw install

生成的 jar 是可執行的,因此可以通過運行它來測試應用程序:

java -jar target/*.jar

要測試應用程序,需要打開另一個終端並鍵入以下命令:

curl -i http://localhost:8080/actuator/health

響應必須是執行器提供的應用程序的健康狀態:

HTTP/1.1 200 OK
Content-Type: application/vnd.spring-boot.actuator.v3+json
Content-Length: 15

{"status":"UP"}

5. 從應用生成容器鏡像

將應用程序部署到 Kubernetes 集羣的過程涉及創建容器映像並將其部署到集羣可訪問的存儲庫。我們通常會將鏡像推送到 DockerHub 或自己私有容器鏡像註冊中心。但是,由於我們正在使用 Minikube,讓我們將 Docker 客戶端環境變量指向 Minikube 的 Docker:

$(minikube docker-env)

現在可以構建應用程序鏡像:

./mvnw spring-boot:build-image

6. 部署應用

現在是時候在 K8s 集羣上部署應用程序了。我們需要創建一些 K8s 對象來部署和測試應用程序,所有需要的文件都可以在演示的存儲庫中找到:

部署對象只是創建運行我們的鏡像所必需的 pod,這是創建它的 YAML 文件:

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: demo
  name: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: demo
    spec:
      containers:
      - image: docker.io/library/demo:0.0.1-SNAPSHOT
        name: demo
        resources: {}
        imagePullPolicy: Never

status: {}

我們指向在 Minikube 中創建的鏡像,獲取其全名。請注意,有必要將 imagePullPolicy 屬性指定爲 Never ,因爲我們沒有使用鏡像註冊服務器,因此不希望 K8s 嘗試下載鏡像,而是使用其內部 Docker 存檔中已有的鏡像。可以使用 kubectl 部署它:

kubectl apply -f serviceDeployment.yaml

如果部署成功,可以看到消息:

deployment.apps/demo created

爲了讓應用程序有一個統一的 IP 地址,需要創建一個服務,爲它分配一個內部集羣範圍的 IP 地址,這是創建它的 YAML 文件:

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: demo
  name: demo
spec:
  ports:
  - name: 8080-8080
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: demo
  type: ClusterIP
status:
  loadBalancer: {}

可以使用 kubectl 部署它:

kubectl apply -f clusterIp.yaml

爲了能夠被外部訪問(在 K8s 集羣之外),需要創建一個 ingress 規則,在我們的例子中,將它指向路徑/actuator/health和端口 8080:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo
spec:
  ingressClassName: kong
  rules:
  - http:
      paths:
      - path: /actuator/health
        pathType: ImplementationSpecific
        backend:
          service:
            name: demo
            port:
              number: 8080

使用 kubectl 部署它:

kubectl apply -f ingress-rule.yaml

現在可以使用 Kong 的代理 IP 地址進行外部訪問:

$ curl -i $PROXY_IP/actuator/health
HTTP/1.1 200 OK
Content-Type: application/vnd.spring-boot.actuator.v3+json
Content-Length: 49
Connection: keep-alive
X-Kong-Upstream-Latency: 325
X-Kong-Proxy-Latency: 1
Via: kong/3.0.0

7. 演示速率限制器

我們設法在 Kubernetes 上部署了一個 Spring Boot 應用程序,並使用 Kong Ingress Controller 提供對它的訪問。但 KIC 的功能遠不止於此:身份驗證、負載均衡、監控、速率限制和其他功能。爲了展示 Kong 的真正力量,我們將對應用程序實施一個簡單的速率限制器,限制每分鐘只能訪問五個請求。爲此,需要 在 K8s 集羣中創建一個名爲KongClusterPlugin的對象。使用以下 YAML 文件執行:

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

插件配置允許我們爲應用程序指定額外的訪問規則,將對它的訪問限制爲每分鐘五個請求。們應用此配置並測試結果:

kubectl apply -f rate-limiter.yaml

爲了測試它,可以在一分鐘內重複之前使用的 CURL 命令五次以上,會得到一個 429 錯誤:

curl -i $PROXY_IP/actuator/health
HTTP/1.1 429 Too Many Requests
Date: Sun, 06 Nov 2022 19:33:36 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
RateLimit-Reset: 24
Retry-After: 24
X-RateLimit-Remaining-Minute: 0
X-RateLimit-Limit-Minute: 5
RateLimit-Remaining: 0
RateLimit-Limit: 5
Content-Length: 41
X-Kong-Response-Latency: 0
Server: kong/3.0.0

{
  "message":"API rate limit exceeded"
}

可以看到響應 HTTP 標頭通知客戶端有關速率限制。

8. 清理資源

爲了清理演示,需要按 LIFO 順序刪除所有對象:

kubectl delete -f rate-limiter.yaml
kubectl delete -f ingress-rule.yaml
kubectl delete -f clusterIp.yaml
kubectl delete -f serviceDeployment.yaml

並停止 Minikube 集羣:

minikube stop

9. 結論

在本文中,我們演示了使用 Kong Ingress Controller 來管理對部署在 K8s 集羣上的 Spring Boot 應用程序的訪問。

用到的示例文件,可以 在 GitHub 上找到源代碼。

https://github.com/eugenp/tutorials/tree/master/kubernetes-modules/kubernetes-spring

作者:baeldung

原文:https://www.baeldung.com/spring-boot-kong-ingress

譯者:# 公衆號:進擊雲原生

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/fDVvWs5fmRALF4Gae_4tjg