Hướng Dẫn Cập Nhật Tự Động AWS ECR Token Trên Kubernetes Với CronJobs
Token của AWS ECR sẽ hết hạn sau 12 giờ. Bài viết này hướng dẫn chi tiết cách sử dụng Kubernetes CronJobs để tự động gia hạn ECR token, giúp quy trình CI/CD không bị gián đoạn.
Mục lục
Bạn đang sử dụng AWS Elastic Container Registry (ECR) để lưu trữ và quản lý các Docker image? Nếu vậy, chắc hẳn bạn đã gặp phải một vấn đề khá phiền toái: Token xác thực của ECR sẽ hết hạn sau mỗi 12 giờ. Điều này đồng nghĩa với việc bạn phải gia hạn token theo cách thủ công hoặc thông qua code để Kubernetes có thể tiếp tục pull (kéo) image từ ECR.
Việc này có thể trở thành một gánh nặng lớn, đặc biệt khi hệ thống của bạn có nhiều cluster hoặc nhiều namespace cùng cần quyền truy cập vào ECR.
Rất may, chúng ta có một giải pháp tối ưu: Sử dụng Kubernetes CronJobs để tự động cập nhật ECR token.
Trong bài viết này, TechCoBan sẽ hướng dẫn bạn cách thiết lập một CronJob chạy định kỳ mỗi 10 giờ để tự động cập nhật ECR token vào một Secret. Sau đó, các Pods hoặc Deployments của bạn có thể sử dụng Secret này để pull image mượt mà. Nhờ đó, bạn sẽ không bao giờ phải bận tâm về việc token bị hết hạn nữa!
Yêu cầu chuẩn bị (Prerequisites)
Trước khi bắt đầu, hãy đảm bảo bạn đã chuẩn bị sẵn các yếu tố sau:
- Tài khoản AWS: Cần thiết để tạo và sử dụng ECR.
- Một kho lưu trữ (Repository) ECR: Nơi chứa Docker images của bạn.
- AWS Credentials (Access Key & Secret Access Key): Quyền truy cập IAM (nên sử dụng tài khoản có gắn policy
AmazonEC2ContainerRegistryReadOnly) để xác thực và lấy token từ ECR. - Một Kubernetes Cluster: Bạn có thể dùng Amazon EKS, Minikube hoặc bất kỳ nền tảng Kubernetes nào.
- Công cụ kubectl: Đã được cài đặt và cấu hình để giao tiếp với cluster của bạn.
Sau khi đã sẵn sàng, hãy tiến hành bước đầu tiên!
Bước 1: Tạo Secret, ConfigMap và ServiceAccount
Bước đầu tiên là tạo các tài nguyên cần thiết để CronJob có thể sử dụng thông tin xác thực AWS và lưu trữ Token mới. Trong ví dụ này, chúng ta sẽ sử dụng namespace default.
Lưu nội dung sau vào file ecr-registry-helper.yaml:
apiVersion: v1
kind: Secret
metadata:
name: ecr-registry-helper-secrets
namespace: default
stringData:
AWS_SECRET_ACCESS_KEY: "THAY_BANG_AWS_SECRET_ACCESS_KEY_CUA_BAN"
AWS_ACCESS_KEY_ID: "THAY_BANG_AWS_ACCESS_KEY_ID_CUA_BAN"
AWS_ACCOUNT: "THAY_BANG_AWS_ACCOUNT_ID_CUA_BAN"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ecr-registry-helper-cm
namespace: default
data:
AWS_REGION: "ap-southeast-1" # Thay bằng Region ECR của bạn (vd: ap-southeast-1)
DOCKER_SECRET_NAME: regcred # Tên của Secret chứa ECR token
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-default
namespace: default
Áp dụng file này vào cluster:
kubectl apply -f ecr-registry-helper.yaml
Kiểm tra xem các tài nguyên đã được tạo thành công chưa:
kubectl get secret ecr-registry-helper-secrets -n default
kubectl get configmap ecr-registry-helper-cm -n default
kubectl get serviceaccount sa-default -n default
Bước 2: Tạo Role và RoleBinding cho CronJob
Tiếp theo, chúng ta cần cấp quyền cho CronJob để nó có thể xóa (delete) và tạo mới (create) Secret (chứa token ECR) trong namespace mong muốn.
Lưu nội dung sau vào file ecr-registry-helper-rbac.yaml:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: role-full-access-to-secrets
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["regcred"] # Phải trùng với DOCKER_SECRET_NAME ở Bước 1
verbs: ["delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: default-role-binding
namespace: default
subjects:
- kind: ServiceAccount
name: sa-default
namespace: default
apiGroup: ""
roleRef:
kind: Role
name: role-full-access-to-secrets
apiGroup: ""
Áp dụng cấu hình RBAC:
kubectl apply -f ecr-registry-helper-rbac.yaml
Kiểm tra lại:
kubectl get role role-full-access-to-secrets -n default
kubectl get rolebinding default-role-binding -n default
Bước 3: Tạo CronJob để chạy Script cập nhật Token
Đây là bước quan trọng nhất. CronJob này sẽ chạy mỗi 10 giờ. Nó sử dụng một image có chứa aws-cli và kubectl để lấy ECR Token mới nhất, sau đó thay thế Secret cũ bằng Secret mới.
Lưu nội dung sau vào file ecr-registry-helper-cronjob.yaml:
apiVersion: batch/v1
kind: CronJob
metadata:
name: ecr-registry-helper
namespace: default
spec:
schedule: "0 */10 * * *" # Chạy mỗi 10 tiếng
successfulJobsHistoryLimit: 2
suspend: false
jobTemplate:
spec:
template:
spec:
serviceAccountName: sa-default
containers:
- name: ecr-registry-helper
image: omarxs/awskctl:v1.0
imagePullPolicy: IfNotPresent
envFrom:
- secretRef:
name: ecr-registry-helper-secrets
- configMapRef:
name: ecr-registry-helper-cm
command:
- /bin/bash
- -c
- |-
ECR_TOKEN="$(aws ecr get-login-password --region ${AWS_REGION})"
NAMESPACE_NAME=default
kubectl delete secret --ignore-not-found $DOCKER_SECRET_NAME -n $NAMESPACE_NAME
kubectl create secret docker-registry $DOCKER_SECRET_NAME \
--docker-server=https://${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com \
--docker-username=AWS \
--docker-password=${ECR_TOKEN} \
--namespace=$NAMESPACE_NAME
echo "Secret đã được cập nhật thành công lúc $(date)"
restartPolicy: Never
Triển khai CronJob:
kubectl apply -f ecr-registry-helper-cronjob.yaml
Kiểm tra CronJob:
kubectl get cronjob ecr-registry-helper -n default
Bước 4: Kiểm tra và xác minh CronJob
Để đảm bảo mọi thứ hoạt động trơn tru, bạn có thể chạy CronJob thủ công thay vì đợi 10 tiếng.
Tạo một Job thủ công từ CronJob:
kubectl create job --from=cronjob/ecr-registry-helper ecr-registry-helper-manual
Kiểm tra trạng thái và xem log của Job này:
kubectl get job ecr-registry-helper-manual -n default
kubectl logs -n default -f job/ecr-registry-helper-manual
Nếu cấu hình đúng, bạn sẽ thấy dòng log hiển thị:
Secret đã được cập nhật thành công lúc Sat Jan 1 00:00:00 UTC 2026
Sau khi kiểm tra thành công, bạn có thể xóa Job thủ công này:
kubectl delete job ecr-registry-helper-manual -n default
Cách sử dụng Secret trong Pod
Bây giờ, bạn đã có một Secret tên là regcred tự động cập nhật. Để sử dụng nó pull image từ ECR, bạn chỉ cần khai báo imagePullSecrets trong cấu hình Pod/Deployment như sau:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: default
spec:
containers:
- name: test-container
image: <AWS_ACCOUNT>.dkr.ecr.<AWS_REGION>.amazonaws.com/<IMAGE_NAME>:<TAG>
imagePullPolicy: Always
imagePullSecrets:
- name: regcred # Tên secret đã khai báo
Cấu hình toàn bộ trong một File (All-in-One)
Nếu bạn muốn tiện lợi hơn, bạn có thể gộp tất cả các bước trên vào một file YAML duy nhất (vd: ecr-registry-helper-all.yaml).
Nhấn vào đây để xem toàn bộ nội dung file (Nhớ thay đổi các thông số cho phù hợp)
apiVersion: v1
kind: Secret
metadata:
name: ecr-registry-helper-secrets
namespace: default
stringData:
AWS_SECRET_ACCESS_KEY: "THAY_BANG_AWS_SECRET_ACCESS_KEY_CUA_BAN"
AWS_ACCESS_KEY_ID: "THAY_BANG_AWS_ACCESS_KEY_ID_CUA_BAN"
AWS_ACCOUNT: "THAY_BANG_AWS_ACCOUNT_ID_CUA_BAN"
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ecr-registry-helper-cm
namespace: default
data:
AWS_REGION: "ap-southeast-1"
DOCKER_SECRET_NAME: regcred
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-default
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: role-full-access-to-secrets
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["regcred"]
verbs: ["delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: default-role-binding
namespace: default
subjects:
- kind: ServiceAccount
name: sa-default
namespace: default
apiGroup: ""
roleRef:
kind: Role
name: role-full-access-to-secrets
apiGroup: ""
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ecr-registry-helper
namespace: default
spec:
schedule: "0 */10 * * *"
successfulJobsHistoryLimit: 2
suspend: false
jobTemplate:
spec:
template:
spec:
serviceAccountName: sa-default
containers:
- name: ecr-registry-helper
image: omarxs/awskctl:v1.0
imagePullPolicy: IfNotPresent
envFrom:
- secretRef:
name: ecr-registry-helper-secrets
- configMapRef:
name: ecr-registry-helper-cm
command:
- /bin/bash
- -c
- |-
ECR_TOKEN="$(aws ecr get-login-password --region ${AWS_REGION})"
NAMESPACE_NAME=default
kubectl delete secret --ignore-not-found $DOCKER_SECRET_NAME -n $NAMESPACE_NAME
kubectl create secret docker-registry $DOCKER_SECRET_NAME \
--docker-server=https://${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com \
--docker-username=AWS \
--docker-password=${ECR_TOKEN} \
--namespace=$NAMESPACE_NAME
echo "Secret đã được cập nhật thành công lúc $(date)"
restartPolicy: Never
Chỉ với một lệnh duy nhất:
kubectl apply -f ecr-registry-helper-all.yaml
Tổng kết
Qua bài viết này, bạn đã học được cách thiết lập một CronJob để tự động lấy Token xác thực từ AWS ECR và lưu vào Secret trong Kubernetes một cách an toàn và định kỳ. Bằng cách này, bạn sẽ loại bỏ được rủi ro lỗi pull image do token hết hạn (sau 12 giờ) và có thể hoàn toàn tập trung vào việc phát triển ứng dụng.
Hy vọng bài viết này của TechCoBan hữu ích cho công việc DevOps của bạn. Nếu có bất kỳ câu hỏi hoặc góp ý nào, đừng ngần ngại để lại bình luận nhé. Chúc bạn thành công!
Bình luận
Bài viết liên quan
Hướng Dẫn Triển Khai Cài Đặt RKE2 Chuẩn Production On-Premises
Bài viết hướng dẫn chi tiết từng bước cách cài đặt và cấu hình cụm Kubernetes với RKE2 (Rancher Kubernetes Engine 2) chuẩn Production, đảm bảo High Availability (HA) và an toàn bảo mật.
Tạo chứng chỉ SSL Wildcard cho Subdomain với Cloudflare và Docker
Hướng dẫn chi tiết cách tạo chứng chỉ SSL Wildcard miễn phí từ Let's Encrypt cho mọi Subdomain tự động thông qua DNS Challenge của Cloudflare và Docker.
Hướng Dẫn Triển Khai Cụm Amazon EKS Trên Nền Tảng AWS Bằng Terraform
Hướng dẫn chi tiết từng bước cách triển khai cụm Kubernetes (EKS) trên nền tảng AWS bằng công cụ Infrastructure as Code (IaC) Terraform. Bài viết phù hợp cho kỹ sư DevOps và Cloud.