Skip to content

CNS corrupts IPAM and Endpoint state when CNI calls arrive out of order #4829

Description

@rbtr

Summary:

In stateless-CNI mode (ManageEndpointState=true), CNS handles CNI ADD and DEL as two independent, unsynchronized sequences that mutate two different stores in opposite order:

Operation 1st mutation 2nd mutation
ADD (requestipconfigs) in-memory IPAM (assign IP) endpoint statefile (write owner)
DEL (releaseipconfigs) endpoint statefile (delete owner) in-memory IPAM (free IP)

The CNI runtime may issue a cleanup DEL while an ADD for the same infra container is still in flight. When that happens, and when there is a delay in processing the original ADD, the two sequences may interleave and cross:

DEL: remove endpoint entry   -> no entry yet, no-op
ADD: assign IP in memory     -> IP = Assigned
ADD: write endpoint entry    -> statefile now says "containerX owns 10.x.y.z"
DEL: release IP in memory    -> IP = Available

CNS state is now corrupt: its memory IPAM pool says the IP is free, while its persisted endpoint statefile says the IP is owned by a container that no longer exists. CNS can later hands that same IP to a different pod, because it appears free in-memory, and it then writes a second endpoint entry for it to the statefile.

On the next CNS restart, endpointStateToPodInfoByIP() walks the statefile, sees the same IP owned by two container IDs, and returns ErrDuplicateIP. This is a terminal, unrecoverable error: CNS never finishes reconciliation and can never safely serve IPAM. Restarting CNS does not help, because the corruption is on disk.

Fixes: CNS should use Tombstone Deletes - processing a DEL should prevent a future ADD for the same containerid. CNS ADD/DEL should be synchronized and exclusive for the same containerid.

Mitigation / recovery for an already-broken node

Replace the node. Restarting is CNS or the Node is not sufficient.

kubectl cordon <node>
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# then delete/recreate the node via the node pool

⚠️ Do not simply delete the whole azure-endpoints.json. In stateless-CNI mode that file is the source of truth CNS uses to rebuild IPAM mappings on restart. Deleting it makes CNS believe every IP is free while running pods still hold them, which can cause genuine duplicate assignment and IP leaks.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions