Envoy Gateway 中使用 HTTP3/QUIC

Envoy Gateway 中使用 HTTP3/QUIC

本文介绍如何通过 Envoy Gateway 处理 HTTP3/QUIC 的流量

什么是 QUIC 协议

HTTP/3 是一种新的网络传输协议,它是 HTTP/2 的后续版本,旨在提高网络性能和安全性。HTTP/3 使用了一个名为 QUIC(Quick UDP Internet Connections)的底层传输协议,它基于 UDP(User Datagram Protocol)而不是传统的 TCP(Transmission Control Protocol)。

QUIC 协议的主要优势在于它可以减少网络延迟、提高连接的可靠性和安全性。以下是 QUIC 协议的一些关键特性:

  1. 连接建立速度更快:QUIC 使用零轮往返(0-RTT)握手,这意味着在建立连接时,客户端和服务器只需交换一次数据包即可。这大大减少了网络延迟,特别是在高延迟或丢包率较高的网络环境中。
  2. 内置加密:QUIC 协议内置了 TLS 1.3 加密,确保了数据传输的安全性。这使得 QUIC 协议在安全性方面与 HTTPS 类似,但传输效率更高。
  3. 更好的拥塞控制:QUIC 协议具有更先进的拥塞控制算法,可以更有效地处理网络拥塞,从而提高数据传输速度。
  4. 多路复用:与 HTTP/2 类似,HTTP/3 支持多路复用,允许在单个连接上同时传输多个请求和响应。这有助于减少网络延迟和提高带宽利用率。
  5. 连接迁移:QUIC 支持连接迁移,这意味着当客户端的 IP 地址或网络接口发生变化时,连接可以在不中断的情况下继续传输数据。这对于移动设备尤为重要,因为它们可能在使用过程中频繁切换网络。

如何在 Envoy Gateway 使用

前置条件

  1. 安装 openssl 用于生成 TLS 证书
  2. kubernetes 集群,并且包含 Service 的 Loadbalancer 实现

步骤

安装 Envoy Gateway 以及 Gateway API

helm install eg oci://docker.io/envoyproxy/gateway-helm --version v0.0.0-latest -n envoy-gateway-system --create-namespace

确保 Envoy Gateway 可用:

kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available

创建 GatewayClass、Gateway、HTTPRoute 以及 Backend

创建 GatewayClass

cat <<EOF | kubectl apply -f -
kind: GatewayClass
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
EOF

创建 Gateway

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
spec:
  gatewayClassName: eg
  listeners:
    - name: http
      protocol: HTTP
      port: 80
EOF

创建 Backend

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend
---
apiVersion: v1
kind: Service
metadata:
  name: backend
  labels:
    app: backend
    service: backend
spec:
  ports:
    - name: http
      port: 3000
      targetPort: 3000
  selector:
    app: backend
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
      version: v1
  template:
    metadata:
      labels:
        app: backend
        version: v1
    spec:
      serviceAccountName: backend
      containers:
        - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e
          imagePullPolicy: IfNotPresent
          name: backend
          ports:
            - containerPort: 3000
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
EOF

创建 HTTPRoute:

cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: backend
spec:
  parentRefs:
    - name: eg
  hostnames:
    - "www.example.com"
  rules:
    - backendRefs:
        - group: ""
          kind: Service
          name: backend
          port: 3000
          weight: 1
      matches:
        - path:
            type: PathPrefix
            value: /
EOF

查看 GatewayClass、Gateway、HTTPRoute 状态

❯ kg gatewayclass
NAME   CONTROLLER                                      ACCEPTED   AGE
eg     gateway.envoyproxy.io/gatewayclass-controller   True       46s
❯ kg gateway
NAME   CLASS   ADDRESS          PROGRAMMED   AGE
eg     eg      172.18.255.200   True         50s
❯ kg httproute
NAME      HOSTNAMES             AGE
backend   ["www.example.com"]   54s

可以看到上述资源状态都为正常,并且能获取正确的 LB IP

