Diagnosing ImagePullBackOff for Private ECR Images on AWS EKS with IRSA
- Get link
- X
- Other Apps
Diagnosing ImagePullBackOff for Private ECR Images on AWS EKS with IRSA
Encountering ImagePullBackOff errors in a Kubernetes environment often signals a problem with accessing container images. When running AWS Elastic Kubernetes Service (EKS) and pulling private images from Elastic Container Registry (ECR) using IAM Roles for Service Accounts (IRSA), this error can point to a nuanced set of misconfigurations. This comprehensive guide provides a detailed breakdown of the common causes and a step-by-step troubleshooting manual to resolve ImagePullBackOff specifically in EKS/ECR/IRSA setups.
Understanding ImagePullBackOff and IRSA on EKS
The ImagePullBackOff status indicates that a Kubernetes pod is unable to pull its specified container image. While generic, in an EKS context leveraging IRSA for private ECR access, this typically means a breakdown in the authentication and authorization chain. IRSA allows Kubernetes service accounts to assume IAM roles, providing granular AWS permissions to pods without distributing AWS credentials. For ECR, this means the pod's service account (via its linked IAM role) needs permission to authenticate with ECR and pull images.
The process involves several components:
- EKS OIDC Provider: An OpenID Connect (OIDC) identity provider for your EKS cluster that allows IAM to trust identities from your cluster.
- Kubernetes Service Account: A Kubernetes object that pods use to identify themselves to the cluster.
- IAM Role: An AWS identity with specific permissions, which is assumed by the Kubernetes service account.
- ECR Repository: The private AWS container registry where your images are stored.
Symptom Analysis & Root Causes
Symptom: ImagePullBackOff
The primary symptom is a pod stuck in a Pending or CrashLoopBackOff state, with the STATUS column eventually showing ImagePullBackOff. You can confirm this with the following commands:
Look for output similar to:
Further investigation into the pod's events will provide more details:
In the "Events" section, you might see errors like:
Failed to pull image "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-private-repo:latest": rpc error: code = Unknown desc = Error response from daemon: Get "https://123456789012.dkr.ecr.us-east-1.amazonaws.com/v2/": no basic auth credentials or Failed to pull image "my-image": rpc error: code = NotFound desc = pull access denied for 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-private-repo, repository does not exist or may require 'docker login'.
Common Root Causes
Here are the most frequent reasons for ImagePullBackOff with private ECR images and IRSA on EKS:
-
Incorrect IAM Role for Service Account (IRSA) Configuration: The Kubernetes Service Account (SA) either doesn't have the correct
eks.amazonaws.com/role-arnannotation, or the specified IAM role ARN is invalid. -
Missing ECR Permissions on IAM Role: The IAM role linked to the service account lacks the necessary permissions to pull images from ECR (e.g.,
ecr:GetDownloadUrlForLayer,ecr:BatchGetImage,ecr:BatchCheckLayerAvailability,ecr:GetAuthorizationToken). -
Trust Policy Issues for the IAM Role: The IAM role's trust policy does not correctly allow the EKS OIDC provider to assume the role, or the OIDC provider URL/audience in the trust policy is incorrect. The
subcondition in the trust policy might also be wrong (e.g., incorrect namespace or service account name). -
Service Account Not Linked to Pod: The pod's manifest does not specify the
serviceAccountName, or it points to a non-existent service account. - Network Connectivity Issues to ECR: EKS worker nodes (or the pod itself if using custom networking) cannot reach the ECR endpoint. This could be due to VPC Security Group rules, Network ACLs, or missing VPC Endpoints for ECR.
- Image Name/Tag Mismatch or Non-Existent Image: The image URI or tag specified in the pod manifest is incorrect, or the image simply doesn't exist in the specified ECR repository.
- EKS OIDC Provider Not Configured or Invalid: The OIDC provider for the EKS cluster might not be set up correctly in IAM.
Step-by-Step Resolution Guide
Step 1: Verify Pod and Service Account Configuration
Ensure your pod is explicitly using the correct service account, and that the service account is annotated with the IAM Role ARN.
- Check Pod Manifest:
Verify that your pod's YAML includes
serviceAccountName: your-service-account-nameand that the image path is correct.apiVersion: v1 kind: Pod metadata: name: my-app-pod labels: app: my-app spec: serviceAccountName: my-service-account # <-- This must match your SA name containers: - name: my-app-container image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-private-repo:latest # <-- Full ECR URI with account ID and region ports: - containerPort: 80 - Inspect Service Account:
Retrieve the YAML for the service account used by your pod and confirm the presence and correctness of the IAM role ARN annotation.
kubectl get sa my-service-account -n your-namespace -o yamlLook for an annotation like:annotations: eks.amazonaws.com/role-arn: arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/YourEKSIRSAIAMRoleName
The IAM Role ARN must precisely match the role created for IRSA.
Step 2: Inspect the IAM Role Associated with the Service Account
The IAM role needs a specific trust policy that allows the EKS OIDC provider to assume it, and an attached permissions policy that grants ECR pull access.
- Retrieve IAM Role Details:
Use the AWS CLI to get the details of the IAM role identified in Step 1.
aws iam get-role --role-name YourEKSIRSAIAMRoleName
From the output, extract the
AssumeRolePolicyDocument(Trust Policy) and check the attached managed/inline policies. - Verify Trust Policy:
The trust policy must permit the OIDC provider of your EKS cluster to assume the role. Pay close attention to the
Federatedprincipal,Action, and especially theConditionblock.{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::YOUR_AWS_ACCOUNT_ID:oidc-provider/oidc.eks.YOUR_AWS_REGION.amazonaws.com/id/YOUR_EKS_OIDC_ID" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.YOUR_AWS_REGION.amazonaws.com/id/YOUR_EKS_OIDC_ID:sub": "system:serviceaccount:your-namespace:my-service-account", "oidc.eks.YOUR_AWS_REGION.amazonaws.com/id/YOUR_EKS_OIDC_ID:aud": "sts.amazonaws.com" } } } ] }Ensure:
YOUR_AWS_ACCOUNT_IDmatches your AWS account ID.YOUR_AWS_REGIONmatches your EKS cluster's region.YOUR_EKS_OIDC_IDis the correct OIDC ID for your cluster (usually found in the EKS cluster details).your-namespaceandmy-service-accountexactly match the Kubernetes namespace and service account name.- The
audcondition is set tosts.amazonaws.com.
- Verify Permissions Policy:
The IAM role needs permissions to interact with ECR. A common policy for pulling images looks like this:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability", "ecr:GetAuthorizationToken" ], "Resource": "*" } ] }
While
"Resource": "*"is often used for simplicity, it is a best practice to restrict the resource to specific ECR repositories if possible (e.g.,"arn:aws:ecr:YOUR_AWS_REGION:YOUR_AWS_ACCOUNT_ID:repository/my-private-repo"for the first three actions, and"*"or specific registries forGetAuthorizationTokenif cross-account pull is needed).
Step 3: Verify EKS OIDC Provider
Ensure your EKS cluster has an associated OIDC identity provider in IAM, and its URL matches the one used in the IAM role's trust policy.
- Get OIDC Issuer URL for your EKS Cluster:
aws eks describe-cluster --name YOUR_EKS_CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text
The output (e.g.,
https://oidc.eks.YOUR_AWS_REGION.amazonaws.com/id/YOUR_EKS_OIDC_ID) should exactly match theFederatedprincipal in your IAM role's trust policy (excluding thearn:aws:iam::ACCOUNT_ID:oidc-provider/prefix). - List IAM OIDC Providers:
aws iam list-open-id-connect-providers
Confirm that an OIDC provider with your EKS cluster's issuer URL exists and is properly configured. If not, you may need to create one (e.g., using
eksctl utils associate-iam-oidc-provider --cluster YOUR_EKS_CLUSTER_NAME --approve).
Step 4: Network Connectivity Checks
Even with correct IAM permissions, if your EKS worker nodes or pods cannot reach ECR, image pulls will fail.
- Security Groups & Network ACLs: Ensure the Security Groups attached to your EKS worker nodes (or Fargate profiles) allow outbound HTTPS (port 443) traffic to ECR endpoints. If ECR VPC Endpoints are used, ensure connectivity to those endpoints.
- VPC Endpoints for ECR:
For private subnets, ensure you have VPC endpoints for ECR (
com.amazonaws.YOUR_REGION.ecr.apiandcom.amazonaws.YOUR_REGION.ecr.dkr) and S3 (com.amazonaws.YOUR_REGION.s3) configured. S3 is required for pulling certain image layers. - Test Connectivity from a Debug Pod:
Launch a simple pod on your cluster (preferably in the same namespace and with the same service account if possible) to test network reachability.
kubectl run -it --rm --restart=Never debug-pod --image=alpine -- sh # Inside the debug pod: apk add curl curl -v https://123456789012.dkr.ecr.us-east-1.amazonaws.com/v2/
You should expect to see an HTTP 401 Unauthorized response, which indicates network reachability. If you see connection timeouts or failures, your network configuration is the problem.
Step 5: Image Name and Tag Verification
A simple typo can cause this error. Double-check the image URI in your pod definition against the actual image in ECR.
- List ECR Images:
aws ecr describe-images --repository-name my-private-repo --region us-east-1
Ensure the image name and tag specified in your pod manifest exist in the ECR repository and match exactly.
Best Practices for Prevention & Performance Optimization
-
Principle of Least Privilege: Always grant the minimum necessary permissions to your IAM roles. For ECR image pulling, this means only the
ecr:GetDownloadUrlForLayer,ecr:BatchGetImage,ecr:BatchCheckLayerAvailability, andecr:GetAuthorizationTokenactions. Specify resource ARNs for specific repositories when possible instead of"*". -
Automated IRSA Provisioning: Utilize tools like
eksctl, AWS CDK, or Terraform to provision your EKS clusters, OIDC providers, IAM roles, and Kubernetes service accounts. This reduces manual errors and ensures consistency. - VPC Endpoints for ECR & S3: For optimal security and performance, especially in private subnets, configure VPC interface endpoints for ECR API, ECR DKR, and a gateway endpoint for S3. This keeps image pulls within the AWS network, reducing latency and avoiding NAT Gateway costs.
-
Consistent Image Tagging Strategy: Implement a clear and consistent image tagging strategy (e.g., semantic versioning, git commit SHAs). Avoid using
:latestin production to prevent unexpected image changes. -
Proactive Monitoring and Alerting: Set up Amazon CloudWatch alarms for EKS-related metrics, ECR pull failures, and Kubernetes event monitoring to quickly detect and respond to
ImagePullBackOffevents. - Regular Audits: Periodically review your IAM roles, service account configurations, and network policies to ensure they align with security best practices and operational requirements.
Frequently Asked Questions (FAQs)
Q1: Can I use imagePullSecrets with IRSA?
While technically possible, it's generally not recommended to use imagePullSecrets (which typically store static ECR login credentials or Docker config.json) when IRSA is available. IRSA provides a more secure and robust way to grant temporary, rotating credentials to pods, eliminating the need to manage sensitive credentials within Kubernetes secrets. Stick to IRSA for ECR access on EKS for better security posture and simplified credential management.
Q2: How do I ensure my ECR images are highly available for pulling?
ECR itself is a highly available service by design, replicating images across multiple Availability Zones within a region. To optimize pull performance and reliability:
- Use ECR in the same AWS region as your EKS cluster.
- Implement VPC Endpoints for ECR and S3 to keep traffic within the AWS network.
- Ensure your worker nodes have sufficient network bandwidth.
- Consider ECR Pull Through Cache rules for upstream public registries like Docker Hub to locally cache frequently pulled images within your private ECR.
Q3: What if I have multiple ECR repositories in different AWS accounts?
To pull images from ECR repositories in different AWS accounts, the IAM role associated with your EKS service account needs permissions to access those cross-account repositories. This involves two main steps:
-
Source Account (where ECR repo resides): Grant the ECR repository policy permission to allow your EKS account's IAM role to perform ECR actions (
ecr:GetDownloadUrlForLayer,ecr:BatchGetImage,ecr:BatchCheckLayerAvailability). -
Target Account (where EKS cluster runs): Ensure the IAM role linked to your EKS service account has the necessary ECR permissions, possibly with resource ARNs pointing to the cross-account repositories, and definitely
ecr:GetAuthorizationTokenfor the cross-account registry.
- Get link
- X
- Other Apps