EKSで、別AWSアカウントのECRリポジトリのDockerイメージをpullする方法

AWS

はじめに

Nishipy
今回はECR上のDockerイメージを、別のAWSアカウントからpullする方法についてです。AWSの公式ドキュメント見ればわかるけど、まとまっていないので、自分のためにもまとめておきます。他にもあったら教えてください。

やりたいこと

今回やりたいことは、以下の通りです。

  • AWSアカウントは2つあるとする
    • AWSアカウント①にEKSクラスタがある
    • AWSアカウント②にECRリポジトリがある
  • AWSアカウント①のEKS上のKubernetesクラスタに対して、コンテナをデプロイする際に、AWSアカウント②のECRリポジトリからコンテナイメージをpullしたい

前提知識

ECR

Amazon Elastic Container Registry (Amazon ECR) は、Dockerレジストリのマネージドサービスです。レジストリは、AWSアカウントごとに用意されるので、今回のように別のAWSアカウントのリソースからアクセスしようとすると、少し設定が必要です。

Amazon Elastic Container Registry とは - Amazon ECR
Amazon ECR はマネージド型 AWS Docker レジストリサービスです。

EKS

Amazon Elastic Container Service for Kubernetes(Amazon EKS)は、Kubernetesのマネージドサービスです。現状は、コントロールプレーン(マスターノード)のみが、AWSのマネージドで提供されているようです。ワーカーノードはマネージドではなく、実態はEC2が動いています。

Amazon EKS とは - Amazon EKS
Amazon EKS は、独自の Kubernetes コントロールプレーンを立ち上げたり維持したりすることなく、AWS で Kubernetes を簡単に実行できるようにするマネージド型サービスです。

実現方法

2パターンまとめます。他にもあれば教えてください。

方法1. k8sのSecretを利用

Secretの生成

1つ目は、k8sのSecretを生成し、レジストリへの認証情報を埋め込む方法です。ECRのみならず、自前のDockerレジストリを利用する場合にも有効です。Dockerレジストリ認証用のSecretの生成については、以下のドキュメントが参考になります。

Pull an Image from a Private Registry

今回はECRへの認証トークンを、Secretに埋め込むことになるのですが、1つ懸念点があります。それは、ECRの認証に必要なトークンは、取得から12時間しか有効でない点です。したがって、ECR認証トークンとSecretを定期的に更新する必要があります。

Amazon ECR における Docker の基本 - Amazon ECR
Docker は、Linux コンテナに基づいた分散アプリケーションの構築、実行、テスト、デプロイを可能にするテクノロジーです。 Amazon ECR はマネージド型 AWS Docker レジストリサービスです。お客様は一般的な Docker CLI を使用してイメージをプッシュ、プル、管理できます。Amazon E...

CronJobで、ECR認証トークンとSecretを定期的に更新

ECR認証トークンとSecretを定期的に更新する仕組みについて、ググってみると、CronJobで実現できるみたいです。以下は、Githubからの引用です。

CronJobによりデプロイするSecret更新用のコンテナは、aws clikubectlが利用できるように適切なコンテナイメージから作成すれば十分です。また、Secretの作成や削除が可能なService Accountを同時に作成し、コンテナにマウントしておく必要がありそうです。デフォルトのService Accountでは、Secretの作成や削除はできません。


方法2. AWSのIAMを利用

正直言うと、ECRをレジストリとして使う場合は、今から紹介する方法が良いと思います。こっちの方が簡単だし、CronJobも不要です。

ワーカーノードの設定

Kubernetesの公式ドキュメントによると、

Images
If you need access to multiple registries, you can create one secret for each registry. Kubelet will merge any imagePullSecrets into a single virtual .docker/co...

Kubernetes has native support for the AWS EC2 Container Registry, when nodes are AWS EC2 instances.Simply use the full image name (e.g. ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag) in the Pod definition.
All users of the cluster who can create pods will be able to run pods that use any of the images in the ECR registry.
The kubelet will fetch and periodically refresh ECR credentials.It needs the following permissions to do this:

  • ecr:GetAuthorizationToken
  • ecr:BatchCheckLayerAvailability
  • ecr:GetDownloadUrlForLayer
  • ecr:GetRepositoryPolicy
  • ecr:DescribeRepositories
  • ecr:ListImages
  • ecr:BatchGetImage

つまり、KubernetesクラスタのワーカーノードがEC2である場合、ECRとの接続をネイティブはサポートされており、ワーカーノード(EC2)に適切なIAMロールを設定しておけばよいです。あとはマニフェストファイルに、pullしたいイメージのURIをそのまま書けば、コンテナが生成できます。
また、方法1で発生する「ECRの認証に必要なトークンは、取得から12時間しか有効でない」問題は、方法2では気にしなくてよいです。ECR認証情報の取得や更新は、ワーカーノードのkubeletくんが代行してくれるみたいです。

ECRリポジトリの設定

仮にECRとEKSを同じAWSアカウントで使っていれば、おそらく上で行ったワーカーノードの設定だけで完結します。しかし、今回はAWSアカウントが2つあり、「AWSアカウント①のEKS上のKubernetesクラスタに対して、コンテナをデプロイする際に、AWSアカウント②のECRリポジトリからコンテナイメージをpullしたい」ので、ECR側にも設定が必要です。

具体的には、ECRリポジトリに対して、セカンダリアクセスを許可するリポジトリーポリシーを設定します。以下のAWS公式ドキュメントに、設定例が書いてあります。

Amazon ECR リポジトリポリシーの例 - Amazon ECR
以下の例では、Amazon ECR リポジトリに対してユーザーが所有するアクセス権限を制御するために使用できるポリシーステートメントを示しています。

さいごに

ECRは、設定次第では公開Dockerレジストリとして使えなくもないと言うことがわかりました。方法1を知ったおかげでCronJobを使う練習にはなりましたが、せっかくAWSを使うなら方法2のようにIAMを利用するのがスマートな気もします。

AWSもKubernetesも奥が深いと言うか、進化がはやすぎて追いつける気がしませんが、今後も積極的に使っていき、あわよくば記事にまとめます。


以上.

コメント