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 マネージドコンテナイメージレジストリサービスです。

EKS

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

Amazon EKS とは - Amazon EKS
Amazon Elastic Kubernetes Service (Amazon EKS) は、Amazon Web Services (AWS) 上で、独自の Kubernetes コントロールプレーンをインストール、運用、保守する必要がないマネージド型サービスです。

実現方法

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

方法1. k8sのSecretを利用

Secretの生成

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

Pull an Image from a Private Registry
This page shows how to create a Pod that uses a Secret to pull an image from a private container image registry or repository. There are many private registries...(続く)

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

Amazon ECR

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

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

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


方法2. AWSのIAMを利用

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

ワーカーノードの設定

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

Images
A container image represents binary data that encapsulates an application and all its software dependencies. Container images are executable software bundles th...(続く)

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

さいごに

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

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


以上.

コメント