K8S 中 AWS ECR 自动登录(更新 Token)

in 工作记录 with 0 comment

AWS 容器注册表(ECR) 主要为 Docker 容器提供镜像仓库服务。

但是,ECR Docker 凭据每12小时过期一次。

也就是每12小时就要重新登录一次,真是反人类的设定。

利用 Kubernetes 的 jobs,定时任务去更新这个 Token,可以解决这个麻烦。

想要获取 Token,又必须依赖 AWS 的 eksctl,也就是说,跑 Job 任务的容器中必须要安装 eksctl,也必须安装 kubectl。

  1. eksctl 获取到 Token
  2. kubectl 去把 Token 更新到 K8S 的 Secret 中。

真是恶心的事,自己做是太麻烦了,找了挺久才找到一个项目去做这些,

项目地址:

https://github.com/nabsul/k8s-ecr-login-renew

作者提供了两种方式:

  1. helm chart,这种最方便,但是我想用 yalm 的形式保存在仓库中,所以选择了第二种。
  2. yalm 文件, kubectl apply 执行。

使用 YAML 文件更新ECR Token

前提条件

创建一个 Secret,用来保存 AWS 的凭据,这里为 k8s-ecr-login-renew-aws-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: k8s-ecr-login-renew-aws-secret
data:
  AWS_ACCESS_KEY_ID: Your keyId (记得Base64编码)
  AWS_SECRET_ACCESS_KEY: Your aceessId (记得Base64编码)

开始

创建 k8s-ecr-login-renew-aws-secret.yaml

---
# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: k8s-ecr-login-renew-account
  namespace: default
---
# ClusterRole 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: k8s-ecr-login-renew-role
rules:
  - apiGroups: [""]
    resources:
      - namespaces
    verbs:
      - list
  - apiGroups: [""]
    resources:
      - secrets
      - serviceaccounts
      - serviceaccounts/token
    verbs:
      - 'delete'
      - 'create'
      - 'patch'
      - 'get'
---
# ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: k8s-ecr-login-renew-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: k8s-ecr-login-renew-role
subjects:
  - kind: ServiceAccount
    name: k8s-ecr-login-renew-account
    namespace: default
---
# CronJob 重点在这里
apiVersion: batch/v1
kind: CronJob
metadata:
  name: k8s-ecr-login-renew-cron
  namespace: default
spec:
  schedule: "* */6 * * *"
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 5
  jobTemplate:
    spec:
      template:
        metadata:
        spec:
          serviceAccountName: k8s-ecr-login-renew-account
          terminationGracePeriodSeconds: 0
          restartPolicy: Never
          containers:
          - name: k8s-ecr-login-renew
            imagePullPolicy: IfNotPresent
            image: nabsul/k8s-ecr-login-renew:v1.7.1
            env:
            # 这里引用了上一步创建的Secret,保存AWS的凭据的Secret。
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  name: k8s-ecr-login-renew-aws-secret
                  key: AWS_ACCESS_KEY_ID
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  name: k8s-ecr-login-renew-aws-secret
                  key: AWS_SECRET_ACCESS_KEY
            # region name,切换为你的账户的。
            - name: AWS_REGION
              value: cn-north-1
            # 最终生成的Secret, kubectl get Secrets可以看到。
            - name: DOCKER_SECRET_NAME
              value: dg-ecr-pull
            - name: TARGET_NAMESPACE
              value: default
            # 我这里是AWS中国 地址是amazonaws.com.cn,记得切换为你的。
            - name: DOCKER_REGISTRIES
              value: https://123456789.dkr.ecr.cn-north-1.amazonaws.com.cn

Apply Job

kubectl apply k8s-ecr-login-renew-aws-secret.yaml

测试 Job

创建一个 Test 的 Job, (此 pod 可随意删除)

kubectl create job --from=cronjob/k8s-ecr-login-renew-cron k8s-ecr-login-renew-cron-manual-1
kubectl get secret

如果能看到 dg-ecr-pull,就是 OK 的啦!

image.png

使用 Secret 登录

deployment.yaml 中,配置 imagePullSecrets 属性就好。

    spec:
      imagePullSecrets:
        - name: dg-ecr-pull