Incident Library

IL-0433 MonotaRO · 2023-08-24 (published)kubernetesawsnetworking

Shifting API traffic from EC2 to EKS on Fargate overloaded two CoreDNS pods and caused mass name-resolution errors

MonotaRO was moving a monolithic backend API with more than 200 endpoints from EC2 to EKS, with Fargate for the nodes and Datadog and Sentry for monitoring. The ALB shifted the share of requests per endpoint step by step. After some endpoints had been moved, raising the rest from 1% to 25% produced mass name resolution errors, and the traffic was moved back to the EC2 version. The two CoreDNS pods had a 100m CPU request and a 170Mi memory limit, so Fargate ran each on a 0.25 vCPU machine, and the load on them exceeded the request. An HPA for CoreDNS was added as a stopgap and the migration was completed with it, but it raised running cost and scale-in still caused occasional resolution errors.

The CoreDNS logs showed each lookup of example.com first trying example.com.default.svc.cluster.local, example.com.svc.cluster.local and example.com.cluster.local for both A and AAAA records, each answered NXDOMAIN, before example.com. answered NOERROR. The pod's /etc/resolv.conf had options ndots:5, so any name with fewer than five dots was tried with every search domain first. The CoreDNS cache TTL had never been set and was the default of 5 seconds, shorter than the TTL of the DNS servers behind CoreDNS. The occasional errors on scale-in came from CoreDNS pods being cut off during termination.

The permanent fixes were dnsConfig with ndots set to "1" in the application Deployments, cache 600 in the Corefile in the coredns ConfigMap (CoreDNS reloaded the changed Corefile by itself without a pod restart), and lameduck 30s in the health plugin so a terminating CoreDNS pod keeps serving for 30 seconds. A preStop sleep was not possible because the CoreDNS image is a distroless image from Google with no shell.

Severity
–
Scope
Requests to the backend API on EKS failed to reach the database and outside services through the proxy, so the traffic shift was rolled back
Users affected
–
Region
–
Time to detect
–
Time to resolve
–

Symptoms

When MonotaRO raised the share of requests for the remaining endpoints of its backend API sent to EKS from 1% to 25%, Sentry filled with errors saying the API could not reach the database and outside services. The errors were about DNS name resolution, and the traffic had to be shifted back to the EC2 version.

The API is written in Python. Connections through the proxy failed with NewConnectionError('<urllib3.connection.HTTPSConnection object at 12345678>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution'), and database connections failed with OperationalError:(2005, "Unknown MySQL server host 'db.example.com' (-3)"). The switch was done at a quiet time, at about 1000 RPS against a peak of 2000 to 3000 RPS.

Name resolution in the cluster is done by CoreDNS, so the team suspected CoreDNS first. After moving the traffic back, the CoreDNS CPU and memory use showed load above the 100m CPU request in the CoreDNS pod spec. With that small request, Fargate had provisioned each CoreDNS pod on a 0.25 vCPU machine, and the Deployment had replicas: 2, so only two CoreDNS pods ran.

As a stopgap the team autoscaled CoreDNS with an HPA, which let the migration finish, but name resolution errors still appeared from time to time when the HPA scaled CoreDNS in.

Symptom DNS resolution failuresHigh error rate

Root cause

Trigger
MonotaRO raised the share of requests for the remaining API endpoints routed by the ALB to the EKS version from 1% to 25%.

Detection

Sentry showed a large number of errors about connecting to the database and outside services right after the traffic share was raised.

Remediation

Action items

Lessons

MonotaRO assumed that a managed service would not cause problems and so skipped researching other companies' migrations, load testing and monitoring. Staging differed from production in its network layout, so ndots differed between them, and staging databases could not take a high-load test. Looking at the CoreDNS logs and resolv.conf instead of guessing found that ndots:5 made lookups of outside names try every search domain first.

Sources

Related cases

Check your cluster for this

kubegap audits a Kubernetes cluster for conditions like the ones in this case, CoreDNS, Client-side DNS resolver and cache, Container CPU limit among them, read-only, from Claude Code or Codex. Its checks cite public reports like this one.

For AI tools and scripts

The API needs no key. The MCP server offers search_incidents, get_incident, list_incidents, get_topic and vocab; both are explained on API and MCP.