What happened:
On an EKS cluster where kube-proxy's initial iptables sync takes longer than usual, a new node can become Ready and start workloads before the Kubernetes Service ClusterIP is usable on that node. The network policy agent builds its Kubernetes client with rest.InClusterConfig(), so it initially targets that Service ClusterIP.
The resulting startup sequence is:
- the network policy agent starts before kube-proxy's initial sync completes;
- API requests to the Kubernetes Service IP time out;
- the PolicyEndpoint informer cache does not sync before its deadline;
- the manager exits and the agent restarts; and
- a later attempt succeeds after kube-proxy finishes programming Service rules.
This has been observed consistently across new-node launches in the affected cluster.
Attach logs
Representative, anonymized messages:
Get "https://<kubernetes-service-ip>:443/apis/networking.k8s.aws/v1alpha1/policyendpoints?...": dial tcp <kubernetes-service-ip>:443: i/o timeout
problem running manager: failed to wait for policyendpoint caches to sync
The network policy agent's RuntimeConfig already has an APIServer field, but it is not bound to a CLI flag and BuildRestConfig does not use it.
What you expected to happen:
The agent should optionally accept a direct Kubernetes API server URL, while continuing to use the normal in-cluster service-account token and CA configuration. When configured with the EKS API endpoint, informer cache sync can proceed before kube-proxy has programmed the Kubernetes Service ClusterIP, avoiding the startup restart loop.
A narrow implementation would:
- expose the existing field as an optional
--apiserver flag;
- construct the REST config as it does today (in-cluster or
--kubeconfig); and
- override only
rest.Config.Host when --apiserver is set.
The default remains unchanged. This does not bypass informer cache synchronization; it only removes kube-proxy's Service VIP from the agent's bootstrap dependency chain. The deployment layer would still be responsible for supplying the endpoint.
How to reproduce it (as minimally and precisely as possible):
- Delay kube-proxy's first iptables sync on a new node.
- Start
aws-node with network policy enabled on that node.
- Allow the node to become Ready before kube-proxy finishes its initial sync.
- Observe the network policy agent time out connecting to the Kubernetes Service ClusterIP and exit after its PolicyEndpoint cache-sync deadline.
- Observe a subsequent restart succeed only after kube-proxy completes its first sync.
Anything else we need to know?:
The EKS API endpoint is routable directly from the node before kube-proxy is ready. Dynamically calling DescribeCluster from the agent is not necessary; the endpoint can be injected by the deployment/add-on layer. The same unused APIServer field and in-cluster-only behavior are present in released and current source.
Detailed timestamps and environment versions can be shared privately if useful.
Environment:
- Kubernetes version (use
kubectl version): EKS (details available privately)
- CNI Version: details available privately
- Network Policy Agent Version: reproduced on a released version; current source has the same configuration gap
- OS: Amazon Linux
- Kernel: details available privately
What happened:
On an EKS cluster where kube-proxy's initial iptables sync takes longer than usual, a new node can become Ready and start workloads before the Kubernetes Service ClusterIP is usable on that node. The network policy agent builds its Kubernetes client with
rest.InClusterConfig(), so it initially targets that Service ClusterIP.The resulting startup sequence is:
This has been observed consistently across new-node launches in the affected cluster.
Attach logs
Representative, anonymized messages:
The network policy agent's
RuntimeConfigalready has anAPIServerfield, but it is not bound to a CLI flag andBuildRestConfigdoes not use it.What you expected to happen:
The agent should optionally accept a direct Kubernetes API server URL, while continuing to use the normal in-cluster service-account token and CA configuration. When configured with the EKS API endpoint, informer cache sync can proceed before kube-proxy has programmed the Kubernetes Service ClusterIP, avoiding the startup restart loop.
A narrow implementation would:
--apiserverflag;--kubeconfig); andrest.Config.Hostwhen--apiserveris set.The default remains unchanged. This does not bypass informer cache synchronization; it only removes kube-proxy's Service VIP from the agent's bootstrap dependency chain. The deployment layer would still be responsible for supplying the endpoint.
How to reproduce it (as minimally and precisely as possible):
aws-nodewith network policy enabled on that node.Anything else we need to know?:
The EKS API endpoint is routable directly from the node before kube-proxy is ready. Dynamically calling
DescribeClusterfrom the agent is not necessary; the endpoint can be injected by the deployment/add-on layer. The same unusedAPIServerfield and in-cluster-only behavior are present in released and current source.Detailed timestamps and environment versions can be shared privately if useful.
Environment:
kubectl version): EKS (details available privately)