Skip to content

Commit aaf0a55

Browse files
authored
fix(e2e): scrape MetricCompressor stats from the proxy pod (#9942)
MetricCompressor* probed <gateway LoadBalancer IP>:19001/stats/prometheus. MetalLB recycles addresses from its pool as tests create and delete Services, and ProxyMetrics runs right before these tests with a LoadBalancer Service on the same port 19001 serving /metrics, so the compressor test can inherit that address and get a steady stream of 404s from the previous owner. In the run that prompted this, the proxy's own counters show only 2 connections ever reached 0.0.0.0_19001, so none of the failing probes made it to Envoy. Scrape the stats endpoint through a port-forward to the proxy pod instead, and drop the two pieces of the manifests that only existed to reach 19001 through the LoadBalancer: the unused <compressor>-gtw-metrics Services, which each took a pool address for nothing, and the envoyService port patch. Signed-off-by: Huabing (Robin) Zhao <zhaohuabing@gmail.com> Signed-off-by: Huabing (Robin) Zhao <huabing@tetrate.io>
1 parent e56c0ff commit aaf0a55

4 files changed

Lines changed: 35 additions & 96 deletions

File tree

test/e2e/testdata/metric-compressor-brotli.yaml

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,12 @@ metadata:
2525
namespace: gateway-conformance-infra
2626
spec:
2727
ipFamily: IPv4
28-
provider:
29-
type: Kubernetes
30-
kubernetes:
31-
envoyService:
32-
patch:
33-
value:
34-
spec:
35-
ports:
36-
- name: metrics
37-
protocol: TCP
38-
port: 19001
39-
targetPort: 19001
4028
telemetry:
4129
metrics:
4230
prometheus:
4331
compression:
4432
type: Brotli
4533
---
46-
apiVersion: v1
47-
kind: Service
48-
metadata:
49-
name: brotli-gtw-metrics
50-
namespace: envoy-gateway-system
51-
spec:
52-
selector:
53-
app.kubernetes.io/component: proxy
54-
app.kubernetes.io/managed-by: envoy-gateway
55-
app.kubernetes.io/name: envoy
56-
gateway.envoyproxy.io/owning-gateway-name: brotli-gtw
57-
gateway.envoyproxy.io/owning-gateway-namespace: gateway-conformance-infra
58-
ports:
59-
- name: metrics
60-
protocol: TCP
61-
port: 19001
62-
targetPort: 19001
63-
type: LoadBalancer
64-
---
6534
apiVersion: gateway.networking.k8s.io/v1
6635
kind: HTTPRoute
6736
metadata:

test/e2e/testdata/metric-compressor-gzip.yaml

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,12 @@ metadata:
2525
namespace: gateway-conformance-infra
2626
spec:
2727
ipFamily: IPv4
28-
provider:
29-
type: Kubernetes
30-
kubernetes:
31-
envoyService:
32-
patch:
33-
value:
34-
spec:
35-
ports:
36-
- name: metrics
37-
protocol: TCP
38-
port: 19001
39-
targetPort: 19001
4028
telemetry:
4129
metrics:
4230
prometheus:
4331
compression:
4432
type: Gzip
4533
---
46-
apiVersion: v1
47-
kind: Service
48-
metadata:
49-
name: gzip-gtw-metrics
50-
namespace: envoy-gateway-system
51-
spec:
52-
selector:
53-
app.kubernetes.io/component: proxy
54-
app.kubernetes.io/managed-by: envoy-gateway
55-
app.kubernetes.io/name: envoy
56-
gateway.envoyproxy.io/owning-gateway-name: gzip-gtw
57-
gateway.envoyproxy.io/owning-gateway-namespace: gateway-conformance-infra
58-
ports:
59-
- name: metrics
60-
protocol: TCP
61-
port: 19001
62-
targetPort: 19001
63-
type: LoadBalancer
64-
---
6534
apiVersion: gateway.networking.k8s.io/v1
6635
kind: HTTPRoute
6736
metadata:

test/e2e/testdata/metric-compressor-zstd.yaml

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,12 @@ metadata:
2525
namespace: gateway-conformance-infra
2626
spec:
2727
ipFamily: IPv4
28-
provider:
29-
type: Kubernetes
30-
kubernetes:
31-
envoyService:
32-
patch:
33-
value:
34-
spec:
35-
ports:
36-
- name: metrics
37-
protocol: TCP
38-
port: 19001
39-
targetPort: 19001
4028
telemetry:
4129
metrics:
4230
prometheus:
4331
compression:
4432
type: Zstd
4533
---
46-
apiVersion: v1
47-
kind: Service
48-
metadata:
49-
name: zstd-gtw-metrics
50-
namespace: envoy-gateway-system
51-
spec:
52-
selector:
53-
app.kubernetes.io/component: proxy
54-
app.kubernetes.io/managed-by: envoy-gateway
55-
app.kubernetes.io/name: envoy
56-
gateway.envoyproxy.io/owning-gateway-name: zstd-gtw
57-
gateway.envoyproxy.io/owning-gateway-namespace: gateway-conformance-infra
58-
ports:
59-
- name: metrics
60-
protocol: TCP
61-
port: 19001
62-
targetPort: 19001
63-
type: LoadBalancer
64-
---
6534
apiVersion: gateway.networking.k8s.io/v1
6635
kind: HTTPRoute
6736
metadata:

test/e2e/tests/metric.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"sigs.k8s.io/gateway-api/conformance/utils/tlog"
2727

2828
egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
29+
kube "github.com/envoyproxy/gateway/internal/kubernetes"
2930
"github.com/envoyproxy/gateway/test/utils/prometheus"
3031
)
3132

