The logs showed a denied network connection, not a bug in the code. It was a missing Kubernetes Network Policy.
In Kubernetes, network policies decide which pods can talk to each other, or to the outside world. Without them, services are exposed. With them, you get control: only the right traffic flows. When you combine network policies with AWS S3 read-only roles, you lock down both network and data paths.
A Kubernetes Network Policy works by selecting pods with labels and defining the allowed ingress and egress rules. You write YAML that specifies namespace selectors, pod selectors, and CIDR blocks. Apply it, and Kubernetes enforces it at the CNI level. This means you can block all outbound traffic except AWS S3 endpoints. This is critical when your workloads should only read from S3.
AWS S3 read-only roles use IAM policies to grant “GetObject” access without “PutObject” or “DeleteObject.” The setup starts with an IAM role scoped to the S3 bucket and paths you choose. Then, integrate with Kubernetes service accounts via IRSA (IAM Roles for Service Accounts). The pod picks up the permissions automatically at runtime.