Amazon ECR "Public" credentials helper script for Kubernetes (ecr-public-creds-helper-for-k8s
for short) allows your Kubernetes clusters pull public container images from Amazon ECR Public registries as authenticated users to get the limit upgraded to 10
pulls per second which is 1
for unauthenticated users as described here, and unlimited data bandwidth as described here.
ecr-public-creds-helper-for-k8s
is one of the workarounds to access ECR Public as authenticated users from your Kubernetes clusters until 1) Amazon ECR Public get supported by the upstream Kubernetes project and/or 2) Official Amazon ECR Public support for AWS Fargate by Amazon EKS.
ecr-public-creds-helper-for-k8s
runs in your cluster as a Kubernetes CronJob every 8 hours by default. It authenticates against ECR Public and stores the auth token as Kubernetes Secrets within namespaces you specified.
Each pod (even on AWS Fargate) will reference that Kubernetes Secret in its namespace by specifying the imagePullSecrets
field in the PodSpec. You may also want to patch the default
service account in each namespace to avoid writing imagePullSecrets
in all PodSpecs, see the comments at the entrypoint.sh#L21 for further details.
See the "Create a Secret by providing credentials on the command line" section and the "Create a Pod that uses your Secret" in the Kubernetes documentation to understand how it works.
This project aims to fill the gap between Amazon EKS (Kubernetes, both EC2 and Fargate) and Amazon ECR Public. There are two pain points for users at the time of release of this repository as follows:
- Kubernetes supports Amazon ECR (the private one) to pull private ECR images with automatic auth via IAM roles, but still the latest version (1.20, at this moment) of Kubernetes doesn't support ECR Public yet. Thus there is no straightforward way to pull ECR Public container images from EKS/Kubernetes clusters as authenticated users. This means users are forced to access ECR Public as unauthenticated users from their Kubernetes clusters, resulting that pulls from ECR Public could be throttled easily and frequently.
- A PR in the "awslabs/amazon-ecr-credential-helper" GitHub repository could solve the pain point #1 someday, but the "awslabs/amazon-ecr-credential-helper" itself cannot be used for EKS/Fargate workloads by its design. EKS/Fargate users, not only EKS/EC2 users, obviously need a way to use ECR Public as authenticated users, so this is also the pain point that this project addresses.
$ git clone https://github.com/aws-containers/amazon-ecr-public-creds-helper-for-k8s.git
$ cd amazon-ecr-public-creds-helper-for-k8s
$ export CREDS_HELPER_CONTAINER_IMAGE=<your-creds-helper-container-image-name-here>
$ docker build -t ${CREDS_HELPER_CONTAINER_IMAGE} .
$ docker push ${CREDS_HELPER_CONTAINER_IMAGE}
Create a namespace for ecr-public-creds-helper-for-k8s
to run as a CronJob in your Kubernetes cluster.
$ kubectl apply -f namespace.yaml
namespace/ecr-public-creds-helper created
Create a service account to allow ecr-public-creds-helper-for-k8s
to edit Kubernetes secrets.
$ kubectl apply -f serviceaccount.yaml
serviceaccount/sa-secrets-editor created
clusterrole.rbac.authorization.k8s.io/secrets-editor created
clusterrolebinding.rbac.authorization.k8s.io/edit-secrets created
Create an AWS IAM role to allow ecr-public-creds-helper-for-k8s
to authenticate against Amazon ECR Public. We use the mechanism called IAM Roles for Service Accounts (IRSA) to map it to the service account which you created in the previous step.
If you have not enabled IRSA in your Kubernetes cluster yet, please follow the IRSA documentation and/or the blog post for enabling IRSA for your Kubernetes cluster.
We're going to use eksctl
here to show the steps to create and map the IAM role in an EKS cluster, but you can also use the AWS CLI, the AWS management console, CloudFormation, Terraform or whatever you want to use.
$ export POLICY_ARN=$(aws iam create-policy --policy-name AmazonECRPublicAuthOnlyPolicy --policy-document file://iam-permission.json --query Policy.Arn --output text)
## Check you've created the policy successfully
$ echo ${POLICY_ARN}
arn:aws:iam::YOUR_AWS_ACCOUNT_ID:policy/AmazonECRPublicAuthOnlyPolicy
$ export EKS_CLUSTER_NAME=<your-eks-cluster-name-here>
$ eksctl create iamserviceaccount --cluster=${EKS_CLUSTER_NAME} \
--name=sa-secrets-editor \
--namespace=ecr-public-creds-helper \
--attach-policy-arn=${POLICY_ARN} \
--override-existing-serviceaccounts \
--approve
Edit the cronjob.yaml before running ecr-public-creds-helper-for-k8s
in your Kubernetes cluster.
$ vim cronjob.yaml
There are two required fields to change.
Replace ${CREDS_HELPER_CONTAINER_IMAGE}
in line.22 in the cronjob.yaml with your creds helper container image name which you built and pushed in the Step 1.
Replace the value (default foo bar
) of TARGET_NAMESPACES
environment variable in line.26 in the cronjob.yaml with a space-delimited list which includes one or multiple Kuberentes namespaces where your pods need the auth token for ECR Public.
Let's say you want to pull ECR Public container images in three namespaces (default
, prometheus
, my-app
) with auth token, then the env.value
field will look like: value: "default prometheus my-app"
.
ecr-public-creds-helper-for-k8s
will store the auth token as Kubernetes Secrets in these namespaces.
Run ecr-public-creds-helper-for-k8s
in your Kubernetes cluster.
$ kubectl apply -f cronjob.yaml
cronjob.batch/ecr-public-creds-helper created
Create an initial auth token manually to let your pods use it without waiting the initial cronjob to be started. Note that ecs-public-creds-helper-for-k8s
refreshes the auth token in every 8 hours by default.
$ kubectl create job initial-creds-job \
-n ecr-public-creds-helper \
--from=cronjob/ecr-public-creds-helper
job.batch/initial-creds-job created
## Check the pod log to make sure it works as expected
$ export POD_NAME=$(kubectl get pods --selector=job-name=initial-creds-job -n ecr-public-creds-helper -o jsonpath='{.items[0].metadata.name}')
$ echo ${POD_NAME}
initial-creds-job-r4fbp # you'll see something like this
$ kubectl logs ${POD_NAME} -n ecr-public-creds-helper
### You'll see the same number of lines as the namespaces you specified in the "TARGET_NAMESPACES" in the cronjob.yaml
secret/ecr-public-token created
secret/ecr-public-token created
secret/ecr-public-token created
$ kubectl delete job initial-creds-job -n ecr-public-creds-helper
job.batch "initial-creds-job" deleted
Now your pod can use the auth token (Kubernetes secret) created by ecr-public-creds-helper-for-k8s
to pull public container images as an authenticated user from Amazon ECR Public registries.
You can reference the auth token from your pods like:
apiVersion: v1
kind: Pod
# ~ snip ~
spec:
# ~ snip ~
imagePullSecrets:
- name: ecr-public-token
# ~ snip ~
See also examples/pod.yaml for full example.
If you don't want to add imagePullSecrets
in each PodSpec, you may want to see the comments in the entrypoint.sh.
See CONTRIBUTING for more information.
Licensed under the MIT-0 License. See the LICENSE file.