bug: ALB reports an HTTP 503 IP target as healthy despite a 200 health-check matcher #68
AndreKurait
started this conversation in
Bugs (AWS)
Replies: 1 comment
|
Hi @AndreKurait, thanks for this report as well. I have escalated this to my engineers, so I will notify you as soon as a fix is ready. If there is anything else I can do for you, please let me know. |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Existing report search
I searched LocalStack's current Discussions and older issue tracker for ALB/IP-target health and unhealthy-target reports. I found no matching current report. Historical Moto issues about stopped, terminated, or deregistered instance targets are a different case; this reproduction uses a reachable IP target serving HTTP 503.
Current and expected behavior
An active application load balancer has a listener forwarding to an IP target group with:
/healthcheck;200;The target returns HTTP 503, including direct requests from the unmodified LocalStack parent container before and after the observation. Nevertheless,
DescribeTargetHealthreports healthy in all six samples at approximately 0, 5, 10, 15, 20 and 25 seconds. The final API readbacks confirm the active ALB, listener association and specified health-check settings.Expected: repeated unsuccessful checks should produce
unhealthy, normallyTarget.ResponseCodeMismatchfor this status-code mismatch, instead of accepting the target as healthy. See the AWS ALB health-check contract.This is a bounded 25-second health-state observation. It does not qualify request forwarding, automatic recovery, HTTPS/gRPC, instance termination, or every timing/threshold combination. No live AWS comparison was performed. If actual periodic HTTP checks are intentionally unsupported, please classify this as the corresponding missing capability and document the health-state limitation.
Measured versions
2026.7.55.1.462026.8.15.1.48Repository digests:
2026.7.5:sha256:0d74e1d2d7ce13a3cb25fc64cf15eb225f1c95c762e56e057bc6a9ed0ed293062026.8.1:sha256:4aef81c531684570d7b3cfd2805afa02194c929d52bbeedabb7d4874798b1572Measured on 2026-10-08. These are two specific version comparisons, not a claim about the latest release. The identical Python client and target fixture below were used in both final runs.
Both runs use Linux ARM64, the normal vendor entrypoint, dummy AWS credentials and a fresh isolated Docker network. There are no custom extensions, source patches, application packages or Docker socket mounts. The only target is the complete stdlib HTTP fixture below. The API client uses boto3/botocore 1.43.101. Owned API resources, parent, target and network are removed after each run.
The target is explicitly assigned a usable RFC1918 address (
10.254.200.10in the example), outside the first four and last addresses of its modeled subnet. The parent/24is split into two/25ALB subnets. Choose an unused nonoverlapping private network on your host. The script refuses reserved-address and too-small-subnet inputs.Reproduction
Save both Python files below. Use a host Python environment with boto3 installed, Docker, and your normal LocalStack license in
LOCALSTACK_AUTH_TOKEN. The token is passed by environment name; do not put it in a report or command transcript.prefix="ls-alb-health-$(python3 -c 'import uuid; print(uuid.uuid4().hex[:12])')", then create a disposable Docker network with an unused/24, for example:docker network create --subnet 10.254.200.0/24 "${prefix}-net"..10, without ports or mounts:docker run -d --name "${prefix}-target" --network "${prefix}-net" --ip 10.254.200.10 python:3.12-slim python -u -c "$(cat alb_http_503_sidecar.py)".docker run -d --name "${prefix}-parent" --network "${prefix}-net" -p 127.0.0.1:4589:4566 --env LOCALSTACK_AUTH_TOKEN -e DNS_ADDRESS=0 -e EC2_DOWNLOAD_DEFAULT_IMAGES=0 --tmpfs /var/lib/localstack localstack/localstack-pro:2026.7.5.python3 alb_ip_target_http_health.py --endpoint-url http://127.0.0.1:4589 --target-ip 10.254.200.10 --network-cidr 10.254.200.0/24.configuration_confirmed=true,observed_unhealthy=false, all six stateshealthy, and every API cleanup entry successful. Exit0 means the observation completed, not that expected health behavior passed.finally, remove only these owned containers withdocker rm -f "${prefix}-parent" "${prefix}-target", thendocker network rm "${prefix}-net". The random prefix keeps cleanup scoped to this invocation. The Python client'sfinallyremoves the synthetic API resources; the outer cleanup remains necessary on any setup/client failure.Connectivity snippet (run before and after):
The expected observed health shape is:
{"Target":{"Id":"10.254.200.10","Port":8080},"HealthCheckPort":"traffic-port","TargetHealth":{"State":"healthy"}}alb_http_503_sidecar.py
alb_ip_target_http_health.py
All reactions