fix(dataplane): make container workloads and load balancers reach each other - #2666
Merged
Merged
Conversation
vieiralucas
force-pushed
the
fix-container-dataplane-reachability
branch
2 times, most recently
from
October 2, 2026 22:24
1a20063 to
72dba7d
Compare
vieiralucas
force-pushed
the
fix-container-dataplane-reachability
branch
2 times, most recently
from
October 4, 2026 10:59
33307ae to
5c0ba3e
Compare
…h other - ELBv2 -> awsvpc ECS: ENI private IP allocated from the task's subnet CIDR (EC2 lookup on the delivery bus), container ports published ephemerally and registered with a shared core dataplane resolver the ALB data plane and health prober use; DescribeTasks/target health keep the ENI IP. - ELBv2 -> EC2 i-* targets: the EC2 runtime installs an instance resolver that starts a socat forwarder per instance port on demand. - EC2 instances reach IMDS at 169.254.169.254 (docker sidecar / k8s sidecar: nft redirect -> loopback nginx -> per-instance /_fakecloud/ec2/imds route with the instance's identity and instance-profile role); user-data waits for it; AWS_EC2_METADATA_SERVICE_ENDPOINT fallback without a helper image. - ECS ECR pulls use the registry host shared with Lambda (loopback, podman machine alias, FAKECLOUD_ECR_REGISTRY_HOST), not the sibling alias. - MSK broker gets a container-facing listener; container env rewriting (Lambda, ECS, CodeBuild) now covers bare host / host:port / DSN loopback endpoints and swaps in the container listener port. - MSK retries port pairs taken on the daemon host; KDA publishes ephemerally; RDS sqlserver/db2 request linux/amd64.
- EC2 forwarders: serialize creation per (instance, port), sweep in-flight ones by label on stop, never forward to a stopped instance (address cleared on stop/reboot, re-validated after a forwarder starts). - Forwarders count as members of the load balancer's security groups in the nft firewall model (LB groups passed through the dataplane resolver), so an instance SG admitting only the ALB's group admits its traffic. - IMDS readiness marker on a tmpfs, so user-data waits for IMDS again after stop/start and reboot. - ECS: awsvpc service tasks get their ENI attachment at creation (decided by the task definition's network mode); the k8s backend attaches the ENI for every awsvpc task. - FAKECLOUD_ECR_REGISTRY_HOST override is authorized in the registry auth map. - elbv2 docs: targets are health-checked; how targets are reached.
…ring - Forwarder security groups accumulate across load balancers sharing a target; the firewall re-renders only when the set grows. - A new forwarder's endpoint is returned only after the firewall re-render admitting it has landed. - remove_sidecars lists in-flight forwarders with an async, bounded CLI call. - The stale-forwarder check runs under the per-(instance, port) lock before the forwarder is recorded, so it can never drop a newer one. - A running instance whose address is unknown (failed inspect after a reboot) is re-inspected on demand instead of staying unreachable. - Firewall / NetworkPolicy models are built inside the reconcile lock.
…le lock The helper image build and sidecar setup ran inside run_instance / start / reboot, whose caller holds the instance lifecycle lock that reset, stop and terminate wait on, so a reset right after RunInstances stalled for the whole setup. The setup now runs as a detached task that re-checks the instance is still the same running container; the env fallback is decided from the cached helper state without waiting.
After rebasing onto the deferred reset teardown (#2677): the reset test now also checks the IMDS sidecar is removed, the duplicate reset e2e is dropped (ec2_instance_runtime covers it), and fake CLI scripts wait out ETXTBSY before use so parallel tests forking can't fail their first exec.
… path Reuse vpc_lookup::create_service_eni (#2674) for awsvpc task ENIs instead of allocating a private IP from the subnet CIDR on the ECS side: the ENI is a real EC2 interface (DescribeNetworkInterfaces, EC2's own address allocator, the service's security groups, described by the attachment ARN) and is deleted when the task stops. Subnets EC2 doesn't know keep a synthetic ENI. Also track the Flink REST port read back after start on the cluster tracked at create (#2667).
vieiralucas
force-pushed
the
fix-container-dataplane-reachability
branch
from
October 4, 2026 12:18
5c0ba3e to
62cfdcf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Container data-plane reachability fixes (bug audit 2026-10-01, Tier 0.10/0.11 + 1g). AWS-visible addresses stay in every API response; fakecloud now resolves them to sockets it can actually open.
Ec2NetworkLookuphook on the delivery bus; AWS-reserved addresses and IPs held by live tasks are skipped;10.0.0.0/16fallback), withsubnetId,networkInterfaceId,privateDnsName. RunTask precreates the ENI attachment (PRECREATED). awsvpc container ports are published on ephemeral host ports and registered in a newfakecloud_core::dataplaneresolver (<ENI IP>:<containerPort>->sibling_host:<hostPort>). The ELBv2 data plane and health prober resolve through it; access logs keep the ENI IP. k8s backend: ENI attaches at Running and targets route to the Pod IP.i-*(MEDIUM-HIGH). The EC2 runtime installs an instance resolver: the first time a target group routes toi-...:<port>, it starts a socat forwarder (default bridge + subnet network, ephemeral published port). Forwarders are removed on stop/reboot/terminate/reset.container_net::ecr_registry_host: loopback,host.containers.internalfor podman machine (macOS/Windows), andFAKECLOUD_ECR_REGISTRY_HOSToverrides. It no longer usessibling_host.--network container:; k8s: a second Pod container). The sidecar adds an nft/iptables redirect of169.254.169.254:80to a loopback nginx, which forwards to the new server route/_fakecloud/ec2/imds/<instance-id>/latest/*. That route answers with the instance's own id, AMI, type, local-ipv4, AZ, identity document, and its instance-profile role credentials (404 underiam/when there's no profile). User-data waits (up to 60s) for/run/fakecloud/imds-ready. If the helper image can't be had, the instance getsAWS_EC2_METADATA_SERVICE_ENDPOINTinstead. The helper image is built locally (alpine + nftables + nginx + socat); override it withFAKECLOUD_EC2_HELPER_IMAGE.CONTAINERlistener advertised ashost_alias:P2. Env rewriting is now one shared helper,container_net::rewrite_loopback_value, used by Lambda, ECS and CodeBuild. It covers URLs, bare127.0.0.1/localhost,host:portlists and DSNs, and swaps the registered container-listener port into127.0.0.1:P. Prose likeEHLO localhostand look-alikes like127.0.0.10are left alone.--platform linux/amd64.Non-code surfaces:
FAKECLOUD_EC2_HELPER_IMAGE,FAKECLOUD_ECR_REGISTRY_HOST), the instance-credentials guide, and AGENTS.md./_fakecloud/*introspection endpoint for SDK users./_fakecloud/ec2/imds/...is internal plumbing for the in-instance proxy.Test plan
Unit tests:
dataplaneresolver (registered endpoint vs. fallback vs. instance resolver, account scoping),rewrite_loopback_valuecases,ecr_registry_hostresolution,parse_published_port, ENI IP allocation (subnet bounds, reserved addresses, in-use skip, exhaustion), awsvpc ephemeral publish argv (task and holder), ECS env rewrite of bare endpoints, ELBv2 upstream resolution plus a prober test against a published awsvpc target (HTTP and TCP), EC2 sidecar/forwarder argv, the IMDS setup script run undershwith fake tools (proxy starts before the redirect, readiness file is written), k8s instance Pod sidecar plus shared volume, Kafka listener env/args, port-conflict detection, and the container-port registration round trip. KDA publish spec and RDS platform.cargo test --lib --binspasses for core, elbv2, ecs, ec2, kafka, kinesisanalyticsv2, rds, lambda, codebuild and fakecloud.cargo test -p fakecloud-conformance ecs_: 78/78 pass. Workspacecargo clippy --all-targets -D warningsandcargo fmtare clean.New Docker-backed E2E
crates/fakecloud-e2e/tests/container_dataplane_reachability.rs:169.254.169.254, including from user-data;FAKECLOUD_IN_CONTAINER=1.The local Docker daemon hangs (
docker infotimes out), so these E2E tests ran only in CI (general partitions). They compile locally (--no-run).Summary by cubic
Makes container workloads and the load balancers in front of them reachable through the data plane: an ALB can route to
awsvpcECS tasks and EC2 instance ports, and EC2 instances reach the real IMDS inside their container.Reachability fixes
awsvpcECS tasks get a real requester-managed ENI created by EC2 in the task's subnet (visible in DescribeNetworkInterfaces, using the service's security groups) —PRECREATEDat task creation, attached on start, deleted when the task stops; subnets EC2 doesn't know keep a synthetic ENI. Container ports publish to ephemeral host ports registered in a new shareddataplaneresolver the ALB data plane and health prober consult, keeping the ENI IP in every API response.169.254.169.254:80to a per-instance IMDS route serving the instance's own identity and instance-profile credentials; user-data waits for a tmpfs readiness marker that resets on stop/start/reboot. The helper-image build and sidecar setup run as a detached task outside the lifecycle lock, so a reset right after run/start no longer stalls on them.host:port/DSN endpoints to it.Other fixes
FAKECLOUD_ECR_REGISTRY_HOSToverride is authorized in the registry auth map.linux/amd64.FAKECLOUD_EC2_HELPER_IMAGEandFAKECLOUD_ECR_REGISTRY_HOSToverrides documented; ELBv2 targets are now health-checked. No SDK changes.Written for commit 62cfdcf. Summary will update on new commits.