TLS 证书

  1. 生成根证书和私钥 用来签署其他证书:

    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
    
  2. www.example.com 创建证书签名请求 (CSR) 和一个新的私钥:

    openssl req -out www.example.com.csr -newkey rsa:2048 -nodes -keyout www.example.com.key -subj "/CN=www.example.com/O=example organization"
    openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in www.example.com.csr -out www.example.com.crt
    
  3. 使用根证书签署 CSR 生成 www.example.com 的证书:

    openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in www.example.com.csr -out www.example.com.crt
    
  4. 将证书和密钥存储在 Kubernetes Secret 中

    kubectl create secret tls example-cert --key=www.example.com.key --cert=www.example.com.crt
    
  5. 更新 Kubernetes Gateway

    添加 HTTPS 监听器,监听 443 端口,并关联 example-cert Secret

      kubectl patch gateway eg --type=json --patch '[{
      "op": "add",
      "path": "/spec/listeners/-",
      "value": {
         "name": "https",
         "protocol": "HTTPS",
         "port": 443,
         "tls": {
           "mode": "Terminate",
           "certificateRefs": [{
             "kind": "Secret",
             "group": "",
             "name": "example-cert",
           }],
         },
       },
      }]'
    
  6. 使用 ClientTrafficPolicy 启用 HTTP3

    kubectl apply -f - <<EOF
    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: ClientTrafficPolicy
    metadata:
      name: enable-http3
    spec:
      http3: {}
      targetRef:
        group: gateway.networking.k8s.io
        kind: Gateway
        name: eg
        namespace: default
    EOF
    
  7. 检查 Gateway 状态:

    可以看到 Gateway 状态是正常

    ❯ kubectl get gateway/eg
    NAME   CLASS   ADDRESS          PROGRAMMED   AGE
    eg     eg      172.18.255.200   True         6m36s
    

测试

  1. 获取 Gateway 的 External IP

    export GATEWAY_HOST=$(kubectl get gateway/eg -o jsonpath='{.status.addresses[0].value}')
    
  2. 通过 Gateway 查询示例应用程序:

    下面的示例使用了自定义的 docker 镜像和内置 http3 的自定义 curl 二进制文件

    docker run --net=host --rm ghcr.io/macbre/curl-http3 curl -kv --http3 -HHost:www.example.com --resolve "www.example.com:443:${GATEWAY_HOST}" https://www.example.com/get
    
  3. 结果:

    可以看到 HTTP3 的请求成功被 Envoy Gateway 处理

    * Added www.example.com:443:172.18.255.200 to DNS cache
    * Hostname www.example.com was found in DNS cache
    *   Trying 172.18.255.200:443...
    * Connect socket 5 over QUIC to 172.18.255.200:443
    * Sent QUIC client Initial, ALPN: h3,h3-29,h3-28,h3-27
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Skipped certificate verification
    * Connected to www.example.com () port 443 (#0)
    * h2h3 [:method: GET]
    * h2h3 [:path: /get]
    * h2h3 [:scheme: https]
    * h2h3 [:authority: www.example.com]
    * h2h3 [user-agent: curl/7.84.0-DEV]
    * h2h3 [accept: */*]
    * Using HTTP/3 Stream ID: 0 (easy handle 0x4001e77ac0)
    > GET /get HTTP/3
    > Host:www.example.com
    > user-agent: curl/7.84.0-DEV
    > accept: */*
    >
    < HTTP/3 200
    < content-type: application/json
    < x-content-type-options: nosniff
    < date: Thu, 21 Dec 2023 09:05:52 GMT
    < content-length: 513
    < x-envoy-upstream-service-time: 0
    < alt-svc: h3=":10443"; ma=86400
    < server: envoy
    <
    { [513 bytes data]
    {
     "path": "/get",
     "host": "www.example.com",
     "method": "GET",
     "proto": "HTTP/1.1",
     "headers": {
      "Accept": [
       "*/*"
      ],
      "User-Agent": [
       "curl/7.84.0-DEV"
      ],
      "X-Envoy-Expected-Rq-Timeout-Ms": [
       "15000"
      ],
      "X-Envoy-Internal": [
       "true"
      ],
      "X-Forwarded-For": [
       "172.18.0.1"
      ],
      "X-Forwarded-Proto": [
       "https"
      ],
      "X-Request-Id": [
       "0c165237-5993-4539-8942-0899d6120409"
      ]
     },
     "namespace": "default",
     "ingress": "",
     "service": "",
     "pod": "backend-58d58f745-l878w"
    100   513  100   513    0     0   3977      0 --:--:-- --:--:-- --:--:-- 13864
    * Connection #0 to host www.example.com left intact
    }%
    

至此,你已经通过 Envoy Gateway 使用 HTTP3 监听下游服务,并访问到目标后端服务。

comments powered by Disqus

Related Posts

Envoy Gateway v0.6 发布

Envoy Gateway v0.6 发布

本文介绍 Envoy Gateway v0.6.0 版本发布有哪些变化

Read More
Envoy Gateway 通往 GA 之路

Envoy Gateway 通往 GA 之路

本文介绍了 Envoy Gateway 对 GA 做了哪些准备

Read More
Envoy Gateway 快速开始

Envoy Gateway 快速开始

本文介绍如何快速部署 Envoy Gateway,以及通过一个简单的例子,来展示如何通过 Envoy Gateway 访问 kubernetes 集群中的服务。

Read More