Files
juwan-backend/deploy/envoy/QUICK_REFERENCE.md
T
wwweww fdbcde13b2 add:
2026-02-23 20:36:21 +08:00

9.1 KiB
Raw Blame History

Envoy 配置完整清单

📋 配置文件清单

1. Proto 更新

  • 文件: desc/rpc/users.proto
  • 更改: 添加了两个 RPC 方法
    • ValidateToken(): 验证 token 是否有效(检查黑名单)
    • CheckPermission(): 检查用户权限

2. Envoy 部署

  • 配置文件: envoy.yaml

    • HTTP 监听器(端口 8080
    • HTTPS 监听器(端口 8443
    • JWT 验证过滤器
    • CSRF 防护过滤器
    • 速率限制(DDoS 防护)
    • 路由配置
  • K8s 部署: ../k8s/envoy-gateway.yaml

    • 2 个副本
    • 负载均衡器服务
    • Service Account 和 RBAC
    • Network Policy
    • ConfigMap 用于配置管理

3. 工具代码

  • JWKS 生成: app/users/rpc/internal/utils/jwks.go
    • GenerateJWKSFromSecret(): 从 JWT 密钥生成 JWKS
    • GenerateJWKSEndpoint(): 生成 JSON 输出供 Envoy 使用
    • ExtractTokenMetadata(): 提取 token 元数据

4. Dockerfile

  • 文件: Dockerfile
  • 用途: 构建 Envoy 容器镜像

5. 脚本

6. 文档


🚀 快速部署步骤

步骤 1: 生成 TLS 证书

# 测试环境:生成自签名证书
openssl req -x509 -newkey rsa:4096 -keyout tls.key -out tls.crt \
  -days 365 -nodes -subj "/CN=api.juwan.local"

# 创建 K8s Secret
kubectl create secret tls envoy-tls \
  --cert=tls.crt \
  --key=tls.key \
  -n juwan

步骤 2: 部署 Envoy Gateway

# 应用部署文件
kubectl apply -f deploy/k8s/envoy-gateway.yaml

# 验证部署
kubectl get pods -n juwan -l app=envoy-gateway
kubectl get svc -n juwan envoy-gateway

# 等待 LoadBalancer 获取外部 IP
kubectl get svc -n juwan envoy-gateway -w

步骤 3: 在 User RPC 中暴露 JWKS 端点

编辑 app/users/rpc/rpcserver.gomain.go

package main

import (
	"http"
	"os"
	"juwan-backend/app/users/rpc/internal/utils"
)

// 在启动 RPC server 前,添加 HTTP 端点
func setupJWKSEndpoint() {
	secretKey := os.Getenv("JWT_SECRET_KEY")
	if secretKey == "" {
		secretKey = "your-default-secret-key"
	}
	
	http.HandleFunc("/.well-known/jwks.json", func(w http.ResponseWriter, r *http.Request) {
		jwksJSON, err := utils.GenerateJWKSEndpoint(secretKey, "default-key-id")
		if err != nil {
			http.Error(w, "Failed to generate JWKS", http.StatusInternalServerError)
			return
		}
		
		w.Header().Set("Content-Type", "application/json")
		w.Header().Set("Cache-Control", "public, max-age=300") // 缓存 5 分钟
		w.Write([]byte(jwksJSON))
	})
	
	// 在独立的 goroutine 中启动 HTTP 服务器
	go func() {
		http.ListenAndServe(":8080", nil)
	}()
}

func main() {
	setupJWKSEndpoint()
	
	// ... 其他 RPC 启动代码 ...
}

步骤 4: 更新 User RPC 配置

编辑 app/users/rpc/etc/pb.yaml

Name: pb.rpc
ListenOn: 0.0.0.0:9001

Prometheus:
  Host: 0.0.0.0
  Port: 4001
  Path: /metrics

# ... 其他配置 ...

Jwt:
  SecretKey: "${JWT_SECRET_KEY:your-secret-jwt-key-change-this-in-production}"
  Issuer: "juwan-user-rpc"

步骤 5: 构建并推送容器镜像

# 构建 User API 镜像
docker build -t your-registry/user-api:latest ./app/users/api/
docker push your-registry/user-api:latest

# 构建 User RPC 镜像
docker build -t your-registry/user-rpc:latest ./app/users/rpc/
docker push your-registry/user-rpc:latest

# 构建 Envoy 镜像
docker build -f deploy/envoy/Dockerfile -t your-registry/envoy-gateway:latest .
docker push your-registry/envoy-gateway:latest

步骤 6: 更新 K8s 部署

更新 deploy/k8s/service/user/user-api.yamluser-rpc.yaml,确保使用正确的镜像和环境变量。


🧪 测试流程

1. 登录获取 Token

# 获取 Envoy 外部 IP
ENVOY_IP=$(kubectl get svc -n juwan envoy-gateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

# 登录
curl -k -X POST "https://$ENVOY_IP:443/api/v1/users/login" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "testuser",
    "password": "password123"
  }' | jq .

# 示例响应:
# {
#   "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
#   "expires": 1708780800
# }

2. 使用 Token 访问受保护资源

TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

curl -k -X GET "https://$ENVOY_IP:443/api/v1/users/123" \
  -H "Authorization: Bearer $TOKEN" | jq .

3. 验证 CSRF 防护

# POST 请求必须有正确的 Origin/Referer
curl -k -X POST "https://$ENVOY_IP:443/api/v1/users/logout" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Origin: https://api.juwan.local" \
  -H "Referer: https://api.juwan.local/" \
  -H "Content-Type: application/json" \
  -d '{"userId": 123}'

📊 验证检查清单

  • Envoy 容器运行正常

    kubectl logs -n juwan -l app=envoy-gateway
    
  • JWKS 端点可访问

    kubectl exec -it -n juwan <envoy-pod> -- \
      curl http://user-rpc-svc:9001/.well-known/jwks.json
    
  • 后端服务健康

    kubectl exec -it -n juwan <envoy-pod> -- \
      curl http://user-api-svc:8888/health
    
  • JWT 验证工作

    # 不带 token 访问受保护资源应返回 401
    curl -k https://api.juwan.local/api/v1/users/123
    
  • CSRF 防护生效

    # 缺少 Origin header 的 POST 应被拒绝
    curl -k -X POST https://api.juwan.local/api/v1/users/logout \
      -H "Authorization: Bearer $TOKEN"
    

🔧 配置调整

修改 JWT 密钥

# 1. 更新 K8s Secret
kubectl patch secret jwt-secret -n juwan \
  -p '{"data":{"JWT_SECRET_KEY":"'$(echo -n 'new-secret-key' | base64)'"}}'

# 2. 重启 User RPC 和 Envoy
kubectl rollout restart deployment/user-rpc-svc -n juwan
kubectl rollout restart deployment/envoy-gateway -n juwan

调整 Envoy 速率限制

编辑 ConfigMap

kubectl edit cm envoy-config -n juwan

修改 token_bucket 参数:

token_bucket:
  max_tokens: 5000       # 降低限制
  tokens_per_fill: 5000
  fill_interval: 1s

添加信任的 CSRF 来源

编辑 ConfigMap

additional_origins:
  - exact: "https://admin.juwan.local"
  - exact: "https://web.juwan.local"
  - prefix: "https://app.juwan.local"  # 支持前缀匹配

📈 监控和日志

查看 Envoy 统计

kubectl port-forward -n juwan svc/envoy-gateway 9901:9901
curl localhost:9901/stats | grep -E "(jwt_authn|csrf|http_ratelimit)"

实时日志

kubectl logs -n juwan -l app=envoy-gateway -f

# 查看特定日志行
kubectl logs -n juwan -l app=envoy-gateway | grep "401\|403"

监控指标(集成 Prometheus

# prometheus-scrape-config.yaml
- job_name: 'envoy-gateway'
  static_configs:
    - targets: ['envoy-gateway.juwan.svc.cluster.local:9901']
  metrics_path: '/stats/prometheus'

📚 相关文件位置

deploy/
├── envoy/
│   ├── envoy.yaml                    ← Envoy 核心配置
│   ├── ENVOY_CONFIG_GUIDE.md         ← 详细指南
│   ├── generate-jwks.sh              ← JWKS 生成脚本
│   ├── Dockerfile                     ← Envoy 镜像
│   └── QUICK_REFERENCE.md            ← 本文件
├── k8s/
│   ├── envoy-gateway.yaml            ← K8s 部署清单
│   └── secrets/jwt-secret.yaml        ← JWT 密钥配置
└── script/
    └── init-secrets.sh               ← 初始化脚本

app/users/
├── rpc/
│   ├── internal/utils/
│   │   ├── jwks.go                   ← JWKS 生成工具
│   │   └── jwt.go                    ← JWT 管理器
│   └── etc/pb.yaml                   ← RPC 配置
└── api/
    └── etc/user-api.yaml             ← API 配置

desc/
└── rpc/users.proto                   ← Proto 定义(已更新)

🤔 常见问题

  1. Envoy 无法连接到后端服务

    • 检查 K8s Service DNS: user-api-svc.juwan.svc.cluster.local
    • 验证 NetworkPolicy 允许流量
  2. JWT 验证失败

    • 确保 JWT_SECRET_KEY 一致
    • 检查 JWKS 端点是否可访问
    • 查看 Envoy 日志: grep "jwt_authn" envoy.log
  3. CSRF 防护过于严格

    • additional_origins 中添加允许的来源
    • 对于单页应用,确保发送 Origin header
  4. 速率限制阻止正常流量

    • 增加 max_tokenstokens_per_fill
    • 针对特定客户端配置不同的限制

📞 获取帮助