With AWS IAM Roles for service accounts (https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) you can now manage all IAM role access through container service accounts, so the instance metadata endpoint is a security liability. AWS recommends disabling access to it (https://docs.aws.amazon.com/eks/latest/userguide/restrict-ec2-credential-access.html) but you can use Calico to do it also.
Install calico https://docs.aws.amazon.com/eks/latest/userguide/calico.html and calicoctl https://github.com/projectcalico/calicoctl. Set up the environment variables so calico can speak to EKS
export CALICO_DATASTORE_TYPE=kubernetes
export CALICO_KUBECONFIG=~/.kube/config
Create the policy which blocks traffic to the instance metadata IP.
cat <<EOF > block-ec2-instance-metadata.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: deny-ec2-instance-metadata
spec:
order: 0
types:
- Egress
egress:
- action: Deny
destination:
nets:
- 169.254.169.254/32
source: {}
EOF
Apply the policy
calicoctl apply -f block-ec2-instance-metadata.yaml
Now every pod will have access to 169.254.169.254
blocked.
This does have the potential downside that a container started before the calico container on a node might be able to briefly access the metadata endpoint, whereas the iptables launch config AWS recommendation would not allow that. I couldn't get that to work with calico however.