@@ -202,9 +203,13 @@ func runMetricCompressorTest(t *testing.T, suite *suite.ConformanceTestSuite, ns
202203
}
203204
httputils.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, expectedResponse)
204205

205-
// stats exposed at port 19001
206-
statsHost := strings.Replace(gwAddr, ":80", ":19001", 1)
207-
statsAddr := fmt.Sprintf("http://%s/stats/prometheus", statsHost)
206+
// Scrape the stats endpoint through a port-forward to the proxy pod rather than through the
207+
// Gateway's LoadBalancer address: MetalLB recycles addresses from its pool as tests create and
208+
// delete Services, so a probe of <gateway address>:19001 can be answered by whatever owned that
209+
// address a moment earlier, which shows up as a confusing HTTP error instead of a connect error.
210+
fwd := proxyStatsForwarder(t, suite, gwNN)
211+
defer fwd.Stop()
212+
statsAddr := fmt.Sprintf("http://%s/stats/prometheus", fwd.Address())
208213
tlog.Logf(t, "check stats from %s", statsAddr)
209214

210215
err := wait.PollUntilContextTimeout(t.Context(), time.Second, time.Minute, true, func(_ context.Context) (done bool, err error) {
@@ -220,6 +225,33 @@ func runMetricCompressorTest(t *testing.T, suite *suite.ConformanceTestSuite, ns
220225
}
221226
}
222227

228+
// proxyStatsForwarder starts a port-forward to the stats port of the Envoy proxy pod backing the
229+
// given Gateway. The caller is responsible for stopping the returned forwarder.
230+
func proxyStatsForwarder(t *testing.T, suite *suite.ConformanceTestSuite, gwNN types.NamespacedName) kube.PortForwarder {
231+
t.Helper()
232+
233+
cli, err := kube.NewForRestConfig(suite.RestConfig)
234+
require.NoError(t, err)
235+
236+
pods, err := cli.PodsForSelector(GetGatewayResourceNamespace(),
237+
"app.kubernetes.io/name=envoy",
238+
fmt.Sprintf("gateway.envoyproxy.io/owning-gateway-name=%s", gwNN.Name),
239+
fmt.Sprintf("gateway.envoyproxy.io/owning-gateway-namespace=%s", gwNN.Namespace),
240+
)
241+
require.NoError(t, err)
242+
require.NotEmpty(t, pods.Items, "no Envoy proxy pod found for Gateway %s", gwNN.String())
243+
244+
// stats are exposed at port 19001
245+
fwd, err := kube.NewLocalPortForwarder(cli, types.NamespacedName{
246+
Namespace: pods.Items[0].Namespace,
247+
Name: pods.Items[0].Name,
248+
}, 0, 19001)
249+
require.NoError(t, err)
250+
require.NoError(t, fwd.Start())
251+
252+
return fwd
253+
}
254+
223255
func checkStatsEncoding(suite *suite.ConformanceTestSuite, statsAddr string, compressorType egv1a1.CompressorType) error {
224256
req, err := http.NewRequest("GET", statsAddr, nil)
225257
if err != nil {

0 commit comments

Comments
 (0)