MITupdated 21d ago
Two modes: Flaky E2E Fix (Kuma/Ginkgo test files) and Mesh Connectivity Debug (live cluster issues).
What can you do with Service Mesh Debug?
name: service-mesh-debug description: > Diagnose and fix flaky e2e tests and general connectivity issues in service mesh environments (Kuma, Istio, Linkerd, Consul). Trigger when: a user mentions intermittent test failures, "test is flaky", e2e failures in CI that don't reproduce locally, Ginkgo/Gomega test files that fail sometimes, 503/connection refused errors, mTLS handshake failures, pods not getting traffic, xDS NACKs or warming resources, cert delivery timing issues, or "works locally but not in cluster". Covers Kuma flakiness patterns (timing races, xDS propagation delays, Envoy circuit breakers, mTLS readiness, Gomega misuse) AND universal mesh debugging (control plane connectivity, proxy lifecycle, certificate problems, traffic routing/policy, service discovery). allowed-tools: Read, Grep, Bash user-invocable: true
Fix Flaky E2E / Service Mesh Debugging Skill
Two modes: Flaky E2E Fix (Kuma/Ginkgo test files) and Mesh Connectivity Debug (live cluster issues).
Scope
- Designed for Kuma/Envoy e2e test flakiness and service mesh connectivity issues
- Not designed for unit test failures, application-level bugs, or non-mesh networking problems
- Assumes the test framework is Ginkgo/Gomega with the Kuma
test/framework/helpers (Mode 1) or a live K8s cluster with mesh sidecar injection (Mode 2)
Mode 1: Flaky E2E Fix
Kuma e2e tests use Ginkgo/Gomega with a custom framework in test/framework/. Flakiness almost
always traces to one of ~11 known root causes. The fix is usually a 1-3 line change.
Process (Flaky E2E)
1. Read the test
Read the file the user provides (or grep for it). Focus on:
Eventually/Consistentlycalls and their timeout stringsExpect(...)calls insideEventuallyblocks- Pod creation / deletion sequences
- Where traffic assertions happen relative to resource creation
- Any
time.Sleepcalls
2. Diagnose: match to the taxonomy
Read references/root-causes.md in full before matching — it contains code examples and fix patterns for all 11 root causes. The most common causes in order of frequency:
| # | Pattern | Fast signal |
|---|---|---|
| 1 | Short Eventually timeout |
"30s" near gateway/policy/mTLS code |
| 2 | Missing xDS readiness gate | Traffic asserted immediately after policy apply |
| 3 | Bare Expect inside Eventually |
Eventually(func() { Expect(...) }) — no g Gomega |
| 4 | Pod not available after create | WaitUntilNumPodsCreatedE without WaitUntilPodAvailableE |
| 5 | PodNameOfApp race after kill |
Called immediately after KillAppPod |
| 6 | External component not awaited | SPIRE / cert-manager / Postgres creation without availability wait |
| 7 | xDS config diff before convergence | config_dump compare without Eventually wrapper |
| 8 | SDS secret timing | mTLS test fails with Secret is not supplied by SDS |
| 9 | Statistical tight margins | Traffic split % assertion with small N |
| 10 | Circuit breaker tripped | Concurrent test runs exhaust CB defaults |
| 11 | Outlier detection ejection | Fault-injection test leaves host ejected for 30s |
3. Apply the minimal fix
Read references/fix-patterns.md before applying any fix — it contains copy-paste templates matched to each root cause.
Key rules:
- Change only what's flaky — keep the diff minimal so reviewers can verify the fix in isolation.
- Use the root-cause-specific fix pattern from fix-patterns.md. Never use
FlakeAttempts(n)as the primary fix because it hides root causes and lets the underlying race regress silently. - Replace
time.SleepwithEventuallybecause sleep-based waits are fragile under variable CI load and slow down the suite unnecessarily. - After fixing, run:
make format && make check - If
make checkreports failures, return to Step 2 with the error output and re-diagnose — the original root cause may have been misidentified.
4. Add AfterEachFailure if missing
If the test lacks a failure debug hook, suggest adding:
AfterEachFailure(func() {
DebugKube(KubeCluster, meshName, namespace)
})
This dumps CP logs, dataplane state, and pod info on failure — essential for future debugging.
5. Envoy diagnosis (if needed)
If the failure involves connectivity, xDS config, or mTLS and you need to guide the user through live debugging, read references/envoy-debug.md before starting — it contains the full admin API reference and 7-step diagnostic workflow.
For live cluster debugging, suggest running the scripts in scripts/ directly against the pod:
# Full diagnostic snapshot (saves to ./envoy-snapshot-<pod>-<ts>/)
"${CLAUDE_SKILL_DIR}/scripts/envoy_snapshot.py" <pod> -n <namespace>
# xDS health: CP connected? NACKs? Warming resources? Specific cluster present?
"${CLAUDE_SKILL_DIR}/scripts/xds_check.py" <pod> -n <namespace> --cluster <cluster-name>
# mTLS health: warming secrets? cert expiry? TLS error stats?
"${CLAUDE_SKILL_DIR}/scripts/mtls_check.py" <pod> -n <namespace>
Scripts require only kubectl in PATH and Python 3.9+. No extra dependencies.
All scripts support --admin-port (default 9901) for non-Kuma meshes (Istio: 15000, Consul: 19000).
Mode 2: Mesh Connectivity Debugging
For general connectivity issues in any service mesh (503s, cert errors, traffic blocked, no healthy hosts, policy denials), follow the 7-phase workflow.
Quick start
# 1. Auto-detect mesh and check control plane health
"${CLAUDE_SKILL_DIR}/scripts/mesh_health.py"
# 2. Run Envoy diagnostics on the affected pod (adjust --admin-port for your mesh)
"${CLAUDE_SKILL_DIR}/scripts/xds_check.py" <pod> -n <ns> # Kuma
"${CLAUDE_SKILL_DIR}/scripts/xds_check.py" <pod> -n <ns> --admin-port 15000 --container istio-proxy # Istio
"${CLAUDE_SKILL_DIR}/scripts/mtls_check.py" <pod> -n <ns> # cert/mTLS issues
"${CLAUDE_SKILL_DIR}/scripts/envoy_snapshot.py" <pod> -n <ns> # full snapshot for offline analysis
Classify the failure first
Read references/failure-taxonomy.md to classify the issue into one of 6 categories before spending time on mesh-specific commands.
| Symptom | Category |
|---|---|
| All pods broken simultaneously | 1 – Control Plane |
| Single pod, no sidecar | 2 – Proxy Lifecycle |
Secret is not supplied by SDS |
3 – Certificates |
| TLS handshake failure | 3 – Certificates |
403 / UAEX flag |
4 – Policy |
UH / no healthy hosts |
5 – Service Discovery |
| Works on some nodes, not others | 6 – Infrastructure |
| Flaky in CI, passes locally | 1 or 3 |
Full debugging workflow
Read references/mesh-debug-workflow.md for the 7-phase workflow with mesh-specific commands for Kuma, Istio, Linkerd, and Consul.
Framework helpers quick reference
| Helper | Location | Use for |
|---|---|---|
WaitForMesh |
test/framework/resources.go |
Multi-zone mesh sync |
WaitForResource |
test/framework/resources.go |
Any resource to appear |
DebugKube / DebugUniversal |
test/framework/debug.go |
State dump on failure |
AfterEachFailure |
test/framework/ginkgo.go |
Hook debug to failure only |
ControlPlaneAssertions |
test/framework/debug.go |
Assert CP not crashed |
CollectEchoResponse |
test/framework/client/collect.go |
HTTP connectivity check |
CollectFailure |
test/framework/client/collect.go |
Assert expected conn failure |
MustPassRepeatedly(n) |
Gomega | Require N consecutive passes |
Within(timeout, task) |
pkg/test/within.go |
Goroutine with timeout |
Gomega timeout guidelines
| Context | Timeout | Rationale |
|---|---|---|
| Pod creation + readiness | "30s" |
Scheduler + kubelet startup |
| Policy propagation (simple) | "30s" |
CP reconcile + xDS push |
| Gateway / ingress policies | "60s" |
Extra reconcile cycles |
| mTLS / SVID / cross-zone | "2m" |
Cert issuance + KDS sync |
MustPassRepeatedly(5) |
"2m" |
Needs many attempts to confirm stable |
Polling interval: "1s" is standard. Use "500ms" only for fast local assertions.
Anti-patterns to flag
Expect(x)insideEventually(func() { ... })— must beEventually(func(g Gomega) { g.Expect(x) })WaitUntilNumPodsCreatedEalone — always follow withWaitUntilPodAvailableEper pod- Asserting traffic before checking xDS config convergence
time.Sleep(N * time.Second)— replace withEventuallyFlakeAttempts(3)as first resort
Install
Add Service Mesh Debug to your client. Pick the one you use.
npx skills add smykla-skalski/saiInstalls every skill in the repository, then prompts for which to keep.
/plugin marketplace add smykla-skalski/saiAdds the repository as a plugin marketplace; install individual plugins with `/plugin install`.
git clone https://github.com/smykla-skalski/sai
cp -r claude/service-mesh-debug/skills/service-mesh-debug ~/.claude/skills/A skill is a plain directory. Copy it into `.claude/skills/` in a project or in your home directory.
Score
87 / 100
Excellent