You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过K3S TestContainers测试Istio EnvoyFilter中的Lua代码?

用K3S TestContainers在Java集成测试中验证Istio嵌入式Lua脚本

完全可以这么做,这种容器化的测试方案能彻底解决真实Kubernetes环境测试慢的问题,非常适合回归测试场景。下面是具体的实现步骤和关键细节:

具体实现步骤

1. 启动K3S TestContainers实例

用TestContainers的K3sContainer快速拉起轻量Kubernetes集群,注意禁用自带的Traefik避免和Istio Ingress冲突:

K3sContainer k3s = new K3sContainer("rancher/k3s:v1.27.3-k3s1")
    .withCommand("server", "--disable", "traefik")
    .withExposedPorts(6443)
    .withResources(ResourceRequirements.builder()
        .limits(CpuCount.of(2), MemorySize.of("4Gi"))
        .build()); // 分配足够资源避免Istio安装失败
k3s.start();

// 获取KubeConfig用于后续Kubernetes操作
String kubeConfig = k3s.getKubeConfigYaml();

2. 在K3S中安装Istio

通过容器内执行istioctl命令安装Istio,选择demo配置文件足够满足测试需求,资源占用更低:

// 下载并安装指定版本的Istio
k3s.execInContainer(
    "sh", "-c",
    "curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.18.2 sh - && " +
    "istio-1.18.2/bin/istioctl install --set profile=demo -y"
);

// 等待Istio核心组件就绪(用Fabric8 Kubernetes Client检查)
try (KubernetesClient client = new DefaultKubernetesClient(new ConfigBuilder().withKubeconfig(kubeConfig).build())) {
    client.pods().inNamespace("istio-system")
          .waitUntilCondition(pod -> "Running".equals(pod.getStatus().getPhase()), Duration.ofMinutes(5));
}

3. 部署Nginx并启用Istio Sidecar

给默认命名空间开启Sidecar自动注入,然后部署Nginx的Deployment和Service:

// 启用默认命名空间的Istio Sidecar注入
k3s.execInContainer("kubectl", "label", "namespace", "default", "istio-injection=enabled");

// 定义Nginx的K8s资源YAML
String nginxYaml = """
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
""";

// 部署Nginx资源
k3s.copyFileToContainer(Transferable.of(nginxYaml.getBytes()), "/tmp/nginx.yaml");
k3s.execInContainer("kubectl", "apply", "-f", "/tmp/nginx.yaml");

// 等待Nginx Pod就绪
try (KubernetesClient client = new DefaultKubernetesClient(new ConfigBuilder().withKubeconfig(kubeConfig).build())) {
    client.pods().inNamespace("default").withLabel("app=nginx")
          .waitUntilCondition(pod -> "Running".equals(pod.getStatus().getPhase()), Duration.ofMinutes(2));
}

4. 配置Envoy Filter嵌入Lua脚本

创建Envoy Filter资源,在Sidecar的入站HTTP链中插入Lua脚本,实现自定义请求头生成:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: lua-header-filter
  namespace: default
spec:
  workloadSelector:
    labels:
      app: nginx
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        portNumber: 8080
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
            subFilter:
              name: "envoy.filters.http.router"
    patch:
      operation: INSERT_BEFORE
      value:
        name: envoy.filters.http.lua
        typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inline_code: |
            function envoy_on_request(request_handle)
              -- 生成自定义请求头
              request_handle:headers():add("X-Generated-By", "Istio-Lua-Script")
              request_handle:headers():add("X-Request-Timestamp", tostring(os.time()))
            end

在Java中部署这个Envoy Filter:

String envoyFilterYaml = // 上述YAML内容
k3s.copyFileToContainer(Transferable.of(envoyFilterYaml.getBytes()), "/tmp/lua-filter.yaml");
k3s.execInContainer("kubectl", "apply", "-f", "/tmp/lua-filter.yaml");

5. 执行端到端测试验证效果

通过端口转发将Nginx服务暴露到本地,发送请求并检查Lua生成的请求头:

// 启动端口转发
Process portForward = k3s.execInContainer("kubectl", "port-forward", "service/nginx-service", "8080:80");
Thread.sleep(2000); // 等待端口转发就绪

// 发送请求并验证响应头
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity("http://localhost:8080", String.class);

// 断言Lua脚本生成的头存在且符合预期
assert response.getHeaders().containsKey("X-Generated-By");
assert "Istio-Lua-Script".equals(response.getHeaders().getFirst("X-Generated-By"));
assert response.getHeaders().containsKey("X-Request-Timestamp");

// 停止端口转发
portForward.destroy();

关键注意事项

  • 资源分配:必须给K3S容器分配足够的CPU和内存,否则Istio组件可能因资源不足启动失败。
  • 就绪等待:所有K8S资源(Istio、Nginx)都要等待Pod进入Running状态再执行测试,避免过早请求导致失败。
  • Lua调试:可以通过kubectl logs <nginx-pod-name> istio-proxy查看Envoy Sidecar日志,排查Lua脚本的执行问题(脚本中可通过request_handle:logInfo("调试信息")输出日志)。
  • 测试隔离:每个测试用例可启动独立的K3S实例,或测试后清理所有K8S资源,避免测试间的干扰。

内容的提问来源于stack exchange,提问作者bobmarksie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 16:33:27