cilium connectivity test: Validate the Data Plane
cilium connectivity test deploys test workloads and exercises pod-to-pod, pod-to-service, and egress paths to prove the data plane actually works.
This is the deepest Cilium gate: it does not just check that pods are up, it sends real traffic and reports exactly which path failed.
What it does
cilium connectivity test creates a dedicated test namespace with client and server pods, then runs a matrix of connectivity scenarios (pod to pod, pod to service, DNS, egress, and policy enforcement). Each scenario passes or fails, and the command exits non-zero if any fail.
Common usage
cilium connectivity test
# run only a subset by name
cilium connectivity test --test pod-to-service
# keep the test namespace for debugging on failure
cilium connectivity test --test '!pod-to-world'Options
| Flag | What it does |
|---|---|
| --test <pattern> | Run only matching tests (prefix ! to exclude) |
| --namespace <ns> | Namespace to create test resources in |
| --force-deploy | Redeploy the test workloads even if present |
| --collect-sysdump-on-failure | Gather a sysdump when a test fails |
| --hubble=false | Skip Hubble flow validation |
In CI
Run cilium connectivity test after cilium status --wait as an integration gate on a fresh cluster. It is slow, so it belongs in a dedicated job, not on every PR. Add --collect-sysdump-on-failure so a red run leaves you evidence to debug.
Common errors in CI
A failing scenario prints like "[=] Test [pod-to-service] ... FAILED" followed by the specific request that failed and the curl exit code. "connectivity test failed: 2 tests failed" is the summary that fails the job. "unable to detect Cilium version" means the CLI cannot find the agent; check namespace and that cilium status is healthy first.
Using this in CI
A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods
# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info
# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes