digitaloceanのkubernetesにECRのprivate registryを追加する

2024年3月7日

add AWS ECR private registry

コンテナレジストリをDigital Ocean RegistryからAWS ECRへ変更しました。

背景

circle CIからの自動デプロイのテストで、digital oceanの500MB上限に達してしまってcircle ciからのPUSHが失敗してしまうので、ECRに移行することにしました。

手順

の通りにやっても401エラーになってしまったので

でうまくいきました。

※2024/1/27 追記
namespaceがdefault以外からの参照が不可能となっていたので、Namespace毎に作成するように変更した。

下記のエラーによりimageのpullが出来なくなっていた。(エラーログはpodのdescribe)

  Warning  FailedToRetrieveImagePullSecret  5m45s (x2458 over 2d3h)  kubelet  Unable to retrieve some image pull secrets (regcred); attempting to pull the image may not succeed.

ECR準備

  • ecr操作用のIAMユーザー作成
    • ecr操作用のIAMユーザーへ割り当てたポリシーは
      • AmazonEC2ContainerRegistryFullAccess
      • AmazonEC2ContainerRegistryPowerUserでも大丈夫だと思います。(未確認)
      • アクセスキーの発行
  • ecrレポジトリの作成
    • dititaloceanのkubernetesをシンガポールで作成しているので、ap-southeast-1 にて作成
    • privateレポジトリ
  • dockerからpushしてイメージを上げておく。
    • aws cliのインストール

imageをECRへPUSHさせるためローカルのdockerからログインしておく

aws ecr get-login-password | docker login --username AWS --password-stdin 1234567890.dkr.ecr.ap-southeast-1.amazonaws.com

12時間でセッションは切れます。

イメージのPUSH

ocarina@ab350-pro4:~/work/doks-wp/prod/k8s$ docker tag myimages/doks-wp:0.0.11 123456789012.dkr.ecr.ap-southeast-1.amazonaws.com:0.0.11
ocarina@ab350-pro4:~/work/doks-wp/prod/k8s$ docker push 123456789012.dkr.ecr.ap-southeast-1.amazonaws.com:0.0.11

Step 1: Create a secret, a configmap, and a service account for the CronJob

ServiceAccountの作成

cat <<END>ecr-registry-helper.yaml
apiVersion: v1
kind: Secret
metadata:
  name: ecr-registry-helper-secrets
  namespace: doks-wp # プロジェクトごとに指定していない場合はdefault
stringData:
  AWS_SECRET_ACCESS_KEY: "" # Replace with your AWS secret access key
  AWS_ACCESS_KEY_ID: "" # Replace with your AWS access key ID
  AWS_ACCOUNT: "" # Replace with your AWS account ID
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: ecr-registry-helper-cm
  namespace:  doks-wp # プロジェクトごとに指定していない場合はdefault
data:
  AWS_REGION: "eu-southeast-1" # Replace with your ECR region
  DOCKER_SECRET_NAME: regcred # Replace with your desired ECR token secret name
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sa-default
  namespace:  doks-wp # プロジェクトごとに指定していない場合はdefault
END

Step 2: Create a role and a role binding for the CronJob

目的の名前空間でシークレットを削除および作成する権限を CronJob に付与するロールとロール バインディングを作成

ServiceAccountへのロールの付与です

vi ecr-registry-helper-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: doks-wp # プロジェクトごとに指定していない場合はdefault
  name: role-full-access-to-secrets
rules:
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["regcred"] # Replace with your desired ECR token secret name
  verbs: ["delete"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: default-role-binding
  namespace: doks-wp # プロジェクトごとに指定していない場合はdefault
subjects:
- kind: ServiceAccount
  name: sa-default # Replace with your service account name if different
  namespace:  doks-wp # プロジェクトごとに指定していない場合はdefault
  apiGroup: ""
roleRef:
  kind: Role
  name: role-full-access-to-secrets # Replace with your role name if different 
  apiGroup: ""

Step 3: Create a CronJob that runs a script to update the ECR token secret

10時間おきにECR トークン シークレットを更新する CronJob を作成

vi ecr-registry-helper-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: ecr-registry-helper
  namespace:  doks-wp # プロジェクトごとに指定していない場合はdefault
spec:
  schedule: "0 */10 * * *" # Replace with your desired schedule
  successfulJobsHistoryLimit: 2
  suspend: false
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: sa-default # Replace with your service account name if different
          containers:
          - name: ecr-registry-helper
            image: omarxs/awskctl:v1.0
            imagePullPolicy: IfNotPresent
            envFrom:
              - secretRef:
                  name: ecr-registry-helper-secrets # Replace with your secret name if different
              - configMapRef:
                  name: ecr-registry-helper-cm # Replace with your configmap name if different
            command:
              - /bin/bash
              - -c
              - |-
                ECR_TOKEN="$(aws ecr get-login-password --region ${AWS_REGION})"
                NAMESPACE_NAME=doks-wp # プロジェクトごとに指定していない場合はdefault# Replace with your desired namespace
                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 was successfully updated at $(date)"
          restartPolicy: Never

apply

kubectl apply -f ecr-registry-helper.yaml
kubectl apply -f ecr-registry-helper-rbac.yaml
kubectl apply -f ecr-registry-helper-cronjob.yaml

手動で一回実行

kubectl create job -n doks-wp --from=cronjob/ecr-registry-helper ecr-registry-helper-manual 
kubectl get job -n doks-wp ecr-registry-helper-manual
kubectl logs -n doks-wp -f job/ecr-registry-helper-manual
問題なければ削除
kubectl delete job -n doks-wp ecr-registry-helper-manual 

確認

kubectl get serviceaccount

NAME SECRETS AGE
default 0 24d
sa-default 0 49m

kubectl get role

NAME CREATED AT
role-full-access-to-secrets 2024-01-24T23:22:39Z

kubectl get rolebinding

NAME ROLE AGE
default-role-binding Role/role-full-access-to-secrets 48m

kubectl get cronjob

NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
ecr-registry-helper 0 /10 False 0 11m 48m

コンテナレジストリをsecretのものを参照できるようにする

deployementごとに設定する場合

kubectl edit deployment/doks-wp-dev-web -n doks-wp

deployment.apps/doks-wp-dev-web edited

kubectl get deployment/doks-wp-dev-web -n doks-wp -o yaml | egrep -i "image\:|imagepullsecret" -A 1

      - image: 123456789012.dkr.ecr.ap-southeast-1.amazonaws.com/doks-wp:0.0.11
        imagePullPolicy: IfNotPresent
--
      imagePullSecrets:
      - name: regcred

デフォルトで参照するコンテナレジストリを変更する場合

https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-imagepullsecrets-to-a-service-account

kubectl edit serviceaccount/default

imagePullSecrets のnameを今回追加したもの(regcred)へ書き換えます

確認

digitaloceanからECRへ変更されたことを確認

kubectl get pods -n doks-wp

NAME READY STATUS RESTARTS AGE
doks-wp-dev-web-57685ff669-pt47n 1/1 Running 0 6s
doks-wp-dev-web-57df868b57-7xmf7 1/1 Terminating 0 9h
doks-wp-prod-web-848dd47496-5k4mm 1/1 Running 0 6d9h
doks-wp-prod-web-848dd47496-f6ksl 1/1 Running 0 6d9h

kubectl describe pods/doks-wp-dev-web-57685ff669-pt47n -n doks-wp | grep -i image\: 
Image:          123456789012.dkr.ecr.ap-southeast-1.amazonaws.com/doks-wp:0.0.11

続・確認

cronjobsが問題ないことを確認

kubectl get secret

NAME TYPE DATA AGE
ecr-registry-helper-secrets Opaque 3 12h
ocarina kubernetes.io/dockerconfigjson 1 25d
regcred kubernetes.io/dockerconfigjson 1 117m

kubectl get cronjobs

NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
ecr-registry-helper 0 /10 False 0 118m 12h

kubectl get jobs

NAME COMPLETIONS DURATION AGE
ecr-registry-helper-28435680 1/1 8s 11h
ecr-registry-helper-28436280 1/1 6s 118m

Posted by ocarina